mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
Use std::string_view and fmtlib across all libraries (#3402)
- Twine, StringRef, Format, and NativeFormatting have been removed - Logging now uses fmtlib style formatting - Nearly all uses of wpi::outs/errs have been replaced with fmt::print() or std::puts()/std::fputs() (for unformatted strings). - A wpi/fmt/raw_ostream.h header has been added to enable fmt::print() with wpi::raw_ostream
This commit is contained in:
@@ -4,10 +4,12 @@
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <networktables/NetworkTableInstance.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/fmt/raw_ostream.h>
|
||||
#include <wpi/json.h>
|
||||
#include <wpi/raw_istream.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
@@ -105,7 +107,7 @@ bool ReadConfig() {
|
||||
try {
|
||||
j = wpi::json::parse(is);
|
||||
} catch (const wpi::json::parse_error& e) {
|
||||
ParseError() << "byte " << e.byte << ": " << e.what() << '\n';
|
||||
fmt::print(ParseError(), "byte {}: {}\n", e.byte, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -127,10 +129,9 @@ bool ReadConfig() {
|
||||
if (j.count("ntmode") != 0) {
|
||||
try {
|
||||
auto str = j.at("ntmode").get<std::string>();
|
||||
wpi::StringRef s(str);
|
||||
if (s.equals_lower("client")) {
|
||||
if (wpi::equals_lower(str, "client")) {
|
||||
server = false;
|
||||
} else if (s.equals_lower("server")) {
|
||||
} else if (wpi::equals_lower(str, "server")) {
|
||||
server = true;
|
||||
} else {
|
||||
ParseError() << "could not understand ntmode value '" << str << "'\n";
|
||||
@@ -156,8 +157,7 @@ bool ReadConfig() {
|
||||
}
|
||||
|
||||
void StartCamera(const CameraConfig& config) {
|
||||
wpi::outs() << "Starting camera '" << config.name << "' on " << config.path
|
||||
<< '\n';
|
||||
fmt::print("Starting camera '{}' on {}\n", config.name, config.path);
|
||||
auto camera = frc::CameraServer::GetInstance()->StartAutomaticCapture(
|
||||
config.name, config.path);
|
||||
|
||||
@@ -178,10 +178,10 @@ int main(int argc, char* argv[]) {
|
||||
// start NetworkTables
|
||||
auto ntinst = nt::NetworkTableInstance::GetDefault();
|
||||
if (server) {
|
||||
wpi::outs() << "Setting up NetworkTables server\n";
|
||||
std::puts("Setting up NetworkTables server");
|
||||
ntinst.StartServer();
|
||||
} else {
|
||||
wpi::outs() << "Setting up NetworkTables client for team " << team << '\n';
|
||||
fmt::print("Setting up NetworkTables client for team {}\n", team);
|
||||
ntinst.StartClientTeam(team);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,14 +7,15 @@
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <networktables/NetworkTable.h>
|
||||
#include <networktables/NetworkTableInstance.h>
|
||||
#include <wpi/DenseMap.h>
|
||||
#include <wpi/ManagedStatic.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/StringMap.h>
|
||||
#include <wpi/mutex.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
#include "cameraserver/CameraServerShared.h"
|
||||
#include "ntcore_cpp.h"
|
||||
@@ -56,20 +57,20 @@ CameraServer* CameraServer::GetInstance() {
|
||||
return &(*instance);
|
||||
}
|
||||
|
||||
static wpi::StringRef MakeSourceValue(CS_Source source,
|
||||
wpi::SmallVectorImpl<char>& buf) {
|
||||
static std::string_view MakeSourceValue(CS_Source source,
|
||||
wpi::SmallVectorImpl<char>& buf) {
|
||||
CS_Status status = 0;
|
||||
buf.clear();
|
||||
switch (cs::GetSourceKind(source, &status)) {
|
||||
case CS_SOURCE_USB: {
|
||||
wpi::StringRef prefix{"usb:"};
|
||||
std::string_view prefix{"usb:"};
|
||||
buf.append(prefix.begin(), prefix.end());
|
||||
auto path = cs::GetUsbCameraPath(source, &status);
|
||||
buf.append(path.begin(), path.end());
|
||||
break;
|
||||
}
|
||||
case CS_SOURCE_HTTP: {
|
||||
wpi::StringRef prefix{"ip:"};
|
||||
std::string_view prefix{"ip:"};
|
||||
buf.append(prefix.begin(), prefix.end());
|
||||
auto urls = cs::GetHttpCameraUrls(source, &status);
|
||||
if (!urls.empty()) {
|
||||
@@ -83,13 +84,11 @@ static wpi::StringRef MakeSourceValue(CS_Source source,
|
||||
return "unknown:";
|
||||
}
|
||||
|
||||
return wpi::StringRef{buf.begin(), buf.size()};
|
||||
return {buf.begin(), buf.size()};
|
||||
}
|
||||
|
||||
static std::string MakeStreamValue(const wpi::Twine& address, int port) {
|
||||
return ("mjpg:http://" + address + wpi::Twine(':') + wpi::Twine(port) +
|
||||
"/?action=stream")
|
||||
.str();
|
||||
static std::string MakeStreamValue(std::string_view address, int port) {
|
||||
return fmt::format("mjpg:http://{}:{}/?action=stream", address, port);
|
||||
}
|
||||
|
||||
std::shared_ptr<nt::NetworkTable> CameraServer::Impl::GetSourceTable(
|
||||
@@ -229,12 +228,8 @@ static std::string PixelFormatToString(int pixelFormat) {
|
||||
}
|
||||
|
||||
static std::string VideoModeToString(const cs::VideoMode& mode) {
|
||||
std::string rv;
|
||||
wpi::raw_string_ostream oss{rv};
|
||||
oss << mode.width << "x" << mode.height;
|
||||
oss << " " << PixelFormatToString(mode.pixelFormat) << " ";
|
||||
oss << mode.fps << " fps";
|
||||
return oss.str();
|
||||
return fmt::format("{}x{} {} {} fps", mode.width, mode.height,
|
||||
PixelFormatToString(mode.pixelFormat), mode.fps);
|
||||
}
|
||||
|
||||
static std::vector<std::string> GetSourceModeValues(int source) {
|
||||
@@ -248,23 +243,20 @@ static std::vector<std::string> GetSourceModeValues(int source) {
|
||||
|
||||
static void PutSourcePropertyValue(nt::NetworkTable* table,
|
||||
const cs::VideoEvent& event, bool isNew) {
|
||||
wpi::SmallString<64> name;
|
||||
wpi::SmallString<64> infoName;
|
||||
if (wpi::StringRef{event.name}.startswith("raw_")) {
|
||||
name = "RawProperty/";
|
||||
name += event.name;
|
||||
infoName = "RawPropertyInfo/";
|
||||
infoName += event.name;
|
||||
std::string_view namePrefix;
|
||||
std::string_view infoPrefix;
|
||||
if (wpi::starts_with(event.name, "raw_")) {
|
||||
namePrefix = "RawProperty";
|
||||
infoPrefix = "RawPropertyInfo";
|
||||
} else {
|
||||
name = "Property/";
|
||||
name += event.name;
|
||||
infoName = "PropertyInfo/";
|
||||
infoName += event.name;
|
||||
namePrefix = "Property";
|
||||
infoPrefix = "PropertyInfo";
|
||||
}
|
||||
|
||||
wpi::SmallString<64> buf;
|
||||
CS_Status status = 0;
|
||||
nt::NetworkTableEntry entry = table->GetEntry(name);
|
||||
nt::NetworkTableEntry entry =
|
||||
table->GetEntry(fmt::format("{}/{}", namePrefix, event.name));
|
||||
switch (event.propertyKind) {
|
||||
case CS_PROP_BOOLEAN:
|
||||
if (isNew) {
|
||||
@@ -277,13 +269,13 @@ static void PutSourcePropertyValue(nt::NetworkTable* table,
|
||||
case CS_PROP_ENUM:
|
||||
if (isNew) {
|
||||
entry.SetDefaultDouble(event.value);
|
||||
table->GetEntry(infoName + "/min")
|
||||
table->GetEntry(fmt::format("{}/{}/min", infoPrefix, event.name))
|
||||
.SetDouble(cs::GetPropertyMin(event.propertyHandle, &status));
|
||||
table->GetEntry(infoName + "/max")
|
||||
table->GetEntry(fmt::format("{}/{}/max", infoPrefix, event.name))
|
||||
.SetDouble(cs::GetPropertyMax(event.propertyHandle, &status));
|
||||
table->GetEntry(infoName + "/step")
|
||||
table->GetEntry(fmt::format("{}/{}/step", infoPrefix, event.name))
|
||||
.SetDouble(cs::GetPropertyStep(event.propertyHandle, &status));
|
||||
table->GetEntry(infoName + "/default")
|
||||
table->GetEntry(fmt::format("{}/{}/default", infoPrefix, event.name))
|
||||
.SetDouble(cs::GetPropertyDefault(event.propertyHandle, &status));
|
||||
} else {
|
||||
entry.SetDouble(event.value);
|
||||
@@ -404,12 +396,11 @@ CameraServer::Impl::Impl() : m_nextPort(kBasePort) {
|
||||
case cs::VideoEvent::kSourcePropertyChoicesUpdated: {
|
||||
auto table = GetSourceTable(event.sourceHandle);
|
||||
if (table) {
|
||||
wpi::SmallString<64> name{"PropertyInfo/"};
|
||||
name += event.name;
|
||||
name += "/choices";
|
||||
auto choices =
|
||||
cs::GetEnumPropertyChoices(event.propertyHandle, &status);
|
||||
table->GetEntry(name).SetStringArray(choices);
|
||||
table
|
||||
->GetEntry(fmt::format("PropertyInfo/{}/choices", event.name))
|
||||
.SetStringArray(choices);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -433,35 +424,35 @@ CameraServer::Impl::Impl() : m_nextPort(kBasePort) {
|
||||
// else tries to change it.
|
||||
wpi::SmallString<64> buf;
|
||||
m_tableListener = nt::NetworkTableInstance::GetDefault().AddEntryListener(
|
||||
kPublishName + wpi::Twine('/'),
|
||||
fmt::format("{}/", kPublishName),
|
||||
[=](const nt::EntryNotification& event) {
|
||||
wpi::StringRef relativeKey =
|
||||
event.name.substr(wpi::StringRef(kPublishName).size() + 1);
|
||||
auto relativeKey = wpi::drop_front(
|
||||
event.name, std::string_view{kPublishName}.size() + 1);
|
||||
|
||||
// get source (sourceName/...)
|
||||
auto subKeyIndex = relativeKey.find('/');
|
||||
if (subKeyIndex == wpi::StringRef::npos) {
|
||||
if (subKeyIndex == std::string_view::npos) {
|
||||
return;
|
||||
}
|
||||
wpi::StringRef sourceName = relativeKey.slice(0, subKeyIndex);
|
||||
auto sourceName = wpi::slice(relativeKey, 0, subKeyIndex);
|
||||
auto sourceIt = m_sources.find(sourceName);
|
||||
if (sourceIt == m_sources.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get subkey
|
||||
relativeKey = relativeKey.substr(subKeyIndex + 1);
|
||||
relativeKey.remove_prefix(subKeyIndex + 1);
|
||||
|
||||
// handle standard names
|
||||
wpi::StringRef propName;
|
||||
std::string_view propName;
|
||||
nt::NetworkTableEntry entry{event.entry};
|
||||
if (relativeKey == "mode") {
|
||||
// reset to current mode
|
||||
entry.SetString(VideoModeToString(sourceIt->second.GetVideoMode()));
|
||||
return;
|
||||
} else if (relativeKey.startswith("Property/")) {
|
||||
} else if (wpi::starts_with(relativeKey, "Property/")) {
|
||||
propName = relativeKey.substr(9);
|
||||
} else if (relativeKey.startswith("RawProperty/")) {
|
||||
} else if (wpi::starts_with(relativeKey, "RawProperty/")) {
|
||||
propName = relativeKey.substr(12);
|
||||
} else {
|
||||
return; // ignore
|
||||
@@ -501,14 +492,14 @@ cs::UsbCamera CameraServer::StartAutomaticCapture() {
|
||||
}
|
||||
|
||||
cs::UsbCamera CameraServer::StartAutomaticCapture(int dev) {
|
||||
cs::UsbCamera camera{"USB Camera " + wpi::Twine(dev), dev};
|
||||
cs::UsbCamera camera{fmt::format("USB Camera {}", dev), dev};
|
||||
StartAutomaticCapture(camera);
|
||||
auto csShared = GetCameraServerShared();
|
||||
csShared->ReportUsbCamera(camera.GetHandle());
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::UsbCamera CameraServer::StartAutomaticCapture(const wpi::Twine& name,
|
||||
cs::UsbCamera CameraServer::StartAutomaticCapture(std::string_view name,
|
||||
int dev) {
|
||||
cs::UsbCamera camera{name, dev};
|
||||
StartAutomaticCapture(camera);
|
||||
@@ -517,8 +508,8 @@ cs::UsbCamera CameraServer::StartAutomaticCapture(const wpi::Twine& name,
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::UsbCamera CameraServer::StartAutomaticCapture(const wpi::Twine& name,
|
||||
const wpi::Twine& path) {
|
||||
cs::UsbCamera CameraServer::StartAutomaticCapture(std::string_view name,
|
||||
std::string_view path) {
|
||||
cs::UsbCamera camera{name, path};
|
||||
StartAutomaticCapture(camera);
|
||||
auto csShared = GetCameraServerShared();
|
||||
@@ -526,7 +517,7 @@ cs::UsbCamera CameraServer::StartAutomaticCapture(const wpi::Twine& name,
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& host) {
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view host) {
|
||||
return AddAxisCamera("Axis Camera", host);
|
||||
}
|
||||
|
||||
@@ -542,8 +533,8 @@ cs::AxisCamera CameraServer::AddAxisCamera(wpi::ArrayRef<std::string> hosts) {
|
||||
return AddAxisCamera("Axis Camera", hosts);
|
||||
}
|
||||
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
const wpi::Twine& host) {
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view name,
|
||||
std::string_view host) {
|
||||
cs::AxisCamera camera{name, host};
|
||||
StartAutomaticCapture(camera);
|
||||
auto csShared = GetCameraServerShared();
|
||||
@@ -551,7 +542,7 @@ cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view name,
|
||||
const char* host) {
|
||||
cs::AxisCamera camera{name, host};
|
||||
StartAutomaticCapture(camera);
|
||||
@@ -560,7 +551,7 @@ cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view name,
|
||||
const std::string& host) {
|
||||
cs::AxisCamera camera{name, host};
|
||||
StartAutomaticCapture(camera);
|
||||
@@ -569,7 +560,7 @@ cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view name,
|
||||
wpi::ArrayRef<std::string> hosts) {
|
||||
cs::AxisCamera camera{name, hosts};
|
||||
StartAutomaticCapture(camera);
|
||||
@@ -578,7 +569,7 @@ cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::MjpegServer CameraServer::AddSwitchedCamera(const wpi::Twine& name) {
|
||||
cs::MjpegServer CameraServer::AddSwitchedCamera(std::string_view name) {
|
||||
// create a dummy CvSource
|
||||
cs::CvSource source{name, cs::VideoMode::PixelFormat::kMJPEG, 160, 120, 30};
|
||||
cs::MjpegServer server = StartAutomaticCapture(source);
|
||||
@@ -590,7 +581,7 @@ cs::MjpegServer CameraServer::AddSwitchedCamera(const wpi::Twine& name) {
|
||||
cs::MjpegServer CameraServer::StartAutomaticCapture(
|
||||
const cs::VideoSource& camera) {
|
||||
AddCamera(camera);
|
||||
auto server = AddServer(wpi::Twine("serve_") + camera.GetName());
|
||||
auto server = AddServer(fmt::format("serve_{}", camera.GetName()));
|
||||
server.SetSource(camera);
|
||||
return server;
|
||||
}
|
||||
@@ -633,22 +624,20 @@ cs::CvSink CameraServer::GetVideo(const cs::VideoSource& camera) {
|
||||
}
|
||||
}
|
||||
|
||||
cs::CvSink newsink{name};
|
||||
cs::CvSink newsink{name.str()};
|
||||
newsink.SetSource(camera);
|
||||
AddServer(newsink);
|
||||
return newsink;
|
||||
}
|
||||
|
||||
cs::CvSink CameraServer::GetVideo(const wpi::Twine& name) {
|
||||
wpi::SmallString<64> nameBuf;
|
||||
wpi::StringRef nameStr = name.toStringRef(nameBuf);
|
||||
cs::CvSink CameraServer::GetVideo(std::string_view name) {
|
||||
cs::VideoSource source;
|
||||
{
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
auto it = m_impl->m_sources.find(nameStr);
|
||||
auto it = m_impl->m_sources.find(name);
|
||||
if (it == m_impl->m_sources.end()) {
|
||||
auto csShared = GetCameraServerShared();
|
||||
csShared->SetCameraServerError("could not find camera {}", nameStr);
|
||||
csShared->SetCameraServerError("could not find camera {}", name);
|
||||
return cs::CvSink{};
|
||||
}
|
||||
source = it->second;
|
||||
@@ -656,14 +645,14 @@ cs::CvSink CameraServer::GetVideo(const wpi::Twine& name) {
|
||||
return GetVideo(source);
|
||||
}
|
||||
|
||||
cs::CvSource CameraServer::PutVideo(const wpi::Twine& name, int width,
|
||||
cs::CvSource CameraServer::PutVideo(std::string_view name, int width,
|
||||
int height) {
|
||||
cs::CvSource source{name, cs::VideoMode::kMJPEG, width, height, 30};
|
||||
StartAutomaticCapture(source);
|
||||
return source;
|
||||
}
|
||||
|
||||
cs::MjpegServer CameraServer::AddServer(const wpi::Twine& name) {
|
||||
cs::MjpegServer CameraServer::AddServer(std::string_view name) {
|
||||
int port;
|
||||
{
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
@@ -672,7 +661,7 @@ cs::MjpegServer CameraServer::AddServer(const wpi::Twine& name) {
|
||||
return AddServer(name, port);
|
||||
}
|
||||
|
||||
cs::MjpegServer CameraServer::AddServer(const wpi::Twine& name, int port) {
|
||||
cs::MjpegServer CameraServer::AddServer(std::string_view name, int port) {
|
||||
cs::MjpegServer server{name, port};
|
||||
AddServer(server);
|
||||
return server;
|
||||
@@ -683,14 +672,13 @@ void CameraServer::AddServer(const cs::VideoSink& server) {
|
||||
m_impl->m_sinks.try_emplace(server.GetName(), server);
|
||||
}
|
||||
|
||||
void CameraServer::RemoveServer(const wpi::Twine& name) {
|
||||
void CameraServer::RemoveServer(std::string_view name) {
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
wpi::SmallString<64> nameBuf;
|
||||
m_impl->m_sinks.erase(name.toStringRef(nameBuf));
|
||||
m_impl->m_sinks.erase(name);
|
||||
}
|
||||
|
||||
cs::VideoSink CameraServer::GetServer() {
|
||||
wpi::SmallString<64> name;
|
||||
std::string name;
|
||||
{
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
if (m_impl->m_primarySourceName.empty()) {
|
||||
@@ -698,20 +686,18 @@ cs::VideoSink CameraServer::GetServer() {
|
||||
csShared->SetCameraServerError("no camera available");
|
||||
return cs::VideoSink{};
|
||||
}
|
||||
name = "serve_";
|
||||
name += m_impl->m_primarySourceName;
|
||||
name = fmt::format("serve_{}", m_impl->m_primarySourceName);
|
||||
}
|
||||
return GetServer(name);
|
||||
}
|
||||
|
||||
cs::VideoSink CameraServer::GetServer(const wpi::Twine& name) {
|
||||
cs::VideoSink CameraServer::GetServer(std::string_view name) {
|
||||
wpi::SmallString<64> nameBuf;
|
||||
wpi::StringRef nameStr = name.toStringRef(nameBuf);
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
auto it = m_impl->m_sinks.find(nameStr);
|
||||
auto it = m_impl->m_sinks.find(name);
|
||||
if (it == m_impl->m_sinks.end()) {
|
||||
auto csShared = GetCameraServerShared();
|
||||
csShared->SetCameraServerError("could not find server {}", nameStr);
|
||||
csShared->SetCameraServerError("could not find server {}", name);
|
||||
return cs::VideoSink{};
|
||||
}
|
||||
return it->second;
|
||||
@@ -726,10 +712,9 @@ void CameraServer::AddCamera(const cs::VideoSource& camera) {
|
||||
m_impl->m_sources.try_emplace(name, camera);
|
||||
}
|
||||
|
||||
void CameraServer::RemoveCamera(const wpi::Twine& name) {
|
||||
void CameraServer::RemoveCamera(std::string_view name) {
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
wpi::SmallString<64> nameBuf;
|
||||
m_impl->m_sources.erase(name.toStringRef(nameBuf));
|
||||
m_impl->m_sources.erase(name);
|
||||
}
|
||||
|
||||
void CameraServer::SetSize(int size) {
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <wpi/ArrayRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
#include "cscore.h"
|
||||
#include "cscore_cv.h"
|
||||
@@ -63,7 +63,7 @@ class CameraServer {
|
||||
* @param name The name to give the camera
|
||||
* @param dev The device number of the camera interface
|
||||
*/
|
||||
cs::UsbCamera StartAutomaticCapture(const wpi::Twine& name, int dev);
|
||||
cs::UsbCamera StartAutomaticCapture(std::string_view name, int dev);
|
||||
|
||||
/**
|
||||
* Start automatically capturing images to send to the dashboard.
|
||||
@@ -71,8 +71,8 @@ class CameraServer {
|
||||
* @param name The name to give the camera
|
||||
* @param path The device path (e.g. "/dev/video0") of the camera
|
||||
*/
|
||||
cs::UsbCamera StartAutomaticCapture(const wpi::Twine& name,
|
||||
const wpi::Twine& path);
|
||||
cs::UsbCamera StartAutomaticCapture(std::string_view name,
|
||||
std::string_view path);
|
||||
|
||||
/**
|
||||
* Start automatically capturing images to send to the dashboard from
|
||||
@@ -89,7 +89,7 @@ class CameraServer {
|
||||
*
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
*/
|
||||
cs::AxisCamera AddAxisCamera(const wpi::Twine& host);
|
||||
cs::AxisCamera AddAxisCamera(std::string_view host);
|
||||
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
@@ -134,7 +134,7 @@ class CameraServer {
|
||||
* @param name The name to give the camera
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
*/
|
||||
cs::AxisCamera AddAxisCamera(const wpi::Twine& name, const wpi::Twine& host);
|
||||
cs::AxisCamera AddAxisCamera(std::string_view name, std::string_view host);
|
||||
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
@@ -142,7 +142,7 @@ class CameraServer {
|
||||
* @param name The name to give the camera
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
*/
|
||||
cs::AxisCamera AddAxisCamera(const wpi::Twine& name, const char* host);
|
||||
cs::AxisCamera AddAxisCamera(std::string_view name, const char* host);
|
||||
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
@@ -150,7 +150,7 @@ class CameraServer {
|
||||
* @param name The name to give the camera
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
*/
|
||||
cs::AxisCamera AddAxisCamera(const wpi::Twine& name, const std::string& host);
|
||||
cs::AxisCamera AddAxisCamera(std::string_view name, const std::string& host);
|
||||
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
@@ -158,7 +158,7 @@ class CameraServer {
|
||||
* @param name The name to give the camera
|
||||
* @param hosts Array of Camera host IPs/DNS names
|
||||
*/
|
||||
cs::AxisCamera AddAxisCamera(const wpi::Twine& name,
|
||||
cs::AxisCamera AddAxisCamera(std::string_view name,
|
||||
wpi::ArrayRef<std::string> hosts);
|
||||
|
||||
/**
|
||||
@@ -168,7 +168,7 @@ class CameraServer {
|
||||
* @param hosts Array of Camera host IPs/DNS names
|
||||
*/
|
||||
template <typename T>
|
||||
cs::AxisCamera AddAxisCamera(const wpi::Twine& name,
|
||||
cs::AxisCamera AddAxisCamera(std::string_view name,
|
||||
std::initializer_list<T> hosts);
|
||||
|
||||
/**
|
||||
@@ -177,7 +177,7 @@ class CameraServer {
|
||||
* VideoSource. Calling SetSource() on the returned object can be used
|
||||
* to switch the actual source of the stream.
|
||||
*/
|
||||
cs::MjpegServer AddSwitchedCamera(const wpi::Twine& name);
|
||||
cs::MjpegServer AddSwitchedCamera(std::string_view name);
|
||||
|
||||
/**
|
||||
* Get OpenCV access to the primary camera feed. This allows you to
|
||||
@@ -202,7 +202,7 @@ class CameraServer {
|
||||
*
|
||||
* @param name Camera name
|
||||
*/
|
||||
cs::CvSink GetVideo(const wpi::Twine& name);
|
||||
cs::CvSink GetVideo(std::string_view name);
|
||||
|
||||
/**
|
||||
* Create a MJPEG stream with OpenCV input. This can be called to pass custom
|
||||
@@ -212,21 +212,21 @@ class CameraServer {
|
||||
* @param width Width of the image being sent
|
||||
* @param height Height of the image being sent
|
||||
*/
|
||||
cs::CvSource PutVideo(const wpi::Twine& name, int width, int height);
|
||||
cs::CvSource PutVideo(std::string_view name, int width, int height);
|
||||
|
||||
/**
|
||||
* Adds a MJPEG server at the next available port.
|
||||
*
|
||||
* @param name Server name
|
||||
*/
|
||||
cs::MjpegServer AddServer(const wpi::Twine& name);
|
||||
cs::MjpegServer AddServer(std::string_view name);
|
||||
|
||||
/**
|
||||
* Adds a MJPEG server.
|
||||
*
|
||||
* @param name Server name
|
||||
*/
|
||||
cs::MjpegServer AddServer(const wpi::Twine& name, int port);
|
||||
cs::MjpegServer AddServer(std::string_view name, int port);
|
||||
|
||||
/**
|
||||
* Adds an already created server.
|
||||
@@ -240,7 +240,7 @@ class CameraServer {
|
||||
*
|
||||
* @param name Server name
|
||||
*/
|
||||
void RemoveServer(const wpi::Twine& name);
|
||||
void RemoveServer(std::string_view name);
|
||||
|
||||
/**
|
||||
* Get server for the primary camera feed.
|
||||
@@ -255,7 +255,7 @@ class CameraServer {
|
||||
*
|
||||
* @param name Server name
|
||||
*/
|
||||
cs::VideoSink GetServer(const wpi::Twine& name);
|
||||
cs::VideoSink GetServer(std::string_view name);
|
||||
|
||||
/**
|
||||
* Adds an already created camera.
|
||||
@@ -269,7 +269,7 @@ class CameraServer {
|
||||
*
|
||||
* @param name Camera name
|
||||
*/
|
||||
void RemoveCamera(const wpi::Twine& name);
|
||||
void RemoveCamera(std::string_view name);
|
||||
|
||||
/**
|
||||
* Sets the size of the image to use. Use the public kSize constants to set
|
||||
|
||||
@@ -19,7 +19,7 @@ inline cs::AxisCamera CameraServer::AddAxisCamera(
|
||||
|
||||
template <typename T>
|
||||
inline cs::AxisCamera CameraServer::AddAxisCamera(
|
||||
const wpi::Twine& name, std::initializer_list<T> hosts) {
|
||||
std::string_view name, std::initializer_list<T> hosts) {
|
||||
std::vector<std::string> vec;
|
||||
vec.reserve(hosts.size());
|
||||
for (const auto& host : hosts) {
|
||||
|
||||
@@ -7,7 +7,7 @@ GET_FILENAME_COMPONENT(inputBase ${input} NAME)
|
||||
STRING(REGEX REPLACE "[^a-zA-Z0-9]" "_" funcName "${inputBase}")
|
||||
SET(funcName "GetResource_${funcName}")
|
||||
|
||||
FILE(WRITE "${output}" "#include <stddef.h>\n#include <wpi/StringRef.h>\nextern \"C\" {\nstatic const unsigned char contents[] = {")
|
||||
FILE(WRITE "${output}" "#include <stddef.h>\n#include <string_view>\nextern \"C\" {\nstatic const unsigned char contents[] = {")
|
||||
|
||||
STRING(REGEX MATCHALL ".." outputData "${fileHex}")
|
||||
STRING(REGEX REPLACE ";" ", 0x" outputData "${outputData}")
|
||||
@@ -17,7 +17,7 @@ FILE(APPEND "${output}" "const unsigned char* ${prefix}${funcName}(size_t* len)
|
||||
IF(NOT namespace STREQUAL "")
|
||||
FILE(APPEND "${output}" "namespace ${namespace} {\n")
|
||||
ENDIF()
|
||||
FILE(APPEND "${output}" "wpi::StringRef ${funcName}() {\n return wpi::StringRef(reinterpret_cast<const char*>(contents), ${fileSize});\n}\n")
|
||||
FILE(APPEND "${output}" "std::string_view ${funcName}() {\n return std::string_view(reinterpret_cast<const char*>(contents), ${fileSize});\n}\n")
|
||||
IF(NOT namespace STREQUAL "")
|
||||
FILE(APPEND "${output}" "}\n")
|
||||
ENDIF()
|
||||
|
||||
@@ -31,6 +31,7 @@ repoRootNameOverride {
|
||||
}
|
||||
|
||||
includeOtherLibs {
|
||||
^fmt/
|
||||
^opencv2/
|
||||
^support/
|
||||
^tcpsockets/
|
||||
|
||||
@@ -2,83 +2,77 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <cstdio>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "cscore.h"
|
||||
|
||||
int main() {
|
||||
CS_Status status = 0;
|
||||
wpi::SmallString<64> buf;
|
||||
|
||||
for (const auto& caminfo : cs::EnumerateUsbCameras(&status)) {
|
||||
wpi::outs() << caminfo.dev << ": " << caminfo.path << " (" << caminfo.name
|
||||
<< ")\n";
|
||||
fmt::print("{}: {} ({})\n", caminfo.dev, caminfo.path, caminfo.name);
|
||||
if (!caminfo.otherPaths.empty()) {
|
||||
wpi::outs() << "Other device paths:\n";
|
||||
std::puts("Other device paths:");
|
||||
for (auto&& path : caminfo.otherPaths) {
|
||||
wpi::outs() << " " << path << '\n';
|
||||
fmt::print(" {}\n", path);
|
||||
}
|
||||
}
|
||||
|
||||
cs::UsbCamera camera{"usbcam", caminfo.dev};
|
||||
|
||||
wpi::outs() << "Properties:\n";
|
||||
std::puts("Properties:");
|
||||
for (const auto& prop : camera.EnumerateProperties()) {
|
||||
wpi::outs() << " " << prop.GetName();
|
||||
fmt::print(" {}", prop.GetName());
|
||||
switch (prop.GetKind()) {
|
||||
case cs::VideoProperty::kBoolean:
|
||||
wpi::outs() << " (bool): "
|
||||
<< "value=" << prop.Get()
|
||||
<< " default=" << prop.GetDefault();
|
||||
fmt::print(" (bool): value={} default={}", prop.Get(),
|
||||
prop.GetDefault());
|
||||
break;
|
||||
case cs::VideoProperty::kInteger:
|
||||
wpi::outs() << " (int): "
|
||||
<< "value=" << prop.Get() << " min=" << prop.GetMin()
|
||||
<< " max=" << prop.GetMax() << " step=" << prop.GetStep()
|
||||
<< " default=" << prop.GetDefault();
|
||||
fmt::print(" (int): value={} min={} max={} step={} default={}",
|
||||
prop.Get(), prop.GetMin(), prop.GetMax(), prop.GetStep(),
|
||||
prop.GetDefault());
|
||||
break;
|
||||
case cs::VideoProperty::kString:
|
||||
wpi::outs() << " (string): " << prop.GetString(buf);
|
||||
fmt::print(" (string): {}", prop.GetString());
|
||||
break;
|
||||
case cs::VideoProperty::kEnum: {
|
||||
wpi::outs() << " (enum): "
|
||||
<< "value=" << prop.Get();
|
||||
fmt::print(" (enum): value={}", prop.Get());
|
||||
auto choices = prop.GetChoices();
|
||||
for (size_t i = 0; i < choices.size(); ++i) {
|
||||
if (choices[i].empty()) {
|
||||
continue;
|
||||
if (!choices[i].empty()) {
|
||||
fmt::print("\n {}: {}", i, choices[i]);
|
||||
}
|
||||
wpi::outs() << "\n " << i << ": " << choices[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
wpi::outs() << '\n';
|
||||
std::fputc('\n', stdout);
|
||||
}
|
||||
|
||||
wpi::outs() << "Video Modes:\n";
|
||||
std::puts("Video Modes:");
|
||||
for (const auto& mode : camera.EnumerateVideoModes()) {
|
||||
wpi::outs() << " PixelFormat:";
|
||||
const char* pixelFormat;
|
||||
switch (mode.pixelFormat) {
|
||||
case cs::VideoMode::kMJPEG:
|
||||
wpi::outs() << "MJPEG";
|
||||
pixelFormat = "MJPEG";
|
||||
break;
|
||||
case cs::VideoMode::kYUYV:
|
||||
wpi::outs() << "YUYV";
|
||||
pixelFormat = "YUYV";
|
||||
break;
|
||||
case cs::VideoMode::kRGB565:
|
||||
wpi::outs() << "RGB565";
|
||||
pixelFormat = "RGB565";
|
||||
break;
|
||||
default:
|
||||
wpi::outs() << "Unknown";
|
||||
pixelFormat = "Unknown";
|
||||
break;
|
||||
}
|
||||
wpi::outs() << " Width:" << mode.width;
|
||||
wpi::outs() << " Height:" << mode.height;
|
||||
wpi::outs() << " FPS:" << mode.fps << '\n';
|
||||
fmt::print(" PixelFormat:{} Width:{} Height:{} FPS:{}\n", pixelFormat,
|
||||
mode.width, mode.height, mode.fps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,23 +3,27 @@
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <thread>
|
||||
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <fmt/format.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
|
||||
#include "cscore.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
wpi::errs() << "Usage: settings camera [prop val] ... -- [prop val]...\n";
|
||||
wpi::errs() << " Example: settings 1 brightness 30 raw_contrast 10\n";
|
||||
std::fputs("Usage: settings camera [prop val] ... -- [prop val]...\n",
|
||||
stderr);
|
||||
std::fputs(" Example: settings 1 brightness 30 raw_contrast 10\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int id;
|
||||
if (wpi::StringRef{argv[1]}.getAsInteger(10, id)) {
|
||||
wpi::errs() << "Expected number for camera\n";
|
||||
if (auto v = wpi::parse_integer<int>(argv[1], 10)) {
|
||||
id = v.value();
|
||||
} else {
|
||||
std::fputs("Expected number for camera\n", stderr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -27,22 +31,21 @@ int main(int argc, char** argv) {
|
||||
|
||||
// Set prior to connect
|
||||
int arg = 2;
|
||||
wpi::StringRef propName;
|
||||
for (; arg < argc && wpi::StringRef{argv[arg]} != "--"; ++arg) {
|
||||
std::string_view propName;
|
||||
for (; arg < argc && std::string_view{argv[arg]} != "--"; ++arg) {
|
||||
if (propName.empty()) {
|
||||
propName = argv[arg];
|
||||
} else {
|
||||
wpi::StringRef propVal{argv[arg]};
|
||||
int intVal;
|
||||
if (propVal.getAsInteger(10, intVal)) {
|
||||
camera.GetProperty(propName).SetString(propVal);
|
||||
std::string_view propVal{argv[arg]};
|
||||
if (auto v = wpi::parse_integer<int>(propVal, 10)) {
|
||||
camera.GetProperty(propName).Set(v.value());
|
||||
} else {
|
||||
camera.GetProperty(propName).Set(intVal);
|
||||
camera.GetProperty(propName).SetString(propVal);
|
||||
}
|
||||
propName = wpi::StringRef{};
|
||||
propName = {};
|
||||
}
|
||||
}
|
||||
if (arg < argc && wpi::StringRef{argv[arg]} == "--") {
|
||||
if (arg < argc && std::string_view{argv[arg]} == "--") {
|
||||
++arg;
|
||||
}
|
||||
|
||||
@@ -52,57 +55,51 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
// Set rest
|
||||
propName = wpi::StringRef{};
|
||||
propName = {};
|
||||
for (; arg < argc; ++arg) {
|
||||
if (propName.empty()) {
|
||||
propName = argv[arg];
|
||||
} else {
|
||||
wpi::StringRef propVal{argv[arg]};
|
||||
int intVal;
|
||||
if (propVal.getAsInteger(10, intVal)) {
|
||||
camera.GetProperty(propName).SetString(propVal);
|
||||
std::string_view propVal{argv[arg]};
|
||||
if (auto v = wpi::parse_integer<int>(propVal, 10)) {
|
||||
camera.GetProperty(propName).Set(v.value());
|
||||
} else {
|
||||
camera.GetProperty(propName).Set(intVal);
|
||||
camera.GetProperty(propName).SetString(propVal);
|
||||
}
|
||||
propName = wpi::StringRef{};
|
||||
propName = {};
|
||||
}
|
||||
}
|
||||
|
||||
// Print settings
|
||||
wpi::SmallString<64> buf;
|
||||
wpi::outs() << "Properties:\n";
|
||||
std::puts("Properties:");
|
||||
for (const auto& prop : camera.EnumerateProperties()) {
|
||||
wpi::outs() << " " << prop.GetName();
|
||||
fmt::print(" {}", prop.GetName());
|
||||
switch (prop.GetKind()) {
|
||||
case cs::VideoProperty::kBoolean:
|
||||
wpi::outs() << " (bool): "
|
||||
<< "value=" << prop.Get()
|
||||
<< " default=" << prop.GetDefault();
|
||||
fmt::print(" (bool): value={} default={}", prop.Get(),
|
||||
prop.GetDefault());
|
||||
break;
|
||||
case cs::VideoProperty::kInteger:
|
||||
wpi::outs() << " (int): "
|
||||
<< "value=" << prop.Get() << " min=" << prop.GetMin()
|
||||
<< " max=" << prop.GetMax() << " step=" << prop.GetStep()
|
||||
<< " default=" << prop.GetDefault();
|
||||
fmt::print(" (int): value={} min={} max={} step={} default={}",
|
||||
prop.Get(), prop.GetMin(), prop.GetMax(), prop.GetStep(),
|
||||
prop.GetDefault());
|
||||
break;
|
||||
case cs::VideoProperty::kString:
|
||||
wpi::outs() << " (string): " << prop.GetString(buf);
|
||||
fmt::print(" (string): {}", prop.GetString());
|
||||
break;
|
||||
case cs::VideoProperty::kEnum: {
|
||||
wpi::outs() << " (enum): "
|
||||
<< "value=" << prop.Get();
|
||||
fmt::print(" (enum): value={}", prop.Get());
|
||||
auto choices = prop.GetChoices();
|
||||
for (size_t i = 0; i < choices.size(); ++i) {
|
||||
if (choices[i].empty()) {
|
||||
continue;
|
||||
if (!choices[i].empty()) {
|
||||
fmt::print("\n {}: {}", i, choices[i]);
|
||||
}
|
||||
wpi::outs() << "\n " << i << ": " << choices[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
wpi::outs() << '\n';
|
||||
std::fputc('\n', stdout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "cscore.h"
|
||||
|
||||
int main() {
|
||||
wpi::outs() << "hostname: " << cs::GetHostname() << '\n';
|
||||
wpi::outs() << "IPv4 network addresses:\n";
|
||||
fmt::print("hostname: {}\n", cs::GetHostname());
|
||||
std::puts("IPv4 network addresses:");
|
||||
for (const auto& addr : cs::GetNetworkInterfaces()) {
|
||||
wpi::outs() << " " << addr << '\n';
|
||||
fmt::print(" {}\n", addr);
|
||||
}
|
||||
cs::UsbCamera camera{"usbcam", 0};
|
||||
camera.SetVideoMode(cs::VideoMode::kMJPEG, 320, 240, 30);
|
||||
@@ -22,9 +22,8 @@ int main() {
|
||||
CS_Status status = 0;
|
||||
cs::AddListener(
|
||||
[&](const cs::RawEvent& event) {
|
||||
wpi::outs() << "FPS=" << camera.GetActualFPS()
|
||||
<< " MBPS=" << (camera.GetActualDataRate() / 1000000.0)
|
||||
<< '\n';
|
||||
fmt::print("FPS={} MBPS={}\n", camera.GetActualFPS(),
|
||||
(camera.GetActualDataRate() / 1000000.0));
|
||||
},
|
||||
cs::RawEvent::kTelemetryUpdated, false, &status);
|
||||
cs::SetTelemetryPeriod(1.0);
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <wpi/spinlock.h>
|
||||
#include <wpigui.h>
|
||||
|
||||
@@ -38,7 +39,7 @@ int main() {
|
||||
// get frame from camera
|
||||
uint64_t time = cvsink.GrabFrame(frame);
|
||||
if (time == 0) {
|
||||
wpi::outs() << "error: " << cvsink.GetError() << '\n';
|
||||
fmt::print("error: {}\n", cvsink.GetError());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
using namespace cs;
|
||||
|
||||
ConfigurableSourceImpl::ConfigurableSourceImpl(const wpi::Twine& name,
|
||||
ConfigurableSourceImpl::ConfigurableSourceImpl(std::string_view name,
|
||||
wpi::Logger& logger,
|
||||
Notifier& notifier,
|
||||
Telemetry& telemetry,
|
||||
@@ -50,11 +50,11 @@ void ConfigurableSourceImpl::NumSinksEnabledChanged() {
|
||||
// ignore
|
||||
}
|
||||
|
||||
void ConfigurableSourceImpl::NotifyError(const wpi::Twine& msg) {
|
||||
void ConfigurableSourceImpl::NotifyError(std::string_view msg) {
|
||||
PutError(msg, wpi::Now());
|
||||
}
|
||||
|
||||
int ConfigurableSourceImpl::CreateProperty(const wpi::Twine& name,
|
||||
int ConfigurableSourceImpl::CreateProperty(std::string_view name,
|
||||
CS_PropertyKind kind, int minimum,
|
||||
int maximum, int step,
|
||||
int defaultValue, int value) {
|
||||
@@ -75,12 +75,12 @@ int ConfigurableSourceImpl::CreateProperty(const wpi::Twine& name,
|
||||
value = prop.value;
|
||||
});
|
||||
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CREATED, name, ndx,
|
||||
kind, value, wpi::Twine{});
|
||||
kind, value, {});
|
||||
return ndx;
|
||||
}
|
||||
|
||||
int ConfigurableSourceImpl::CreateProperty(
|
||||
const wpi::Twine& name, CS_PropertyKind kind, int minimum, int maximum,
|
||||
std::string_view name, CS_PropertyKind kind, int minimum, int maximum,
|
||||
int step, int defaultValue, int value,
|
||||
std::function<void(CS_Property property)> onChange) {
|
||||
// TODO
|
||||
@@ -102,5 +102,5 @@ void ConfigurableSourceImpl::SetEnumPropertyChoices(
|
||||
prop->enumChoices = choices;
|
||||
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CHOICES_UPDATED,
|
||||
prop->name, property, CS_PROP_ENUM,
|
||||
prop->value, wpi::Twine{});
|
||||
prop->value, {});
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/ArrayRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
#include "SourceImpl.h"
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace cs {
|
||||
|
||||
class ConfigurableSourceImpl : public SourceImpl {
|
||||
protected:
|
||||
ConfigurableSourceImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
ConfigurableSourceImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
const VideoMode& mode);
|
||||
|
||||
@@ -35,10 +35,10 @@ class ConfigurableSourceImpl : public SourceImpl {
|
||||
void NumSinksEnabledChanged() override;
|
||||
|
||||
// OpenCV-specific functions
|
||||
void NotifyError(const wpi::Twine& msg);
|
||||
int CreateProperty(const wpi::Twine& name, CS_PropertyKind kind, int minimum,
|
||||
void NotifyError(std::string_view msg);
|
||||
int CreateProperty(std::string_view name, CS_PropertyKind kind, int minimum,
|
||||
int maximum, int step, int defaultValue, int value);
|
||||
int CreateProperty(const wpi::Twine& name, CS_PropertyKind kind, int minimum,
|
||||
int CreateProperty(std::string_view name, CS_PropertyKind kind, int minimum,
|
||||
int maximum, int step, int defaultValue, int value,
|
||||
std::function<void(CS_Property property)> onChange);
|
||||
void SetEnumPropertyChoices(int property, wpi::ArrayRef<std::string> choices,
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
|
||||
using namespace cs;
|
||||
|
||||
CvSinkImpl::CvSinkImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
CvSinkImpl::CvSinkImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry)
|
||||
: SinkImpl{name, logger, notifier, telemetry} {
|
||||
m_active = true;
|
||||
// m_thread = std::thread(&CvSinkImpl::ThreadMain, this);
|
||||
}
|
||||
|
||||
CvSinkImpl::CvSinkImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
CvSinkImpl::CvSinkImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
std::function<void(uint64_t time)> processFrame)
|
||||
: SinkImpl{name, logger, notifier, telemetry} {}
|
||||
@@ -110,7 +110,7 @@ void CvSinkImpl::ThreadMain() {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
continue;
|
||||
}
|
||||
SDEBUG4("waiting for frame");
|
||||
SDEBUG4("{}", "waiting for frame");
|
||||
Frame frame = source->GetNextFrame(); // blocks
|
||||
if (!m_active) {
|
||||
break;
|
||||
@@ -127,14 +127,14 @@ void CvSinkImpl::ThreadMain() {
|
||||
|
||||
namespace cs {
|
||||
|
||||
CS_Sink CreateCvSink(const wpi::Twine& name, CS_Status* status) {
|
||||
CS_Sink CreateCvSink(std::string_view name, CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
return inst.CreateSink(
|
||||
CS_SINK_CV, std::make_shared<CvSinkImpl>(name, inst.logger, inst.notifier,
|
||||
inst.telemetry));
|
||||
}
|
||||
|
||||
CS_Sink CreateCvSinkCallback(const wpi::Twine& name,
|
||||
CS_Sink CreateCvSinkCallback(std::string_view name,
|
||||
std::function<void(uint64_t time)> processFrame,
|
||||
CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
@@ -145,7 +145,7 @@ CS_Sink CreateCvSinkCallback(const wpi::Twine& name,
|
||||
|
||||
static constexpr unsigned SinkMask = CS_SINK_CV | CS_SINK_RAW;
|
||||
|
||||
void SetSinkDescription(CS_Sink sink, const wpi::Twine& description,
|
||||
void SetSinkDescription(CS_Sink sink, std::string_view description,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data || (data->kind & SinkMask) == 0) {
|
||||
@@ -183,12 +183,12 @@ std::string GetSinkError(CS_Sink sink, CS_Status* status) {
|
||||
return static_cast<CvSinkImpl&>(*data->sink).GetError();
|
||||
}
|
||||
|
||||
wpi::StringRef GetSinkError(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
std::string_view GetSinkError(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data || (data->kind & SinkMask) == 0) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return wpi::StringRef{};
|
||||
return {};
|
||||
}
|
||||
return static_cast<CvSinkImpl&>(*data->sink).GetError(buf);
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/condition_variable.h>
|
||||
|
||||
#include "Frame.h"
|
||||
@@ -24,9 +24,9 @@ class SourceImpl;
|
||||
|
||||
class CvSinkImpl : public SinkImpl {
|
||||
public:
|
||||
CvSinkImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
|
||||
CvSinkImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry);
|
||||
CvSinkImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
|
||||
CvSinkImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
~CvSinkImpl() override;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
using namespace cs;
|
||||
|
||||
CvSourceImpl::CvSourceImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
CvSourceImpl::CvSourceImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
const VideoMode& mode)
|
||||
: ConfigurableSourceImpl{name, logger, notifier, telemetry, mode} {}
|
||||
@@ -53,8 +53,7 @@ void CvSourceImpl::PutFrame(cv::Mat& image) {
|
||||
cv::cvtColor(finalImage, dest->AsMat(), cv::COLOR_BGRA2BGR);
|
||||
break;
|
||||
default:
|
||||
SERROR("PutFrame: " << image.channels()
|
||||
<< "-channel images not supported");
|
||||
SERROR("PutFrame: {}-channel images not supported", image.channels());
|
||||
return;
|
||||
}
|
||||
SourceImpl::PutFrame(std::move(dest), wpi::Now());
|
||||
@@ -62,7 +61,7 @@ void CvSourceImpl::PutFrame(cv::Mat& image) {
|
||||
|
||||
namespace cs {
|
||||
|
||||
CS_Source CreateCvSource(const wpi::Twine& name, const VideoMode& mode,
|
||||
CS_Source CreateCvSource(std::string_view name, const VideoMode& mode,
|
||||
CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
return inst.CreateSource(CS_SOURCE_CV, std::make_shared<CvSourceImpl>(
|
||||
@@ -81,7 +80,7 @@ void PutSourceFrame(CS_Source source, cv::Mat& image, CS_Status* status) {
|
||||
|
||||
static constexpr unsigned SourceMask = CS_SINK_CV | CS_SINK_RAW;
|
||||
|
||||
void NotifySourceError(CS_Source source, const wpi::Twine& msg,
|
||||
void NotifySourceError(CS_Source source, std::string_view msg,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data || (data->kind & SourceMask) == 0) {
|
||||
@@ -100,7 +99,7 @@ void SetSourceConnected(CS_Source source, bool connected, CS_Status* status) {
|
||||
static_cast<CvSourceImpl&>(*data->source).SetConnected(connected);
|
||||
}
|
||||
|
||||
void SetSourceDescription(CS_Source source, const wpi::Twine& description,
|
||||
void SetSourceDescription(CS_Source source, std::string_view description,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data || (data->kind & SourceMask) == 0) {
|
||||
@@ -110,7 +109,7 @@ void SetSourceDescription(CS_Source source, const wpi::Twine& description,
|
||||
static_cast<CvSourceImpl&>(*data->source).SetDescription(description);
|
||||
}
|
||||
|
||||
CS_Property CreateSourceProperty(CS_Source source, const wpi::Twine& name,
|
||||
CS_Property CreateSourceProperty(CS_Source source, std::string_view name,
|
||||
CS_PropertyKind kind, int minimum, int maximum,
|
||||
int step, int defaultValue, int value,
|
||||
CS_Status* status) {
|
||||
@@ -126,7 +125,7 @@ CS_Property CreateSourceProperty(CS_Source source, const wpi::Twine& name,
|
||||
}
|
||||
|
||||
CS_Property CreateSourcePropertyCallback(
|
||||
CS_Source source, const wpi::Twine& name, CS_PropertyKind kind, int minimum,
|
||||
CS_Source source, std::string_view name, CS_PropertyKind kind, int minimum,
|
||||
int maximum, int step, int defaultValue, int value,
|
||||
std::function<void(CS_Property property)> onChange, CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <wpi/ArrayRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
#include "ConfigurableSourceImpl.h"
|
||||
#include "SourceImpl.h"
|
||||
@@ -22,7 +22,7 @@ namespace cs {
|
||||
|
||||
class CvSourceImpl : public ConfigurableSourceImpl {
|
||||
public:
|
||||
CvSourceImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
|
||||
CvSourceImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry, const VideoMode& mode);
|
||||
~CvSourceImpl() override;
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
using namespace cs;
|
||||
|
||||
Frame::Frame(SourceImpl& source, const wpi::Twine& error, Time time)
|
||||
Frame::Frame(SourceImpl& source, std::string_view error, Time time)
|
||||
: m_impl{source.AllocFrameImpl().release()} {
|
||||
m_impl->refcount = 1;
|
||||
m_impl->error = error.str();
|
||||
m_impl->error = error;
|
||||
m_impl->time = time;
|
||||
}
|
||||
|
||||
@@ -522,10 +522,8 @@ Image* Frame::GetImageImpl(int width, int height,
|
||||
}
|
||||
|
||||
WPI_DEBUG4(Instance::GetInstance().logger,
|
||||
"converting image from " << cur->width << "x" << cur->height
|
||||
<< " type " << cur->pixelFormat << " to "
|
||||
<< width << "x" << height << " type "
|
||||
<< pixelFormat);
|
||||
"converting image from {}x{} type {} to {}x{} type {}", cur->width,
|
||||
cur->height, cur->pixelFormat, width, height, pixelFormat);
|
||||
|
||||
// If the source image is a JPEG, we need to decode it before we can do
|
||||
// anything else with it. Note that if the destination format is JPEG, we
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/mutex.h>
|
||||
|
||||
#include "Image.h"
|
||||
@@ -44,7 +44,7 @@ class Frame {
|
||||
public:
|
||||
Frame() noexcept = default;
|
||||
|
||||
Frame(SourceImpl& source, const wpi::Twine& error, Time time);
|
||||
Frame(SourceImpl& source, std::string_view error, Time time);
|
||||
|
||||
Frame(SourceImpl& source, std::unique_ptr<Image> image, Time time);
|
||||
|
||||
@@ -72,7 +72,7 @@ class Frame {
|
||||
|
||||
Time GetTime() const { return m_impl ? m_impl->time : 0; }
|
||||
|
||||
wpi::StringRef GetError() const {
|
||||
std::string_view GetError() const {
|
||||
if (!m_impl) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "HttpCameraImpl.h"
|
||||
|
||||
#include <wpi/MemAlloc.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/TCPConnector.h>
|
||||
#include <wpi/timestamp.h>
|
||||
|
||||
@@ -18,7 +19,7 @@
|
||||
|
||||
using namespace cs;
|
||||
|
||||
HttpCameraImpl::HttpCameraImpl(const wpi::Twine& name, CS_HttpCameraKind kind,
|
||||
HttpCameraImpl::HttpCameraImpl(std::string_view name, CS_HttpCameraKind kind,
|
||||
wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry)
|
||||
: SourceImpl{name, logger, notifier, telemetry}, m_kind{kind} {}
|
||||
@@ -84,7 +85,7 @@ void HttpCameraImpl::MonitorThreadMain() {
|
||||
// (this will result in an error at the read point, and ultimately
|
||||
// a reconnect attempt)
|
||||
if (m_streamConn && m_frameCount == 0) {
|
||||
SWARNING("Monitor detected stream hung, disconnecting");
|
||||
SWARNING("{}", "Monitor detected stream hung, disconnecting");
|
||||
m_streamConn->stream->close();
|
||||
}
|
||||
|
||||
@@ -92,7 +93,7 @@ void HttpCameraImpl::MonitorThreadMain() {
|
||||
m_frameCount = 0;
|
||||
}
|
||||
|
||||
SDEBUG("Monitor Thread exiting");
|
||||
SDEBUG("{}", "Monitor Thread exiting");
|
||||
}
|
||||
|
||||
void HttpCameraImpl::StreamThreadMain() {
|
||||
@@ -132,14 +133,14 @@ void HttpCameraImpl::StreamThreadMain() {
|
||||
SetConnected(true);
|
||||
|
||||
// stream
|
||||
DeviceStream(conn->is, boundary);
|
||||
DeviceStream(conn->is, boundary.str());
|
||||
{
|
||||
std::unique_lock lock(m_mutex);
|
||||
m_streamConn = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
SDEBUG("Camera Thread exiting");
|
||||
SDEBUG("{}", "Camera Thread exiting");
|
||||
SetConnected(false);
|
||||
}
|
||||
|
||||
@@ -150,7 +151,7 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
{
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (m_locations.empty()) {
|
||||
SERROR("locations array is empty!?");
|
||||
SERROR("{}", "locations array is empty!?");
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
return nullptr;
|
||||
}
|
||||
@@ -181,19 +182,17 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
|
||||
std::string warn;
|
||||
if (!conn->Handshake(req, &warn)) {
|
||||
SWARNING(GetName() << ": " << warn);
|
||||
SWARNING("{}", warn);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_streamConn = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Parse Content-Type header to get the boundary
|
||||
wpi::StringRef mediaType, contentType;
|
||||
std::tie(mediaType, contentType) = conn->contentType.str().split(';');
|
||||
mediaType = mediaType.trim();
|
||||
auto [mediaType, contentType] = wpi::split(conn->contentType.str(), ';');
|
||||
mediaType = wpi::trim(mediaType);
|
||||
if (mediaType != "multipart/x-mixed-replace") {
|
||||
SWARNING("\"" << req.host << "\": unrecognized Content-Type \"" << mediaType
|
||||
<< "\"");
|
||||
SWARNING("\"{}\": unrecognized Content-Type \"{}\"", req.host, mediaType);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_streamConn = nullptr;
|
||||
return nullptr;
|
||||
@@ -202,14 +201,13 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
// media parameters
|
||||
boundary.clear();
|
||||
while (!contentType.empty()) {
|
||||
wpi::StringRef keyvalue;
|
||||
std::tie(keyvalue, contentType) = contentType.split(';');
|
||||
contentType = contentType.ltrim();
|
||||
wpi::StringRef key, value;
|
||||
std::tie(key, value) = keyvalue.split('=');
|
||||
if (key.trim() == "boundary") {
|
||||
value = value.trim().trim('"'); // value may be quoted
|
||||
if (value.startswith("--")) {
|
||||
std::string_view keyvalue;
|
||||
std::tie(keyvalue, contentType) = wpi::split(contentType, ';');
|
||||
contentType = wpi::ltrim(contentType);
|
||||
auto [key, value] = wpi::split(keyvalue, '=');
|
||||
if (wpi::trim(key) == "boundary") {
|
||||
value = wpi::trim(wpi::trim(value), '"'); // value may be quoted
|
||||
if (wpi::starts_with(value, "--")) {
|
||||
value = value.substr(2);
|
||||
}
|
||||
boundary.append(value.begin(), value.end());
|
||||
@@ -217,8 +215,7 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
}
|
||||
|
||||
if (boundary.empty()) {
|
||||
SWARNING("\"" << req.host
|
||||
<< "\": empty multi-part boundary or no Content-Type");
|
||||
SWARNING("\"{}\": empty multi-part boundary or no Content-Type", req.host);
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_streamConn = nullptr;
|
||||
return nullptr;
|
||||
@@ -228,7 +225,7 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
|
||||
}
|
||||
|
||||
void HttpCameraImpl::DeviceStream(wpi::raw_istream& is,
|
||||
wpi::StringRef boundary) {
|
||||
std::string_view boundary) {
|
||||
// Stored here so we reuse it from frame to frame
|
||||
std::string imageBuf;
|
||||
|
||||
@@ -275,28 +272,29 @@ bool HttpCameraImpl::DeviceStreamFrame(wpi::raw_istream& is,
|
||||
wpi::SmallString<64> contentTypeBuf;
|
||||
wpi::SmallString<64> contentLengthBuf;
|
||||
if (!ParseHttpHeaders(is, &contentTypeBuf, &contentLengthBuf)) {
|
||||
SWARNING("disconnected during headers");
|
||||
SWARNING("{}", "disconnected during headers");
|
||||
PutError("disconnected during headers", wpi::Now());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the content type (if present)
|
||||
if (!contentTypeBuf.str().empty() &&
|
||||
!contentTypeBuf.str().startswith("image/jpeg")) {
|
||||
wpi::SmallString<64> errBuf;
|
||||
wpi::raw_svector_ostream errMsg{errBuf};
|
||||
errMsg << "received unknown Content-Type \"" << contentTypeBuf << "\"";
|
||||
SWARNING(errMsg.str());
|
||||
PutError(errMsg.str(), wpi::Now());
|
||||
!wpi::starts_with(contentTypeBuf, "image/jpeg")) {
|
||||
auto errMsg =
|
||||
fmt::format("received unknown Content-Type \"{}\"", contentTypeBuf);
|
||||
SWARNING("{}", errMsg);
|
||||
PutError(errMsg, wpi::Now());
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int contentLength = 0;
|
||||
if (contentLengthBuf.str().getAsInteger(10, contentLength)) {
|
||||
if (auto v = wpi::parse_integer<unsigned int>(contentLengthBuf, 10)) {
|
||||
contentLength = v.value();
|
||||
} else {
|
||||
// Ugh, no Content-Length? Read the blocks of the JPEG file.
|
||||
int width, height;
|
||||
if (!ReadJpeg(is, imageBuf, &width, &height)) {
|
||||
SWARNING("did not receive a JPEG image");
|
||||
SWARNING("{}", "did not receive a JPEG image");
|
||||
PutError("did not receive a JPEG image", wpi::Now());
|
||||
return false;
|
||||
}
|
||||
@@ -315,7 +313,7 @@ bool HttpCameraImpl::DeviceStreamFrame(wpi::raw_istream& is,
|
||||
}
|
||||
int width, height;
|
||||
if (!GetJpegSize(image->str(), &width, &height)) {
|
||||
SWARNING("did not receive a JPEG image");
|
||||
SWARNING("{}", "did not receive a JPEG image");
|
||||
PutError("did not receive a JPEG image", wpi::Now());
|
||||
return false;
|
||||
}
|
||||
@@ -345,7 +343,7 @@ void HttpCameraImpl::SettingsThreadMain() {
|
||||
DeviceSendSettings(req);
|
||||
}
|
||||
|
||||
SDEBUG("Settings Thread exiting");
|
||||
SDEBUG("{}", "Settings Thread exiting");
|
||||
}
|
||||
|
||||
void HttpCameraImpl::DeviceSendSettings(wpi::HttpRequest& req) {
|
||||
@@ -369,7 +367,7 @@ void HttpCameraImpl::DeviceSendSettings(wpi::HttpRequest& req) {
|
||||
// Just need a handshake as settings are sent via GET parameters
|
||||
std::string warn;
|
||||
if (!conn->Handshake(req, &warn)) {
|
||||
SWARNING(GetName() << ": " << warn);
|
||||
SWARNING("{}", warn);
|
||||
}
|
||||
|
||||
conn->stream->close();
|
||||
@@ -388,7 +386,7 @@ bool HttpCameraImpl::SetUrls(wpi::ArrayRef<std::string> urls,
|
||||
std::string errorMsg;
|
||||
locations.emplace_back(url, &error, &errorMsg);
|
||||
if (error) {
|
||||
SERROR(GetName() << ": " << errorMsg);
|
||||
SERROR("{}", errorMsg);
|
||||
*status = CS_BAD_URL;
|
||||
return false;
|
||||
}
|
||||
@@ -410,8 +408,8 @@ std::vector<std::string> HttpCameraImpl::GetUrls() const {
|
||||
return urls;
|
||||
}
|
||||
|
||||
void HttpCameraImpl::CreateProperty(const wpi::Twine& name,
|
||||
const wpi::Twine& httpParam,
|
||||
void HttpCameraImpl::CreateProperty(std::string_view name,
|
||||
std::string_view httpParam,
|
||||
bool viaSettings, CS_PropertyKind kind,
|
||||
int minimum, int maximum, int step,
|
||||
int defaultValue, int value) const {
|
||||
@@ -421,13 +419,12 @@ void HttpCameraImpl::CreateProperty(const wpi::Twine& name,
|
||||
value));
|
||||
|
||||
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CREATED, name,
|
||||
m_propertyData.size() + 1, kind, value,
|
||||
wpi::Twine{});
|
||||
m_propertyData.size() + 1, kind, value, {});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void HttpCameraImpl::CreateEnumProperty(
|
||||
const wpi::Twine& name, const wpi::Twine& httpParam, bool viaSettings,
|
||||
std::string_view name, std::string_view httpParam, bool viaSettings,
|
||||
int defaultValue, int value, std::initializer_list<T> choices) const {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_propertyData.emplace_back(std::make_unique<PropertyData>(
|
||||
@@ -442,14 +439,14 @@ void HttpCameraImpl::CreateEnumProperty(
|
||||
|
||||
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CREATED, name,
|
||||
m_propertyData.size() + 1, CS_PROP_ENUM,
|
||||
value, wpi::Twine{});
|
||||
value, {});
|
||||
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CHOICES_UPDATED,
|
||||
name, m_propertyData.size() + 1, CS_PROP_ENUM,
|
||||
value, wpi::Twine{});
|
||||
value, {});
|
||||
}
|
||||
|
||||
std::unique_ptr<PropertyImpl> HttpCameraImpl::CreateEmptyProperty(
|
||||
const wpi::Twine& name) const {
|
||||
std::string_view name) const {
|
||||
return std::make_unique<PropertyData>(name);
|
||||
}
|
||||
|
||||
@@ -474,7 +471,7 @@ void HttpCameraImpl::SetProperty(int property, int value, CS_Status* status) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void HttpCameraImpl::SetStringProperty(int property, const wpi::Twine& value,
|
||||
void HttpCameraImpl::SetStringProperty(int property, std::string_view value,
|
||||
CS_Status* status) {
|
||||
// TODO
|
||||
}
|
||||
@@ -560,7 +557,7 @@ bool AxisCameraImpl::CacheProperties(CS_Status* status) const {
|
||||
|
||||
namespace cs {
|
||||
|
||||
CS_Source CreateHttpCamera(const wpi::Twine& name, const wpi::Twine& url,
|
||||
CS_Source CreateHttpCamera(std::string_view name, std::string_view url,
|
||||
CS_HttpCameraKind kind, CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
std::shared_ptr<HttpCameraImpl> source;
|
||||
@@ -574,13 +571,13 @@ CS_Source CreateHttpCamera(const wpi::Twine& name, const wpi::Twine& url,
|
||||
inst.notifier, inst.telemetry);
|
||||
break;
|
||||
}
|
||||
if (!source->SetUrls(url.str(), status)) {
|
||||
if (!source->SetUrls(std::string{url}, status)) {
|
||||
return 0;
|
||||
}
|
||||
return inst.CreateSource(CS_SOURCE_HTTP, source);
|
||||
}
|
||||
|
||||
CS_Source CreateHttpCamera(const wpi::Twine& name,
|
||||
CS_Source CreateHttpCamera(std::string_view name,
|
||||
wpi::ArrayRef<std::string> urls,
|
||||
CS_HttpCameraKind kind, CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/HttpUtil.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/StringMap.h>
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/condition_variable.h>
|
||||
#include <wpi/raw_istream.h>
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace cs {
|
||||
|
||||
class HttpCameraImpl : public SourceImpl {
|
||||
public:
|
||||
HttpCameraImpl(const wpi::Twine& name, CS_HttpCameraKind kind,
|
||||
HttpCameraImpl(std::string_view name, CS_HttpCameraKind kind,
|
||||
wpi::Logger& logger, Notifier& notifier, Telemetry& telemetry);
|
||||
~HttpCameraImpl() override;
|
||||
|
||||
@@ -35,7 +35,7 @@ class HttpCameraImpl : public SourceImpl {
|
||||
|
||||
// Property functions
|
||||
void SetProperty(int property, int value, CS_Status* status) override;
|
||||
void SetStringProperty(int property, const wpi::Twine& value,
|
||||
void SetStringProperty(int property, std::string_view value,
|
||||
CS_Status* status) override;
|
||||
|
||||
// Standard common camera properties
|
||||
@@ -61,13 +61,13 @@ class HttpCameraImpl : public SourceImpl {
|
||||
class PropertyData : public PropertyImpl {
|
||||
public:
|
||||
PropertyData() = default;
|
||||
explicit PropertyData(const wpi::Twine& name_) : PropertyImpl{name_} {}
|
||||
PropertyData(const wpi::Twine& name_, const wpi::Twine& httpParam_,
|
||||
explicit PropertyData(std::string_view name_) : PropertyImpl{name_} {}
|
||||
PropertyData(std::string_view name_, std::string_view httpParam_,
|
||||
bool viaSettings_, CS_PropertyKind kind_, int minimum_,
|
||||
int maximum_, int step_, int defaultValue_, int value_)
|
||||
: PropertyImpl(name_, kind_, step_, defaultValue_, value_),
|
||||
viaSettings(viaSettings_),
|
||||
httpParam(httpParam_.str()) {
|
||||
httpParam(httpParam_) {
|
||||
hasMinimum = true;
|
||||
minimum = minimum_;
|
||||
hasMaximum = true;
|
||||
@@ -81,16 +81,16 @@ class HttpCameraImpl : public SourceImpl {
|
||||
|
||||
protected:
|
||||
std::unique_ptr<PropertyImpl> CreateEmptyProperty(
|
||||
const wpi::Twine& name) const override;
|
||||
std::string_view name) const override;
|
||||
|
||||
bool CacheProperties(CS_Status* status) const override;
|
||||
|
||||
void CreateProperty(const wpi::Twine& name, const wpi::Twine& httpParam,
|
||||
void CreateProperty(std::string_view name, std::string_view httpParam,
|
||||
bool viaSettings, CS_PropertyKind kind, int minimum,
|
||||
int maximum, int step, int defaultValue, int value) const;
|
||||
|
||||
template <typename T>
|
||||
void CreateEnumProperty(const wpi::Twine& name, const wpi::Twine& httpParam,
|
||||
void CreateEnumProperty(std::string_view name, std::string_view httpParam,
|
||||
bool viaSettings, int defaultValue, int value,
|
||||
std::initializer_list<T> choices) const;
|
||||
|
||||
@@ -101,7 +101,7 @@ class HttpCameraImpl : public SourceImpl {
|
||||
// Functions used by StreamThreadMain()
|
||||
wpi::HttpConnection* DeviceStreamConnect(
|
||||
wpi::SmallVectorImpl<char>& boundary);
|
||||
void DeviceStream(wpi::raw_istream& is, wpi::StringRef boundary);
|
||||
void DeviceStream(wpi::raw_istream& is, std::string_view boundary);
|
||||
bool DeviceStreamFrame(wpi::raw_istream& is, std::string& imageBuf);
|
||||
|
||||
// The camera settings thread
|
||||
@@ -146,12 +146,12 @@ class HttpCameraImpl : public SourceImpl {
|
||||
|
||||
class AxisCameraImpl : public HttpCameraImpl {
|
||||
public:
|
||||
AxisCameraImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry)
|
||||
AxisCameraImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry)
|
||||
: HttpCameraImpl{name, CS_HTTP_AXIS, logger, notifier, telemetry} {}
|
||||
#if 0
|
||||
void SetProperty(int property, int value, CS_Status* status) override;
|
||||
void SetStringProperty(int property, const wpi::Twine& value,
|
||||
void SetStringProperty(int property, std::string_view value,
|
||||
CS_Status* status) override;
|
||||
#endif
|
||||
protected:
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
#ifndef CSCORE_IMAGE_H_
|
||||
#define CSCORE_IMAGE_H_
|
||||
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
#include "cscore_cpp.h"
|
||||
#include "default_init_allocator.h"
|
||||
@@ -34,8 +34,8 @@ class Image {
|
||||
Image& operator=(const Image&) = delete;
|
||||
|
||||
// Getters
|
||||
operator wpi::StringRef() const { return str(); } // NOLINT
|
||||
wpi::StringRef str() const { return wpi::StringRef(data(), size()); }
|
||||
operator std::string_view() const { return str(); } // NOLINT
|
||||
std::string_view str() const { return {data(), size()}; }
|
||||
size_t capacity() const { return m_data.capacity(); }
|
||||
const char* data() const {
|
||||
return reinterpret_cast<const char*>(m_data.data());
|
||||
|
||||
@@ -4,36 +4,32 @@
|
||||
|
||||
#include "Instance.h"
|
||||
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <string_view>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <wpi/fs.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
using namespace cs;
|
||||
|
||||
static void def_log_func(unsigned int level, const char* file,
|
||||
unsigned int line, const char* msg) {
|
||||
wpi::SmallString<128> buf;
|
||||
wpi::raw_svector_ostream oss(buf);
|
||||
if (level == 20) {
|
||||
oss << "CS: " << msg << '\n';
|
||||
wpi::errs() << oss.str();
|
||||
fmt::print(stderr, "CS: {}\n", msg);
|
||||
return;
|
||||
}
|
||||
|
||||
wpi::StringRef levelmsg;
|
||||
std::string_view levelmsg;
|
||||
if (level >= 50) {
|
||||
levelmsg = "CRITICAL: ";
|
||||
levelmsg = "CRITICAL";
|
||||
} else if (level >= 40) {
|
||||
levelmsg = "ERROR: ";
|
||||
levelmsg = "ERROR";
|
||||
} else if (level >= 30) {
|
||||
levelmsg = "WARNING: ";
|
||||
levelmsg = "WARNING";
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
oss << "CS: " << levelmsg << msg << " (" << fs::path{file}.filename().string()
|
||||
<< ':' << line << ")\n";
|
||||
wpi::errs() << oss.str();
|
||||
fmt::print(stderr, "CS: {}: {} ({}:{})\n", levelmsg, msg,
|
||||
fs::path{file}.filename().string(), line);
|
||||
}
|
||||
|
||||
Instance::Instance()
|
||||
|
||||
@@ -46,20 +46,20 @@ static const unsigned char dhtData[] = {
|
||||
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa};
|
||||
|
||||
bool IsJpeg(wpi::StringRef data) {
|
||||
bool IsJpeg(std::string_view data) {
|
||||
if (data.size() < 11) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for valid SOI
|
||||
auto bytes = data.bytes_begin();
|
||||
auto bytes = reinterpret_cast<const unsigned char*>(data.data());
|
||||
if (bytes[0] != 0xff || bytes[1] != 0xd8) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetJpegSize(wpi::StringRef data, int* width, int* height) {
|
||||
bool GetJpegSize(std::string_view data, int* width, int* height) {
|
||||
if (!IsJpeg(data)) {
|
||||
return false;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ bool GetJpegSize(wpi::StringRef data, int* width, int* height) {
|
||||
if (data.size() < 4) {
|
||||
return false; // EOF
|
||||
}
|
||||
auto bytes = data.bytes_begin();
|
||||
auto bytes = reinterpret_cast<const unsigned char*>(data.data());
|
||||
if (bytes[0] != 0xff) {
|
||||
return false; // not a tag
|
||||
}
|
||||
@@ -94,7 +94,7 @@ bool GetJpegSize(wpi::StringRef data, int* width, int* height) {
|
||||
}
|
||||
|
||||
bool JpegNeedsDHT(const char* data, size_t* size, size_t* locSOF) {
|
||||
wpi::StringRef sdata(data, *size);
|
||||
std::string_view sdata(data, *size);
|
||||
if (!IsJpeg(sdata)) {
|
||||
return false;
|
||||
}
|
||||
@@ -107,7 +107,7 @@ bool JpegNeedsDHT(const char* data, size_t* size, size_t* locSOF) {
|
||||
if (sdata.size() < 4) {
|
||||
return false; // EOF
|
||||
}
|
||||
auto bytes = sdata.bytes_begin();
|
||||
auto bytes = reinterpret_cast<const unsigned char*>(sdata.data());
|
||||
if (bytes[0] != 0xff) {
|
||||
return false; // not a tag
|
||||
}
|
||||
@@ -132,9 +132,8 @@ bool JpegNeedsDHT(const char* data, size_t* size, size_t* locSOF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wpi::StringRef JpegGetDHT() {
|
||||
return wpi::StringRef(reinterpret_cast<const char*>(dhtData),
|
||||
sizeof(dhtData));
|
||||
std::string_view JpegGetDHT() {
|
||||
return {reinterpret_cast<const char*>(dhtData), sizeof(dhtData)};
|
||||
}
|
||||
|
||||
static inline void ReadInto(wpi::raw_istream& is, std::string& buf,
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
#define CSCORE_JPEGUTIL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <wpi/StringRef.h>
|
||||
#include <string_view>
|
||||
|
||||
namespace wpi {
|
||||
class raw_istream;
|
||||
@@ -15,13 +14,13 @@ class raw_istream;
|
||||
|
||||
namespace cs {
|
||||
|
||||
bool IsJpeg(wpi::StringRef data);
|
||||
bool IsJpeg(std::string_view data);
|
||||
|
||||
bool GetJpegSize(wpi::StringRef data, int* width, int* height);
|
||||
bool GetJpegSize(std::string_view data, int* width, int* height);
|
||||
|
||||
bool JpegNeedsDHT(const char* data, size_t* size, size_t* locSOF);
|
||||
|
||||
wpi::StringRef JpegGetDHT();
|
||||
std::string_view JpegGetDHT();
|
||||
|
||||
bool ReadJpeg(wpi::raw_istream& is, std::string& buf, int* width, int* height);
|
||||
|
||||
|
||||
15
cscore/src/main/native/cpp/Log.cpp
Normal file
15
cscore/src/main/native/cpp/Log.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
void cs::NamedLogV(wpi::Logger& logger, unsigned int level, const char* file,
|
||||
unsigned int line, std::string_view name,
|
||||
fmt::string_view format, fmt::format_args args) {
|
||||
fmt::memory_buffer out;
|
||||
fmt::format_to(out, "{}: ", name);
|
||||
fmt::vformat_to(out, format, args);
|
||||
out.push_back('\0');
|
||||
logger.DoLog(level, file, line, out.data());
|
||||
}
|
||||
@@ -5,29 +5,71 @@
|
||||
#ifndef CSCORE_LOG_H_
|
||||
#define CSCORE_LOG_H_
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <wpi/Logger.h>
|
||||
|
||||
#define LOG(level, x) WPI_LOG(m_logger, level, x)
|
||||
namespace cs {
|
||||
|
||||
void NamedLogV(wpi::Logger& logger, unsigned int level, const char* file,
|
||||
unsigned int line, std::string_view name,
|
||||
fmt::string_view format, fmt::format_args args);
|
||||
|
||||
template <typename S, typename... Args>
|
||||
inline void NamedLog(wpi::Logger& logger, unsigned int level, const char* file,
|
||||
unsigned int line, std::string_view name, const S& format,
|
||||
Args&&... args) {
|
||||
if (logger.HasLogger() && level >= logger.min_level()) {
|
||||
NamedLogV(logger, level, file, line, name, format,
|
||||
fmt::make_args_checked<Args...>(format, args...));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cs
|
||||
|
||||
#define LOG(level, format, ...) WPI_LOG(m_logger, level, format, __VA_ARGS__)
|
||||
|
||||
#undef ERROR
|
||||
#define ERROR(x) WPI_ERROR(m_logger, x)
|
||||
#define WARNING(x) WPI_WARNING(m_logger, x)
|
||||
#define INFO(x) WPI_INFO(m_logger, x)
|
||||
#define ERROR(format, ...) WPI_ERROR(m_logger, format, __VA_ARGS__)
|
||||
#define WARNING(format, ...) WPI_WARNING(m_logger, format, __VA_ARGS__)
|
||||
#define INFO(format, ...) WPI_INFO(m_logger, format, __VA_ARGS__)
|
||||
|
||||
#define DEBUG0(x) WPI_DEBUG(m_logger, x)
|
||||
#define DEBUG1(x) WPI_DEBUG1(m_logger, x)
|
||||
#define DEBUG2(x) WPI_DEBUG2(m_logger, x)
|
||||
#define DEBUG3(x) WPI_DEBUG3(m_logger, x)
|
||||
#define DEBUG4(x) WPI_DEBUG4(m_logger, x)
|
||||
#define DEBUG0(format, ...) WPI_DEBUG(m_logger, format, __VA_ARGS__)
|
||||
#define DEBUG1(format, ...) WPI_DEBUG1(m_logger, format, __VA_ARGS__)
|
||||
#define DEBUG2(format, ...) WPI_DEBUG2(m_logger, format, __VA_ARGS__)
|
||||
#define DEBUG3(format, ...) WPI_DEBUG3(m_logger, format, __VA_ARGS__)
|
||||
#define DEBUG4(format, ...) WPI_DEBUG4(m_logger, format, __VA_ARGS__)
|
||||
|
||||
#define SERROR(x) ERROR(GetName() << ": " << x)
|
||||
#define SWARNING(x) WARNING(GetName() << ": " << x)
|
||||
#define SINFO(x) INFO(GetName() << ": " << x)
|
||||
#define SLOG(level, format, ...) \
|
||||
NamedLog(m_logger, level, __FILE__, __LINE__, GetName(), FMT_STRING(format), \
|
||||
__VA_ARGS__)
|
||||
|
||||
#define SDEBUG(x) DEBUG0(GetName() << ": " << x)
|
||||
#define SDEBUG1(x) DEBUG1(GetName() << ": " << x)
|
||||
#define SDEBUG2(x) DEBUG2(GetName() << ": " << x)
|
||||
#define SDEBUG3(x) DEBUG3(GetName() << ": " << x)
|
||||
#define SDEBUG4(x) DEBUG4(GetName() << ": " << x)
|
||||
#define SERROR(format, ...) SLOG(::wpi::WPI_LOG_ERROR, format, __VA_ARGS__)
|
||||
#define SWARNING(format, ...) SLOG(::wpi::WPI_LOG_WARNING, format, __VA_ARGS__)
|
||||
#define SINFO(format, ...) SLOG(::wpi::WPI_LOG_INFO, format, __VA_ARGS__)
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define SDEBUG(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define SDEBUG1(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define SDEBUG2(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define SDEBUG3(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define SDEBUG4(format, ...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#else
|
||||
#define SDEBUG(format, ...) SLOG(::wpi::WPI_LOG_DEBUG, format, __VA_ARGS__)
|
||||
#define SDEBUG1(format, ...) SLOG(::wpi::WPI_LOG_DEBUG1, format, __VA_ARGS__)
|
||||
#define SDEBUG2(format, ...) SLOG(::wpi::WPI_LOG_DEBUG2, format, __VA_ARGS__)
|
||||
#define SDEBUG3(format, ...) SLOG(::wpi::WPI_LOG_DEBUG3, format, __VA_ARGS__)
|
||||
#define SDEBUG4(format, ...) SLOG(::wpi::WPI_LOG_DEBUG4, format, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#endif // CSCORE_LOG_H_
|
||||
|
||||
@@ -6,9 +6,12 @@
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <wpi/HttpUtil.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/TCPAcceptor.h>
|
||||
#include <wpi/fmt/raw_ostream.h>
|
||||
#include <wpi/raw_socket_istream.h>
|
||||
#include <wpi/raw_socket_ostream.h>
|
||||
|
||||
@@ -72,13 +75,13 @@ static const char* endRootPage = "</div></body></html>";
|
||||
|
||||
class MjpegServerImpl::ConnThread : public wpi::SafeThread {
|
||||
public:
|
||||
explicit ConnThread(const wpi::Twine& name, wpi::Logger& logger)
|
||||
: m_name(name.str()), m_logger(logger) {}
|
||||
explicit ConnThread(std::string_view name, wpi::Logger& logger)
|
||||
: m_name(name), m_logger(logger) {}
|
||||
|
||||
void Main() override;
|
||||
|
||||
bool ProcessCommand(wpi::raw_ostream& os, SourceImpl& source,
|
||||
wpi::StringRef parameters, bool respond);
|
||||
std::string_view parameters, bool respond);
|
||||
void SendJSON(wpi::raw_ostream& os, SourceImpl& source, bool header);
|
||||
void SendHTMLHeadTitle(wpi::raw_ostream& os) const;
|
||||
void SendHTML(wpi::raw_ostream& os, SourceImpl& source, bool header);
|
||||
@@ -99,7 +102,7 @@ class MjpegServerImpl::ConnThread : public wpi::SafeThread {
|
||||
std::string m_name;
|
||||
wpi::Logger& m_logger;
|
||||
|
||||
wpi::StringRef GetName() { return m_name; }
|
||||
std::string_view GetName() { return m_name; }
|
||||
|
||||
std::shared_ptr<SourceImpl> GetSource() {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
@@ -130,10 +133,9 @@ class MjpegServerImpl::ConnThread : public wpi::SafeThread {
|
||||
// Using cached pictures would lead to showing old/outdated pictures.
|
||||
// Many browsers seem to ignore, or at least not always obey, those headers.
|
||||
static void SendHeader(wpi::raw_ostream& os, int code,
|
||||
const wpi::Twine& codeText,
|
||||
const wpi::Twine& contentType,
|
||||
const wpi::Twine& extra = wpi::Twine{}) {
|
||||
os << "HTTP/1.0 " << code << ' ' << codeText << "\r\n";
|
||||
std::string_view codeText, std::string_view contentType,
|
||||
std::string_view extra = {}) {
|
||||
fmt::print(os, "HTTP/1.0 {} {}\r\n", code, codeText);
|
||||
os << "Connection: close\r\n"
|
||||
"Server: CameraServer/1.0\r\n"
|
||||
"Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, "
|
||||
@@ -142,10 +144,8 @@ static void SendHeader(wpi::raw_ostream& os, int code,
|
||||
"Expires: Mon, 3 Jan 2000 12:34:56 GMT\r\n";
|
||||
os << "Content-Type: " << contentType << "\r\n";
|
||||
os << "Access-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: *\r\n";
|
||||
wpi::SmallString<128> extraBuf;
|
||||
wpi::StringRef extraStr = extra.toStringRef(extraBuf);
|
||||
if (!extraStr.empty()) {
|
||||
os << extraStr << "\r\n";
|
||||
if (!extra.empty()) {
|
||||
os << extra << "\r\n";
|
||||
}
|
||||
os << "\r\n"; // header ends with a blank line
|
||||
}
|
||||
@@ -154,8 +154,8 @@ static void SendHeader(wpi::raw_ostream& os, int code,
|
||||
// @param code HTTP error code (e.g. 404)
|
||||
// @param message Additional message text
|
||||
static void SendError(wpi::raw_ostream& os, int code,
|
||||
const wpi::Twine& message) {
|
||||
wpi::StringRef codeText, extra, baseMessage;
|
||||
std::string_view message) {
|
||||
std::string_view codeText, extra, baseMessage;
|
||||
switch (code) {
|
||||
case 401:
|
||||
codeText = "Unauthorized";
|
||||
@@ -195,66 +195,61 @@ static void SendError(wpi::raw_ostream& os, int code,
|
||||
// Perform a command specified by HTTP GET parameters.
|
||||
bool MjpegServerImpl::ConnThread::ProcessCommand(wpi::raw_ostream& os,
|
||||
SourceImpl& source,
|
||||
wpi::StringRef parameters,
|
||||
std::string_view parameters,
|
||||
bool respond) {
|
||||
wpi::SmallString<256> responseBuf;
|
||||
wpi::raw_svector_ostream response{responseBuf};
|
||||
// command format: param1=value1¶m2=value2...
|
||||
while (!parameters.empty()) {
|
||||
// split out next param and value
|
||||
wpi::StringRef rawParam, rawValue;
|
||||
std::tie(rawParam, parameters) = parameters.split('&');
|
||||
std::string_view rawParam, rawValue;
|
||||
std::tie(rawParam, parameters) = wpi::split(parameters, '&');
|
||||
if (rawParam.empty()) {
|
||||
continue; // ignore "&&"
|
||||
}
|
||||
std::tie(rawParam, rawValue) = rawParam.split('=');
|
||||
std::tie(rawParam, rawValue) = wpi::split(rawParam, '=');
|
||||
if (rawParam.empty() || rawValue.empty()) {
|
||||
continue; // ignore "param="
|
||||
}
|
||||
SDEBUG4("HTTP parameter \"" << rawParam << "\" value \"" << rawValue
|
||||
<< "\"");
|
||||
SDEBUG4("HTTP parameter \"{}\" value \"{}\"", rawParam, rawValue);
|
||||
|
||||
// unescape param
|
||||
bool error = false;
|
||||
wpi::SmallString<64> paramBuf;
|
||||
wpi::StringRef param = wpi::UnescapeURI(rawParam, paramBuf, &error);
|
||||
std::string_view param = wpi::UnescapeURI(rawParam, paramBuf, &error);
|
||||
if (error) {
|
||||
wpi::SmallString<128> error;
|
||||
wpi::raw_svector_ostream oss{error};
|
||||
oss << "could not unescape parameter \"" << rawParam << "\"";
|
||||
SendError(os, 500, error.str());
|
||||
SDEBUG(error.str());
|
||||
auto estr = fmt::format("could not unescape parameter \"{}\"", rawParam);
|
||||
SendError(os, 500, estr);
|
||||
SDEBUG("{}", estr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// unescape value
|
||||
wpi::SmallString<64> valueBuf;
|
||||
wpi::StringRef value = wpi::UnescapeURI(rawValue, valueBuf, &error);
|
||||
std::string_view value = wpi::UnescapeURI(rawValue, valueBuf, &error);
|
||||
if (error) {
|
||||
wpi::SmallString<128> error;
|
||||
wpi::raw_svector_ostream oss{error};
|
||||
oss << "could not unescape value \"" << rawValue << "\"";
|
||||
SendError(os, 500, error.str());
|
||||
SDEBUG(error.str());
|
||||
auto estr = fmt::format("could not unescape value \"{}\"", rawValue);
|
||||
SendError(os, 500, estr);
|
||||
SDEBUG("{}", estr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle resolution, compression, and FPS. These are handled locally
|
||||
// rather than passed to the source.
|
||||
if (param == "resolution") {
|
||||
wpi::StringRef widthStr, heightStr;
|
||||
std::tie(widthStr, heightStr) = value.split('x');
|
||||
int width, height;
|
||||
if (widthStr.getAsInteger(10, width)) {
|
||||
auto [widthStr, heightStr] = wpi::split(value, 'x');
|
||||
int width = wpi::parse_integer<int>(widthStr, 10).value_or(-1);
|
||||
int height = wpi::parse_integer<int>(heightStr, 10).value_or(-1);
|
||||
if (width < 0) {
|
||||
response << param << ": \"width is not an integer\"\r\n";
|
||||
SWARNING("HTTP parameter \"" << param << "\" width \"" << widthStr
|
||||
<< "\" is not an integer");
|
||||
SWARNING("HTTP parameter \"{}\" width \"{}\" is not an integer", param,
|
||||
widthStr);
|
||||
continue;
|
||||
}
|
||||
if (heightStr.getAsInteger(10, height)) {
|
||||
if (height < 0) {
|
||||
response << param << ": \"height is not an integer\"\r\n";
|
||||
SWARNING("HTTP parameter \"" << param << "\" height \"" << heightStr
|
||||
<< "\" is not an integer");
|
||||
SWARNING("HTTP parameter \"{}\" height \"{}\" is not an integer", param,
|
||||
heightStr);
|
||||
continue;
|
||||
}
|
||||
m_width = width;
|
||||
@@ -264,29 +259,25 @@ bool MjpegServerImpl::ConnThread::ProcessCommand(wpi::raw_ostream& os,
|
||||
}
|
||||
|
||||
if (param == "fps") {
|
||||
int fps;
|
||||
if (value.getAsInteger(10, fps)) {
|
||||
response << param << ": \"invalid integer\"\r\n";
|
||||
SWARNING("HTTP parameter \"" << param << "\" value \"" << value
|
||||
<< "\" is not an integer");
|
||||
continue;
|
||||
} else {
|
||||
m_fps = fps;
|
||||
if (auto v = wpi::parse_integer<int>(value, 10)) {
|
||||
m_fps = v.value();
|
||||
response << param << ": \"ok\"\r\n";
|
||||
} else {
|
||||
response << param << ": \"invalid integer\"\r\n";
|
||||
SWARNING("HTTP parameter \"{}\" value \"{}\" is not an integer", param,
|
||||
value);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == "compression") {
|
||||
int compression;
|
||||
if (value.getAsInteger(10, compression)) {
|
||||
response << param << ": \"invalid integer\"\r\n";
|
||||
SWARNING("HTTP parameter \"" << param << "\" value \"" << value
|
||||
<< "\" is not an integer");
|
||||
continue;
|
||||
} else {
|
||||
m_compression = compression;
|
||||
if (auto v = wpi::parse_integer<int>(value, 10)) {
|
||||
m_compression = v.value();
|
||||
response << param << ": \"ok\"\r\n";
|
||||
} else {
|
||||
response << param << ": \"invalid integer\"\r\n";
|
||||
SWARNING("HTTP parameter \"{}\" value \"{}\" is not an integer", param,
|
||||
value);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -300,7 +291,7 @@ bool MjpegServerImpl::ConnThread::ProcessCommand(wpi::raw_ostream& os,
|
||||
auto prop = source.GetPropertyIndex(param);
|
||||
if (!prop) {
|
||||
response << param << ": \"ignored\"\r\n";
|
||||
SWARNING("ignoring HTTP parameter \"" << param << "\"");
|
||||
SWARNING("ignoring HTTP parameter \"{}\"", param);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -310,21 +301,20 @@ bool MjpegServerImpl::ConnThread::ProcessCommand(wpi::raw_ostream& os,
|
||||
case CS_PROP_BOOLEAN:
|
||||
case CS_PROP_INTEGER:
|
||||
case CS_PROP_ENUM: {
|
||||
int val = 0;
|
||||
if (value.getAsInteger(10, val)) {
|
||||
response << param << ": \"invalid integer\"\r\n";
|
||||
SWARNING("HTTP parameter \"" << param << "\" value \"" << value
|
||||
<< "\" is not an integer");
|
||||
if (auto v = wpi::parse_integer<int>(value, 10)) {
|
||||
fmt::print(response, "{}: {}\r\n", param, v.value());
|
||||
SDEBUG4("HTTP parameter \"{}\" value {}", param, value);
|
||||
source.SetProperty(prop, v.value(), &status);
|
||||
} else {
|
||||
response << param << ": " << val << "\r\n";
|
||||
SDEBUG4("HTTP parameter \"" << param << "\" value " << value);
|
||||
source.SetProperty(prop, val, &status);
|
||||
response << param << ": \"invalid integer\"\r\n";
|
||||
SWARNING("HTTP parameter \"{}\" value \"{}\" is not an integer",
|
||||
param, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CS_PROP_STRING: {
|
||||
response << param << ": \"ok\"\r\n";
|
||||
SDEBUG4("HTTP parameter \"" << param << "\" value \"" << value << "\"");
|
||||
SDEBUG4("HTTP parameter \"{}\" value \"{}\"", param, value);
|
||||
source.SetStringProperty(prop, value, &status);
|
||||
break;
|
||||
}
|
||||
@@ -362,17 +352,17 @@ void MjpegServerImpl::ConnThread::SendHTML(wpi::raw_ostream& os,
|
||||
for (auto prop : source.EnumerateProperties(properties_vec, &status)) {
|
||||
wpi::SmallString<128> name_buf;
|
||||
auto name = source.GetPropertyName(prop, name_buf, &status);
|
||||
if (name.startswith("raw_")) {
|
||||
if (wpi::starts_with(name, "raw_")) {
|
||||
continue;
|
||||
}
|
||||
auto kind = source.GetPropertyKind(prop);
|
||||
os << "<p />"
|
||||
<< "<label for=\"" << name << "\">" << name << "</label>\n";
|
||||
fmt::print(os, "<p /><label for=\"{0}\">{0}</label>\n", name);
|
||||
switch (kind) {
|
||||
case CS_PROP_BOOLEAN:
|
||||
os << "<input id=\"" << name
|
||||
<< "\" type=\"checkbox\" onclick=\"update('" << name
|
||||
<< "', this.checked ? 1 : 0)\" ";
|
||||
fmt::print(os,
|
||||
"<input id=\"{0}\" type=\"checkbox\" "
|
||||
"onclick=\"update('{0}', this.checked ? 1 : 0)\" ",
|
||||
name);
|
||||
if (source.GetProperty(prop, &status) != 0) {
|
||||
os << "checked />\n";
|
||||
} else {
|
||||
@@ -384,12 +374,13 @@ void MjpegServerImpl::ConnThread::SendHTML(wpi::raw_ostream& os,
|
||||
auto min = source.GetPropertyMin(prop, &status);
|
||||
auto max = source.GetPropertyMax(prop, &status);
|
||||
auto step = source.GetPropertyStep(prop, &status);
|
||||
os << "<input type=\"range\" min=\"" << min << "\" max=\"" << max
|
||||
<< "\" value=\"" << valI << "\" id=\"" << name << "\" step=\""
|
||||
<< step << "\" oninput=\"updateInt('#" << name << "op', '" << name
|
||||
<< "', value)\" />\n";
|
||||
os << "<output for=\"" << name << "\" id=\"" << name << "op\">" << valI
|
||||
<< "</output>\n";
|
||||
fmt::print(os,
|
||||
"<input type=\"range\" min=\"{1}\" max=\"{2}\" "
|
||||
"value=\"{3}\" id=\"{0}\" step=\"{4}\" "
|
||||
"oninput=\"updateInt('#{0}op', '{0}', value)\" />\n",
|
||||
name, min, max, valI, step);
|
||||
fmt::print(os, "<output for=\"{0}\" id=\"{0}op\">{1}</output>\n", name,
|
||||
valI);
|
||||
break;
|
||||
}
|
||||
case CS_PROP_ENUM: {
|
||||
@@ -404,26 +395,30 @@ void MjpegServerImpl::ConnThread::SendHTML(wpi::raw_ostream& os,
|
||||
// replace any non-printable characters in name with spaces
|
||||
wpi::SmallString<128> ch_name;
|
||||
for (char ch : *choice) {
|
||||
ch_name.push_back(std::isprint(ch) ? ch : ' ');
|
||||
ch_name.push_back(wpi::isPrint(ch) ? ch : ' ');
|
||||
}
|
||||
os << "<input id=\"" << name << j << "\" type=\"radio\" name=\""
|
||||
<< name << "\" value=\"" << ch_name << "\" onclick=\"update('"
|
||||
<< name << "', " << j << ")\"";
|
||||
fmt::print(os,
|
||||
"<input id=\"{0}{1}\" type=\"radio\" name=\"{0}\" "
|
||||
"value=\"{2}\" onclick=\"update('{0}', {1})\"",
|
||||
name, j, ch_name);
|
||||
if (j == valE) {
|
||||
os << " checked";
|
||||
}
|
||||
os << " /><label for=\"" << name << j << "\">" << ch_name
|
||||
<< "</label>\n";
|
||||
fmt::print(os, " /><label for=\"{}{}\">{}</label>\n", name, j,
|
||||
ch_name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CS_PROP_STRING: {
|
||||
wpi::SmallString<128> strval_buf;
|
||||
os << "<input type=\"text\" id=\"" << name << "box\" name=\"" << name
|
||||
<< "\" value=\""
|
||||
<< source.GetStringProperty(prop, strval_buf, &status) << "\" />\n";
|
||||
os << "<input type=\"button\" value =\"Submit\" onclick=\"update('"
|
||||
<< name << "', " << name << "box.value)\" />\n";
|
||||
fmt::print(os,
|
||||
"<input type=\"text\" id=\"{0}box\" name=\"{0}\" "
|
||||
"value=\"{1}\" />\n",
|
||||
name, source.GetStringProperty(prop, strval_buf, &status));
|
||||
fmt::print(os,
|
||||
"<input type=\"button\" value =\"Submit\" "
|
||||
"onclick=\"update('{0}', {0}box.value)\" />\n",
|
||||
name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -469,10 +464,8 @@ void MjpegServerImpl::ConnThread::SendHTML(wpi::raw_ostream& os,
|
||||
os << "unknown";
|
||||
break;
|
||||
}
|
||||
os << "</td><td>" << mode.width;
|
||||
os << "</td><td>" << mode.height;
|
||||
os << "</td><td>" << mode.fps;
|
||||
os << "</td></tr>";
|
||||
fmt::print(os, "</td><td>{}</td><td>{}</td><td>{}</td></tr>", mode.width,
|
||||
mode.height, mode.fps);
|
||||
}
|
||||
os << "</table>\n";
|
||||
os << endRootPage << "\r\n";
|
||||
@@ -500,20 +493,21 @@ void MjpegServerImpl::ConnThread::SendJSON(wpi::raw_ostream& os,
|
||||
wpi::SmallString<128> name_buf;
|
||||
auto name = source.GetPropertyName(prop, name_buf, &status);
|
||||
auto kind = source.GetPropertyKind(prop);
|
||||
os << "\n\"name\": \"" << name << '"';
|
||||
os << ",\n\"id\": \"" << prop << '"';
|
||||
os << ",\n\"type\": \"" << kind << '"';
|
||||
os << ",\n\"min\": \"" << source.GetPropertyMin(prop, &status) << '"';
|
||||
os << ",\n\"max\": \"" << source.GetPropertyMax(prop, &status) << '"';
|
||||
os << ",\n\"step\": \"" << source.GetPropertyStep(prop, &status) << '"';
|
||||
os << ",\n\"default\": \"" << source.GetPropertyDefault(prop, &status)
|
||||
<< '"';
|
||||
fmt::print(os, "\n\"name\": \"{}\"", name);
|
||||
fmt::print(os, ",\n\"id\": \"{}\"", prop);
|
||||
fmt::print(os, ",\n\"type\": \"{}\"", kind);
|
||||
fmt::print(os, ",\n\"min\": \"{}\"", source.GetPropertyMin(prop, &status));
|
||||
fmt::print(os, ",\n\"max\": \"{}\"", source.GetPropertyMax(prop, &status));
|
||||
fmt::print(os, ",\n\"step\": \"{}\"",
|
||||
source.GetPropertyStep(prop, &status));
|
||||
fmt::print(os, ",\n\"default\": \"{}\"",
|
||||
source.GetPropertyDefault(prop, &status));
|
||||
os << ",\n\"value\": \"";
|
||||
switch (kind) {
|
||||
case CS_PROP_BOOLEAN:
|
||||
case CS_PROP_INTEGER:
|
||||
case CS_PROP_ENUM:
|
||||
os << source.GetProperty(prop, &status);
|
||||
fmt::print(os, "{}", source.GetProperty(prop, &status));
|
||||
break;
|
||||
case CS_PROP_STRING: {
|
||||
wpi::SmallString<128> strval_buf;
|
||||
@@ -543,7 +537,7 @@ void MjpegServerImpl::ConnThread::SendJSON(wpi::raw_ostream& os,
|
||||
for (char ch : *choice) {
|
||||
ch_name.push_back(std::isprint(ch) ? ch : ' ');
|
||||
}
|
||||
os << '"' << j << "\": \"" << ch_name << '"';
|
||||
fmt::print(os, "\"{}\": \"{}\"", j, ch_name);
|
||||
}
|
||||
os << "}\n";
|
||||
}
|
||||
@@ -579,29 +573,26 @@ void MjpegServerImpl::ConnThread::SendJSON(wpi::raw_ostream& os,
|
||||
os << "unknown";
|
||||
break;
|
||||
}
|
||||
os << "\",\n\"width\": \"" << mode.width << '"';
|
||||
os << ",\n\"height\": \"" << mode.height << '"';
|
||||
os << ",\n\"fps\": \"" << mode.fps << '"';
|
||||
fmt::print(os, "\",\n\"width\": \"{}\"", mode.width);
|
||||
fmt::print(os, ",\n\"height\": \"{}\"", mode.height);
|
||||
fmt::print(os, ",\n\"fps\": \"{}\"", mode.fps);
|
||||
os << '}';
|
||||
}
|
||||
os << "\n]\n}\n";
|
||||
os.flush();
|
||||
}
|
||||
|
||||
MjpegServerImpl::MjpegServerImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
MjpegServerImpl::MjpegServerImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
const wpi::Twine& listenAddress, int port,
|
||||
std::string_view listenAddress, int port,
|
||||
std::unique_ptr<wpi::NetworkAcceptor> acceptor)
|
||||
: SinkImpl{name, logger, notifier, telemetry},
|
||||
m_listenAddress(listenAddress.str()),
|
||||
m_listenAddress(listenAddress),
|
||||
m_port(port),
|
||||
m_acceptor{std::move(acceptor)} {
|
||||
m_active = true;
|
||||
|
||||
wpi::SmallString<128> descBuf;
|
||||
wpi::raw_svector_ostream desc{descBuf};
|
||||
desc << "HTTP Server on port " << port;
|
||||
SetDescription(desc.str());
|
||||
SetDescription(fmt::format("HTTP Server on port {}", port));
|
||||
|
||||
// Create properties
|
||||
m_widthProp = CreateProperty("width", [] {
|
||||
@@ -659,7 +650,7 @@ void MjpegServerImpl::Stop() {
|
||||
// Send HTTP response and a stream of JPG-frames
|
||||
void MjpegServerImpl::ConnThread::SendStream(wpi::raw_socket_ostream& os) {
|
||||
if (m_noStreaming) {
|
||||
SERROR("Too many simultaneous client streams");
|
||||
SERROR("{}", "Too many simultaneous client streams");
|
||||
SendError(os, 503, "Too many simultaneous streams");
|
||||
return;
|
||||
}
|
||||
@@ -672,7 +663,7 @@ void MjpegServerImpl::ConnThread::SendStream(wpi::raw_socket_ostream& os) {
|
||||
SendHeader(oss, 200, "OK", "multipart/x-mixed-replace;boundary=" BOUNDARY);
|
||||
os << oss.str();
|
||||
|
||||
SDEBUG("Headers send, sending stream now");
|
||||
SDEBUG("{}", "Headers send, sending stream now");
|
||||
|
||||
Frame::Time lastFrameTime = 0;
|
||||
Frame::Time timePerFrame = 0;
|
||||
@@ -694,7 +685,7 @@ void MjpegServerImpl::ConnThread::SendStream(wpi::raw_socket_ostream& os) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
continue;
|
||||
}
|
||||
SDEBUG4("waiting for frame");
|
||||
SDEBUG4("{}", "waiting for frame");
|
||||
Frame frame = source->GetNextFrame(0.225); // blocks
|
||||
if (!m_active) {
|
||||
break;
|
||||
@@ -757,7 +748,7 @@ void MjpegServerImpl::ConnThread::SendStream(wpi::raw_socket_ostream& os) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SDEBUG4("sending frame size=" << size << " addDHT=" << addDHT);
|
||||
SDEBUG4("sending frame size={} addDHT={}", size, addDHT);
|
||||
|
||||
// print the individual mimetype and the length
|
||||
// sending the content-length fixes random stream disruption observed
|
||||
@@ -766,18 +757,18 @@ void MjpegServerImpl::ConnThread::SendStream(wpi::raw_socket_ostream& os) {
|
||||
double timestamp = lastFrameTime / 1000000.0;
|
||||
header.clear();
|
||||
oss << "\r\n--" BOUNDARY "\r\n"
|
||||
<< "Content-Type: image/jpeg\r\n"
|
||||
<< "Content-Length: " << size << "\r\n"
|
||||
<< "X-Timestamp: " << timestamp << "\r\n"
|
||||
<< "\r\n";
|
||||
<< "Content-Type: image/jpeg\r\n";
|
||||
fmt::print(oss, "Content-Length: {}\r\n", size);
|
||||
fmt::print(oss, "X-Timestamp: {}\r\n", timestamp);
|
||||
oss << "\r\n";
|
||||
os << oss.str();
|
||||
if (addDHT) {
|
||||
// Insert DHT data immediately before SOF
|
||||
os << wpi::StringRef(data, locSOF);
|
||||
os << std::string_view(data, locSOF);
|
||||
os << JpegGetDHT();
|
||||
os << wpi::StringRef(data + locSOF, image->size() - locSOF);
|
||||
os << std::string_view(data + locSOF, image->size() - locSOF);
|
||||
} else {
|
||||
os << wpi::StringRef(data, size);
|
||||
os << std::string_view(data, size);
|
||||
}
|
||||
// os.flush();
|
||||
}
|
||||
@@ -790,48 +781,50 @@ void MjpegServerImpl::ConnThread::ProcessRequest() {
|
||||
|
||||
// Read the request string from the stream
|
||||
wpi::SmallString<128> reqBuf;
|
||||
wpi::StringRef req = is.getline(reqBuf, 4096);
|
||||
std::string_view req = is.getline(reqBuf, 4096);
|
||||
if (is.has_error()) {
|
||||
SDEBUG("error getting request string");
|
||||
SDEBUG("{}", "error getting request string");
|
||||
return;
|
||||
}
|
||||
|
||||
enum { kCommand, kStream, kGetSettings, kGetSourceConfig, kRootPage } kind;
|
||||
wpi::StringRef parameters;
|
||||
std::string_view parameters;
|
||||
size_t pos;
|
||||
|
||||
SDEBUG("HTTP request: '" << req << "'\n");
|
||||
SDEBUG("HTTP request: '{}'\n", req);
|
||||
|
||||
// Determine request kind. Most of these are for mjpgstreamer
|
||||
// compatibility, others are for Axis camera compatibility.
|
||||
if ((pos = req.find("POST /stream")) != wpi::StringRef::npos) {
|
||||
if ((pos = req.find("POST /stream")) != std::string_view::npos) {
|
||||
kind = kStream;
|
||||
parameters = req.substr(req.find('?', pos + 12)).substr(1);
|
||||
} else if ((pos = req.find("GET /?action=stream")) != wpi::StringRef::npos) {
|
||||
} else if ((pos = req.find("GET /?action=stream")) !=
|
||||
std::string_view::npos) {
|
||||
kind = kStream;
|
||||
parameters = req.substr(req.find('&', pos + 19)).substr(1);
|
||||
} else if ((pos = req.find("GET /stream.mjpg")) != wpi::StringRef::npos) {
|
||||
} else if ((pos = req.find("GET /stream.mjpg")) != std::string_view::npos) {
|
||||
kind = kStream;
|
||||
parameters = req.substr(req.find('?', pos + 16)).substr(1);
|
||||
} else if (req.find("GET /settings") != wpi::StringRef::npos &&
|
||||
req.find(".json") != wpi::StringRef::npos) {
|
||||
} else if (req.find("GET /settings") != std::string_view::npos &&
|
||||
req.find(".json") != std::string_view::npos) {
|
||||
kind = kGetSettings;
|
||||
} else if (req.find("GET /config") != wpi::StringRef::npos &&
|
||||
req.find(".json") != wpi::StringRef::npos) {
|
||||
} else if (req.find("GET /config") != std::string_view::npos &&
|
||||
req.find(".json") != std::string_view::npos) {
|
||||
kind = kGetSourceConfig;
|
||||
} else if (req.find("GET /input") != wpi::StringRef::npos &&
|
||||
req.find(".json") != wpi::StringRef::npos) {
|
||||
} else if (req.find("GET /input") != std::string_view::npos &&
|
||||
req.find(".json") != std::string_view::npos) {
|
||||
kind = kGetSettings;
|
||||
} else if (req.find("GET /output") != wpi::StringRef::npos &&
|
||||
req.find(".json") != wpi::StringRef::npos) {
|
||||
} else if (req.find("GET /output") != std::string_view::npos &&
|
||||
req.find(".json") != std::string_view::npos) {
|
||||
kind = kGetSettings;
|
||||
} else if ((pos = req.find("GET /?action=command")) != wpi::StringRef::npos) {
|
||||
} else if ((pos = req.find("GET /?action=command")) !=
|
||||
std::string_view::npos) {
|
||||
kind = kCommand;
|
||||
parameters = req.substr(req.find('&', pos + 20)).substr(1);
|
||||
} else if (req.find("GET / ") != wpi::StringRef::npos || req == "GET /\n") {
|
||||
} else if (req.find("GET / ") != std::string_view::npos || req == "GET /\n") {
|
||||
kind = kRootPage;
|
||||
} else {
|
||||
SDEBUG("HTTP request resource not found");
|
||||
SDEBUG("{}", "HTTP request resource not found");
|
||||
SendError(os, 404, "Resource not found");
|
||||
return;
|
||||
}
|
||||
@@ -841,13 +834,13 @@ void MjpegServerImpl::ConnThread::ProcessRequest() {
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"
|
||||
"-=&1234567890%./");
|
||||
parameters = parameters.substr(0, pos);
|
||||
SDEBUG("command parameters: \"" << parameters << "\"");
|
||||
SDEBUG("command parameters: \"{}\"", parameters);
|
||||
|
||||
// Read the rest of the HTTP request.
|
||||
// The end of the request is marked by a single, empty line
|
||||
wpi::SmallString<128> lineBuf;
|
||||
for (;;) {
|
||||
if (is.getline(lineBuf, 4096).startswith("\n")) {
|
||||
if (wpi::starts_with(is.getline(lineBuf, 4096), "\n")) {
|
||||
break;
|
||||
}
|
||||
if (is.has_error()) {
|
||||
@@ -859,7 +852,7 @@ void MjpegServerImpl::ConnThread::ProcessRequest() {
|
||||
switch (kind) {
|
||||
case kStream:
|
||||
if (auto source = GetSource()) {
|
||||
SDEBUG("request for stream " << source->GetName());
|
||||
SDEBUG("request for stream {}", source->GetName());
|
||||
if (!ProcessCommand(os, *source, parameters, false)) {
|
||||
return;
|
||||
}
|
||||
@@ -873,11 +866,11 @@ void MjpegServerImpl::ConnThread::ProcessRequest() {
|
||||
SendHeader(os, 200, "OK", "text/plain");
|
||||
os << "Ignored due to no connected source."
|
||||
<< "\r\n";
|
||||
SDEBUG("Ignored due to no connected source.");
|
||||
SDEBUG("{}", "Ignored due to no connected source.");
|
||||
}
|
||||
break;
|
||||
case kGetSettings:
|
||||
SDEBUG("request for JSON file");
|
||||
SDEBUG("{}", "request for JSON file");
|
||||
if (auto source = GetSource()) {
|
||||
SendJSON(os, *source, true);
|
||||
} else {
|
||||
@@ -885,7 +878,7 @@ void MjpegServerImpl::ConnThread::ProcessRequest() {
|
||||
}
|
||||
break;
|
||||
case kGetSourceConfig:
|
||||
SDEBUG("request for JSON file");
|
||||
SDEBUG("{}", "request for JSON file");
|
||||
if (auto source = GetSource()) {
|
||||
SendHeader(os, 200, "OK", "application/json");
|
||||
CS_Status status = CS_OK;
|
||||
@@ -896,7 +889,7 @@ void MjpegServerImpl::ConnThread::ProcessRequest() {
|
||||
}
|
||||
break;
|
||||
case kRootPage:
|
||||
SDEBUG("request for root page");
|
||||
SDEBUG("{}", "request for root page");
|
||||
SendHeader(os, 200, "OK", "text/html");
|
||||
if (auto source = GetSource()) {
|
||||
SendHTML(os, *source, false);
|
||||
@@ -907,7 +900,7 @@ void MjpegServerImpl::ConnThread::ProcessRequest() {
|
||||
break;
|
||||
}
|
||||
|
||||
SDEBUG("leaving HTTP client thread");
|
||||
SDEBUG("{}", "leaving HTTP client thread");
|
||||
}
|
||||
|
||||
// worker thread for clients that connected to this server
|
||||
@@ -934,7 +927,7 @@ void MjpegServerImpl::ServerThreadMain() {
|
||||
return;
|
||||
}
|
||||
|
||||
SDEBUG("waiting for clients to connect");
|
||||
SDEBUG("{}", "waiting for clients to connect");
|
||||
while (m_active) {
|
||||
auto stream = m_acceptor->accept();
|
||||
if (!stream) {
|
||||
@@ -945,7 +938,7 @@ void MjpegServerImpl::ServerThreadMain() {
|
||||
return;
|
||||
}
|
||||
|
||||
SDEBUG("client connection from " << stream->getPeerIP());
|
||||
SDEBUG("client connection from {}", stream->getPeerIP());
|
||||
|
||||
auto source = GetSource();
|
||||
|
||||
@@ -984,7 +977,7 @@ void MjpegServerImpl::ServerThreadMain() {
|
||||
thr->m_cond.notify_one();
|
||||
}
|
||||
|
||||
SDEBUG("leaving server thread");
|
||||
SDEBUG("{}", "leaving server thread");
|
||||
}
|
||||
|
||||
void MjpegServerImpl::SetSourceImpl(std::shared_ptr<SourceImpl> source) {
|
||||
@@ -1007,19 +1000,15 @@ void MjpegServerImpl::SetSourceImpl(std::shared_ptr<SourceImpl> source) {
|
||||
|
||||
namespace cs {
|
||||
|
||||
CS_Sink CreateMjpegServer(const wpi::Twine& name,
|
||||
const wpi::Twine& listenAddress, int port,
|
||||
CS_Status* status) {
|
||||
CS_Sink CreateMjpegServer(std::string_view name, std::string_view listenAddress,
|
||||
int port, CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
wpi::SmallString<128> listenAddressBuf;
|
||||
return inst.CreateSink(
|
||||
CS_SINK_MJPEG,
|
||||
std::make_shared<MjpegServerImpl>(
|
||||
name, inst.logger, inst.notifier, inst.telemetry, listenAddress, port,
|
||||
std::unique_ptr<wpi::NetworkAcceptor>(new wpi::TCPAcceptor(
|
||||
port,
|
||||
listenAddress.toNullTerminatedStringRef(listenAddressBuf).data(),
|
||||
inst.logger))));
|
||||
std::unique_ptr<wpi::NetworkAcceptor>(
|
||||
new wpi::TCPAcceptor(port, listenAddress, inst.logger))));
|
||||
}
|
||||
|
||||
std::string GetMjpegServerListenAddress(CS_Sink sink, CS_Status* status) {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
@@ -15,7 +16,6 @@
|
||||
#include <wpi/NetworkStream.h>
|
||||
#include <wpi/SafeThread.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/raw_istream.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <wpi/raw_socket_ostream.h>
|
||||
@@ -28,9 +28,9 @@ class SourceImpl;
|
||||
|
||||
class MjpegServerImpl : public SinkImpl {
|
||||
public:
|
||||
MjpegServerImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
MjpegServerImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
const wpi::Twine& listenAddress, int port,
|
||||
std::string_view listenAddress, int port,
|
||||
std::unique_ptr<wpi::NetworkAcceptor> acceptor);
|
||||
~MjpegServerImpl() override;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ unsigned int Notifier::AddPolled(unsigned int pollerUid, int eventMask) {
|
||||
return DoAdd(pollerUid, eventMask);
|
||||
}
|
||||
|
||||
void Notifier::NotifySource(const wpi::Twine& name, CS_Source source,
|
||||
void Notifier::NotifySource(std::string_view name, CS_Source source,
|
||||
CS_EventKind kind) {
|
||||
Send(UINT_MAX, name, source, static_cast<RawEvent::Kind>(kind));
|
||||
}
|
||||
@@ -49,9 +49,9 @@ void Notifier::NotifySourceVideoMode(const SourceImpl& source,
|
||||
}
|
||||
|
||||
void Notifier::NotifySourceProperty(const SourceImpl& source, CS_EventKind kind,
|
||||
const wpi::Twine& propertyName,
|
||||
int property, CS_PropertyKind propertyKind,
|
||||
int value, const wpi::Twine& valueStr) {
|
||||
std::string_view propertyName, int property,
|
||||
CS_PropertyKind propertyKind, int value,
|
||||
std::string_view valueStr) {
|
||||
auto handleData = Instance::GetInstance().FindSource(source);
|
||||
Send(UINT_MAX, propertyName, handleData.first,
|
||||
static_cast<RawEvent::Kind>(kind),
|
||||
@@ -59,7 +59,7 @@ void Notifier::NotifySourceProperty(const SourceImpl& source, CS_EventKind kind,
|
||||
value, valueStr);
|
||||
}
|
||||
|
||||
void Notifier::NotifySink(const wpi::Twine& name, CS_Sink sink,
|
||||
void Notifier::NotifySink(std::string_view name, CS_Sink sink,
|
||||
CS_EventKind kind) {
|
||||
Send(UINT_MAX, name, sink, static_cast<RawEvent::Kind>(kind));
|
||||
}
|
||||
@@ -69,7 +69,7 @@ void Notifier::NotifySink(const SinkImpl& sink, CS_EventKind kind) {
|
||||
NotifySink(sink.GetName(), handleData.first, kind);
|
||||
}
|
||||
|
||||
void Notifier::NotifySinkSourceChanged(const wpi::Twine& name, CS_Sink sink,
|
||||
void Notifier::NotifySinkSourceChanged(std::string_view name, CS_Sink sink,
|
||||
CS_Source source) {
|
||||
RawEvent event{name, sink, RawEvent::kSinkSourceChanged};
|
||||
event.sourceHandle = source;
|
||||
@@ -77,9 +77,9 @@ void Notifier::NotifySinkSourceChanged(const wpi::Twine& name, CS_Sink sink,
|
||||
}
|
||||
|
||||
void Notifier::NotifySinkProperty(const SinkImpl& sink, CS_EventKind kind,
|
||||
const wpi::Twine& propertyName, int property,
|
||||
std::string_view propertyName, int property,
|
||||
CS_PropertyKind propertyKind, int value,
|
||||
const wpi::Twine& valueStr) {
|
||||
std::string_view valueStr) {
|
||||
auto handleData = Instance::GetInstance().FindSink(sink);
|
||||
Send(UINT_MAX, propertyName, handleData.first,
|
||||
static_cast<RawEvent::Kind>(kind),
|
||||
|
||||
@@ -65,22 +65,21 @@ class Notifier : public wpi::CallbackManager<Notifier, impl::NotifierThread> {
|
||||
unsigned int AddPolled(unsigned int pollerUid, int eventMask);
|
||||
|
||||
// Notification events
|
||||
void NotifySource(const wpi::Twine& name, CS_Source source,
|
||||
CS_EventKind kind);
|
||||
void NotifySource(std::string_view name, CS_Source source, CS_EventKind kind);
|
||||
void NotifySource(const SourceImpl& source, CS_EventKind kind);
|
||||
void NotifySourceVideoMode(const SourceImpl& source, const VideoMode& mode);
|
||||
void NotifySourceProperty(const SourceImpl& source, CS_EventKind kind,
|
||||
const wpi::Twine& propertyName, int property,
|
||||
std::string_view propertyName, int property,
|
||||
CS_PropertyKind propertyKind, int value,
|
||||
const wpi::Twine& valueStr);
|
||||
void NotifySink(const wpi::Twine& name, CS_Sink sink, CS_EventKind kind);
|
||||
std::string_view valueStr);
|
||||
void NotifySink(std::string_view name, CS_Sink sink, CS_EventKind kind);
|
||||
void NotifySink(const SinkImpl& sink, CS_EventKind kind);
|
||||
void NotifySinkSourceChanged(const wpi::Twine& name, CS_Sink sink,
|
||||
void NotifySinkSourceChanged(std::string_view name, CS_Sink sink,
|
||||
CS_Source source);
|
||||
void NotifySinkProperty(const SinkImpl& sink, CS_EventKind kind,
|
||||
const wpi::Twine& propertyName, int property,
|
||||
std::string_view propertyName, int property,
|
||||
CS_PropertyKind propertyKind, int value,
|
||||
const wpi::Twine& valueStr);
|
||||
std::string_view valueStr);
|
||||
void NotifyNetworkInterfacesChanged();
|
||||
void NotifyTelemetryUpdated();
|
||||
void NotifyUsbCamerasChanged();
|
||||
|
||||
@@ -11,15 +11,14 @@
|
||||
|
||||
using namespace cs;
|
||||
|
||||
int PropertyContainer::GetPropertyIndex(const wpi::Twine& name) const {
|
||||
int PropertyContainer::GetPropertyIndex(std::string_view name) const {
|
||||
// We can't fail, so instead we create a new index if caching fails.
|
||||
CS_Status status = 0;
|
||||
if (!m_properties_cached) {
|
||||
CacheProperties(&status);
|
||||
}
|
||||
std::scoped_lock lock(m_mutex);
|
||||
wpi::SmallVector<char, 64> nameBuf;
|
||||
int& ndx = m_properties[name.toStringRef(nameBuf)];
|
||||
int& ndx = m_properties[name];
|
||||
if (ndx == 0) {
|
||||
// create a new index
|
||||
ndx = m_propertyData.size() + 1;
|
||||
@@ -55,7 +54,7 @@ CS_PropertyKind PropertyContainer::GetPropertyKind(int property) const {
|
||||
return prop->propKind;
|
||||
}
|
||||
|
||||
wpi::StringRef PropertyContainer::GetPropertyName(
|
||||
std::string_view PropertyContainer::GetPropertyName(
|
||||
int property, wpi::SmallVectorImpl<char>& buf, CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status)) {
|
||||
return {};
|
||||
@@ -108,7 +107,7 @@ void PropertyContainer::SetProperty(int property, int value,
|
||||
return;
|
||||
}
|
||||
|
||||
UpdatePropertyValue(property, false, value, wpi::Twine{});
|
||||
UpdatePropertyValue(property, false, value, {});
|
||||
}
|
||||
|
||||
int PropertyContainer::GetPropertyMin(int property, CS_Status* status) const {
|
||||
@@ -164,7 +163,7 @@ int PropertyContainer::GetPropertyDefault(int property,
|
||||
return prop->defaultValue;
|
||||
}
|
||||
|
||||
wpi::StringRef PropertyContainer::GetStringProperty(
|
||||
std::string_view PropertyContainer::GetStringProperty(
|
||||
int property, wpi::SmallVectorImpl<char>& buf, CS_Status* status) const {
|
||||
if (!m_properties_cached && !CacheProperties(status)) {
|
||||
return {};
|
||||
@@ -181,10 +180,10 @@ wpi::StringRef PropertyContainer::GetStringProperty(
|
||||
}
|
||||
buf.clear();
|
||||
buf.append(prop->valueStr.begin(), prop->valueStr.end());
|
||||
return wpi::StringRef(buf.data(), buf.size());
|
||||
return {buf.data(), buf.size()};
|
||||
}
|
||||
|
||||
void PropertyContainer::SetStringProperty(int property, const wpi::Twine& value,
|
||||
void PropertyContainer::SetStringProperty(int property, std::string_view value,
|
||||
CS_Status* status) {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
auto prop = GetProperty(property);
|
||||
@@ -225,7 +224,7 @@ std::vector<std::string> PropertyContainer::GetEnumPropertyChoices(
|
||||
}
|
||||
|
||||
std::unique_ptr<PropertyImpl> PropertyContainer::CreateEmptyProperty(
|
||||
const wpi::Twine& name) const {
|
||||
std::string_view name) const {
|
||||
return std::make_unique<PropertyImpl>(name);
|
||||
}
|
||||
|
||||
@@ -237,16 +236,15 @@ bool PropertyContainer::CacheProperties(CS_Status* status) const {
|
||||
|
||||
bool PropertyContainer::SetPropertiesJson(const wpi::json& config,
|
||||
wpi::Logger& logger,
|
||||
wpi::StringRef logName,
|
||||
std::string_view logName,
|
||||
CS_Status* status) {
|
||||
for (auto&& prop : config) {
|
||||
std::string name;
|
||||
try {
|
||||
name = prop.at("name").get<std::string>();
|
||||
} catch (const wpi::json::exception& e) {
|
||||
WPI_WARNING(logger,
|
||||
logName << ": SetConfigJson: could not read property name: "
|
||||
<< e.what());
|
||||
WPI_WARNING(logger, "{}: SetConfigJson: could not read property name: {}",
|
||||
logName, e.what());
|
||||
continue;
|
||||
}
|
||||
int n = GetPropertyIndex(name);
|
||||
@@ -254,24 +252,24 @@ bool PropertyContainer::SetPropertiesJson(const wpi::json& config,
|
||||
auto& v = prop.at("value");
|
||||
if (v.is_string()) {
|
||||
std::string val = v.get<std::string>();
|
||||
WPI_INFO(logger, logName << ": SetConfigJson: setting property '"
|
||||
<< name << "' to '" << val << '\'');
|
||||
WPI_INFO(logger, "{}: SetConfigJson: setting property '{}' to '{}'",
|
||||
logName, name, val);
|
||||
SetStringProperty(n, val, status);
|
||||
} else if (v.is_boolean()) {
|
||||
bool val = v.get<bool>();
|
||||
WPI_INFO(logger, logName << ": SetConfigJson: setting property '"
|
||||
<< name << "' to " << val);
|
||||
WPI_INFO(logger, "{}: SetConfigJson: setting property '{}' to {}",
|
||||
logName, name, val);
|
||||
SetProperty(n, val, status);
|
||||
} else {
|
||||
int val = v.get<int>();
|
||||
WPI_INFO(logger, logName << ": SetConfigJson: setting property '"
|
||||
<< name << "' to " << val);
|
||||
WPI_INFO(logger, "{}: SetConfigJson: setting property '{}' to {}",
|
||||
logName, name, val);
|
||||
SetProperty(n, val, status);
|
||||
}
|
||||
} catch (const wpi::json::exception& e) {
|
||||
WPI_WARNING(logger,
|
||||
logName << ": SetConfigJson: could not read property value: "
|
||||
<< e.what());
|
||||
"{}: SetConfigJson: could not read property value: {}",
|
||||
logName, e.what());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,11 @@
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/ArrayRef.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpi/StringMap.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/mutex.h>
|
||||
|
||||
#include "PropertyImpl.h"
|
||||
@@ -23,6 +21,8 @@
|
||||
|
||||
namespace wpi {
|
||||
class Logger;
|
||||
template <typename T>
|
||||
class SmallVectorImpl;
|
||||
class json;
|
||||
} // namespace wpi
|
||||
|
||||
@@ -32,28 +32,29 @@ class PropertyContainer {
|
||||
public:
|
||||
virtual ~PropertyContainer() = default;
|
||||
|
||||
int GetPropertyIndex(const wpi::Twine& name) const;
|
||||
int GetPropertyIndex(std::string_view name) const;
|
||||
wpi::ArrayRef<int> EnumerateProperties(wpi::SmallVectorImpl<int>& vec,
|
||||
CS_Status* status) const;
|
||||
CS_PropertyKind GetPropertyKind(int property) const;
|
||||
wpi::StringRef GetPropertyName(int property, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) const;
|
||||
std::string_view GetPropertyName(int property,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) const;
|
||||
int GetProperty(int property, CS_Status* status) const;
|
||||
virtual void SetProperty(int property, int value, CS_Status* status);
|
||||
int GetPropertyMin(int property, CS_Status* status) const;
|
||||
int GetPropertyMax(int property, CS_Status* status) const;
|
||||
int GetPropertyStep(int property, CS_Status* status) const;
|
||||
int GetPropertyDefault(int property, CS_Status* status) const;
|
||||
wpi::StringRef GetStringProperty(int property,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) const;
|
||||
virtual void SetStringProperty(int property, const wpi::Twine& value,
|
||||
std::string_view GetStringProperty(int property,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) const;
|
||||
virtual void SetStringProperty(int property, std::string_view value,
|
||||
CS_Status* status);
|
||||
std::vector<std::string> GetEnumPropertyChoices(int property,
|
||||
CS_Status* status) const;
|
||||
|
||||
bool SetPropertiesJson(const wpi::json& config, wpi::Logger& logger,
|
||||
wpi::StringRef logName, CS_Status* status);
|
||||
std::string_view logName, CS_Status* status);
|
||||
wpi::json GetPropertiesJsonObject(CS_Status* status);
|
||||
|
||||
protected:
|
||||
@@ -76,10 +77,9 @@ class PropertyContainer {
|
||||
// @tparam NewFunc functor that returns a std::unique_ptr<PropertyImpl>
|
||||
// @tparam UpdateFunc functor that takes a PropertyImpl&.
|
||||
template <typename NewFunc, typename UpdateFunc>
|
||||
int CreateOrUpdateProperty(const wpi::Twine& name, NewFunc newFunc,
|
||||
int CreateOrUpdateProperty(std::string_view name, NewFunc newFunc,
|
||||
UpdateFunc updateFunc) {
|
||||
wpi::SmallVector<char, 64> nameBuf;
|
||||
int& ndx = m_properties[name.toStringRef(nameBuf)];
|
||||
int& ndx = m_properties[name];
|
||||
if (ndx == 0) {
|
||||
// create a new index
|
||||
ndx = m_propertyData.size() + 1;
|
||||
@@ -91,7 +91,7 @@ class PropertyContainer {
|
||||
return ndx;
|
||||
}
|
||||
template <typename NewFunc>
|
||||
int CreateProperty(const wpi::Twine& name, NewFunc newFunc) {
|
||||
int CreateProperty(std::string_view name, NewFunc newFunc) {
|
||||
return CreateOrUpdateProperty(name, newFunc, [](PropertyImpl&) {});
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ class PropertyContainer {
|
||||
// Note: called with m_mutex held.
|
||||
// The default implementation simply creates a PropertyImpl object.
|
||||
virtual std::unique_ptr<PropertyImpl> CreateEmptyProperty(
|
||||
const wpi::Twine& name) const;
|
||||
std::string_view name) const;
|
||||
|
||||
// Cache properties. Implementations must return false and set status to
|
||||
// CS_SOURCE_IS_DISCONNECTED if not possible to cache.
|
||||
@@ -111,7 +111,7 @@ class PropertyContainer {
|
||||
|
||||
// Update property value; must be called with m_mutex held.
|
||||
virtual void UpdatePropertyValue(int property, bool setString, int value,
|
||||
const wpi::Twine& valueStr) = 0;
|
||||
std::string_view valueStr) = 0;
|
||||
|
||||
// Whether CacheProperties() has been successful at least once (and thus
|
||||
// should not be called again)
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
|
||||
using namespace cs;
|
||||
|
||||
PropertyImpl::PropertyImpl(const wpi::Twine& name_) : name{name_.str()} {}
|
||||
PropertyImpl::PropertyImpl(const wpi::Twine& name_, CS_PropertyKind kind_,
|
||||
PropertyImpl::PropertyImpl(std::string_view name_) : name{name_} {}
|
||||
PropertyImpl::PropertyImpl(std::string_view name_, CS_PropertyKind kind_,
|
||||
int step_, int defaultValue_, int value_)
|
||||
: name{name_.str()},
|
||||
: name{name_},
|
||||
propKind{kind_},
|
||||
step{step_},
|
||||
defaultValue{defaultValue_},
|
||||
value{value_} {}
|
||||
PropertyImpl::PropertyImpl(const wpi::Twine& name_, CS_PropertyKind kind_,
|
||||
PropertyImpl::PropertyImpl(std::string_view name_, CS_PropertyKind kind_,
|
||||
int minimum_, int maximum_, int step_,
|
||||
int defaultValue_, int value_)
|
||||
: name{name_.str()},
|
||||
: name{name_},
|
||||
propKind{kind_},
|
||||
hasMinimum{true},
|
||||
hasMaximum{true},
|
||||
@@ -43,11 +43,10 @@ void PropertyImpl::SetValue(int v) {
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyImpl::SetValue(const wpi::Twine& v) {
|
||||
void PropertyImpl::SetValue(std::string_view v) {
|
||||
bool valueChanged = false;
|
||||
std::string vStr = v.str();
|
||||
if (valueStr != vStr) {
|
||||
valueStr = vStr;
|
||||
if (valueStr != v) {
|
||||
valueStr = v;
|
||||
valueChanged = true;
|
||||
}
|
||||
bool wasValueSet = valueSet;
|
||||
|
||||
@@ -6,11 +6,10 @@
|
||||
#define CSCORE_PROPERTYIMPL_H_
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/Signal.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
#include "cscore_c.h"
|
||||
|
||||
@@ -20,17 +19,17 @@ namespace cs {
|
||||
class PropertyImpl {
|
||||
public:
|
||||
PropertyImpl() = default;
|
||||
explicit PropertyImpl(const wpi::Twine& name_);
|
||||
PropertyImpl(const wpi::Twine& name_, CS_PropertyKind kind_, int step_,
|
||||
explicit PropertyImpl(std::string_view name_);
|
||||
PropertyImpl(std::string_view name_, CS_PropertyKind kind_, int step_,
|
||||
int defaultValue_, int value_);
|
||||
PropertyImpl(const wpi::Twine& name_, CS_PropertyKind kind_, int minimum_,
|
||||
PropertyImpl(std::string_view name_, CS_PropertyKind kind_, int minimum_,
|
||||
int maximum_, int step_, int defaultValue_, int value_);
|
||||
virtual ~PropertyImpl() = default;
|
||||
PropertyImpl(const PropertyImpl& oth) = delete;
|
||||
PropertyImpl& operator=(const PropertyImpl& oth) = delete;
|
||||
|
||||
void SetValue(int v);
|
||||
void SetValue(const wpi::Twine& v);
|
||||
void SetValue(std::string_view v);
|
||||
void SetDefaultValue(int v);
|
||||
|
||||
std::string name;
|
||||
|
||||
@@ -10,14 +10,14 @@
|
||||
|
||||
using namespace cs;
|
||||
|
||||
RawSinkImpl::RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
RawSinkImpl::RawSinkImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry)
|
||||
: SinkImpl{name, logger, notifier, telemetry} {
|
||||
m_active = true;
|
||||
// m_thread = std::thread(&RawSinkImpl::ThreadMain, this);
|
||||
}
|
||||
|
||||
RawSinkImpl::RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
RawSinkImpl::RawSinkImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
std::function<void(uint64_t time)> processFrame)
|
||||
: SinkImpl{name, logger, notifier, telemetry} {}
|
||||
@@ -127,7 +127,7 @@ void RawSinkImpl::ThreadMain() {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
continue;
|
||||
}
|
||||
SDEBUG4("waiting for frame");
|
||||
SDEBUG4("{}", "waiting for frame");
|
||||
Frame frame = source->GetNextFrame(); // blocks
|
||||
if (!m_active) {
|
||||
break;
|
||||
@@ -143,14 +143,14 @@ void RawSinkImpl::ThreadMain() {
|
||||
}
|
||||
|
||||
namespace cs {
|
||||
CS_Sink CreateRawSink(const wpi::Twine& name, CS_Status* status) {
|
||||
CS_Sink CreateRawSink(std::string_view name, CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
return inst.CreateSink(CS_SINK_RAW,
|
||||
std::make_shared<RawSinkImpl>(
|
||||
name, inst.logger, inst.notifier, inst.telemetry));
|
||||
}
|
||||
|
||||
CS_Sink CreateRawSinkCallback(const wpi::Twine& name,
|
||||
CS_Sink CreateRawSinkCallback(std::string_view name,
|
||||
std::function<void(uint64_t time)> processFrame,
|
||||
CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/condition_variable.h>
|
||||
|
||||
#include "Frame.h"
|
||||
@@ -23,9 +23,9 @@ class SourceImpl;
|
||||
|
||||
class RawSinkImpl : public SinkImpl {
|
||||
public:
|
||||
RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
|
||||
RawSinkImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry);
|
||||
RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
|
||||
RawSinkImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
~RawSinkImpl() override;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
using namespace cs;
|
||||
|
||||
RawSourceImpl::RawSourceImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
RawSourceImpl::RawSourceImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
const VideoMode& mode)
|
||||
: ConfigurableSourceImpl{name, logger, notifier, telemetry, mode} {}
|
||||
@@ -47,7 +47,7 @@ void RawSourceImpl::PutFrame(const CS_RawFrame& image) {
|
||||
}
|
||||
|
||||
namespace cs {
|
||||
CS_Source CreateRawSource(const wpi::Twine& name, const VideoMode& mode,
|
||||
CS_Source CreateRawSource(std::string_view name, const VideoMode& mode,
|
||||
CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
return inst.CreateSource(CS_SOURCE_RAW, std::make_shared<RawSourceImpl>(
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/ArrayRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
#include "ConfigurableSourceImpl.h"
|
||||
#include "SourceImpl.h"
|
||||
@@ -22,7 +22,7 @@ namespace cs {
|
||||
|
||||
class RawSourceImpl : public ConfigurableSourceImpl {
|
||||
public:
|
||||
RawSourceImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
|
||||
RawSourceImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry, const VideoMode& mode);
|
||||
~RawSourceImpl() override;
|
||||
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
|
||||
using namespace cs;
|
||||
|
||||
SinkImpl::SinkImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
SinkImpl::SinkImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry)
|
||||
: m_logger(logger),
|
||||
m_notifier(notifier),
|
||||
m_telemetry(telemetry),
|
||||
m_name{name.str()} {}
|
||||
m_name{name} {}
|
||||
|
||||
SinkImpl::~SinkImpl() {
|
||||
if (m_source) {
|
||||
@@ -28,15 +28,16 @@ SinkImpl::~SinkImpl() {
|
||||
}
|
||||
}
|
||||
|
||||
void SinkImpl::SetDescription(const wpi::Twine& description) {
|
||||
void SinkImpl::SetDescription(std::string_view description) {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_description = description.str();
|
||||
m_description = description;
|
||||
}
|
||||
|
||||
wpi::StringRef SinkImpl::GetDescription(wpi::SmallVectorImpl<char>& buf) const {
|
||||
std::string_view SinkImpl::GetDescription(
|
||||
wpi::SmallVectorImpl<char>& buf) const {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
buf.append(m_description.begin(), m_description.end());
|
||||
return wpi::StringRef{buf.data(), buf.size()};
|
||||
return {buf.data(), buf.size()};
|
||||
}
|
||||
|
||||
void SinkImpl::Enable() {
|
||||
@@ -106,28 +107,27 @@ std::string SinkImpl::GetError() const {
|
||||
if (!m_source) {
|
||||
return "no source connected";
|
||||
}
|
||||
return m_source->GetCurFrame().GetError();
|
||||
return std::string{m_source->GetCurFrame().GetError()};
|
||||
}
|
||||
|
||||
wpi::StringRef SinkImpl::GetError(wpi::SmallVectorImpl<char>& buf) const {
|
||||
std::string_view SinkImpl::GetError(wpi::SmallVectorImpl<char>& buf) const {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (!m_source) {
|
||||
return "no source connected";
|
||||
}
|
||||
// Make a copy as it's shared data
|
||||
wpi::StringRef error = m_source->GetCurFrame().GetError();
|
||||
std::string_view error = m_source->GetCurFrame().GetError();
|
||||
buf.clear();
|
||||
buf.append(error.data(), error.data() + error.size());
|
||||
return wpi::StringRef{buf.data(), buf.size()};
|
||||
return {buf.data(), buf.size()};
|
||||
}
|
||||
|
||||
bool SinkImpl::SetConfigJson(wpi::StringRef config, CS_Status* status) {
|
||||
bool SinkImpl::SetConfigJson(std::string_view config, CS_Status* status) {
|
||||
wpi::json j;
|
||||
try {
|
||||
j = wpi::json::parse(config);
|
||||
} catch (const wpi::json::parse_error& e) {
|
||||
SWARNING("SetConfigJson: parse error at byte " << e.byte << ": "
|
||||
<< e.what());
|
||||
SWARNING("SetConfigJson: parse error at byte {}: {}", e.byte, e.what());
|
||||
*status = CS_PROPERTY_WRITE_FAILED;
|
||||
return false;
|
||||
}
|
||||
@@ -169,12 +169,12 @@ void SinkImpl::NotifyPropertyCreated(int propIndex, PropertyImpl& prop) {
|
||||
if (prop.propKind == CS_PROP_ENUM) {
|
||||
m_notifier.NotifySinkProperty(*this, CS_SINK_PROPERTY_CHOICES_UPDATED,
|
||||
prop.name, propIndex, prop.propKind,
|
||||
prop.value, wpi::Twine{});
|
||||
prop.value, {});
|
||||
}
|
||||
}
|
||||
|
||||
void SinkImpl::UpdatePropertyValue(int property, bool setString, int value,
|
||||
const wpi::Twine& valueStr) {
|
||||
std::string_view valueStr) {
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) {
|
||||
return;
|
||||
|
||||
@@ -7,10 +7,9 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <wpi/Logger.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/mutex.h>
|
||||
|
||||
#include "SourceImpl.h"
|
||||
@@ -27,16 +26,16 @@ class Telemetry;
|
||||
|
||||
class SinkImpl : public PropertyContainer {
|
||||
public:
|
||||
explicit SinkImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
explicit SinkImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry);
|
||||
~SinkImpl() override;
|
||||
SinkImpl(const SinkImpl& queue) = delete;
|
||||
SinkImpl& operator=(const SinkImpl& queue) = delete;
|
||||
|
||||
wpi::StringRef GetName() const { return m_name; }
|
||||
std::string_view GetName() const { return m_name; }
|
||||
|
||||
void SetDescription(const wpi::Twine& description);
|
||||
wpi::StringRef GetDescription(wpi::SmallVectorImpl<char>& buf) const;
|
||||
void SetDescription(std::string_view description);
|
||||
std::string_view GetDescription(wpi::SmallVectorImpl<char>& buf) const;
|
||||
|
||||
void Enable();
|
||||
void Disable();
|
||||
@@ -50,9 +49,9 @@ class SinkImpl : public PropertyContainer {
|
||||
}
|
||||
|
||||
std::string GetError() const;
|
||||
wpi::StringRef GetError(wpi::SmallVectorImpl<char>& buf) const;
|
||||
std::string_view GetError(wpi::SmallVectorImpl<char>& buf) const;
|
||||
|
||||
bool SetConfigJson(wpi::StringRef config, CS_Status* status);
|
||||
bool SetConfigJson(std::string_view config, CS_Status* status);
|
||||
virtual bool SetConfigJson(const wpi::json& config, CS_Status* status);
|
||||
std::string GetConfigJson(CS_Status* status);
|
||||
virtual wpi::json GetConfigJsonObject(CS_Status* status);
|
||||
@@ -61,7 +60,7 @@ class SinkImpl : public PropertyContainer {
|
||||
// PropertyContainer implementation
|
||||
void NotifyPropertyCreated(int propIndex, PropertyImpl& prop) override;
|
||||
void UpdatePropertyValue(int property, bool setString, int value,
|
||||
const wpi::Twine& valueStr) override;
|
||||
std::string_view valueStr) override;
|
||||
|
||||
virtual void SetSourceImpl(std::shared_ptr<SourceImpl> source);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/json.h>
|
||||
#include <wpi/timestamp.h>
|
||||
|
||||
@@ -19,13 +20,13 @@ using namespace cs;
|
||||
|
||||
static constexpr size_t kMaxImagesAvail = 32;
|
||||
|
||||
SourceImpl::SourceImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
SourceImpl::SourceImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry)
|
||||
: m_logger(logger),
|
||||
m_notifier(notifier),
|
||||
m_telemetry(telemetry),
|
||||
m_name{name.str()} {
|
||||
m_frame = Frame{*this, wpi::StringRef{}, 0};
|
||||
m_name{name} {
|
||||
m_frame = Frame{*this, std::string_view{}, 0};
|
||||
}
|
||||
|
||||
SourceImpl::~SourceImpl() {
|
||||
@@ -41,16 +42,16 @@ SourceImpl::~SourceImpl() {
|
||||
// Everything else can clean up itself.
|
||||
}
|
||||
|
||||
void SourceImpl::SetDescription(const wpi::Twine& description) {
|
||||
void SourceImpl::SetDescription(std::string_view description) {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_description = description.str();
|
||||
m_description = description;
|
||||
}
|
||||
|
||||
wpi::StringRef SourceImpl::GetDescription(
|
||||
std::string_view SourceImpl::GetDescription(
|
||||
wpi::SmallVectorImpl<char>& buf) const {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
buf.append(m_description.begin(), m_description.end());
|
||||
return wpi::StringRef{buf.data(), buf.size()};
|
||||
return {buf.data(), buf.size()};
|
||||
}
|
||||
|
||||
void SourceImpl::SetConnected(bool connected) {
|
||||
@@ -93,7 +94,7 @@ Frame SourceImpl::GetNextFrame(double timeout) {
|
||||
void SourceImpl::Wakeup() {
|
||||
{
|
||||
std::scoped_lock lock{m_frameMutex};
|
||||
m_frame = Frame{*this, wpi::StringRef{}, 0};
|
||||
m_frame = Frame{*this, std::string_view{}, 0};
|
||||
}
|
||||
m_frameCv.notify_all();
|
||||
}
|
||||
@@ -168,13 +169,12 @@ bool SourceImpl::SetFPS(int fps, CS_Status* status) {
|
||||
return SetVideoMode(mode, status);
|
||||
}
|
||||
|
||||
bool SourceImpl::SetConfigJson(wpi::StringRef config, CS_Status* status) {
|
||||
bool SourceImpl::SetConfigJson(std::string_view config, CS_Status* status) {
|
||||
wpi::json j;
|
||||
try {
|
||||
j = wpi::json::parse(config);
|
||||
} catch (const wpi::json::parse_error& e) {
|
||||
SWARNING("SetConfigJson: parse error at byte " << e.byte << ": "
|
||||
<< e.what());
|
||||
SWARNING("SetConfigJson: parse error at byte {}: {}", e.byte, e.what());
|
||||
*status = CS_PROPERTY_WRITE_FAILED;
|
||||
return false;
|
||||
}
|
||||
@@ -188,23 +188,22 @@ bool SourceImpl::SetConfigJson(const wpi::json& config, CS_Status* status) {
|
||||
if (config.count("pixel format") != 0) {
|
||||
try {
|
||||
auto str = config.at("pixel format").get<std::string>();
|
||||
wpi::StringRef s(str);
|
||||
if (s.equals_lower("mjpeg")) {
|
||||
if (wpi::equals_lower(str, "mjpeg")) {
|
||||
mode.pixelFormat = cs::VideoMode::kMJPEG;
|
||||
} else if (s.equals_lower("yuyv")) {
|
||||
} else if (wpi::equals_lower(str, "yuyv")) {
|
||||
mode.pixelFormat = cs::VideoMode::kYUYV;
|
||||
} else if (s.equals_lower("rgb565")) {
|
||||
} else if (wpi::equals_lower(str, "rgb565")) {
|
||||
mode.pixelFormat = cs::VideoMode::kRGB565;
|
||||
} else if (s.equals_lower("bgr")) {
|
||||
} else if (wpi::equals_lower(str, "bgr")) {
|
||||
mode.pixelFormat = cs::VideoMode::kBGR;
|
||||
} else if (s.equals_lower("gray")) {
|
||||
} else if (wpi::equals_lower(str, "gray")) {
|
||||
mode.pixelFormat = cs::VideoMode::kGray;
|
||||
} else {
|
||||
SWARNING("SetConfigJson: could not understand pixel format value '"
|
||||
<< str << '\'');
|
||||
SWARNING("SetConfigJson: could not understand pixel format value '{}'",
|
||||
str);
|
||||
}
|
||||
} catch (const wpi::json::exception& e) {
|
||||
SWARNING("SetConfigJson: could not read pixel format: " << e.what());
|
||||
SWARNING("SetConfigJson: could not read pixel format: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +212,7 @@ bool SourceImpl::SetConfigJson(const wpi::json& config, CS_Status* status) {
|
||||
try {
|
||||
mode.width = config.at("width").get<unsigned int>();
|
||||
} catch (const wpi::json::exception& e) {
|
||||
SWARNING("SetConfigJson: could not read width: " << e.what());
|
||||
SWARNING("SetConfigJson: could not read width: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +221,7 @@ bool SourceImpl::SetConfigJson(const wpi::json& config, CS_Status* status) {
|
||||
try {
|
||||
mode.height = config.at("height").get<unsigned int>();
|
||||
} catch (const wpi::json::exception& e) {
|
||||
SWARNING("SetConfigJson: could not read height: " << e.what());
|
||||
SWARNING("SetConfigJson: could not read height: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,30 +230,31 @@ bool SourceImpl::SetConfigJson(const wpi::json& config, CS_Status* status) {
|
||||
try {
|
||||
mode.fps = config.at("fps").get<unsigned int>();
|
||||
} catch (const wpi::json::exception& e) {
|
||||
SWARNING("SetConfigJson: could not read fps: " << e.what());
|
||||
SWARNING("SetConfigJson: could not read fps: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// if all of video mode is set, use SetVideoMode, otherwise piecemeal it
|
||||
if (mode.pixelFormat != VideoMode::kUnknown && mode.width != 0 &&
|
||||
mode.height != 0 && mode.fps != 0) {
|
||||
SINFO("SetConfigJson: setting video mode to pixelFormat "
|
||||
<< mode.pixelFormat << ", width " << mode.width << ", height "
|
||||
<< mode.height << ", fps " << mode.fps);
|
||||
SINFO(
|
||||
"SetConfigJson: setting video mode to pixelFormat {}, width {}, height "
|
||||
"{}, fps {}",
|
||||
mode.pixelFormat, mode.width, mode.height, mode.fps);
|
||||
SetVideoMode(mode, status);
|
||||
} else {
|
||||
if (mode.pixelFormat != cs::VideoMode::kUnknown) {
|
||||
SINFO("SetConfigJson: setting pixelFormat " << mode.pixelFormat);
|
||||
SINFO("SetConfigJson: setting pixelFormat {}", mode.pixelFormat);
|
||||
SetPixelFormat(static_cast<cs::VideoMode::PixelFormat>(mode.pixelFormat),
|
||||
status);
|
||||
}
|
||||
if (mode.width != 0 && mode.height != 0) {
|
||||
SINFO("SetConfigJson: setting width " << mode.width << ", height "
|
||||
<< mode.height);
|
||||
SINFO("SetConfigJson: setting width {}, height {}", mode.width,
|
||||
mode.height);
|
||||
SetResolution(mode.width, mode.height, status);
|
||||
}
|
||||
if (mode.fps != 0) {
|
||||
SINFO("SetConfigJson: setting fps " << mode.fps);
|
||||
SINFO("SetConfigJson: setting fps {}", mode.fps);
|
||||
SetFPS(mode.fps, status);
|
||||
}
|
||||
}
|
||||
@@ -263,10 +263,10 @@ bool SourceImpl::SetConfigJson(const wpi::json& config, CS_Status* status) {
|
||||
if (config.count("brightness") != 0) {
|
||||
try {
|
||||
int val = config.at("brightness").get<int>();
|
||||
SINFO("SetConfigJson: setting brightness to " << val);
|
||||
SINFO("SetConfigJson: setting brightness to {}", val);
|
||||
SetBrightness(val, status);
|
||||
} catch (const wpi::json::exception& e) {
|
||||
SWARNING("SetConfigJson: could not read brightness: " << e.what());
|
||||
SWARNING("SetConfigJson: could not read brightness: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,24 +276,24 @@ bool SourceImpl::SetConfigJson(const wpi::json& config, CS_Status* status) {
|
||||
auto& setting = config.at("white balance");
|
||||
if (setting.is_string()) {
|
||||
auto str = setting.get<std::string>();
|
||||
wpi::StringRef s(str);
|
||||
if (s.equals_lower("auto")) {
|
||||
SINFO("SetConfigJson: setting white balance to auto");
|
||||
if (wpi::equals_lower(str, "auto")) {
|
||||
SINFO("SetConfigJson: setting white balance to {}", "auto");
|
||||
SetWhiteBalanceAuto(status);
|
||||
} else if (s.equals_lower("hold")) {
|
||||
SINFO("SetConfigJson: setting white balance to hold current");
|
||||
} else if (wpi::equals_lower(str, "hold")) {
|
||||
SINFO("SetConfigJson: setting white balance to {}", "hold current");
|
||||
SetWhiteBalanceHoldCurrent(status);
|
||||
} else {
|
||||
SWARNING("SetConfigJson: could not understand white balance value '"
|
||||
<< str << '\'');
|
||||
SWARNING(
|
||||
"SetConfigJson: could not understand white balance value '{}'",
|
||||
str);
|
||||
}
|
||||
} else {
|
||||
int val = setting.get<int>();
|
||||
SINFO("SetConfigJson: setting white balance to " << val);
|
||||
SINFO("SetConfigJson: setting white balance to {}", val);
|
||||
SetWhiteBalanceManual(val, status);
|
||||
}
|
||||
} catch (const wpi::json::exception& e) {
|
||||
SWARNING("SetConfigJson: could not read white balance: " << e.what());
|
||||
SWARNING("SetConfigJson: could not read white balance: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,24 +303,23 @@ bool SourceImpl::SetConfigJson(const wpi::json& config, CS_Status* status) {
|
||||
auto& setting = config.at("exposure");
|
||||
if (setting.is_string()) {
|
||||
auto str = setting.get<std::string>();
|
||||
wpi::StringRef s(str);
|
||||
if (s.equals_lower("auto")) {
|
||||
SINFO("SetConfigJson: setting exposure to auto");
|
||||
if (wpi::equals_lower(str, "auto")) {
|
||||
SINFO("SetConfigJson: setting exposure to {}", "auto");
|
||||
SetExposureAuto(status);
|
||||
} else if (s.equals_lower("hold")) {
|
||||
SINFO("SetConfigJson: setting exposure to hold current");
|
||||
} else if (wpi::equals_lower(str, "hold")) {
|
||||
SINFO("SetConfigJson: setting exposure to {}", "hold current");
|
||||
SetExposureHoldCurrent(status);
|
||||
} else {
|
||||
SWARNING("SetConfigJson: could not understand exposure value '"
|
||||
<< str << '\'');
|
||||
SWARNING("SetConfigJson: could not understand exposure value '{}'",
|
||||
str);
|
||||
}
|
||||
} else {
|
||||
int val = setting.get<int>();
|
||||
SINFO("SetConfigJson: setting exposure to " << val);
|
||||
SINFO("SetConfigJson: setting exposure to {}", val);
|
||||
SetExposureManual(val, status);
|
||||
}
|
||||
} catch (const wpi::json::exception& e) {
|
||||
SWARNING("SetConfigJson: could not read exposure: " << e.what());
|
||||
SWARNING("SetConfigJson: could not read exposure: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,7 +343,7 @@ wpi::json SourceImpl::GetConfigJsonObject(CS_Status* status) {
|
||||
wpi::json j;
|
||||
|
||||
// pixel format
|
||||
wpi::StringRef pixelFormat;
|
||||
std::string_view pixelFormat;
|
||||
switch (m_mode.pixelFormat) {
|
||||
case VideoMode::kMJPEG:
|
||||
pixelFormat = "mjpeg";
|
||||
@@ -440,14 +439,12 @@ std::unique_ptr<Image> SourceImpl::AllocImage(
|
||||
}
|
||||
|
||||
void SourceImpl::PutFrame(VideoMode::PixelFormat pixelFormat, int width,
|
||||
int height, wpi::StringRef data, Frame::Time time) {
|
||||
int height, std::string_view data, Frame::Time time) {
|
||||
auto image = AllocImage(pixelFormat, width, height, data.size());
|
||||
|
||||
// Copy in image data
|
||||
SDEBUG4("Copying data to "
|
||||
<< reinterpret_cast<const void*>(image->data()) << " from "
|
||||
<< reinterpret_cast<const void*>(data.data()) << " (" << data.size()
|
||||
<< " bytes)");
|
||||
SDEBUG4("Copying data to {} from {} ({} bytes)", fmt::ptr(image->data()),
|
||||
fmt::ptr(data.data()), data.size());
|
||||
std::memcpy(image->data(), data.data(), data.size());
|
||||
|
||||
PutFrame(std::move(image), time);
|
||||
@@ -468,7 +465,7 @@ void SourceImpl::PutFrame(std::unique_ptr<Image> image, Frame::Time time) {
|
||||
m_frameCv.notify_all();
|
||||
}
|
||||
|
||||
void SourceImpl::PutError(const wpi::Twine& msg, Frame::Time time) {
|
||||
void SourceImpl::PutError(std::string_view msg, Frame::Time time) {
|
||||
// Update frame
|
||||
{
|
||||
std::scoped_lock lock{m_frameMutex};
|
||||
@@ -487,12 +484,12 @@ void SourceImpl::NotifyPropertyCreated(int propIndex, PropertyImpl& prop) {
|
||||
if (prop.propKind == CS_PROP_ENUM) {
|
||||
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CHOICES_UPDATED,
|
||||
prop.name, propIndex, prop.propKind,
|
||||
prop.value, wpi::Twine{});
|
||||
prop.value, {});
|
||||
}
|
||||
}
|
||||
|
||||
void SourceImpl::UpdatePropertyValue(int property, bool setString, int value,
|
||||
const wpi::Twine& valueStr) {
|
||||
std::string_view valueStr) {
|
||||
auto prop = GetProperty(property);
|
||||
if (!prop) {
|
||||
return;
|
||||
|
||||
@@ -9,12 +9,11 @@
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/ArrayRef.h>
|
||||
#include <wpi/Logger.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/condition_variable.h>
|
||||
#include <wpi/mutex.h>
|
||||
|
||||
@@ -37,7 +36,7 @@ class SourceImpl : public PropertyContainer {
|
||||
friend class Frame;
|
||||
|
||||
public:
|
||||
SourceImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
|
||||
SourceImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry);
|
||||
~SourceImpl() override;
|
||||
SourceImpl(const SourceImpl& oth) = delete;
|
||||
@@ -45,10 +44,10 @@ class SourceImpl : public PropertyContainer {
|
||||
|
||||
virtual void Start() = 0;
|
||||
|
||||
wpi::StringRef GetName() const { return m_name; }
|
||||
std::string_view GetName() const { return m_name; }
|
||||
|
||||
void SetDescription(const wpi::Twine& description);
|
||||
wpi::StringRef GetDescription(wpi::SmallVectorImpl<char>& buf) const;
|
||||
void SetDescription(std::string_view description);
|
||||
std::string_view GetDescription(wpi::SmallVectorImpl<char>& buf) const;
|
||||
|
||||
void SetConnectionStrategy(CS_ConnectionStrategy strategy) {
|
||||
m_strategy = static_cast<int>(strategy);
|
||||
@@ -128,7 +127,7 @@ class SourceImpl : public PropertyContainer {
|
||||
virtual bool SetResolution(int width, int height, CS_Status* status);
|
||||
virtual bool SetFPS(int fps, CS_Status* status);
|
||||
|
||||
bool SetConfigJson(wpi::StringRef config, CS_Status* status);
|
||||
bool SetConfigJson(std::string_view config, CS_Status* status);
|
||||
virtual bool SetConfigJson(const wpi::json& config, CS_Status* status);
|
||||
std::string GetConfigJson(CS_Status* status);
|
||||
virtual wpi::json GetConfigJsonObject(CS_Status* status);
|
||||
@@ -141,12 +140,12 @@ class SourceImpl : public PropertyContainer {
|
||||
protected:
|
||||
void NotifyPropertyCreated(int propIndex, PropertyImpl& prop) override;
|
||||
void UpdatePropertyValue(int property, bool setString, int value,
|
||||
const wpi::Twine& valueStr) override;
|
||||
std::string_view valueStr) override;
|
||||
|
||||
void PutFrame(VideoMode::PixelFormat pixelFormat, int width, int height,
|
||||
wpi::StringRef data, Frame::Time time);
|
||||
std::string_view data, Frame::Time time);
|
||||
void PutFrame(std::unique_ptr<Image> image, Frame::Time time);
|
||||
void PutError(const wpi::Twine& msg, Frame::Time time);
|
||||
void PutError(std::string_view msg, Frame::Time time);
|
||||
|
||||
// Notification functions for corresponding atomics
|
||||
virtual void NumSinksChanged() = 0;
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string_view>
|
||||
|
||||
#include <wpi/MemAlloc.h>
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
namespace cs {
|
||||
|
||||
inline char* ConvertToC(wpi::StringRef in) {
|
||||
inline char* ConvertToC(std::string_view in) {
|
||||
char* out = static_cast<char*>(wpi::safe_malloc(in.size() + 1));
|
||||
std::memmove(out, in.data(), in.size());
|
||||
out[in.size()] = '\0';
|
||||
|
||||
@@ -70,12 +70,12 @@ std::string GetPropertyName(CS_Property property, CS_Status* status) {
|
||||
if (!container) {
|
||||
return {};
|
||||
}
|
||||
return container->GetPropertyName(propertyIndex, buf, status);
|
||||
return std::string{container->GetPropertyName(propertyIndex, buf, status)};
|
||||
}
|
||||
|
||||
wpi::StringRef GetPropertyName(CS_Property property,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
std::string_view GetPropertyName(CS_Property property,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
int propertyIndex;
|
||||
auto container = GetPropertyContainer(property, &propertyIndex, status);
|
||||
if (!container) {
|
||||
@@ -145,12 +145,12 @@ std::string GetStringProperty(CS_Property property, CS_Status* status) {
|
||||
if (!container) {
|
||||
return {};
|
||||
}
|
||||
return container->GetStringProperty(propertyIndex, buf, status);
|
||||
return std::string{container->GetStringProperty(propertyIndex, buf, status)};
|
||||
}
|
||||
|
||||
wpi::StringRef GetStringProperty(CS_Property property,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
std::string_view GetStringProperty(CS_Property property,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
int propertyIndex;
|
||||
auto container = GetPropertyContainer(property, &propertyIndex, status);
|
||||
if (!container) {
|
||||
@@ -159,7 +159,7 @@ wpi::StringRef GetStringProperty(CS_Property property,
|
||||
return container->GetStringProperty(propertyIndex, buf, status);
|
||||
}
|
||||
|
||||
void SetStringProperty(CS_Property property, const wpi::Twine& value,
|
||||
void SetStringProperty(CS_Property property, std::string_view value,
|
||||
CS_Status* status) {
|
||||
int propertyIndex;
|
||||
auto container = GetPropertyContainer(property, &propertyIndex, status);
|
||||
@@ -196,17 +196,18 @@ std::string GetSourceName(CS_Source source, CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return std::string{};
|
||||
return {};
|
||||
}
|
||||
return data->source->GetName();
|
||||
return std::string{data->source->GetName()};
|
||||
}
|
||||
|
||||
wpi::StringRef GetSourceName(CS_Source source, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
std::string_view GetSourceName(CS_Source source,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return wpi::StringRef{};
|
||||
return {};
|
||||
}
|
||||
return data->source->GetName();
|
||||
}
|
||||
@@ -215,19 +216,19 @@ std::string GetSourceDescription(CS_Source source, CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return std::string{};
|
||||
return {};
|
||||
}
|
||||
wpi::SmallString<128> buf;
|
||||
return data->source->GetDescription(buf);
|
||||
return std::string{data->source->GetDescription(buf)};
|
||||
}
|
||||
|
||||
wpi::StringRef GetSourceDescription(CS_Source source,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
std::string_view GetSourceDescription(CS_Source source,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return wpi::StringRef{};
|
||||
return {};
|
||||
}
|
||||
return data->source->GetDescription(buf);
|
||||
}
|
||||
@@ -270,7 +271,7 @@ bool IsSourceEnabled(CS_Source source, CS_Status* status) {
|
||||
return data->source->IsEnabled();
|
||||
}
|
||||
|
||||
CS_Property GetSourceProperty(CS_Source source, const wpi::Twine& name,
|
||||
CS_Property GetSourceProperty(CS_Source source, std::string_view name,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data) {
|
||||
@@ -349,7 +350,7 @@ bool SetSourceFPS(CS_Source source, int fps, CS_Status* status) {
|
||||
return data->source->SetFPS(fps, status);
|
||||
}
|
||||
|
||||
bool SetSourceConfigJson(CS_Source source, wpi::StringRef config,
|
||||
bool SetSourceConfigJson(CS_Source source, std::string_view config,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data) {
|
||||
@@ -531,17 +532,17 @@ std::string GetSinkName(CS_Sink sink, CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return std::string{};
|
||||
return {};
|
||||
}
|
||||
return data->sink->GetName();
|
||||
return std::string{data->sink->GetName()};
|
||||
}
|
||||
|
||||
wpi::StringRef GetSinkName(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
std::string_view GetSinkName(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return wpi::StringRef{};
|
||||
return {};
|
||||
}
|
||||
return data->sink->GetName();
|
||||
}
|
||||
@@ -550,23 +551,24 @@ std::string GetSinkDescription(CS_Sink sink, CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return std::string{};
|
||||
return {};
|
||||
}
|
||||
wpi::SmallString<128> buf;
|
||||
return data->sink->GetDescription(buf);
|
||||
return std::string{data->sink->GetDescription(buf)};
|
||||
}
|
||||
|
||||
wpi::StringRef GetSinkDescription(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
std::string_view GetSinkDescription(CS_Sink sink,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return wpi::StringRef{};
|
||||
return {};
|
||||
}
|
||||
return data->sink->GetDescription(buf);
|
||||
}
|
||||
|
||||
CS_Property GetSinkProperty(CS_Sink sink, const wpi::Twine& name,
|
||||
CS_Property GetSinkProperty(CS_Sink sink, std::string_view name,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data) {
|
||||
@@ -596,7 +598,8 @@ wpi::ArrayRef<CS_Property> EnumerateSinkProperties(
|
||||
return vec;
|
||||
}
|
||||
|
||||
bool SetSinkConfigJson(CS_Sink sink, wpi::StringRef config, CS_Status* status) {
|
||||
bool SetSinkConfigJson(CS_Sink sink, std::string_view config,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
@@ -663,7 +666,7 @@ CS_Source GetSinkSource(CS_Sink sink, CS_Status* status) {
|
||||
return data->sourceHandle.load();
|
||||
}
|
||||
|
||||
CS_Property GetSinkSourceProperty(CS_Sink sink, const wpi::Twine& name,
|
||||
CS_Property GetSinkSourceProperty(CS_Sink sink, std::string_view name,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSink(sink);
|
||||
if (!data) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "cscore_oo.h"
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <wpi/json.h>
|
||||
|
||||
using namespace cs;
|
||||
@@ -82,3 +83,7 @@ std::vector<VideoSink> VideoSink::EnumerateSinks() {
|
||||
}
|
||||
return sinks;
|
||||
}
|
||||
|
||||
std::string AxisCamera::HostToUrl(std::string_view host) {
|
||||
return fmt::format("http://{}/mjpg/video.mjpg", host);
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
#include <exception>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/jni_util.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
#include "cscore_cpp.h"
|
||||
#include "cscore_cv.h"
|
||||
@@ -197,7 +197,8 @@ static void ReportError(JNIEnv* env, CS_Status status) {
|
||||
if (status == CS_OK) {
|
||||
return;
|
||||
}
|
||||
wpi::SmallString<64> msg;
|
||||
std::string_view msg;
|
||||
std::string msgBuf;
|
||||
switch (status) {
|
||||
case CS_PROPERTY_WRITE_FAILED:
|
||||
msg = "property write failed";
|
||||
@@ -230,8 +231,8 @@ static void ReportError(JNIEnv* env, CS_Status status) {
|
||||
msg = "telemetry not enabled";
|
||||
break;
|
||||
default: {
|
||||
wpi::raw_svector_ostream oss{msg};
|
||||
oss << "unknown error code=" << status;
|
||||
msgBuf = fmt::format("unknown error code={}", status);
|
||||
msg = msgBuf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -577,7 +578,7 @@ Java_edu_wpi_first_cscore_CameraServerJNI_createHttpCameraMulti
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
vec.push_back(JStringRef{env, elem}.str());
|
||||
vec.emplace_back(JStringRef{env, elem}.str());
|
||||
}
|
||||
CS_Status status = 0;
|
||||
auto val =
|
||||
@@ -1172,7 +1173,7 @@ Java_edu_wpi_first_cscore_CameraServerJNI_setHttpCameraUrls
|
||||
// TODO
|
||||
return;
|
||||
}
|
||||
vec.push_back(JStringRef{env, elem}.str());
|
||||
vec.emplace_back(JStringRef{env, elem}.str());
|
||||
}
|
||||
CS_Status status = 0;
|
||||
cs::SetHttpCameraUrls(source, vec, &status);
|
||||
@@ -1353,7 +1354,7 @@ Java_edu_wpi_first_cscore_CameraServerJNI_setSourceEnumPropertyChoices
|
||||
// TODO
|
||||
return;
|
||||
}
|
||||
vec.push_back(JStringRef{env, elem}.str());
|
||||
vec.emplace_back(JStringRef{env, elem}.str());
|
||||
}
|
||||
CS_Status status = 0;
|
||||
cs::SetSourceEnumPropertyChoices(source, property, vec, &status);
|
||||
|
||||
@@ -9,12 +9,11 @@
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/ArrayRef.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
#include "cscore_c.h"
|
||||
|
||||
@@ -122,8 +121,8 @@ struct RawEvent {
|
||||
|
||||
RawEvent() = default;
|
||||
explicit RawEvent(RawEvent::Kind kind_) : kind{kind_} {}
|
||||
RawEvent(const wpi::Twine& name_, CS_Handle handle_, RawEvent::Kind kind_)
|
||||
: kind{kind_}, name{name_.str()} {
|
||||
RawEvent(std::string_view name_, CS_Handle handle_, RawEvent::Kind kind_)
|
||||
: kind{kind_}, name{name_} {
|
||||
if (kind_ == kSinkCreated || kind_ == kSinkDestroyed ||
|
||||
kind_ == kSinkEnabled || kind_ == kSinkDisabled) {
|
||||
sinkHandle = handle_;
|
||||
@@ -131,21 +130,21 @@ struct RawEvent {
|
||||
sourceHandle = handle_;
|
||||
}
|
||||
}
|
||||
RawEvent(const wpi::Twine& name_, CS_Source source_, const VideoMode& mode_)
|
||||
RawEvent(std::string_view name_, CS_Source source_, const VideoMode& mode_)
|
||||
: kind{kSourceVideoModeChanged},
|
||||
sourceHandle{source_},
|
||||
name{name_.str()},
|
||||
name{name_},
|
||||
mode{mode_} {}
|
||||
RawEvent(const wpi::Twine& name_, CS_Source source_, RawEvent::Kind kind_,
|
||||
RawEvent(std::string_view name_, CS_Source source_, RawEvent::Kind kind_,
|
||||
CS_Property property_, CS_PropertyKind propertyKind_, int value_,
|
||||
const wpi::Twine& valueStr_)
|
||||
std::string_view valueStr_)
|
||||
: kind{kind_},
|
||||
sourceHandle{source_},
|
||||
name{name_.str()},
|
||||
name{name_},
|
||||
propertyHandle{property_},
|
||||
propertyKind{propertyKind_},
|
||||
value{value_},
|
||||
valueStr{valueStr_.str()} {}
|
||||
valueStr{valueStr_} {}
|
||||
|
||||
Kind kind;
|
||||
|
||||
@@ -175,9 +174,9 @@ struct RawEvent {
|
||||
*/
|
||||
CS_PropertyKind GetPropertyKind(CS_Property property, CS_Status* status);
|
||||
std::string GetPropertyName(CS_Property property, CS_Status* status);
|
||||
wpi::StringRef GetPropertyName(CS_Property property,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
std::string_view GetPropertyName(CS_Property property,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
int GetProperty(CS_Property property, CS_Status* status);
|
||||
void SetProperty(CS_Property property, int value, CS_Status* status);
|
||||
int GetPropertyMin(CS_Property property, CS_Status* status);
|
||||
@@ -185,10 +184,10 @@ int GetPropertyMax(CS_Property property, CS_Status* status);
|
||||
int GetPropertyStep(CS_Property property, CS_Status* status);
|
||||
int GetPropertyDefault(CS_Property property, CS_Status* status);
|
||||
std::string GetStringProperty(CS_Property property, CS_Status* status);
|
||||
wpi::StringRef GetStringProperty(CS_Property property,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
void SetStringProperty(CS_Property property, const wpi::Twine& value,
|
||||
std::string_view GetStringProperty(CS_Property property,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
void SetStringProperty(CS_Property property, std::string_view value,
|
||||
CS_Status* status);
|
||||
std::vector<std::string> GetEnumPropertyChoices(CS_Property property,
|
||||
CS_Status* status);
|
||||
@@ -198,16 +197,15 @@ std::vector<std::string> GetEnumPropertyChoices(CS_Property property,
|
||||
* @defgroup cscore_source_create_func Source Creation Functions
|
||||
* @{
|
||||
*/
|
||||
CS_Source CreateUsbCameraDev(const wpi::Twine& name, int dev,
|
||||
CS_Status* status);
|
||||
CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path,
|
||||
CS_Source CreateUsbCameraDev(std::string_view name, int dev, CS_Status* status);
|
||||
CS_Source CreateUsbCameraPath(std::string_view name, std::string_view path,
|
||||
CS_Status* status);
|
||||
CS_Source CreateHttpCamera(const wpi::Twine& name, const wpi::Twine& url,
|
||||
CS_Source CreateHttpCamera(std::string_view name, std::string_view url,
|
||||
CS_HttpCameraKind kind, CS_Status* status);
|
||||
CS_Source CreateHttpCamera(const wpi::Twine& name,
|
||||
CS_Source CreateHttpCamera(std::string_view name,
|
||||
wpi::ArrayRef<std::string> urls,
|
||||
CS_HttpCameraKind kind, CS_Status* status);
|
||||
CS_Source CreateCvSource(const wpi::Twine& name, const VideoMode& mode,
|
||||
CS_Source CreateCvSource(std::string_view name, const VideoMode& mode,
|
||||
CS_Status* status);
|
||||
/** @} */
|
||||
|
||||
@@ -217,19 +215,20 @@ CS_Source CreateCvSource(const wpi::Twine& name, const VideoMode& mode,
|
||||
*/
|
||||
CS_SourceKind GetSourceKind(CS_Source source, CS_Status* status);
|
||||
std::string GetSourceName(CS_Source source, CS_Status* status);
|
||||
wpi::StringRef GetSourceName(CS_Source source, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
std::string_view GetSourceName(CS_Source source,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
std::string GetSourceDescription(CS_Source source, CS_Status* status);
|
||||
wpi::StringRef GetSourceDescription(CS_Source source,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
std::string_view GetSourceDescription(CS_Source source,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
uint64_t GetSourceLastFrameTime(CS_Source source, CS_Status* status);
|
||||
void SetSourceConnectionStrategy(CS_Source source,
|
||||
CS_ConnectionStrategy strategy,
|
||||
CS_Status* status);
|
||||
bool IsSourceConnected(CS_Source source, CS_Status* status);
|
||||
bool IsSourceEnabled(CS_Source source, CS_Status* status);
|
||||
CS_Property GetSourceProperty(CS_Source source, const wpi::Twine& name,
|
||||
CS_Property GetSourceProperty(CS_Source source, std::string_view name,
|
||||
CS_Status* status);
|
||||
wpi::ArrayRef<CS_Property> EnumerateSourceProperties(
|
||||
CS_Source source, wpi::SmallVectorImpl<CS_Property>& vec,
|
||||
@@ -242,7 +241,7 @@ bool SetSourcePixelFormat(CS_Source source, VideoMode::PixelFormat pixelFormat,
|
||||
bool SetSourceResolution(CS_Source source, int width, int height,
|
||||
CS_Status* status);
|
||||
bool SetSourceFPS(CS_Source source, int fps, CS_Status* status);
|
||||
bool SetSourceConfigJson(CS_Source source, wpi::StringRef config,
|
||||
bool SetSourceConfigJson(CS_Source source, std::string_view config,
|
||||
CS_Status* status);
|
||||
bool SetSourceConfigJson(CS_Source source, const wpi::json& config,
|
||||
CS_Status* status);
|
||||
@@ -276,7 +275,7 @@ void SetCameraExposureManual(CS_Source source, int value, CS_Status* status);
|
||||
* @defgroup cscore_usbcamera_func UsbCamera Source Functions
|
||||
* @{
|
||||
*/
|
||||
void SetUsbCameraPath(CS_Source, const wpi::Twine& path, CS_Status* status);
|
||||
void SetUsbCameraPath(CS_Source, std::string_view path, CS_Status* status);
|
||||
std::string GetUsbCameraPath(CS_Source source, CS_Status* status);
|
||||
UsbCameraInfo GetUsbCameraInfo(CS_Source source, CS_Status* status);
|
||||
/** @} */
|
||||
@@ -295,12 +294,12 @@ std::vector<std::string> GetHttpCameraUrls(CS_Source source, CS_Status* status);
|
||||
* @defgroup cscore_opencv_source_func OpenCV Source Functions
|
||||
* @{
|
||||
*/
|
||||
void NotifySourceError(CS_Source source, const wpi::Twine& msg,
|
||||
void NotifySourceError(CS_Source source, std::string_view msg,
|
||||
CS_Status* status);
|
||||
void SetSourceConnected(CS_Source source, bool connected, CS_Status* status);
|
||||
void SetSourceDescription(CS_Source source, const wpi::Twine& description,
|
||||
void SetSourceDescription(CS_Source source, std::string_view description,
|
||||
CS_Status* status);
|
||||
CS_Property CreateSourceProperty(CS_Source source, const wpi::Twine& name,
|
||||
CS_Property CreateSourceProperty(CS_Source source, std::string_view name,
|
||||
CS_PropertyKind kind, int minimum, int maximum,
|
||||
int step, int defaultValue, int value,
|
||||
CS_Status* status);
|
||||
@@ -313,11 +312,10 @@ void SetSourceEnumPropertyChoices(CS_Source source, CS_Property property,
|
||||
* @defgroup cscore_sink_create_func Sink Creation Functions
|
||||
* @{
|
||||
*/
|
||||
CS_Sink CreateMjpegServer(const wpi::Twine& name,
|
||||
const wpi::Twine& listenAddress, int port,
|
||||
CS_Status* status);
|
||||
CS_Sink CreateCvSink(const wpi::Twine& name, CS_Status* status);
|
||||
CS_Sink CreateCvSinkCallback(const wpi::Twine& name,
|
||||
CS_Sink CreateMjpegServer(std::string_view name, std::string_view listenAddress,
|
||||
int port, CS_Status* status);
|
||||
CS_Sink CreateCvSink(std::string_view name, CS_Status* status);
|
||||
CS_Sink CreateCvSinkCallback(std::string_view name,
|
||||
std::function<void(uint64_t time)> processFrame,
|
||||
CS_Status* status);
|
||||
|
||||
@@ -329,19 +327,21 @@ CS_Sink CreateCvSinkCallback(const wpi::Twine& name,
|
||||
*/
|
||||
CS_SinkKind GetSinkKind(CS_Sink sink, CS_Status* status);
|
||||
std::string GetSinkName(CS_Sink sink, CS_Status* status);
|
||||
wpi::StringRef GetSinkName(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
std::string_view GetSinkName(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
std::string GetSinkDescription(CS_Sink sink, CS_Status* status);
|
||||
wpi::StringRef GetSinkDescription(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
CS_Property GetSinkProperty(CS_Sink sink, const wpi::Twine& name,
|
||||
std::string_view GetSinkDescription(CS_Sink sink,
|
||||
wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
CS_Property GetSinkProperty(CS_Sink sink, std::string_view name,
|
||||
CS_Status* status);
|
||||
wpi::ArrayRef<CS_Property> EnumerateSinkProperties(
|
||||
CS_Sink sink, wpi::SmallVectorImpl<CS_Property>& vec, CS_Status* status);
|
||||
void SetSinkSource(CS_Sink sink, CS_Source source, CS_Status* status);
|
||||
CS_Property GetSinkSourceProperty(CS_Sink sink, const wpi::Twine& name,
|
||||
CS_Property GetSinkSourceProperty(CS_Sink sink, std::string_view name,
|
||||
CS_Status* status);
|
||||
bool SetSinkConfigJson(CS_Sink sink, wpi::StringRef config, CS_Status* status);
|
||||
bool SetSinkConfigJson(CS_Sink sink, std::string_view config,
|
||||
CS_Status* status);
|
||||
bool SetSinkConfigJson(CS_Sink sink, const wpi::json& config,
|
||||
CS_Status* status);
|
||||
std::string GetSinkConfigJson(CS_Sink sink, CS_Status* status);
|
||||
@@ -363,11 +363,11 @@ int GetMjpegServerPort(CS_Sink sink, CS_Status* status);
|
||||
* @defgroup cscore_opencv_sink_func OpenCV Sink Functions
|
||||
* @{
|
||||
*/
|
||||
void SetSinkDescription(CS_Sink sink, const wpi::Twine& description,
|
||||
void SetSinkDescription(CS_Sink sink, std::string_view description,
|
||||
CS_Status* status);
|
||||
std::string GetSinkError(CS_Sink sink, CS_Status* status);
|
||||
wpi::StringRef GetSinkError(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
std::string_view GetSinkError(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
void SetSinkEnabled(CS_Sink sink, bool enabled, CS_Status* status);
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ class CvSource : public ImageSource {
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
CvSource(const wpi::Twine& name, const VideoMode& mode);
|
||||
CvSource(std::string_view name, const VideoMode& mode);
|
||||
|
||||
/**
|
||||
* Create an OpenCV source.
|
||||
@@ -93,8 +93,8 @@ class CvSource : public ImageSource {
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
CvSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
|
||||
int width, int height, int fps);
|
||||
CvSource(std::string_view name, VideoMode::PixelFormat pixelFormat, int width,
|
||||
int height, int fps);
|
||||
|
||||
/**
|
||||
* Put an OpenCV image and notify sinks.
|
||||
@@ -126,7 +126,7 @@ class CvSink : public ImageSink {
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
explicit CvSink(const wpi::Twine& name);
|
||||
explicit CvSink(std::string_view name);
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images in a separate thread.
|
||||
@@ -140,7 +140,7 @@ class CvSink : public ImageSink {
|
||||
* or GetError() as needed, but should not call (except in very
|
||||
* unusual circumstances) WaitForImage().
|
||||
*/
|
||||
CvSink(const wpi::Twine& name,
|
||||
CvSink(std::string_view name,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
|
||||
/**
|
||||
@@ -165,11 +165,11 @@ class CvSink : public ImageSink {
|
||||
uint64_t GrabFrameNoTimeout(cv::Mat& image) const;
|
||||
};
|
||||
|
||||
inline CvSource::CvSource(const wpi::Twine& name, const VideoMode& mode) {
|
||||
inline CvSource::CvSource(std::string_view name, const VideoMode& mode) {
|
||||
m_handle = CreateCvSource(name, mode, &m_status);
|
||||
}
|
||||
|
||||
inline CvSource::CvSource(const wpi::Twine& name, VideoMode::PixelFormat format,
|
||||
inline CvSource::CvSource(std::string_view name, VideoMode::PixelFormat format,
|
||||
int width, int height, int fps) {
|
||||
m_handle =
|
||||
CreateCvSource(name, VideoMode{format, width, height, fps}, &m_status);
|
||||
@@ -180,11 +180,11 @@ inline void CvSource::PutFrame(cv::Mat& image) {
|
||||
PutSourceFrame(m_handle, image, &m_status);
|
||||
}
|
||||
|
||||
inline CvSink::CvSink(const wpi::Twine& name) {
|
||||
inline CvSink::CvSink(std::string_view name) {
|
||||
m_handle = CreateCvSink(name, &m_status);
|
||||
}
|
||||
|
||||
inline CvSink::CvSink(const wpi::Twine& name,
|
||||
inline CvSink::CvSink(std::string_view name,
|
||||
std::function<void(uint64_t time)> processFrame) {
|
||||
m_handle = CreateCvSinkCallback(name, processFrame, &m_status);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <initializer_list>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -71,8 +72,8 @@ class VideoProperty {
|
||||
|
||||
// String-specific functions
|
||||
std::string GetString() const;
|
||||
wpi::StringRef GetString(wpi::SmallVectorImpl<char>& buf) const;
|
||||
void SetString(const wpi::Twine& value);
|
||||
std::string_view GetString(wpi::SmallVectorImpl<char>& buf) const;
|
||||
void SetString(std::string_view value);
|
||||
|
||||
// Enum-specific functions
|
||||
std::vector<std::string> GetChoices() const;
|
||||
@@ -194,7 +195,7 @@ class VideoSource {
|
||||
* @return Property contents (of kind Property::kNone if no property with
|
||||
* the given name exists)
|
||||
*/
|
||||
VideoProperty GetProperty(const wpi::Twine& name);
|
||||
VideoProperty GetProperty(std::string_view name);
|
||||
|
||||
/**
|
||||
* Enumerate all properties of this source.
|
||||
@@ -276,7 +277,7 @@ class VideoSource {
|
||||
* @param config configuration
|
||||
* @return True if set successfully
|
||||
*/
|
||||
bool SetConfigJson(wpi::StringRef config);
|
||||
bool SetConfigJson(std::string_view config);
|
||||
|
||||
/**
|
||||
* Set video mode and properties from a JSON configuration object.
|
||||
@@ -424,7 +425,7 @@ class UsbCamera : public VideoCamera {
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param dev Device number (e.g. 0 for /dev/video0)
|
||||
*/
|
||||
UsbCamera(const wpi::Twine& name, int dev);
|
||||
UsbCamera(std::string_view name, int dev);
|
||||
|
||||
/**
|
||||
* Create a source for a USB camera based on device path.
|
||||
@@ -432,7 +433,7 @@ class UsbCamera : public VideoCamera {
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param path Path to device (e.g. "/dev/video0" on Linux)
|
||||
*/
|
||||
UsbCamera(const wpi::Twine& name, const wpi::Twine& path);
|
||||
UsbCamera(std::string_view name, std::string_view path);
|
||||
|
||||
/**
|
||||
* Enumerate USB cameras on the local system.
|
||||
@@ -444,7 +445,7 @@ class UsbCamera : public VideoCamera {
|
||||
/**
|
||||
* Change the path to the device.
|
||||
*/
|
||||
void SetPath(const wpi::Twine& path);
|
||||
void SetPath(std::string_view path);
|
||||
|
||||
/**
|
||||
* Get the path to the device.
|
||||
@@ -483,7 +484,7 @@ class HttpCamera : public VideoCamera {
|
||||
* @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg")
|
||||
* @param kind Camera kind (e.g. kAxis)
|
||||
*/
|
||||
HttpCamera(const wpi::Twine& name, const wpi::Twine& url,
|
||||
HttpCamera(std::string_view name, std::string_view url,
|
||||
HttpCameraKind kind = kUnknown);
|
||||
|
||||
/**
|
||||
@@ -493,7 +494,7 @@ class HttpCamera : public VideoCamera {
|
||||
* @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg")
|
||||
* @param kind Camera kind (e.g. kAxis)
|
||||
*/
|
||||
HttpCamera(const wpi::Twine& name, const char* url,
|
||||
HttpCamera(std::string_view name, const char* url,
|
||||
HttpCameraKind kind = kUnknown);
|
||||
|
||||
/**
|
||||
@@ -503,7 +504,7 @@ class HttpCamera : public VideoCamera {
|
||||
* @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg")
|
||||
* @param kind Camera kind (e.g. kAxis)
|
||||
*/
|
||||
HttpCamera(const wpi::Twine& name, const std::string& url,
|
||||
HttpCamera(std::string_view name, const std::string& url,
|
||||
HttpCameraKind kind = kUnknown);
|
||||
|
||||
/**
|
||||
@@ -513,7 +514,7 @@ class HttpCamera : public VideoCamera {
|
||||
* @param urls Array of Camera URLs
|
||||
* @param kind Camera kind (e.g. kAxis)
|
||||
*/
|
||||
HttpCamera(const wpi::Twine& name, wpi::ArrayRef<std::string> urls,
|
||||
HttpCamera(std::string_view name, wpi::ArrayRef<std::string> urls,
|
||||
HttpCameraKind kind = kUnknown);
|
||||
|
||||
/**
|
||||
@@ -524,7 +525,7 @@ class HttpCamera : public VideoCamera {
|
||||
* @param kind Camera kind (e.g. kAxis)
|
||||
*/
|
||||
template <typename T>
|
||||
HttpCamera(const wpi::Twine& name, std::initializer_list<T> urls,
|
||||
HttpCamera(std::string_view name, std::initializer_list<T> urls,
|
||||
HttpCameraKind kind = kUnknown);
|
||||
|
||||
/**
|
||||
@@ -556,7 +557,7 @@ class HttpCamera : public VideoCamera {
|
||||
* A source that represents an Axis IP camera.
|
||||
*/
|
||||
class AxisCamera : public HttpCamera {
|
||||
static std::string HostToUrl(const wpi::Twine& host);
|
||||
static std::string HostToUrl(std::string_view host);
|
||||
static std::vector<std::string> HostToUrl(wpi::ArrayRef<std::string> hosts);
|
||||
template <typename T>
|
||||
static std::vector<std::string> HostToUrl(std::initializer_list<T> hosts);
|
||||
@@ -569,7 +570,7 @@ class AxisCamera : public HttpCamera {
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
* @param kind Camera kind (e.g. kAxis)
|
||||
*/
|
||||
AxisCamera(const wpi::Twine& name, const wpi::Twine& host);
|
||||
AxisCamera(std::string_view name, std::string_view host);
|
||||
|
||||
/**
|
||||
* Create a source for an Axis IP camera.
|
||||
@@ -578,7 +579,7 @@ class AxisCamera : public HttpCamera {
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
* @param kind Camera kind (e.g. kAxis)
|
||||
*/
|
||||
AxisCamera(const wpi::Twine& name, const char* host);
|
||||
AxisCamera(std::string_view name, const char* host);
|
||||
|
||||
/**
|
||||
* Create a source for an Axis IP camera.
|
||||
@@ -587,16 +588,7 @@ class AxisCamera : public HttpCamera {
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
* @param kind Camera kind (e.g. kAxis)
|
||||
*/
|
||||
AxisCamera(const wpi::Twine& name, const std::string& host);
|
||||
|
||||
/**
|
||||
* Create a source for an Axis IP camera.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
* @param kind Camera kind (e.g. kAxis)
|
||||
*/
|
||||
AxisCamera(const wpi::Twine& name, wpi::StringRef host);
|
||||
AxisCamera(std::string_view name, const std::string& host);
|
||||
|
||||
/**
|
||||
* Create a source for an Axis IP camera.
|
||||
@@ -605,7 +597,7 @@ class AxisCamera : public HttpCamera {
|
||||
* @param hosts Array of Camera host IPs/DNS names
|
||||
* @param kind Camera kind (e.g. kAxis)
|
||||
*/
|
||||
AxisCamera(const wpi::Twine& name, wpi::ArrayRef<std::string> hosts);
|
||||
AxisCamera(std::string_view name, wpi::ArrayRef<std::string> hosts);
|
||||
|
||||
/**
|
||||
* Create a source for an Axis IP camera.
|
||||
@@ -615,7 +607,7 @@ class AxisCamera : public HttpCamera {
|
||||
* @param kind Camera kind (e.g. kAxis)
|
||||
*/
|
||||
template <typename T>
|
||||
AxisCamera(const wpi::Twine& name, std::initializer_list<T> hosts);
|
||||
AxisCamera(std::string_view name, std::initializer_list<T> hosts);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -630,7 +622,7 @@ class ImageSource : public VideoSource {
|
||||
* Signal sinks that an error has occurred. This should be called instead
|
||||
* of NotifyFrame when an error occurs.
|
||||
*/
|
||||
void NotifyError(const wpi::Twine& msg);
|
||||
void NotifyError(std::string_view msg);
|
||||
|
||||
/**
|
||||
* Set source connection status. Defaults to true.
|
||||
@@ -644,7 +636,7 @@ class ImageSource : public VideoSource {
|
||||
*
|
||||
* @param description Description
|
||||
*/
|
||||
void SetDescription(const wpi::Twine& description);
|
||||
void SetDescription(std::string_view description);
|
||||
|
||||
/**
|
||||
* Create a property.
|
||||
@@ -658,7 +650,7 @@ class ImageSource : public VideoSource {
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
VideoProperty CreateProperty(const wpi::Twine& name, VideoProperty::Kind kind,
|
||||
VideoProperty CreateProperty(std::string_view name, VideoProperty::Kind kind,
|
||||
int minimum, int maximum, int step,
|
||||
int defaultValue, int value);
|
||||
|
||||
@@ -673,7 +665,7 @@ class ImageSource : public VideoSource {
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
VideoProperty CreateIntegerProperty(const wpi::Twine& name, int minimum,
|
||||
VideoProperty CreateIntegerProperty(std::string_view name, int minimum,
|
||||
int maximum, int step, int defaultValue,
|
||||
int value);
|
||||
|
||||
@@ -685,7 +677,7 @@ class ImageSource : public VideoSource {
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
VideoProperty CreateBooleanProperty(const wpi::Twine& name, bool defaultValue,
|
||||
VideoProperty CreateBooleanProperty(std::string_view name, bool defaultValue,
|
||||
bool value);
|
||||
|
||||
/**
|
||||
@@ -696,8 +688,8 @@ class ImageSource : public VideoSource {
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
VideoProperty CreateStringProperty(const wpi::Twine& name,
|
||||
const wpi::Twine& value);
|
||||
VideoProperty CreateStringProperty(std::string_view name,
|
||||
std::string_view value);
|
||||
|
||||
/**
|
||||
* Configure enum property choices.
|
||||
@@ -772,7 +764,7 @@ class VideoSink {
|
||||
* @return Property (kind Property::kNone if no property with
|
||||
* the given name exists)
|
||||
*/
|
||||
VideoProperty GetProperty(const wpi::Twine& name);
|
||||
VideoProperty GetProperty(std::string_view name);
|
||||
|
||||
/**
|
||||
* Enumerate all properties of this sink.
|
||||
@@ -798,7 +790,7 @@ class VideoSink {
|
||||
* @param config configuration
|
||||
* @return True if set successfully
|
||||
*/
|
||||
bool SetConfigJson(wpi::StringRef config);
|
||||
bool SetConfigJson(std::string_view config);
|
||||
|
||||
/**
|
||||
* Set properties from a JSON configuration object.
|
||||
@@ -845,7 +837,7 @@ class VideoSink {
|
||||
* @return Property (kind Property::kNone if no property with
|
||||
* the given name exists or no source connected)
|
||||
*/
|
||||
VideoProperty GetSourceProperty(const wpi::Twine& name);
|
||||
VideoProperty GetSourceProperty(std::string_view name);
|
||||
|
||||
CS_Status GetLastStatus() const { return m_status; }
|
||||
|
||||
@@ -883,8 +875,7 @@ class MjpegServer : public VideoSink {
|
||||
* @param listenAddress TCP listen address (empty string for all addresses)
|
||||
* @param port TCP port number
|
||||
*/
|
||||
MjpegServer(const wpi::Twine& name, const wpi::Twine& listenAddress,
|
||||
int port);
|
||||
MjpegServer(std::string_view name, std::string_view listenAddress, int port);
|
||||
|
||||
/**
|
||||
* Create a MJPEG-over-HTTP server sink.
|
||||
@@ -892,7 +883,7 @@ class MjpegServer : public VideoSink {
|
||||
* @param name Sink name (arbitrary unique identifier)
|
||||
* @param port TCP port number
|
||||
*/
|
||||
MjpegServer(const wpi::Twine& name, int port) : MjpegServer(name, "", port) {}
|
||||
MjpegServer(std::string_view name, int port) : MjpegServer(name, "", port) {}
|
||||
|
||||
/**
|
||||
* Get the listen address of the server.
|
||||
@@ -963,7 +954,7 @@ class ImageSink : public VideoSink {
|
||||
*
|
||||
* @param description Description
|
||||
*/
|
||||
void SetDescription(const wpi::Twine& description);
|
||||
void SetDescription(std::string_view description);
|
||||
|
||||
/**
|
||||
* Get error string. Call this if WaitForFrame() returns 0 to determine
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define CSCORE_CSCORE_OO_INC_
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -53,13 +54,13 @@ inline std::string VideoProperty::GetString() const {
|
||||
return GetStringProperty(m_handle, &m_status);
|
||||
}
|
||||
|
||||
inline wpi::StringRef VideoProperty::GetString(
|
||||
inline std::string_view VideoProperty::GetString(
|
||||
wpi::SmallVectorImpl<char>& buf) const {
|
||||
m_status = 0;
|
||||
return GetStringProperty(m_handle, buf, &m_status);
|
||||
}
|
||||
|
||||
inline void VideoProperty::SetString(const wpi::Twine& value) {
|
||||
inline void VideoProperty::SetString(std::string_view value) {
|
||||
m_status = 0;
|
||||
SetStringProperty(m_handle, value, &m_status);
|
||||
}
|
||||
@@ -139,7 +140,7 @@ inline bool VideoSource::IsEnabled() const {
|
||||
return IsSourceEnabled(m_handle, &m_status);
|
||||
}
|
||||
|
||||
inline VideoProperty VideoSource::GetProperty(const wpi::Twine& name) {
|
||||
inline VideoProperty VideoSource::GetProperty(std::string_view name) {
|
||||
m_status = 0;
|
||||
return VideoProperty{GetSourceProperty(m_handle, name, &m_status)};
|
||||
}
|
||||
@@ -176,7 +177,7 @@ inline bool VideoSource::SetFPS(int fps) {
|
||||
return SetSourceFPS(m_handle, fps, &m_status);
|
||||
}
|
||||
|
||||
inline bool VideoSource::SetConfigJson(wpi::StringRef config) {
|
||||
inline bool VideoSource::SetConfigJson(std::string_view config) {
|
||||
m_status = 0;
|
||||
return SetSourceConfigJson(m_handle, config, &m_status);
|
||||
}
|
||||
@@ -248,11 +249,11 @@ inline void VideoCamera::SetExposureManual(int value) {
|
||||
SetCameraExposureManual(m_handle, value, &m_status);
|
||||
}
|
||||
|
||||
inline UsbCamera::UsbCamera(const wpi::Twine& name, int dev) {
|
||||
inline UsbCamera::UsbCamera(std::string_view name, int dev) {
|
||||
m_handle = CreateUsbCameraDev(name, dev, &m_status);
|
||||
}
|
||||
|
||||
inline UsbCamera::UsbCamera(const wpi::Twine& name, const wpi::Twine& path) {
|
||||
inline UsbCamera::UsbCamera(std::string_view name, std::string_view path) {
|
||||
m_handle = CreateUsbCameraPath(name, path, &m_status);
|
||||
}
|
||||
|
||||
@@ -261,7 +262,7 @@ inline std::vector<UsbCameraInfo> UsbCamera::EnumerateUsbCameras() {
|
||||
return ::cs::EnumerateUsbCameras(&status);
|
||||
}
|
||||
|
||||
inline void UsbCamera::SetPath(const wpi::Twine& path) {
|
||||
inline void UsbCamera::SetPath(std::string_view path) {
|
||||
m_status = 0;
|
||||
return ::cs::SetUsbCameraPath(m_handle, path, &m_status);
|
||||
}
|
||||
@@ -282,25 +283,25 @@ inline void UsbCamera::SetConnectVerbose(int level) {
|
||||
&m_status);
|
||||
}
|
||||
|
||||
inline HttpCamera::HttpCamera(const wpi::Twine& name, const wpi::Twine& url,
|
||||
inline HttpCamera::HttpCamera(std::string_view name, std::string_view url,
|
||||
HttpCameraKind kind) {
|
||||
m_handle = CreateHttpCamera(
|
||||
name, url, static_cast<CS_HttpCameraKind>(static_cast<int>(kind)),
|
||||
&m_status);
|
||||
}
|
||||
|
||||
inline HttpCamera::HttpCamera(const wpi::Twine& name, const char* url,
|
||||
inline HttpCamera::HttpCamera(std::string_view name, const char* url,
|
||||
HttpCameraKind kind) {
|
||||
m_handle = CreateHttpCamera(
|
||||
name, url, static_cast<CS_HttpCameraKind>(static_cast<int>(kind)),
|
||||
&m_status);
|
||||
}
|
||||
|
||||
inline HttpCamera::HttpCamera(const wpi::Twine& name, const std::string& url,
|
||||
inline HttpCamera::HttpCamera(std::string_view name, const std::string& url,
|
||||
HttpCameraKind kind)
|
||||
: HttpCamera(name, wpi::Twine{url}, kind) {}
|
||||
: HttpCamera(name, std::string_view{url}, kind) {}
|
||||
|
||||
inline HttpCamera::HttpCamera(const wpi::Twine& name,
|
||||
inline HttpCamera::HttpCamera(std::string_view name,
|
||||
wpi::ArrayRef<std::string> urls,
|
||||
HttpCameraKind kind) {
|
||||
m_handle = CreateHttpCamera(
|
||||
@@ -309,7 +310,7 @@ inline HttpCamera::HttpCamera(const wpi::Twine& name,
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline HttpCamera::HttpCamera(const wpi::Twine& name,
|
||||
inline HttpCamera::HttpCamera(std::string_view name,
|
||||
std::initializer_list<T> urls,
|
||||
HttpCameraKind kind) {
|
||||
std::vector<std::string> vec;
|
||||
@@ -349,16 +350,12 @@ inline std::vector<std::string> HttpCamera::GetUrls() const {
|
||||
return ::cs::GetHttpCameraUrls(m_handle, &m_status);
|
||||
}
|
||||
|
||||
inline std::string AxisCamera::HostToUrl(const wpi::Twine& host) {
|
||||
return ("http://" + host + "/mjpg/video.mjpg").str();
|
||||
}
|
||||
|
||||
inline std::vector<std::string> AxisCamera::HostToUrl(
|
||||
wpi::ArrayRef<std::string> hosts) {
|
||||
std::vector<std::string> rv;
|
||||
rv.reserve(hosts.size());
|
||||
for (const auto& host : hosts) {
|
||||
rv.emplace_back(HostToUrl(wpi::StringRef{host}));
|
||||
rv.emplace_back(HostToUrl(std::string_view{host}));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -369,33 +366,30 @@ inline std::vector<std::string> AxisCamera::HostToUrl(
|
||||
std::vector<std::string> rv;
|
||||
rv.reserve(hosts.size());
|
||||
for (const auto& host : hosts) {
|
||||
rv.emplace_back(HostToUrl(wpi::StringRef{host}));
|
||||
rv.emplace_back(HostToUrl(std::string_view{host}));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
inline AxisCamera::AxisCamera(const wpi::Twine& name, const wpi::Twine& host)
|
||||
inline AxisCamera::AxisCamera(std::string_view name, std::string_view host)
|
||||
: HttpCamera(name, HostToUrl(host), kAxis) {}
|
||||
|
||||
inline AxisCamera::AxisCamera(const wpi::Twine& name, const char* host)
|
||||
inline AxisCamera::AxisCamera(std::string_view name, const char* host)
|
||||
: HttpCamera(name, HostToUrl(host), kAxis) {}
|
||||
|
||||
inline AxisCamera::AxisCamera(const wpi::Twine& name, const std::string& host)
|
||||
: HttpCamera(name, HostToUrl(wpi::Twine{host}), kAxis) {}
|
||||
inline AxisCamera::AxisCamera(std::string_view name, const std::string& host)
|
||||
: HttpCamera(name, HostToUrl(std::string_view{host}), kAxis) {}
|
||||
|
||||
inline AxisCamera::AxisCamera(const wpi::Twine& name, wpi::StringRef host)
|
||||
: HttpCamera(name, HostToUrl(host), kAxis) {}
|
||||
|
||||
inline AxisCamera::AxisCamera(const wpi::Twine& name,
|
||||
inline AxisCamera::AxisCamera(std::string_view name,
|
||||
wpi::ArrayRef<std::string> hosts)
|
||||
: HttpCamera(name, HostToUrl(hosts), kAxis) {}
|
||||
|
||||
template <typename T>
|
||||
inline AxisCamera::AxisCamera(const wpi::Twine& name,
|
||||
inline AxisCamera::AxisCamera(std::string_view name,
|
||||
std::initializer_list<T> hosts)
|
||||
: HttpCamera(name, HostToUrl(hosts), kAxis) {}
|
||||
|
||||
inline void ImageSource::NotifyError(const wpi::Twine& msg) {
|
||||
inline void ImageSource::NotifyError(std::string_view msg) {
|
||||
m_status = 0;
|
||||
NotifySourceError(m_handle, msg, &m_status);
|
||||
}
|
||||
@@ -405,12 +399,12 @@ inline void ImageSource::SetConnected(bool connected) {
|
||||
SetSourceConnected(m_handle, connected, &m_status);
|
||||
}
|
||||
|
||||
inline void ImageSource::SetDescription(const wpi::Twine& description) {
|
||||
inline void ImageSource::SetDescription(std::string_view description) {
|
||||
m_status = 0;
|
||||
SetSourceDescription(m_handle, description, &m_status);
|
||||
}
|
||||
|
||||
inline VideoProperty ImageSource::CreateProperty(const wpi::Twine& name,
|
||||
inline VideoProperty ImageSource::CreateProperty(std::string_view name,
|
||||
VideoProperty::Kind kind,
|
||||
int minimum, int maximum,
|
||||
int step, int defaultValue,
|
||||
@@ -421,7 +415,7 @@ inline VideoProperty ImageSource::CreateProperty(const wpi::Twine& name,
|
||||
minimum, maximum, step, defaultValue, value, &m_status)};
|
||||
}
|
||||
|
||||
inline VideoProperty ImageSource::CreateIntegerProperty(const wpi::Twine& name,
|
||||
inline VideoProperty ImageSource::CreateIntegerProperty(std::string_view name,
|
||||
int minimum,
|
||||
int maximum, int step,
|
||||
int defaultValue,
|
||||
@@ -434,7 +428,7 @@ inline VideoProperty ImageSource::CreateIntegerProperty(const wpi::Twine& name,
|
||||
minimum, maximum, step, defaultValue, value, &m_status)};
|
||||
}
|
||||
|
||||
inline VideoProperty ImageSource::CreateBooleanProperty(const wpi::Twine& name,
|
||||
inline VideoProperty ImageSource::CreateBooleanProperty(std::string_view name,
|
||||
bool defaultValue,
|
||||
bool value) {
|
||||
m_status = 0;
|
||||
@@ -445,8 +439,8 @@ inline VideoProperty ImageSource::CreateBooleanProperty(const wpi::Twine& name,
|
||||
0, 1, 1, defaultValue ? 1 : 0, value ? 1 : 0, &m_status)};
|
||||
}
|
||||
|
||||
inline VideoProperty ImageSource::CreateStringProperty(
|
||||
const wpi::Twine& name, const wpi::Twine& value) {
|
||||
inline VideoProperty ImageSource::CreateStringProperty(std::string_view name,
|
||||
std::string_view value) {
|
||||
m_status = 0;
|
||||
auto prop = VideoProperty{
|
||||
CreateSourceProperty(m_handle, name,
|
||||
@@ -509,7 +503,7 @@ inline std::string VideoSink::GetDescription() const {
|
||||
return GetSinkDescription(m_handle, &m_status);
|
||||
}
|
||||
|
||||
inline VideoProperty VideoSink::GetProperty(const wpi::Twine& name) {
|
||||
inline VideoProperty VideoSink::GetProperty(std::string_view name) {
|
||||
m_status = 0;
|
||||
return VideoProperty{GetSinkProperty(m_handle, name, &m_status)};
|
||||
}
|
||||
@@ -529,12 +523,12 @@ inline VideoSource VideoSink::GetSource() const {
|
||||
return VideoSource{handle == 0 ? 0 : CopySource(handle, &m_status)};
|
||||
}
|
||||
|
||||
inline VideoProperty VideoSink::GetSourceProperty(const wpi::Twine& name) {
|
||||
inline VideoProperty VideoSink::GetSourceProperty(std::string_view name) {
|
||||
m_status = 0;
|
||||
return VideoProperty{GetSinkSourceProperty(m_handle, name, &m_status)};
|
||||
}
|
||||
|
||||
inline bool VideoSink::SetConfigJson(wpi::StringRef config) {
|
||||
inline bool VideoSink::SetConfigJson(std::string_view config) {
|
||||
m_status = 0;
|
||||
return SetSinkConfigJson(m_handle, config, &m_status);
|
||||
}
|
||||
@@ -549,8 +543,8 @@ inline std::string VideoSink::GetConfigJson() const {
|
||||
return GetSinkConfigJson(m_handle, &m_status);
|
||||
}
|
||||
|
||||
inline MjpegServer::MjpegServer(const wpi::Twine& name,
|
||||
const wpi::Twine& listenAddress, int port) {
|
||||
inline MjpegServer::MjpegServer(std::string_view name,
|
||||
std::string_view listenAddress, int port) {
|
||||
m_handle = CreateMjpegServer(name, listenAddress, port, &m_status);
|
||||
}
|
||||
|
||||
@@ -588,7 +582,7 @@ inline void MjpegServer::SetDefaultCompression(int quality) {
|
||||
quality, &m_status);
|
||||
}
|
||||
|
||||
inline void ImageSink::SetDescription(const wpi::Twine& description) {
|
||||
inline void ImageSink::SetDescription(std::string_view description) {
|
||||
m_status = 0;
|
||||
SetSinkDescription(m_handle, description, &m_status);
|
||||
}
|
||||
|
||||
@@ -78,11 +78,11 @@ struct RawFrame : public CS_RawFrame {
|
||||
* @{
|
||||
*/
|
||||
|
||||
CS_Source CreateRawSource(const wpi::Twine& name, const VideoMode& mode,
|
||||
CS_Source CreateRawSource(std::string_view name, const VideoMode& mode,
|
||||
CS_Status* status);
|
||||
|
||||
CS_Sink CreateRawSink(const wpi::Twine& name, CS_Status* status);
|
||||
CS_Sink CreateRawSinkCallback(const wpi::Twine& name,
|
||||
CS_Sink CreateRawSink(std::string_view name, CS_Status* status);
|
||||
CS_Sink CreateRawSinkCallback(std::string_view name,
|
||||
std::function<void(uint64_t time)> processFrame,
|
||||
CS_Status* status);
|
||||
|
||||
@@ -107,7 +107,7 @@ class RawSource : public ImageSource {
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
RawSource(const wpi::Twine& name, const VideoMode& mode);
|
||||
RawSource(std::string_view name, const VideoMode& mode);
|
||||
|
||||
/**
|
||||
* Create a raw frame source.
|
||||
@@ -118,7 +118,7 @@ class RawSource : public ImageSource {
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
RawSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
|
||||
RawSource(std::string_view name, VideoMode::PixelFormat pixelFormat,
|
||||
int width, int height, int fps);
|
||||
|
||||
protected:
|
||||
@@ -147,7 +147,7 @@ class RawSink : public ImageSink {
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
explicit RawSink(const wpi::Twine& name);
|
||||
explicit RawSink(std::string_view name);
|
||||
|
||||
/**
|
||||
* Create a sink for accepting raws images in a separate thread.
|
||||
@@ -161,7 +161,7 @@ class RawSink : public ImageSink {
|
||||
* or GetError() as needed, but should not call (except in very
|
||||
* unusual circumstances) WaitForImage().
|
||||
*/
|
||||
RawSink(const wpi::Twine& name,
|
||||
RawSink(std::string_view name,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
|
||||
protected:
|
||||
@@ -187,11 +187,11 @@ class RawSink : public ImageSink {
|
||||
uint64_t GrabFrameNoTimeout(RawFrame& image) const;
|
||||
};
|
||||
|
||||
inline RawSource::RawSource(const wpi::Twine& name, const VideoMode& mode) {
|
||||
inline RawSource::RawSource(std::string_view name, const VideoMode& mode) {
|
||||
m_handle = CreateRawSource(name, mode, &m_status);
|
||||
}
|
||||
|
||||
inline RawSource::RawSource(const wpi::Twine& name,
|
||||
inline RawSource::RawSource(std::string_view name,
|
||||
VideoMode::PixelFormat format, int width,
|
||||
int height, int fps) {
|
||||
m_handle =
|
||||
@@ -203,11 +203,11 @@ inline void RawSource::PutFrame(RawFrame& image) {
|
||||
PutSourceFrame(m_handle, image, &m_status);
|
||||
}
|
||||
|
||||
inline RawSink::RawSink(const wpi::Twine& name) {
|
||||
inline RawSink::RawSink(std::string_view name) {
|
||||
m_handle = CreateRawSink(name, &m_status);
|
||||
}
|
||||
|
||||
inline RawSink::RawSink(const wpi::Twine& name,
|
||||
inline RawSink::RawSink(std::string_view name,
|
||||
std::function<void(uint64_t time)> processFrame) {
|
||||
m_handle = CreateRawSinkCallback(name, processFrame, &m_status);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ class RawCvSource : public RawSource {
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
RawCvSource(const wpi::Twine& name, const VideoMode& mode);
|
||||
RawCvSource(std::string_view name, const VideoMode& mode);
|
||||
|
||||
/**
|
||||
* Create a Raw OpenCV source.
|
||||
@@ -43,7 +43,7 @@ class RawCvSource : public RawSource {
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
RawCvSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
|
||||
RawCvSource(std::string_view name, VideoMode::PixelFormat pixelFormat,
|
||||
int width, int height, int fps);
|
||||
|
||||
/**
|
||||
@@ -83,7 +83,7 @@ class RawCvSink : public RawSink {
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
explicit RawCvSink(const wpi::Twine& name);
|
||||
explicit RawCvSink(std::string_view name);
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images in a separate thread.
|
||||
@@ -97,7 +97,7 @@ class RawCvSink : public RawSink {
|
||||
* or GetError() as needed, but should not call (except in very
|
||||
* unusual circumstances) WaitForImage().
|
||||
*/
|
||||
RawCvSink(const wpi::Twine& name,
|
||||
RawCvSink(std::string_view name,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
|
||||
/**
|
||||
@@ -146,10 +146,10 @@ class RawCvSink : public RawSink {
|
||||
RawFrame rawFrame;
|
||||
};
|
||||
|
||||
inline RawCvSource::RawCvSource(const wpi::Twine& name, const VideoMode& mode)
|
||||
inline RawCvSource::RawCvSource(std::string_view name, const VideoMode& mode)
|
||||
: RawSource{name, mode} {}
|
||||
|
||||
inline RawCvSource::RawCvSource(const wpi::Twine& name,
|
||||
inline RawCvSource::RawCvSource(std::string_view name,
|
||||
VideoMode::PixelFormat format, int width,
|
||||
int height, int fps)
|
||||
: RawSource{name, format, width, height, fps} {}
|
||||
@@ -164,9 +164,9 @@ inline void RawCvSource::PutFrame(cv::Mat& image) {
|
||||
PutSourceFrame(m_handle, rawFrame, &m_status);
|
||||
}
|
||||
|
||||
inline RawCvSink::RawCvSink(const wpi::Twine& name) : RawSink{name} {}
|
||||
inline RawCvSink::RawCvSink(std::string_view name) : RawSink{name} {}
|
||||
|
||||
inline RawCvSink::RawCvSink(const wpi::Twine& name,
|
||||
inline RawCvSink::RawCvSink(std::string_view name,
|
||||
std::function<void(uint64_t time)> processFrame)
|
||||
: RawSink{name, processFrame} {}
|
||||
|
||||
|
||||
@@ -70,15 +70,15 @@ void NetworkListener::Impl::Thread::Main() {
|
||||
// Create event socket so we can be shut down
|
||||
m_command_fd = ::eventfd(0, 0);
|
||||
if (m_command_fd < 0) {
|
||||
ERROR(
|
||||
"NetworkListener: could not create eventfd: " << std::strerror(errno));
|
||||
ERROR("NetworkListener: could not create eventfd: {}",
|
||||
std::strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create netlink socket
|
||||
int sd = ::socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if (sd < 0) {
|
||||
ERROR("NetworkListener: could not create socket: " << std::strerror(errno));
|
||||
ERROR("NetworkListener: could not create socket: {}", std::strerror(errno));
|
||||
::close(m_command_fd);
|
||||
m_command_fd = -1;
|
||||
return;
|
||||
@@ -90,7 +90,7 @@ void NetworkListener::Impl::Thread::Main() {
|
||||
addr.nl_family = AF_NETLINK;
|
||||
addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
|
||||
if (bind(sd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
|
||||
ERROR("NetworkListener: could not create socket: " << std::strerror(errno));
|
||||
ERROR("NetworkListener: could not create socket: {}", std::strerror(errno));
|
||||
::close(sd);
|
||||
::close(m_command_fd);
|
||||
m_command_fd = -1;
|
||||
@@ -113,7 +113,7 @@ void NetworkListener::Impl::Thread::Main() {
|
||||
int nfds = std::max(m_command_fd, sd) + 1;
|
||||
|
||||
if (::select(nfds, &readfds, nullptr, nullptr, &tv) < 0) {
|
||||
ERROR("NetworkListener: select(): " << std::strerror(errno));
|
||||
ERROR("NetworkListener: select(): {}", std::strerror(errno));
|
||||
break; // XXX: is this the right thing to do here?
|
||||
}
|
||||
|
||||
@@ -134,8 +134,8 @@ void NetworkListener::Impl::Thread::Main() {
|
||||
if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
||||
continue;
|
||||
}
|
||||
ERROR(
|
||||
"NetworkListener: could not read netlink: " << std::strerror(errno));
|
||||
ERROR("NetworkListener: could not read netlink: {}",
|
||||
std::strerror(errno));
|
||||
break; // XXX: is this the right thing to do here?
|
||||
}
|
||||
if (len == 0) {
|
||||
|
||||
@@ -22,8 +22,10 @@
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <wpi/MemAlloc.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/fs.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <wpi/timestamp.h>
|
||||
@@ -95,8 +97,8 @@ static __u32 FromPixelFormat(VideoMode::PixelFormat pixelFormat) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsPercentageProperty(wpi::StringRef name) {
|
||||
if (name.startswith("raw_")) {
|
||||
static bool IsPercentageProperty(std::string_view name) {
|
||||
if (wpi::starts_with(name, "raw_")) {
|
||||
name = name.substr(4);
|
||||
}
|
||||
return name == "brightness" || name == "contrast" || name == "saturation" ||
|
||||
@@ -154,11 +156,8 @@ int UsbCameraImpl::PercentageToRaw(const UsbCameraProperty& rawProp,
|
||||
}
|
||||
|
||||
static bool GetVendorProduct(int dev, int* vendor, int* product) {
|
||||
wpi::SmallString<64> ifpath;
|
||||
{
|
||||
wpi::raw_svector_ostream oss{ifpath};
|
||||
oss << "/sys/class/video4linux/video" << dev << "/device/modalias";
|
||||
}
|
||||
auto ifpath =
|
||||
fmt::format("/sys/class/video4linux/video{}/device/modalias", dev);
|
||||
|
||||
int fd = open(ifpath.c_str(), O_RDONLY);
|
||||
if (fd < 0) {
|
||||
@@ -172,15 +171,17 @@ static bool GetVendorProduct(int dev, int* vendor, int* product) {
|
||||
if (n <= 0) {
|
||||
return false;
|
||||
}
|
||||
wpi::StringRef readStr{readBuf};
|
||||
if (readStr.substr(readStr.find('v'))
|
||||
.substr(1, 4)
|
||||
.getAsInteger(16, *vendor)) {
|
||||
std::string_view readStr{readBuf};
|
||||
if (auto v = wpi::parse_integer<int>(
|
||||
readStr.substr(readStr.find('v')).substr(1, 4), 16)) {
|
||||
*vendor = v.value();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (readStr.substr(readStr.find('p'))
|
||||
.substr(1, 4)
|
||||
.getAsInteger(16, *product)) {
|
||||
if (auto v = wpi::parse_integer<int>(
|
||||
readStr.substr(readStr.find('p')).substr(1, 4), 16)) {
|
||||
*product = v.value();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -188,11 +189,8 @@ static bool GetVendorProduct(int dev, int* vendor, int* product) {
|
||||
}
|
||||
|
||||
static bool GetDescriptionSysV4L(int dev, std::string* desc) {
|
||||
wpi::SmallString<64> ifpath;
|
||||
{
|
||||
wpi::raw_svector_ostream oss{ifpath};
|
||||
oss << "/sys/class/video4linux/video" << dev << "/device/interface";
|
||||
}
|
||||
auto ifpath =
|
||||
fmt::format("/sys/class/video4linux/video{}/device/interface", dev);
|
||||
|
||||
int fd = open(ifpath.c_str(), O_RDONLY);
|
||||
if (fd < 0) {
|
||||
@@ -207,7 +205,7 @@ static bool GetDescriptionSysV4L(int dev, std::string* desc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*desc = wpi::StringRef(readBuf, n).rtrim();
|
||||
*desc = wpi::rtrim(std::string_view(readBuf, n));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -225,17 +223,16 @@ static bool GetDescriptionIoctl(const char* cpath, std::string* desc) {
|
||||
}
|
||||
close(fd);
|
||||
|
||||
wpi::StringRef card{reinterpret_cast<const char*>(vcap.card)};
|
||||
std::string_view card{reinterpret_cast<const char*>(vcap.card)};
|
||||
// try to convert "UVC Camera (0000:0000)" into a better name
|
||||
int vendor = 0;
|
||||
int product = 0;
|
||||
if (card.startswith("UVC Camera (") &&
|
||||
!card.substr(12, 4).getAsInteger(16, vendor) &&
|
||||
!card.substr(17, 4).getAsInteger(16, product)) {
|
||||
wpi::SmallString<64> card2Buf;
|
||||
wpi::StringRef card2 = GetUsbNameFromId(vendor, product, card2Buf);
|
||||
std::optional<int> vendor;
|
||||
std::optional<int> product;
|
||||
if (wpi::starts_with(card, "UVC Camera (") &&
|
||||
(vendor = wpi::parse_integer<int>(card.substr(12, 4), 16)) &&
|
||||
(product = wpi::parse_integer<int>(card.substr(17, 4), 16))) {
|
||||
std::string card2 = GetUsbNameFromId(vendor.value(), product.value());
|
||||
if (!card2.empty()) {
|
||||
*desc = card2;
|
||||
*desc = std::move(card2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -274,15 +271,14 @@ static int GetDeviceNum(const char* cpath) {
|
||||
path = fs::canonical(path);
|
||||
}
|
||||
|
||||
auto fn = path.filename();
|
||||
if (!wpi::StringRef{fn}.startswith("video")) {
|
||||
std::string fn = path.filename();
|
||||
if (!wpi::starts_with(fn, "video")) {
|
||||
return -1;
|
||||
}
|
||||
int dev = -1;
|
||||
if (wpi::StringRef{fn}.substr(5).getAsInteger(10, dev)) {
|
||||
return -1;
|
||||
if (auto dev = wpi::parse_integer<int>(fn.substr(5), 10)) {
|
||||
return dev.value();
|
||||
}
|
||||
return dev;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static std::string GetDescriptionImpl(const char* cpath) {
|
||||
@@ -304,14 +300,14 @@ static std::string GetDescriptionImpl(const char* cpath) {
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
UsbCameraImpl::UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
UsbCameraImpl::UsbCameraImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
const wpi::Twine& path)
|
||||
std::string_view path)
|
||||
: SourceImpl{name, logger, notifier, telemetry},
|
||||
m_fd{-1},
|
||||
m_command_fd{eventfd(0, 0)},
|
||||
m_active{true},
|
||||
m_path{path.str()} {
|
||||
m_path{path} {
|
||||
SetDescription(GetDescriptionImpl(m_path.c_str()));
|
||||
SetQuirks();
|
||||
|
||||
@@ -439,7 +435,7 @@ void UsbCameraImpl::CameraThreadMain() {
|
||||
DoFdSet(notify_fd, &readfds, &nfds);
|
||||
|
||||
if (select(nfds, &readfds, nullptr, nullptr, &tv) < 0) {
|
||||
SERROR("select(): " << std::strerror(errno));
|
||||
SERROR("select(): {}", std::strerror(errno));
|
||||
break; // XXX: is this the right thing to do here?
|
||||
}
|
||||
|
||||
@@ -450,7 +446,7 @@ void UsbCameraImpl::CameraThreadMain() {
|
||||
|
||||
// Handle notify events
|
||||
if (notify_fd >= 0 && FD_ISSET(notify_fd, &readfds)) {
|
||||
SDEBUG4("notify event");
|
||||
SDEBUG4("{}", "notify event");
|
||||
struct inotify_event event;
|
||||
do {
|
||||
// Read the event structure
|
||||
@@ -460,10 +456,9 @@ void UsbCameraImpl::CameraThreadMain() {
|
||||
raw_name.resize(event.len);
|
||||
notify_is->read(raw_name.data(), event.len);
|
||||
// If the name is what we expect...
|
||||
wpi::StringRef name{raw_name.c_str()};
|
||||
SDEBUG4("got event on '" << name << "' (" << name.size()
|
||||
<< ") compare to '" << base << "' ("
|
||||
<< base.size() << ") mask " << event.mask);
|
||||
std::string_view name{raw_name.c_str()};
|
||||
SDEBUG4("got event on '{}' ({}) compare to '{}' ({}) mask {}", name,
|
||||
name.size(), base, base.size(), event.mask);
|
||||
if (name == base) {
|
||||
if ((event.mask & IN_DELETE) != 0) {
|
||||
wasStreaming = m_streaming;
|
||||
@@ -480,7 +475,7 @@ void UsbCameraImpl::CameraThreadMain() {
|
||||
|
||||
// Handle commands
|
||||
if (command_fd >= 0 && FD_ISSET(command_fd, &readfds)) {
|
||||
SDEBUG4("got command");
|
||||
SDEBUG4("{}", "got command");
|
||||
// Read it to clear
|
||||
eventfd_t val;
|
||||
eventfd_read(command_fd, &val);
|
||||
@@ -490,7 +485,7 @@ void UsbCameraImpl::CameraThreadMain() {
|
||||
|
||||
// Handle frames
|
||||
if (m_streaming && fd >= 0 && FD_ISSET(fd, &readfds)) {
|
||||
SDEBUG4("grabbing image");
|
||||
SDEBUG4("{}", "grabbing image");
|
||||
|
||||
// Dequeue buffer
|
||||
struct v4l2_buffer buf;
|
||||
@@ -498,7 +493,7 @@ void UsbCameraImpl::CameraThreadMain() {
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
if (DoIoctl(fd, VIDIOC_DQBUF, &buf) != 0) {
|
||||
SWARNING("could not dequeue buffer");
|
||||
SWARNING("{}", "could not dequeue buffer");
|
||||
wasStreaming = m_streaming;
|
||||
DeviceStreamOff();
|
||||
DeviceDisconnect();
|
||||
@@ -507,14 +502,14 @@ void UsbCameraImpl::CameraThreadMain() {
|
||||
}
|
||||
|
||||
if ((buf.flags & V4L2_BUF_FLAG_ERROR) == 0) {
|
||||
SDEBUG4("got image size=" << buf.bytesused << " index=" << buf.index);
|
||||
SDEBUG4("got image size={} index={}", buf.bytesused, buf.index);
|
||||
|
||||
if (buf.index >= kNumBuffers || !m_buffers[buf.index].m_data) {
|
||||
SWARNING("invalid buffer" << buf.index);
|
||||
SWARNING("invalid buffer {}", buf.index);
|
||||
continue;
|
||||
}
|
||||
|
||||
wpi::StringRef image{
|
||||
std::string_view image{
|
||||
static_cast<const char*>(m_buffers[buf.index].m_data),
|
||||
static_cast<size_t>(buf.bytesused)};
|
||||
int width = m_mode.width;
|
||||
@@ -522,7 +517,7 @@ void UsbCameraImpl::CameraThreadMain() {
|
||||
bool good = true;
|
||||
if (m_mode.pixelFormat == VideoMode::kMJPEG &&
|
||||
!GetJpegSize(image, &width, &height)) {
|
||||
SWARNING("invalid JPEG image received from camera");
|
||||
SWARNING("{}", "invalid JPEG image received from camera");
|
||||
good = false;
|
||||
}
|
||||
if (good) {
|
||||
@@ -533,7 +528,7 @@ void UsbCameraImpl::CameraThreadMain() {
|
||||
|
||||
// Requeue buffer
|
||||
if (DoIoctl(fd, VIDIOC_QBUF, &buf) != 0) {
|
||||
SWARNING("could not requeue buffer");
|
||||
SWARNING("{}", "could not requeue buffer");
|
||||
wasStreaming = m_streaming;
|
||||
DeviceStreamOff();
|
||||
DeviceDisconnect();
|
||||
@@ -572,11 +567,11 @@ void UsbCameraImpl::DeviceConnect() {
|
||||
}
|
||||
|
||||
if (m_connectVerbose) {
|
||||
SINFO("Connecting to USB camera on " << m_path);
|
||||
SINFO("Connecting to USB camera on {}", m_path);
|
||||
}
|
||||
|
||||
// Try to open the device
|
||||
SDEBUG3("opening device");
|
||||
SDEBUG3("{}", "opening device");
|
||||
int fd = open(m_path.c_str(), O_RDWR);
|
||||
if (fd < 0) {
|
||||
return;
|
||||
@@ -584,7 +579,7 @@ void UsbCameraImpl::DeviceConnect() {
|
||||
m_fd = fd;
|
||||
|
||||
// Get capabilities
|
||||
SDEBUG3("getting capabilities");
|
||||
SDEBUG3("{}", "getting capabilities");
|
||||
struct v4l2_capability vcap;
|
||||
std::memset(&vcap, 0, sizeof(vcap));
|
||||
if (DoIoctl(fd, VIDIOC_QUERYCAP, &vcap) >= 0) {
|
||||
@@ -596,18 +591,18 @@ void UsbCameraImpl::DeviceConnect() {
|
||||
|
||||
// Get or restore video mode
|
||||
if (!m_properties_cached) {
|
||||
SDEBUG3("caching properties");
|
||||
SDEBUG3("{}", "caching properties");
|
||||
DeviceCacheProperties();
|
||||
DeviceCacheVideoModes();
|
||||
DeviceCacheMode();
|
||||
m_properties_cached = true;
|
||||
} else {
|
||||
SDEBUG3("restoring video mode");
|
||||
SDEBUG3("{}", "restoring video mode");
|
||||
DeviceSetMode();
|
||||
DeviceSetFPS();
|
||||
|
||||
// Restore settings
|
||||
SDEBUG3("restoring settings");
|
||||
SDEBUG3("{}", "restoring settings");
|
||||
std::unique_lock lock2(m_mutex);
|
||||
for (size_t i = 0; i < m_propertyData.size(); ++i) {
|
||||
const auto prop =
|
||||
@@ -616,27 +611,27 @@ void UsbCameraImpl::DeviceConnect() {
|
||||
continue;
|
||||
}
|
||||
if (!prop->DeviceSet(lock2, m_fd)) {
|
||||
SWARNING("failed to set property " << prop->name);
|
||||
SWARNING("failed to set property {}", prop->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Request buffers
|
||||
SDEBUG3("allocating buffers");
|
||||
SDEBUG3("{}", "allocating buffers");
|
||||
struct v4l2_requestbuffers rb;
|
||||
std::memset(&rb, 0, sizeof(rb));
|
||||
rb.count = kNumBuffers;
|
||||
rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
rb.memory = V4L2_MEMORY_MMAP;
|
||||
if (DoIoctl(fd, VIDIOC_REQBUFS, &rb) != 0) {
|
||||
SWARNING("could not allocate buffers");
|
||||
SWARNING("{}", "could not allocate buffers");
|
||||
close(fd);
|
||||
m_fd = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Map buffers
|
||||
SDEBUG3("mapping buffers");
|
||||
SDEBUG3("{}", "mapping buffers");
|
||||
for (int i = 0; i < kNumBuffers; ++i) {
|
||||
struct v4l2_buffer buf;
|
||||
std::memset(&buf, 0, sizeof(buf));
|
||||
@@ -644,17 +639,16 @@ void UsbCameraImpl::DeviceConnect() {
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
if (DoIoctl(fd, VIDIOC_QUERYBUF, &buf) != 0) {
|
||||
SWARNING("could not query buffer " << i);
|
||||
SWARNING("could not query buffer {}", i);
|
||||
close(fd);
|
||||
m_fd = -1;
|
||||
return;
|
||||
}
|
||||
SDEBUG4("buf " << i << " length=" << buf.length
|
||||
<< " offset=" << buf.m.offset);
|
||||
SDEBUG4("buf {} length={} offset={}", i, buf.length, buf.m.offset);
|
||||
|
||||
m_buffers[i] = UsbCameraBuffer(fd, buf.length, buf.m.offset);
|
||||
if (!m_buffers[i].m_data) {
|
||||
SWARNING("could not map buffer " << i);
|
||||
SWARNING("could not map buffer {}", i);
|
||||
// release other buffers
|
||||
for (int j = 0; j < i; ++j) {
|
||||
m_buffers[j] = UsbCameraBuffer{};
|
||||
@@ -664,7 +658,7 @@ void UsbCameraImpl::DeviceConnect() {
|
||||
return;
|
||||
}
|
||||
|
||||
SDEBUG4("buf " << i << " address=" << m_buffers[i].m_data);
|
||||
SDEBUG4("buf {} address={}", i, m_buffers[i].m_data);
|
||||
}
|
||||
|
||||
// Update description (as it may have changed)
|
||||
@@ -687,7 +681,7 @@ bool UsbCameraImpl::DeviceStreamOn() {
|
||||
}
|
||||
|
||||
// Queue buffers
|
||||
SDEBUG3("queuing buffers");
|
||||
SDEBUG3("{}", "queuing buffers");
|
||||
for (int i = 0; i < kNumBuffers; ++i) {
|
||||
struct v4l2_buffer buf;
|
||||
std::memset(&buf, 0, sizeof(buf));
|
||||
@@ -695,7 +689,7 @@ bool UsbCameraImpl::DeviceStreamOn() {
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
if (DoIoctl(fd, VIDIOC_QBUF, &buf) != 0) {
|
||||
SWARNING("could not queue buffer " << i);
|
||||
SWARNING("could not queue buffer {}", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -706,16 +700,17 @@ bool UsbCameraImpl::DeviceStreamOn() {
|
||||
if (errno == ENOSPC) {
|
||||
// indicates too much USB bandwidth requested
|
||||
SERROR(
|
||||
"{}",
|
||||
"could not start streaming due to USB bandwidth limitations; try a "
|
||||
"lower resolution or a different pixel format (VIDIOC_STREAMON: "
|
||||
"No space left on device)");
|
||||
} else {
|
||||
// some other error
|
||||
SERROR("ioctl VIDIOC_STREAMON failed: " << std::strerror(errno));
|
||||
SERROR("ioctl VIDIOC_STREAMON failed: {}", std::strerror(errno));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
SDEBUG4("enabled streaming");
|
||||
SDEBUG4("{}", "enabled streaming");
|
||||
m_streaming = true;
|
||||
return true;
|
||||
}
|
||||
@@ -732,7 +727,7 @@ bool UsbCameraImpl::DeviceStreamOff() {
|
||||
if (DoIoctl(fd, VIDIOC_STREAMOFF, &type) != 0) {
|
||||
return false;
|
||||
}
|
||||
SDEBUG4("disabled streaming");
|
||||
SDEBUG4("{}", "disabled streaming");
|
||||
m_streaming = false;
|
||||
return true;
|
||||
}
|
||||
@@ -806,7 +801,7 @@ CS_StatusValue UsbCameraImpl::DeviceCmdSetProperty(
|
||||
bool setString = (msg.kind == Message::kCmdSetPropertyStr);
|
||||
int property = msg.data[0];
|
||||
int value = msg.data[1];
|
||||
wpi::StringRef valueStr = msg.dataStr;
|
||||
std::string_view valueStr = msg.dataStr;
|
||||
|
||||
// Look up
|
||||
auto prop = static_cast<UsbCameraProperty*>(GetProperty(property));
|
||||
@@ -940,19 +935,19 @@ void UsbCameraImpl::DeviceSetMode() {
|
||||
vfmt.fmt.pix.pixelformat =
|
||||
FromPixelFormat(static_cast<VideoMode::PixelFormat>(m_mode.pixelFormat));
|
||||
if (vfmt.fmt.pix.pixelformat == 0) {
|
||||
SWARNING("could not set format " << m_mode.pixelFormat
|
||||
<< ", defaulting to MJPEG");
|
||||
SWARNING("could not set format {}, defaulting to MJPEG",
|
||||
m_mode.pixelFormat);
|
||||
vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
|
||||
}
|
||||
vfmt.fmt.pix.width = m_mode.width;
|
||||
vfmt.fmt.pix.height = m_mode.height;
|
||||
vfmt.fmt.pix.field = V4L2_FIELD_ANY;
|
||||
if (DoIoctl(fd, VIDIOC_S_FMT, &vfmt) != 0) {
|
||||
SWARNING("could not set format " << m_mode.pixelFormat << " res "
|
||||
<< m_mode.width << "x" << m_mode.height);
|
||||
SWARNING("could not set format {} res {}x{}", m_mode.pixelFormat,
|
||||
m_mode.width, m_mode.height);
|
||||
} else {
|
||||
SINFO("set format " << m_mode.pixelFormat << " res " << m_mode.width << "x"
|
||||
<< m_mode.height);
|
||||
SINFO("set format {} res {}x{}", m_mode.pixelFormat, m_mode.width,
|
||||
m_mode.height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -975,9 +970,9 @@ void UsbCameraImpl::DeviceSetFPS() {
|
||||
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
parm.parm.capture.timeperframe = FPSToFract(m_mode.fps);
|
||||
if (DoIoctl(fd, VIDIOC_S_PARM, &parm) != 0) {
|
||||
SWARNING("could not set FPS to " << m_mode.fps);
|
||||
SWARNING("could not set FPS to {}", m_mode.fps);
|
||||
} else {
|
||||
SINFO("set FPS to " << m_mode.fps);
|
||||
SINFO("set FPS to {}", m_mode.fps);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -997,7 +992,7 @@ void UsbCameraImpl::DeviceCacheMode() {
|
||||
#endif
|
||||
vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if (DoIoctl(fd, VIDIOC_G_FMT, &vfmt) != 0) {
|
||||
SERROR("could not read current video mode");
|
||||
SERROR("{}", "could not read current video mode");
|
||||
std::scoped_lock lock(m_mutex);
|
||||
m_mode = VideoMode{VideoMode::kMJPEG, 320, 240, 30};
|
||||
return;
|
||||
@@ -1133,7 +1128,7 @@ void UsbCameraImpl::DeviceCacheProperty(
|
||||
} else {
|
||||
// Read current raw value and set percentage from it
|
||||
if (!rawProp->DeviceGet(lock, m_fd)) {
|
||||
SWARNING("failed to get property " << rawProp->name);
|
||||
SWARNING("failed to get property {}", rawProp->name);
|
||||
}
|
||||
|
||||
if (perProp) {
|
||||
@@ -1145,7 +1140,7 @@ void UsbCameraImpl::DeviceCacheProperty(
|
||||
// Set value on device if user-configured
|
||||
if (rawProp->valueSet) {
|
||||
if (!rawProp->DeviceSet(lock, m_fd)) {
|
||||
SWARNING("failed to set property " << rawProp->name);
|
||||
SWARNING("failed to set property {}", rawProp->name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1360,7 +1355,7 @@ void UsbCameraImpl::Send(Message&& msg) const {
|
||||
}
|
||||
|
||||
std::unique_ptr<PropertyImpl> UsbCameraImpl::CreateEmptyProperty(
|
||||
const wpi::Twine& name) const {
|
||||
std::string_view name) const {
|
||||
return std::make_unique<UsbCameraProperty>(name);
|
||||
}
|
||||
|
||||
@@ -1379,10 +1374,10 @@ bool UsbCameraImpl::CacheProperties(CS_Status* status) const {
|
||||
|
||||
void UsbCameraImpl::SetQuirks() {
|
||||
wpi::SmallString<128> descbuf;
|
||||
wpi::StringRef desc = GetDescription(descbuf);
|
||||
m_lifecam_exposure =
|
||||
desc.endswith("LifeCam HD-3000") || desc.endswith("LifeCam Cinema (TM)");
|
||||
m_picamera = desc.startswith("mmal service");
|
||||
std::string_view desc = GetDescription(descbuf);
|
||||
m_lifecam_exposure = wpi::ends_with(desc, "LifeCam HD-3000") ||
|
||||
wpi::ends_with(desc, "LifeCam Cinema (TM)");
|
||||
m_picamera = wpi::ends_with(desc, "mmal service");
|
||||
|
||||
int deviceNum = GetDeviceNum(m_path.c_str());
|
||||
if (deviceNum >= 0) {
|
||||
@@ -1400,11 +1395,11 @@ void UsbCameraImpl::SetProperty(int property, int value, CS_Status* status) {
|
||||
*status = SendAndWait(std::move(msg));
|
||||
}
|
||||
|
||||
void UsbCameraImpl::SetStringProperty(int property, const wpi::Twine& value,
|
||||
void UsbCameraImpl::SetStringProperty(int property, std::string_view value,
|
||||
CS_Status* status) {
|
||||
Message msg{Message::kCmdSetPropertyStr};
|
||||
msg.data[0] = property;
|
||||
msg.dataStr = value.str();
|
||||
msg.dataStr = value;
|
||||
*status = SendAndWait(std::move(msg));
|
||||
}
|
||||
|
||||
@@ -1524,9 +1519,9 @@ void UsbCameraImpl::NumSinksEnabledChanged() {
|
||||
Send(Message{Message::kNumSinksEnabledChanged});
|
||||
}
|
||||
|
||||
void UsbCameraImpl::SetPath(const wpi::Twine& path, CS_Status* status) {
|
||||
void UsbCameraImpl::SetPath(std::string_view path, CS_Status* status) {
|
||||
Message msg{Message::kCmdSetPath};
|
||||
msg.dataStr = path.str();
|
||||
msg.dataStr = path;
|
||||
*status = SendAndWait(std::move(msg));
|
||||
}
|
||||
|
||||
@@ -1537,15 +1532,12 @@ std::string UsbCameraImpl::GetPath() const {
|
||||
|
||||
namespace cs {
|
||||
|
||||
CS_Source CreateUsbCameraDev(const wpi::Twine& name, int dev,
|
||||
CS_Source CreateUsbCameraDev(std::string_view name, int dev,
|
||||
CS_Status* status) {
|
||||
wpi::SmallString<32> path;
|
||||
wpi::raw_svector_ostream oss{path};
|
||||
oss << "/dev/video" << dev;
|
||||
return CreateUsbCameraPath(name, oss.str(), status);
|
||||
return CreateUsbCameraPath(name, fmt::format("/dev/video{}", dev), status);
|
||||
}
|
||||
|
||||
CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path,
|
||||
CS_Source CreateUsbCameraPath(std::string_view name, std::string_view path,
|
||||
CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
return inst.CreateSource(CS_SOURCE_USB, std::make_shared<UsbCameraImpl>(
|
||||
@@ -1553,7 +1545,7 @@ CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path,
|
||||
inst.telemetry, path));
|
||||
}
|
||||
|
||||
void SetUsbCameraPath(CS_Source source, const wpi::Twine& path,
|
||||
void SetUsbCameraPath(CS_Source source, std::string_view path,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data || data->kind != CS_SOURCE_USB) {
|
||||
@@ -1629,13 +1621,15 @@ std::vector<UsbCameraInfo> EnumerateUsbCameras(CS_Status* status) {
|
||||
|
||||
if (DIR* dp = ::opendir("/dev")) {
|
||||
while (struct dirent* ep = ::readdir(dp)) {
|
||||
wpi::StringRef fname{ep->d_name};
|
||||
if (!fname.startswith("video")) {
|
||||
std::string_view fname{ep->d_name};
|
||||
if (!wpi::starts_with(fname, "video")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int dev = 0;
|
||||
if (fname.substr(5).getAsInteger(10, dev)) {
|
||||
if (auto v = wpi::parse_integer<unsigned int>(fname.substr(5), 10)) {
|
||||
dev = v.value();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1665,7 +1659,7 @@ std::vector<UsbCameraInfo> EnumerateUsbCameras(CS_Status* status) {
|
||||
::closedir(dp);
|
||||
} else {
|
||||
// *status = ;
|
||||
WPI_ERROR(Instance::GetInstance().logger, "Could not open /dev");
|
||||
WPI_ERROR(Instance::GetInstance().logger, "{}", "Could not open /dev");
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -1682,11 +1676,11 @@ std::vector<UsbCameraInfo> EnumerateUsbCameras(CS_Status* status) {
|
||||
char* target = ::realpath(path.c_str(), nullptr);
|
||||
if (target) {
|
||||
std::string fname = fs::path{target}.filename();
|
||||
unsigned int dev = 0;
|
||||
if (wpi::StringRef{fname}.startswith("video") &&
|
||||
!wpi::StringRef{fname}.substr(5).getAsInteger(10, dev) &&
|
||||
dev < retval.size()) {
|
||||
retval[dev].otherPaths.emplace_back(path.str());
|
||||
std::optional<unsigned int> dev;
|
||||
if (wpi::starts_with(fname, "video") &&
|
||||
(dev = wpi::parse_integer<unsigned int>(fname.substr(5), 10)) &&
|
||||
dev.value() < retval.size()) {
|
||||
retval[dev.value()].otherPaths.emplace_back(path.str());
|
||||
}
|
||||
std::free(target);
|
||||
}
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/condition_variable.h>
|
||||
#include <wpi/mutex.h>
|
||||
#include <wpi/raw_istream.h>
|
||||
@@ -33,15 +33,15 @@ class Telemetry;
|
||||
|
||||
class UsbCameraImpl : public SourceImpl {
|
||||
public:
|
||||
UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry, const wpi::Twine& path);
|
||||
UsbCameraImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry, std::string_view path);
|
||||
~UsbCameraImpl() override;
|
||||
|
||||
void Start() override;
|
||||
|
||||
// Property functions
|
||||
void SetProperty(int property, int value, CS_Status* status) override;
|
||||
void SetStringProperty(int property, const wpi::Twine& value,
|
||||
void SetStringProperty(int property, std::string_view value,
|
||||
CS_Status* status) override;
|
||||
|
||||
// Standard common camera properties
|
||||
@@ -63,7 +63,7 @@ class UsbCameraImpl : public SourceImpl {
|
||||
void NumSinksChanged() override;
|
||||
void NumSinksEnabledChanged() override;
|
||||
|
||||
void SetPath(const wpi::Twine& path, CS_Status* status);
|
||||
void SetPath(std::string_view path, CS_Status* status);
|
||||
std::string GetPath() const;
|
||||
|
||||
// Messages passed to/from camera thread
|
||||
@@ -95,7 +95,7 @@ class UsbCameraImpl : public SourceImpl {
|
||||
|
||||
protected:
|
||||
std::unique_ptr<PropertyImpl> CreateEmptyProperty(
|
||||
const wpi::Twine& name) const override;
|
||||
std::string_view name) const override;
|
||||
|
||||
// Cache properties. Immediately successful if properties are already cached.
|
||||
// If they are not, tries to connect to the camera to do so; returns false and
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "UsbCameraListener.h"
|
||||
|
||||
#include <wpi/EventLoopRunner.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/uv/FsEvent.h>
|
||||
#include <wpi/uv/Timer.h>
|
||||
|
||||
@@ -38,7 +39,7 @@ void UsbCameraListener::Start() {
|
||||
|
||||
auto devEvents = wpi::uv::FsEvent::Create(loop);
|
||||
devEvents->fsEvent.connect([refreshTimer](const char* fn, int flags) {
|
||||
if (wpi::StringRef(fn).startswith("video")) {
|
||||
if (wpi::starts_with(fn, "video")) {
|
||||
refreshTimer->Start(wpi::uv::Timer::Time(200));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
#include "UsbCameraProperty.h"
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
#include "UsbUtil.h"
|
||||
|
||||
@@ -92,15 +92,8 @@ static int GetStringCtrlIoctl(int fd, int id, int maximum, std::string* value) {
|
||||
}
|
||||
|
||||
static int SetStringCtrlIoctl(int fd, int id, int maximum,
|
||||
const wpi::Twine& value) {
|
||||
wpi::SmallString<64> strBuf, strBuf2;
|
||||
wpi::StringRef str = value.toNullTerminatedStringRef(strBuf);
|
||||
if (str.size() > static_cast<size_t>(maximum)) {
|
||||
// don't know if strBuf was used, just recopy
|
||||
strBuf2 = str.take_front(maximum);
|
||||
str = strBuf2;
|
||||
strBuf2.push_back('\0'); // null terminate
|
||||
}
|
||||
std::string_view value) {
|
||||
wpi::SmallString<64> str{value.substr(0, maximum)};
|
||||
|
||||
struct v4l2_ext_control ctrl;
|
||||
struct v4l2_ext_controls ctrls;
|
||||
@@ -108,7 +101,7 @@ static int SetStringCtrlIoctl(int fd, int id, int maximum,
|
||||
std::memset(&ctrls, 0, sizeof(ctrls));
|
||||
ctrl.id = id;
|
||||
ctrl.size = str.size();
|
||||
ctrl.string = const_cast<char*>(str.data());
|
||||
ctrl.string = const_cast<char*>(str.c_str());
|
||||
ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(id);
|
||||
ctrls.count = 1;
|
||||
ctrls.controls = &ctrl;
|
||||
@@ -117,8 +110,8 @@ static int SetStringCtrlIoctl(int fd, int id, int maximum,
|
||||
|
||||
// Removes non-alphanumeric characters and replaces spaces with underscores.
|
||||
// e.g. "Zoom, Absolute" -> "zoom_absolute", "Pan (Absolute)" -> "pan_absolute"
|
||||
static wpi::StringRef NormalizeName(wpi::StringRef name,
|
||||
wpi::SmallVectorImpl<char>& buf) {
|
||||
static std::string_view NormalizeName(std::string_view name,
|
||||
wpi::SmallVectorImpl<char>& buf) {
|
||||
bool newWord = false;
|
||||
for (auto ch : name) {
|
||||
if (std::isalnum(ch)) {
|
||||
@@ -131,13 +124,12 @@ static wpi::StringRef NormalizeName(wpi::StringRef name,
|
||||
newWord = true;
|
||||
}
|
||||
}
|
||||
return wpi::StringRef(buf.data(), buf.size());
|
||||
return {buf.data(), buf.size()};
|
||||
}
|
||||
|
||||
#ifdef VIDIOC_QUERY_EXT_CTRL
|
||||
UsbCameraProperty::UsbCameraProperty(const struct v4l2_query_ext_ctrl& ctrl)
|
||||
: PropertyImpl(wpi::StringRef{}, CS_PROP_NONE, ctrl.step,
|
||||
ctrl.default_value, 0),
|
||||
: PropertyImpl({}, CS_PROP_NONE, ctrl.step, ctrl.default_value, 0),
|
||||
id(ctrl.id & V4L2_CTRL_ID_MASK),
|
||||
type(ctrl.type) {
|
||||
hasMinimum = true;
|
||||
@@ -174,13 +166,12 @@ UsbCameraProperty::UsbCameraProperty(const struct v4l2_query_ext_ctrl& ctrl)
|
||||
++len;
|
||||
}
|
||||
wpi::SmallString<64> name_buf;
|
||||
name = NormalizeName(wpi::StringRef(ctrl.name, len), name_buf);
|
||||
name = NormalizeName({ctrl.name, len}, name_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
UsbCameraProperty::UsbCameraProperty(const struct v4l2_queryctrl& ctrl)
|
||||
: PropertyImpl(wpi::StringRef{}, CS_PROP_NONE, ctrl.step,
|
||||
ctrl.default_value, 0),
|
||||
: PropertyImpl({}, CS_PROP_NONE, ctrl.step, ctrl.default_value, 0),
|
||||
id(ctrl.id & V4L2_CTRL_ID_MASK),
|
||||
type(ctrl.type) {
|
||||
hasMinimum = true;
|
||||
@@ -214,8 +205,8 @@ UsbCameraProperty::UsbCameraProperty(const struct v4l2_queryctrl& ctrl)
|
||||
++len;
|
||||
}
|
||||
wpi::SmallString<64> name_buf;
|
||||
name = NormalizeName(
|
||||
wpi::StringRef(reinterpret_cast<const char*>(ctrl.name), len), name_buf);
|
||||
name =
|
||||
NormalizeName({reinterpret_cast<const char*>(ctrl.name), len}, name_buf);
|
||||
}
|
||||
|
||||
std::unique_ptr<UsbCameraProperty> UsbCameraProperty::DeviceQuery(int fd,
|
||||
@@ -261,8 +252,7 @@ std::unique_ptr<UsbCameraProperty> UsbCameraProperty::DeviceQuery(int fd,
|
||||
continue;
|
||||
}
|
||||
if (prop->intMenu) {
|
||||
wpi::raw_string_ostream os(prop->enumChoices[i]);
|
||||
os << qmenu.value;
|
||||
prop->enumChoices[i] = fmt::to_string(qmenu.value);
|
||||
} else {
|
||||
prop->enumChoices[i] = reinterpret_cast<const char*>(qmenu.name);
|
||||
}
|
||||
@@ -315,12 +305,12 @@ bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
|
||||
int fd) const {
|
||||
// Make a copy of the string as we're about to release the lock
|
||||
wpi::SmallString<128> valueStrCopy{valueStr};
|
||||
return DeviceSet(lock, fd, value, valueStrCopy);
|
||||
return DeviceSet(lock, fd, value, valueStrCopy.str());
|
||||
}
|
||||
|
||||
bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock, int fd,
|
||||
int newValue,
|
||||
const wpi::Twine& newValueStr) const {
|
||||
std::string_view newValueStr) const {
|
||||
if (!device || fd < 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
#include <wpi/mutex.h>
|
||||
|
||||
@@ -19,19 +20,19 @@ namespace cs {
|
||||
class UsbCameraProperty : public PropertyImpl {
|
||||
public:
|
||||
UsbCameraProperty() = default;
|
||||
explicit UsbCameraProperty(const wpi::Twine& name_) : PropertyImpl{name_} {}
|
||||
explicit UsbCameraProperty(std::string_view name_) : PropertyImpl{name_} {}
|
||||
|
||||
// Software property constructor
|
||||
UsbCameraProperty(const wpi::Twine& name_, unsigned id_,
|
||||
CS_PropertyKind kind_, int minimum_, int maximum_,
|
||||
int step_, int defaultValue_, int value_)
|
||||
UsbCameraProperty(std::string_view name_, unsigned id_, CS_PropertyKind kind_,
|
||||
int minimum_, int maximum_, int step_, int defaultValue_,
|
||||
int value_)
|
||||
: PropertyImpl(name_, kind_, minimum_, maximum_, step_, defaultValue_,
|
||||
value_),
|
||||
device{false},
|
||||
id{id_} {}
|
||||
|
||||
// Normalized property constructor
|
||||
UsbCameraProperty(const wpi::Twine& name_, int rawIndex_,
|
||||
UsbCameraProperty(std::string_view name_, int rawIndex_,
|
||||
const UsbCameraProperty& rawProp, int defaultValue_,
|
||||
int value_)
|
||||
: PropertyImpl(name_, rawProp.propKind, 1, defaultValue_, value_),
|
||||
@@ -55,7 +56,7 @@ class UsbCameraProperty : public PropertyImpl {
|
||||
bool DeviceGet(std::unique_lock<wpi::mutex>& lock, int fd);
|
||||
bool DeviceSet(std::unique_lock<wpi::mutex>& lock, int fd) const;
|
||||
bool DeviceSet(std::unique_lock<wpi::mutex>& lock, int fd, int newValue,
|
||||
const wpi::Twine& newValueStr) const;
|
||||
std::string_view newValueStr) const;
|
||||
|
||||
// If this is a device (rather than software) property
|
||||
bool device{true};
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
#include <libgen.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <wpi/Format.h>
|
||||
#include <fmt/format.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/fs.h>
|
||||
#include <wpi/raw_istream.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
@@ -18,21 +20,18 @@
|
||||
|
||||
namespace cs {
|
||||
|
||||
static wpi::StringRef GetUsbNameFromFile(int vendor, int product,
|
||||
wpi::SmallVectorImpl<char>& buf) {
|
||||
static std::string GetUsbNameFromFile(int vendor, int product) {
|
||||
int fd = open("/var/lib/usbutils/usb.ids", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
wpi::raw_svector_ostream os{buf};
|
||||
wpi::SmallString<128> buf;
|
||||
wpi::raw_fd_istream is{fd, true};
|
||||
|
||||
// build vendor and product 4-char hex strings
|
||||
wpi::SmallString<16> vendorStr, productStr;
|
||||
wpi::raw_svector_ostream vendorOs{vendorStr}, productOs{productStr};
|
||||
vendorOs << wpi::format_hex_no_prefix(vendor, 4);
|
||||
productOs << wpi::format_hex_no_prefix(product, 4);
|
||||
auto vendorStr = fmt::format("{:04x}", vendor);
|
||||
auto productStr = fmt::format("{:04x}", product);
|
||||
|
||||
// scan file
|
||||
wpi::SmallString<128> lineBuf;
|
||||
@@ -48,23 +47,24 @@ static wpi::StringRef GetUsbNameFromFile(int vendor, int product,
|
||||
}
|
||||
|
||||
// look for vendor at start of line
|
||||
if (line.startswith(vendorStr)) {
|
||||
if (wpi::starts_with(line, vendorStr)) {
|
||||
foundVendor = true;
|
||||
os << line.substr(5).trim() << ' ';
|
||||
buf += wpi::trim(line.substr(5));
|
||||
buf += ' ';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (foundVendor) {
|
||||
// next vendor, but didn't match product?
|
||||
if (line[0] != '\t') {
|
||||
os << "Unknown";
|
||||
return os.str();
|
||||
buf += "Unknown";
|
||||
return buf;
|
||||
}
|
||||
|
||||
// look for product
|
||||
if (line.substr(1).startswith(productStr)) {
|
||||
os << line.substr(6).trim();
|
||||
return os.str();
|
||||
if (wpi::starts_with(line.substr(1), productStr)) {
|
||||
buf += wpi::trim(line.substr(6));
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,93 +72,90 @@ static wpi::StringRef GetUsbNameFromFile(int vendor, int product,
|
||||
return {};
|
||||
}
|
||||
|
||||
wpi::StringRef GetUsbNameFromId(int vendor, int product,
|
||||
wpi::SmallVectorImpl<char>& buf) {
|
||||
std::string GetUsbNameFromId(int vendor, int product) {
|
||||
// try reading usb.ids
|
||||
wpi::StringRef rv = GetUsbNameFromFile(vendor, product, buf);
|
||||
std::string rv = GetUsbNameFromFile(vendor, product);
|
||||
if (!rv.empty()) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Fall back to internal database
|
||||
wpi::raw_svector_ostream os{buf};
|
||||
switch (vendor) {
|
||||
case 0x046d:
|
||||
os << "Logitech, Inc. ";
|
||||
case 0x046d: {
|
||||
std::string_view productStr;
|
||||
switch (product) {
|
||||
case 0x0802:
|
||||
os << "Webcam C200";
|
||||
productStr = "Webcam C200";
|
||||
break;
|
||||
case 0x0804:
|
||||
os << "Webcam C250";
|
||||
productStr = "Webcam C250";
|
||||
break;
|
||||
case 0x0805:
|
||||
os << "Webcam C300";
|
||||
productStr = "Webcam C300";
|
||||
break;
|
||||
case 0x0807:
|
||||
os << "Webcam B500";
|
||||
productStr = "Webcam B500";
|
||||
break;
|
||||
case 0x0808:
|
||||
os << "Webcam C600";
|
||||
productStr = "Webcam C600";
|
||||
break;
|
||||
case 0x0809:
|
||||
os << "Webcam Pro 9000";
|
||||
productStr = "Webcam Pro 9000";
|
||||
break;
|
||||
case 0x080a:
|
||||
os << "Portable Webcam C905";
|
||||
productStr = "Portable Webcam C905";
|
||||
break;
|
||||
case 0x080f:
|
||||
os << "Webcam C120";
|
||||
productStr = "Webcam C120";
|
||||
break;
|
||||
case 0x0819:
|
||||
os << "Webcam C210";
|
||||
productStr = "Webcam C210";
|
||||
break;
|
||||
case 0x081b:
|
||||
os << "Webcam C310";
|
||||
productStr = "Webcam C310";
|
||||
break;
|
||||
case 0x081d:
|
||||
os << "HD Webcam C510";
|
||||
productStr = "HD Webcam C510";
|
||||
break;
|
||||
case 0x0821:
|
||||
os << "HD Webcam C910";
|
||||
productStr = "HD Webcam C910";
|
||||
break;
|
||||
case 0x0825:
|
||||
os << "Webcam C270";
|
||||
productStr = "Webcam C270";
|
||||
break;
|
||||
case 0x0826:
|
||||
os << "HD Webcam C525";
|
||||
productStr = "HD Webcam C525";
|
||||
break;
|
||||
case 0x0828:
|
||||
os << "HD Webcam B990";
|
||||
productStr = "HD Webcam B990";
|
||||
break;
|
||||
case 0x082b:
|
||||
os << "Webcam C170";
|
||||
productStr = "Webcam C170";
|
||||
break;
|
||||
case 0x082d:
|
||||
os << "HD Pro Webcam C920";
|
||||
productStr = "HD Pro Webcam C920";
|
||||
break;
|
||||
case 0x0836:
|
||||
os << "B525 HD Webcam";
|
||||
productStr = "B525 HD Webcam";
|
||||
break;
|
||||
case 0x0843:
|
||||
os << "Webcam C930e";
|
||||
productStr = "Webcam C930e";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
return fmt::format("Logitech, Inc. {}", productStr);
|
||||
}
|
||||
}
|
||||
|
||||
return os.str();
|
||||
return {};
|
||||
}
|
||||
|
||||
int CheckedIoctl(int fd, unsigned long req, void* data, // NOLINT(runtime/int)
|
||||
const char* name, const char* file, int line, bool quiet) {
|
||||
int retval = ioctl(fd, req, data);
|
||||
if (!quiet && retval < 0) {
|
||||
wpi::SmallString<64> localfile{file};
|
||||
localfile.push_back('\0');
|
||||
WPI_ERROR(Instance::GetInstance().logger,
|
||||
"ioctl " << name << " failed at " << basename(localfile.data())
|
||||
<< ":" << line << ": " << std::strerror(errno));
|
||||
WPI_ERROR(Instance::GetInstance().logger, "ioctl {} failed at {}:{}: {}",
|
||||
name, fs::path{file}.filename().string(), line,
|
||||
std::strerror(errno));
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -5,15 +5,11 @@
|
||||
#ifndef CSCORE_USBUTIL_H_
|
||||
#define CSCORE_USBUTIL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <string>
|
||||
|
||||
namespace cs {
|
||||
|
||||
wpi::StringRef GetUsbNameFromId(int vendor, int product,
|
||||
wpi::SmallVectorImpl<char>& buf);
|
||||
std::string GetUsbNameFromId(int vendor, int product);
|
||||
|
||||
int CheckedIoctl(int fd, unsigned long req, void* data, // NOLINT(runtime/int)
|
||||
const char* name, const char* file, int line, bool quiet);
|
||||
|
||||
@@ -6,19 +6,19 @@
|
||||
|
||||
namespace cs {
|
||||
|
||||
CS_Source CreateUsbCameraDev(const wpi::Twine& name, int dev,
|
||||
CS_Source CreateUsbCameraDev(std::string_view name, int dev,
|
||||
CS_Status* status) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path,
|
||||
CS_Source CreateUsbCameraPath(std::string_view name, std::string_view path,
|
||||
CS_Status* status) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetUsbCameraPath(CS_Source source, const wpi::Twine& path,
|
||||
void SetUsbCameraPath(CS_Source source, std::string_view path,
|
||||
CS_Status* status) {
|
||||
*status = CS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
#include <wpi/MemAlloc.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/timestamp.h>
|
||||
|
||||
#include "COMCreators.h"
|
||||
@@ -69,17 +68,17 @@ using namespace cs;
|
||||
|
||||
namespace cs {
|
||||
|
||||
UsbCameraImpl::UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
UsbCameraImpl::UsbCameraImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
const wpi::Twine& path)
|
||||
: SourceImpl{name, logger, notifier, telemetry}, m_path{path.str()} {
|
||||
std::string_view path)
|
||||
: SourceImpl{name, logger, notifier, telemetry}, m_path{path} {
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
|
||||
m_widePath = utf8_conv.from_bytes(m_path.c_str());
|
||||
m_deviceId = -1;
|
||||
StartMessagePump();
|
||||
}
|
||||
|
||||
UsbCameraImpl::UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger,
|
||||
UsbCameraImpl::UsbCameraImpl(std::string_view name, wpi::Logger& logger,
|
||||
Notifier& notifier, Telemetry& telemetry,
|
||||
int deviceId)
|
||||
: SourceImpl{name, logger, notifier, telemetry}, m_deviceId(deviceId) {
|
||||
@@ -99,11 +98,11 @@ void UsbCameraImpl::SetProperty(int property, int value, CS_Status* status) {
|
||||
SetCameraMessage, msg.kind, &msg);
|
||||
*status = result;
|
||||
}
|
||||
void UsbCameraImpl::SetStringProperty(int property, const wpi::Twine& value,
|
||||
void UsbCameraImpl::SetStringProperty(int property, std::string_view value,
|
||||
CS_Status* status) {
|
||||
Message msg{Message::kCmdSetPropertyStr};
|
||||
msg.data[0] = property;
|
||||
msg.dataStr = value.str();
|
||||
msg.dataStr = value;
|
||||
auto result =
|
||||
m_messagePump->SendWindowMessage<CS_Status, Message::Kind, Message*>(
|
||||
SetCameraMessage, msg.kind, &msg);
|
||||
@@ -197,9 +196,9 @@ void UsbCameraImpl::NumSinksEnabledChanged() {
|
||||
SetCameraMessage, Message::kNumSinksEnabledChanged, nullptr);
|
||||
}
|
||||
|
||||
void UsbCameraImpl::SetPath(const wpi::Twine& path, CS_Status* status) {
|
||||
void UsbCameraImpl::SetPath(std::string_view path, CS_Status* status) {
|
||||
Message msg{Message::kCmdSetPath};
|
||||
msg.dataStr = path.str();
|
||||
msg.dataStr = path;
|
||||
auto result =
|
||||
m_messagePump->SendWindowMessage<CS_Status, Message::Kind, Message*>(
|
||||
SetCameraMessage, msg.kind, &msg);
|
||||
@@ -257,7 +256,7 @@ bool UsbCameraImpl::CheckDeviceChange(WPARAM wParam, DEV_BROADCAST_HDR* pHdr,
|
||||
|
||||
void UsbCameraImpl::DeviceDisconnect() {
|
||||
if (m_connectVerbose)
|
||||
SINFO("Disconnected from " << m_path);
|
||||
SINFO("Disconnected from {}", m_path);
|
||||
m_sourceReader.Reset();
|
||||
m_mediaSource.Reset();
|
||||
if (m_imageCallback) {
|
||||
@@ -268,8 +267,8 @@ void UsbCameraImpl::DeviceDisconnect() {
|
||||
SetConnected(false);
|
||||
}
|
||||
|
||||
static bool IsPercentageProperty(wpi::StringRef name) {
|
||||
if (name.startswith("raw_"))
|
||||
static bool IsPercentageProperty(std::string_view name) {
|
||||
if (wpi::starts_with(name, "raw_"))
|
||||
name = name.substr(4);
|
||||
return name == "Brightness" || name == "Contrast" || name == "Saturation" ||
|
||||
name == "Hue" || name == "Sharpness" || name == "Gain" ||
|
||||
@@ -341,8 +340,7 @@ void UsbCameraImpl::ProcessFrame(IMFSample* videoSample,
|
||||
case cs::VideoMode::PixelFormat::kMJPEG: {
|
||||
// Special case
|
||||
PutFrame(VideoMode::kMJPEG, mode.width, mode.height,
|
||||
wpi::StringRef(reinterpret_cast<char*>(ptr), length),
|
||||
wpi::Now());
|
||||
{reinterpret_cast<char*>(ptr), length}, wpi::Now());
|
||||
doFinalSet = false;
|
||||
break;
|
||||
}
|
||||
@@ -477,9 +475,9 @@ bool UsbCameraImpl::DeviceConnect() {
|
||||
return true;
|
||||
|
||||
if (m_connectVerbose)
|
||||
SINFO("Connecting to USB camera on " << m_path);
|
||||
SINFO("Connecting to USB camera on {}", m_path);
|
||||
|
||||
SDEBUG3("opening device");
|
||||
SDEBUG3("{}", "opening device");
|
||||
|
||||
const wchar_t* path = m_widePath.c_str();
|
||||
m_mediaSource = CreateVideoCaptureDevice(path);
|
||||
@@ -506,13 +504,13 @@ bool UsbCameraImpl::DeviceConnect() {
|
||||
}
|
||||
|
||||
if (!m_properties_cached) {
|
||||
SDEBUG3("caching properties");
|
||||
SDEBUG3("{}", "caching properties");
|
||||
DeviceCacheProperties();
|
||||
DeviceCacheVideoModes();
|
||||
DeviceCacheMode();
|
||||
m_properties_cached = true;
|
||||
} else {
|
||||
SDEBUG3("restoring video mode");
|
||||
SDEBUG3("{}", "restoring video mode");
|
||||
DeviceSetMode();
|
||||
}
|
||||
|
||||
@@ -526,7 +524,7 @@ bool UsbCameraImpl::DeviceConnect() {
|
||||
}
|
||||
|
||||
std::unique_ptr<PropertyImpl> UsbCameraImpl::CreateEmptyProperty(
|
||||
const wpi::Twine& name) const {
|
||||
std::string_view name) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -545,7 +543,7 @@ bool UsbCameraImpl::CacheProperties(CS_Status* status) const {
|
||||
}
|
||||
|
||||
template <typename TagProperty, typename IAM>
|
||||
void UsbCameraImpl::DeviceAddProperty(const wpi::Twine& name_, TagProperty tag,
|
||||
void UsbCameraImpl::DeviceAddProperty(std::string_view name_, TagProperty tag,
|
||||
IAM* pProcAmp) {
|
||||
// First see if properties exist
|
||||
bool isValid = false;
|
||||
@@ -556,11 +554,11 @@ void UsbCameraImpl::DeviceAddProperty(const wpi::Twine& name_, TagProperty tag,
|
||||
}
|
||||
}
|
||||
|
||||
template void UsbCameraImpl::DeviceAddProperty(const wpi::Twine& name_,
|
||||
template void UsbCameraImpl::DeviceAddProperty(std::string_view name_,
|
||||
tagVideoProcAmpProperty tag,
|
||||
IAMVideoProcAmp* pProcAmp);
|
||||
|
||||
template void UsbCameraImpl::DeviceAddProperty(const wpi::Twine& name_,
|
||||
template void UsbCameraImpl::DeviceAddProperty(std::string_view name_,
|
||||
tagCameraControlProperty tag,
|
||||
IAMCameraControl* pProcAmp);
|
||||
|
||||
@@ -669,7 +667,7 @@ void UsbCameraImpl::DeviceCacheProperty(
|
||||
} else {
|
||||
// Read current raw value and set percentage from it
|
||||
if (!rawProp->DeviceGet(lock, pProcAmp))
|
||||
SWARNING("failed to get property " << rawProp->name);
|
||||
SWARNING("failed to get property {}", rawProp->name);
|
||||
|
||||
if (perProp) {
|
||||
perProp->SetValue(RawToPercentage(*rawProp, rawProp->value));
|
||||
@@ -680,7 +678,7 @@ void UsbCameraImpl::DeviceCacheProperty(
|
||||
// Set value on device if user-configured
|
||||
if (rawProp->valueSet) {
|
||||
if (!rawProp->DeviceSet(lock, pProcAmp))
|
||||
SWARNING("failed to set property " << rawProp->name);
|
||||
SWARNING("failed to set property {}", rawProp->name);
|
||||
}
|
||||
|
||||
// Update pointers since we released the lock
|
||||
@@ -764,7 +762,7 @@ CS_StatusValue UsbCameraImpl::DeviceCmdSetProperty(
|
||||
bool setString = (msg.kind == Message::kCmdSetPropertyStr);
|
||||
int property = msg.data[0];
|
||||
int value = msg.data[1];
|
||||
wpi::StringRef valueStr = msg.dataStr;
|
||||
std::string_view valueStr = msg.dataStr;
|
||||
|
||||
// Look up
|
||||
auto prop = static_cast<UsbCameraProperty*>(GetProperty(property));
|
||||
@@ -1022,23 +1020,21 @@ void UsbCameraImpl::DeviceCacheVideoModes() {
|
||||
m_notifier.NotifySource(*this, CS_SOURCE_VIDEOMODES_UPDATED);
|
||||
}
|
||||
|
||||
static void ParseVidAndPid(wpi::StringRef path, int* pid, int* vid) {
|
||||
auto vidIndex = path.find_lower("vid_");
|
||||
auto pidIndex = path.find_lower("pid_");
|
||||
static void ParseVidAndPid(std::string_view path, int* pid, int* vid) {
|
||||
auto vidIndex = wpi::find_lower(path, "vid_");
|
||||
auto pidIndex = wpi::find_lower(path, "pid_");
|
||||
|
||||
if (vidIndex != wpi::StringRef::npos) {
|
||||
auto vidSlice = path.slice(vidIndex + 4, vidIndex + 8);
|
||||
uint16_t val = 0;
|
||||
if (!vidSlice.getAsInteger(16, val)) {
|
||||
*vid = val;
|
||||
if (vidIndex != std::string_view::npos) {
|
||||
auto vidSlice = wpi::slice(path, vidIndex + 4, vidIndex + 8);
|
||||
if (auto v = wpi::parse_integer<uint16_t>(vidSlice, 16)) {
|
||||
*vid = v.value();
|
||||
}
|
||||
}
|
||||
|
||||
if (pidIndex != wpi::StringRef::npos) {
|
||||
auto pidSlice = path.slice(pidIndex + 4, pidIndex + 8);
|
||||
uint16_t val = 0;
|
||||
if (!pidSlice.getAsInteger(16, val)) {
|
||||
*pid = val;
|
||||
if (pidIndex != std::string_view::npos) {
|
||||
auto pidSlice = wpi::slice(path, pidIndex + 4, pidIndex + 8);
|
||||
if (auto v = wpi::parse_integer<uint16_t>(pidSlice, 16)) {
|
||||
*pid = v.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1112,7 +1108,7 @@ done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
CS_Source CreateUsbCameraDev(const wpi::Twine& name, int dev,
|
||||
CS_Source CreateUsbCameraDev(std::string_view name, int dev,
|
||||
CS_Status* status) {
|
||||
// First check if device exists
|
||||
auto devices = cs::EnumerateUsbCameras(status);
|
||||
@@ -1125,7 +1121,7 @@ CS_Source CreateUsbCameraDev(const wpi::Twine& name, int dev,
|
||||
return inst.CreateSource(CS_SOURCE_USB, source);
|
||||
}
|
||||
|
||||
CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path,
|
||||
CS_Source CreateUsbCameraPath(std::string_view name, std::string_view path,
|
||||
CS_Status* status) {
|
||||
auto& inst = Instance::GetInstance();
|
||||
auto source = std::make_shared<UsbCameraImpl>(
|
||||
@@ -1133,7 +1129,7 @@ CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path,
|
||||
return inst.CreateSource(CS_SOURCE_USB, source);
|
||||
}
|
||||
|
||||
void SetUsbCameraPath(CS_Source source, const wpi::Twine& path,
|
||||
void SetUsbCameraPath(CS_Source source, std::string_view path,
|
||||
CS_Status* status) {
|
||||
auto data = Instance::GetInstance().GetSource(source);
|
||||
if (!data || data->kind != CS_SOURCE_USB) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -23,7 +24,6 @@
|
||||
#include <Dbt.h>
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/condition_variable.h>
|
||||
#include <wpi/mutex.h>
|
||||
#include <wpi/raw_istream.h>
|
||||
@@ -40,9 +40,9 @@ namespace cs {
|
||||
class UsbCameraImpl : public SourceImpl,
|
||||
public std::enable_shared_from_this<UsbCameraImpl> {
|
||||
public:
|
||||
UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry, const wpi::Twine& path);
|
||||
UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
|
||||
UsbCameraImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry, std::string_view path);
|
||||
UsbCameraImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
|
||||
Telemetry& telemetry, int deviceId);
|
||||
~UsbCameraImpl() override;
|
||||
|
||||
@@ -50,7 +50,7 @@ class UsbCameraImpl : public SourceImpl,
|
||||
|
||||
// Property functions
|
||||
void SetProperty(int property, int value, CS_Status* status) override;
|
||||
void SetStringProperty(int property, const wpi::Twine& value,
|
||||
void SetStringProperty(int property, std::string_view value,
|
||||
CS_Status* status) override;
|
||||
|
||||
// Standard common camera properties
|
||||
@@ -75,7 +75,7 @@ class UsbCameraImpl : public SourceImpl,
|
||||
void ProcessFrame(IMFSample* sample, const VideoMode& mode);
|
||||
void PostRequestNewFrame();
|
||||
|
||||
void SetPath(const wpi::Twine& path, CS_Status* status);
|
||||
void SetPath(std::string_view path, CS_Status* status);
|
||||
std::string GetPath() const;
|
||||
|
||||
// Messages passed to/from camera thread
|
||||
@@ -107,7 +107,7 @@ class UsbCameraImpl : public SourceImpl,
|
||||
|
||||
protected:
|
||||
std::unique_ptr<PropertyImpl> CreateEmptyProperty(
|
||||
const wpi::Twine& name) const override;
|
||||
std::string_view name) const override;
|
||||
|
||||
// Cache properties. Immediately successful if properties are already cached.
|
||||
// If they are not, tries to connect to the camera to do so; returns false and
|
||||
@@ -132,7 +132,7 @@ class UsbCameraImpl : public SourceImpl,
|
||||
void DeviceCacheProperties();
|
||||
void DeviceCacheVideoModes();
|
||||
template <typename TagProperty, typename IAM>
|
||||
void DeviceAddProperty(const wpi::Twine& name_, TagProperty tag,
|
||||
void DeviceAddProperty(std::string_view name_, TagProperty tag,
|
||||
IAM* pProcAmp);
|
||||
|
||||
ComPtr<IMFMediaType> DeviceCheckModeValid(const VideoMode& toCheck);
|
||||
|
||||
@@ -4,14 +4,16 @@
|
||||
|
||||
#include "UsbCameraProperty.h"
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "ComPtr.h"
|
||||
|
||||
using namespace cs;
|
||||
|
||||
UsbCameraProperty::UsbCameraProperty(const wpi::Twine& name_,
|
||||
UsbCameraProperty::UsbCameraProperty(std::string_view name_,
|
||||
tagVideoProcAmpProperty tag, bool autoProp,
|
||||
IAMVideoProcAmp* pProcAmp, bool* isValid)
|
||||
: PropertyImpl{autoProp ? name_ + "_auto" : name_} {
|
||||
: PropertyImpl{autoProp ? fmt::format("{}_auto", name_) : name_} {
|
||||
this->tagVideoProc = tag;
|
||||
this->isControlProperty = false;
|
||||
this->isAutoProp = autoProp;
|
||||
@@ -71,11 +73,11 @@ bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
|
||||
return false;
|
||||
}
|
||||
|
||||
UsbCameraProperty::UsbCameraProperty(const wpi::Twine& name_,
|
||||
UsbCameraProperty::UsbCameraProperty(std::string_view name_,
|
||||
tagCameraControlProperty tag,
|
||||
bool autoProp, IAMCameraControl* pProcAmp,
|
||||
bool* isValid)
|
||||
: PropertyImpl{autoProp ? name_ + "_auto" : name_} {
|
||||
: PropertyImpl{autoProp ? fmt::format("{}_auto", name_) : name_} {
|
||||
this->tagCameraControl = tag;
|
||||
this->isControlProperty = true;
|
||||
this->isAutoProp = autoProp;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <mfreadwrite.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
#include <Dshow.h>
|
||||
#include <wpi/mutex.h>
|
||||
@@ -21,19 +22,19 @@ namespace cs {
|
||||
class UsbCameraProperty : public PropertyImpl {
|
||||
public:
|
||||
UsbCameraProperty() = default;
|
||||
explicit UsbCameraProperty(const wpi::Twine& name_) : PropertyImpl{name_} {}
|
||||
explicit UsbCameraProperty(std::string_view name_) : PropertyImpl{name_} {}
|
||||
|
||||
// Software property constructor
|
||||
UsbCameraProperty(const wpi::Twine& name_, unsigned id_,
|
||||
CS_PropertyKind kind_, int minimum_, int maximum_,
|
||||
int step_, int defaultValue_, int value_)
|
||||
UsbCameraProperty(std::string_view name_, unsigned id_, CS_PropertyKind kind_,
|
||||
int minimum_, int maximum_, int step_, int defaultValue_,
|
||||
int value_)
|
||||
: PropertyImpl(name_, kind_, minimum_, maximum_, step_, defaultValue_,
|
||||
value_),
|
||||
device{false},
|
||||
id{id_} {}
|
||||
|
||||
// Normalized property constructor
|
||||
UsbCameraProperty(const wpi::Twine& name_, int rawIndex_,
|
||||
UsbCameraProperty(std::string_view name_, int rawIndex_,
|
||||
const UsbCameraProperty& rawProp, int defaultValue_,
|
||||
int value_)
|
||||
: PropertyImpl(name_, rawProp.propKind, 1, defaultValue_, value_),
|
||||
@@ -47,10 +48,10 @@ class UsbCameraProperty : public PropertyImpl {
|
||||
maximum = 100;
|
||||
}
|
||||
|
||||
UsbCameraProperty(const wpi::Twine& name_, tagVideoProcAmpProperty tag,
|
||||
UsbCameraProperty(std::string_view name_, tagVideoProcAmpProperty tag,
|
||||
bool autoProp, IAMVideoProcAmp* pProcAmp, bool* isValid);
|
||||
|
||||
UsbCameraProperty(const wpi::Twine& name_, tagCameraControlProperty tag,
|
||||
UsbCameraProperty(std::string_view name_, tagCameraControlProperty tag,
|
||||
bool autoProp, IAMCameraControl* pProcAmp, bool* isValid);
|
||||
|
||||
bool DeviceGet(std::unique_lock<wpi::mutex>& lock,
|
||||
|
||||
@@ -21,6 +21,7 @@ repoRootNameOverride {
|
||||
includeOtherLibs {
|
||||
^GLFW
|
||||
^cscore
|
||||
^fmt/
|
||||
^frc/
|
||||
^imgui
|
||||
^ntcore
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
#include <memory>
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <fmt/format.h>
|
||||
#include <imgui.h>
|
||||
#include <ntcore_cpp.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpigui.h>
|
||||
|
||||
#include "glass/Context.h"
|
||||
@@ -24,13 +24,13 @@ namespace gui = wpi::gui;
|
||||
const char* GetWPILibVersion();
|
||||
|
||||
namespace glass {
|
||||
wpi::StringRef GetResource_glass_16_png();
|
||||
wpi::StringRef GetResource_glass_32_png();
|
||||
wpi::StringRef GetResource_glass_48_png();
|
||||
wpi::StringRef GetResource_glass_64_png();
|
||||
wpi::StringRef GetResource_glass_128_png();
|
||||
wpi::StringRef GetResource_glass_256_png();
|
||||
wpi::StringRef GetResource_glass_512_png();
|
||||
std::string_view GetResource_glass_16_png();
|
||||
std::string_view GetResource_glass_32_png();
|
||||
std::string_view GetResource_glass_48_png();
|
||||
std::string_view GetResource_glass_64_png();
|
||||
std::string_view GetResource_glass_128_png();
|
||||
std::string_view GetResource_glass_256_png();
|
||||
std::string_view GetResource_glass_512_png();
|
||||
} // namespace glass
|
||||
|
||||
static std::unique_ptr<glass::PlotProvider> gPlotProvider;
|
||||
@@ -56,11 +56,9 @@ static void NtInitialize() {
|
||||
bool timedOut;
|
||||
for (auto&& event : nt::PollConnectionListener(poller, 0, &timedOut)) {
|
||||
if (event.connected) {
|
||||
wpi::SmallString<64> title;
|
||||
title = "Glass - Connected (";
|
||||
title += event.conn.remote_ip;
|
||||
title += ')';
|
||||
glfwSetWindowTitle(win, title.c_str());
|
||||
glfwSetWindowTitle(
|
||||
win, fmt::format("Glass - Connected ({})", event.conn.remote_ip)
|
||||
.c_str());
|
||||
} else {
|
||||
glfwSetWindowTitle(win, "Glass - DISCONNECTED");
|
||||
}
|
||||
@@ -81,9 +79,8 @@ static void NtInitialize() {
|
||||
} else if (msg.level >= NT_LOG_WARNING) {
|
||||
level = "WARNING: ";
|
||||
}
|
||||
gNetworkTablesLog.Append(
|
||||
wpi::Twine{level} + msg.message + wpi::Twine{" ("} + msg.filename +
|
||||
wpi::Twine{':'} + wpi::Twine{msg.line} + wpi::Twine{")\n"});
|
||||
gNetworkTablesLog.Append(fmt::format("{}{} ({}:{})\n", level, msg.message,
|
||||
msg.filename, msg.line));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <imgui_stdlib.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/timestamp.h>
|
||||
#include <wpigui.h>
|
||||
|
||||
@@ -23,64 +23,47 @@ Context* glass::gContext;
|
||||
|
||||
static bool ConvertInt(Storage::Value* value) {
|
||||
value->type = Storage::Value::kInt;
|
||||
if (value->stringVal.empty()) {
|
||||
return false;
|
||||
} else {
|
||||
if (wpi::StringRef{value->stringVal}.getAsInteger(10, value->intVal)) {
|
||||
return false;
|
||||
}
|
||||
if (auto val = wpi::parse_integer<int>(value->stringVal, 10)) {
|
||||
value->intVal = val.value();
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ConvertInt64(Storage::Value* value) {
|
||||
value->type = Storage::Value::kInt64;
|
||||
if (value->stringVal.empty()) {
|
||||
return false;
|
||||
} else {
|
||||
if (wpi::StringRef{value->stringVal}.getAsInteger(10, value->int64Val)) {
|
||||
return false;
|
||||
}
|
||||
if (auto val = wpi::parse_integer<int64_t>(value->stringVal, 10)) {
|
||||
value->int64Val = val.value();
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ConvertBool(Storage::Value* value) {
|
||||
value->type = Storage::Value::kBool;
|
||||
if (value->stringVal.empty()) {
|
||||
return false;
|
||||
} else {
|
||||
int val;
|
||||
if (wpi::StringRef{value->stringVal}.getAsInteger(10, val)) {
|
||||
return false;
|
||||
}
|
||||
value->boolVal = (val != 0);
|
||||
if (auto val = wpi::parse_integer<int>(value->stringVal, 10)) {
|
||||
value->intVal = (val.value() != 0);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ConvertFloat(Storage::Value* value) {
|
||||
value->type = Storage::Value::kFloat;
|
||||
if (value->stringVal.empty()) {
|
||||
return false;
|
||||
} else {
|
||||
if (std::sscanf(value->stringVal.c_str(), "%f", &value->floatVal) != 1) {
|
||||
return false;
|
||||
}
|
||||
if (auto val = wpi::parse_float<float>(value->stringVal)) {
|
||||
value->floatVal = val.value();
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ConvertDouble(Storage::Value* value) {
|
||||
value->type = Storage::Value::kDouble;
|
||||
if (value->stringVal.empty()) {
|
||||
return false;
|
||||
} else {
|
||||
if (std::sscanf(value->stringVal.c_str(), "%lf", &value->doubleVal) != 1) {
|
||||
return false;
|
||||
}
|
||||
if (auto val = wpi::parse_float<double>(value->stringVal)) {
|
||||
value->doubleVal = val.value();
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void* GlassStorageReadOpen(ImGuiContext*, ImGuiSettingsHandler* handler,
|
||||
@@ -96,7 +79,7 @@ static void* GlassStorageReadOpen(ImGuiContext*, ImGuiSettingsHandler* handler,
|
||||
static void GlassStorageReadLine(ImGuiContext*, ImGuiSettingsHandler*,
|
||||
void* entry, const char* line) {
|
||||
auto storage = static_cast<Storage*>(entry);
|
||||
auto [key, val] = wpi::StringRef{line}.split('=');
|
||||
auto [key, val] = wpi::split(line, '=');
|
||||
auto& keys = storage->GetKeys();
|
||||
auto& values = storage->GetValues();
|
||||
auto it = std::find(keys.begin(), keys.end(), key);
|
||||
@@ -144,7 +127,8 @@ static void GlassStorageWriteAll(ImGuiContext*, ImGuiSettingsHandler* handler,
|
||||
for (auto&& entryIt : sorted) {
|
||||
auto& entry = *entryIt;
|
||||
out_buf->append("[GlassStorage][");
|
||||
out_buf->append(entry.first().begin(), entry.first().end());
|
||||
out_buf->append(entry.first().data(),
|
||||
entry.first().data() + entry.first().size());
|
||||
out_buf->append("]\n");
|
||||
auto& keys = entry.second->GetKeys();
|
||||
auto& values = entry.second->GetValues();
|
||||
@@ -233,7 +217,7 @@ uint64_t glass::GetZeroTime() {
|
||||
return gContext->zeroTime;
|
||||
}
|
||||
|
||||
Storage::Value& Storage::GetValue(wpi::StringRef key) {
|
||||
Storage::Value& Storage::GetValue(std::string_view key) {
|
||||
auto it = std::find(m_keys.begin(), m_keys.end(), key);
|
||||
if (it == m_keys.end()) {
|
||||
m_keys.emplace_back(key);
|
||||
@@ -244,49 +228,49 @@ Storage::Value& Storage::GetValue(wpi::StringRef key) {
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFUN(CapsName, LowerName, CType) \
|
||||
CType Storage::Get##CapsName(wpi::StringRef key, CType defaultVal) const { \
|
||||
auto it = std::find(m_keys.begin(), m_keys.end(), key); \
|
||||
if (it == m_keys.end()) \
|
||||
return defaultVal; \
|
||||
Value& value = *m_values[it - m_keys.begin()]; \
|
||||
if (value.type != Value::k##CapsName) { \
|
||||
if (!Convert##CapsName(&value)) \
|
||||
value.LowerName##Val = defaultVal; \
|
||||
} \
|
||||
return value.LowerName##Val; \
|
||||
} \
|
||||
\
|
||||
void Storage::Set##CapsName(wpi::StringRef key, CType val) { \
|
||||
auto it = std::find(m_keys.begin(), m_keys.end(), key); \
|
||||
if (it == m_keys.end()) { \
|
||||
m_keys.emplace_back(key); \
|
||||
m_values.emplace_back(std::make_unique<Value>()); \
|
||||
m_values.back()->type = Value::k##CapsName; \
|
||||
m_values.back()->LowerName##Val = val; \
|
||||
} else { \
|
||||
Value& value = *m_values[it - m_keys.begin()]; \
|
||||
value.type = Value::k##CapsName; \
|
||||
value.LowerName##Val = val; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
CType* Storage::Get##CapsName##Ref(wpi::StringRef key, CType defaultVal) { \
|
||||
auto it = std::find(m_keys.begin(), m_keys.end(), key); \
|
||||
if (it == m_keys.end()) { \
|
||||
m_keys.emplace_back(key); \
|
||||
m_values.emplace_back(std::make_unique<Value>()); \
|
||||
m_values.back()->type = Value::k##CapsName; \
|
||||
m_values.back()->LowerName##Val = defaultVal; \
|
||||
return &m_values.back()->LowerName##Val; \
|
||||
} else { \
|
||||
Value& value = *m_values[it - m_keys.begin()]; \
|
||||
if (value.type != Value::k##CapsName) { \
|
||||
if (!Convert##CapsName(&value)) \
|
||||
value.LowerName##Val = defaultVal; \
|
||||
} \
|
||||
return &value.LowerName##Val; \
|
||||
} \
|
||||
#define DEFUN(CapsName, LowerName, CType) \
|
||||
CType Storage::Get##CapsName(std::string_view key, CType defaultVal) const { \
|
||||
auto it = std::find(m_keys.begin(), m_keys.end(), key); \
|
||||
if (it == m_keys.end()) \
|
||||
return defaultVal; \
|
||||
Value& value = *m_values[it - m_keys.begin()]; \
|
||||
if (value.type != Value::k##CapsName) { \
|
||||
if (!Convert##CapsName(&value)) \
|
||||
value.LowerName##Val = defaultVal; \
|
||||
} \
|
||||
return value.LowerName##Val; \
|
||||
} \
|
||||
\
|
||||
void Storage::Set##CapsName(std::string_view key, CType val) { \
|
||||
auto it = std::find(m_keys.begin(), m_keys.end(), key); \
|
||||
if (it == m_keys.end()) { \
|
||||
m_keys.emplace_back(key); \
|
||||
m_values.emplace_back(std::make_unique<Value>()); \
|
||||
m_values.back()->type = Value::k##CapsName; \
|
||||
m_values.back()->LowerName##Val = val; \
|
||||
} else { \
|
||||
Value& value = *m_values[it - m_keys.begin()]; \
|
||||
value.type = Value::k##CapsName; \
|
||||
value.LowerName##Val = val; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
CType* Storage::Get##CapsName##Ref(std::string_view key, CType defaultVal) { \
|
||||
auto it = std::find(m_keys.begin(), m_keys.end(), key); \
|
||||
if (it == m_keys.end()) { \
|
||||
m_keys.emplace_back(key); \
|
||||
m_values.emplace_back(std::make_unique<Value>()); \
|
||||
m_values.back()->type = Value::k##CapsName; \
|
||||
m_values.back()->LowerName##Val = defaultVal; \
|
||||
return &m_values.back()->LowerName##Val; \
|
||||
} else { \
|
||||
Value& value = *m_values[it - m_keys.begin()]; \
|
||||
if (value.type != Value::k##CapsName) { \
|
||||
if (!Convert##CapsName(&value)) \
|
||||
value.LowerName##Val = defaultVal; \
|
||||
} \
|
||||
return &value.LowerName##Val; \
|
||||
} \
|
||||
}
|
||||
|
||||
DEFUN(Int, int, int)
|
||||
@@ -295,18 +279,18 @@ DEFUN(Bool, bool, bool)
|
||||
DEFUN(Float, float, float)
|
||||
DEFUN(Double, double, double)
|
||||
|
||||
std::string Storage::GetString(wpi::StringRef key,
|
||||
const std::string& defaultVal) const {
|
||||
std::string Storage::GetString(std::string_view key,
|
||||
std::string_view defaultVal) const {
|
||||
auto it = std::find(m_keys.begin(), m_keys.end(), key);
|
||||
if (it == m_keys.end()) {
|
||||
return defaultVal;
|
||||
return std::string{defaultVal};
|
||||
}
|
||||
Value& value = *m_values[it - m_keys.begin()];
|
||||
value.type = Value::kString;
|
||||
return value.stringVal;
|
||||
}
|
||||
|
||||
void Storage::SetString(wpi::StringRef key, const wpi::Twine& val) {
|
||||
void Storage::SetString(std::string_view key, std::string_view val) {
|
||||
auto it = std::find(m_keys.begin(), m_keys.end(), key);
|
||||
if (it == m_keys.end()) {
|
||||
m_keys.emplace_back(key);
|
||||
@@ -315,12 +299,12 @@ void Storage::SetString(wpi::StringRef key, const wpi::Twine& val) {
|
||||
} else {
|
||||
Value& value = *m_values[it - m_keys.begin()];
|
||||
value.type = Value::kString;
|
||||
value.stringVal = val.str();
|
||||
value.stringVal = val;
|
||||
}
|
||||
}
|
||||
|
||||
std::string* Storage::GetStringRef(wpi::StringRef key,
|
||||
wpi::StringRef defaultVal) {
|
||||
std::string* Storage::GetStringRef(std::string_view key,
|
||||
std::string_view defaultVal) {
|
||||
auto it = std::find(m_keys.begin(), m_keys.end(), key);
|
||||
if (it == m_keys.end()) {
|
||||
m_keys.emplace_back(key);
|
||||
@@ -342,7 +326,7 @@ Storage& glass::GetStorage() {
|
||||
return *storage;
|
||||
}
|
||||
|
||||
Storage& glass::GetStorage(wpi::StringRef id) {
|
||||
Storage& glass::GetStorage(std::string_view id) {
|
||||
auto& storage = gContext->storage[id];
|
||||
if (!storage) {
|
||||
storage = std::make_unique<Storage>();
|
||||
@@ -350,10 +334,10 @@ Storage& glass::GetStorage(wpi::StringRef id) {
|
||||
return *storage;
|
||||
}
|
||||
|
||||
static void PushIDStack(wpi::StringRef label_id) {
|
||||
static void PushIDStack(std::string_view label_id) {
|
||||
gContext->idStack.emplace_back(gContext->curId.size());
|
||||
|
||||
auto [label, id] = wpi::StringRef{label_id}.split("###");
|
||||
auto [label, id] = wpi::split(label_id, "###");
|
||||
// if no ###id, use label as id
|
||||
if (id.empty()) {
|
||||
id = label;
|
||||
@@ -392,7 +376,7 @@ void glass::EndChild() {
|
||||
|
||||
bool glass::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) {
|
||||
wpi::SmallString<64> openKey;
|
||||
auto [name, id] = wpi::StringRef{label}.split("###");
|
||||
auto [name, id] = wpi::split(label, "###");
|
||||
// if no ###id, use name as id
|
||||
if (id.empty()) {
|
||||
id = name;
|
||||
@@ -400,7 +384,7 @@ bool glass::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) {
|
||||
openKey = id;
|
||||
openKey += "###open";
|
||||
|
||||
bool* open = GetStorage().GetBoolRef(openKey);
|
||||
bool* open = GetStorage().GetBoolRef(openKey.str());
|
||||
*open = ImGui::CollapsingHeader(
|
||||
label, flags | (*open ? ImGuiTreeNodeFlags_DefaultOpen : 0));
|
||||
return *open;
|
||||
@@ -428,7 +412,7 @@ void glass::PushID(const char* str_id) {
|
||||
}
|
||||
|
||||
void glass::PushID(const char* str_id_begin, const char* str_id_end) {
|
||||
PushIDStack(wpi::StringRef(str_id_begin, str_id_end - str_id_begin));
|
||||
PushIDStack(std::string_view(str_id_begin, str_id_end - str_id_begin));
|
||||
ImGui::PushID(str_id_begin, str_id_end);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,13 +4,15 @@
|
||||
|
||||
#include "glass/DataSource.h"
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "glass/ContextInternal.h"
|
||||
|
||||
using namespace glass;
|
||||
|
||||
wpi::sig::Signal<const char*, DataSource*> DataSource::sourceCreated;
|
||||
|
||||
DataSource::DataSource(const wpi::Twine& id) : m_id{id.str()} {
|
||||
DataSource::DataSource(std::string_view id) : m_id{id} {
|
||||
auto it = gContext->sources.try_emplace(m_id, this);
|
||||
auto& srcName = it.first->getValue();
|
||||
m_name = srcName.name.get();
|
||||
@@ -20,12 +22,11 @@ DataSource::DataSource(const wpi::Twine& id) : m_id{id.str()} {
|
||||
sourceCreated(m_id.c_str(), this);
|
||||
}
|
||||
|
||||
DataSource::DataSource(const wpi::Twine& id, int index)
|
||||
: DataSource{id + wpi::Twine('[') + wpi::Twine(index) + wpi::Twine(']')} {}
|
||||
DataSource::DataSource(std::string_view id, int index)
|
||||
: DataSource{fmt::format("{}[{}]", id, index)} {}
|
||||
|
||||
DataSource::DataSource(const wpi::Twine& id, int index, int index2)
|
||||
: DataSource{id + wpi::Twine('[') + wpi::Twine(index) + wpi::Twine(',') +
|
||||
wpi::Twine(index2) + wpi::Twine(']')} {}
|
||||
DataSource::DataSource(std::string_view id, int index, int index2)
|
||||
: DataSource{fmt::format("{}[{},{}]", id, index, index2)} {}
|
||||
|
||||
DataSource::~DataSource() {
|
||||
if (!gContext) {
|
||||
@@ -41,7 +42,7 @@ DataSource::~DataSource() {
|
||||
}
|
||||
}
|
||||
|
||||
void DataSource::SetName(const wpi::Twine& name) {
|
||||
void DataSource::SetName(std::string_view name) {
|
||||
m_name->SetName(name);
|
||||
}
|
||||
|
||||
@@ -146,7 +147,7 @@ void DataSource::EmitDrag(ImGuiDragDropFlags flags) const {
|
||||
}
|
||||
}
|
||||
|
||||
DataSource* DataSource::Find(wpi::StringRef id) {
|
||||
DataSource* DataSource::Find(std::string_view id) {
|
||||
auto it = gContext->sources.find(id);
|
||||
if (it == gContext->sources.end()) {
|
||||
return nullptr;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "glass/Window.h"
|
||||
|
||||
#include <imgui_internal.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
|
||||
#include "glass/Context.h"
|
||||
|
||||
@@ -86,26 +86,21 @@ void Window::ScaleDefault(float scale) {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::IniReadLine(const char* lineStr) {
|
||||
wpi::StringRef line{lineStr};
|
||||
auto [name, value] = line.split('=');
|
||||
name = name.trim();
|
||||
value = value.trim();
|
||||
void Window::IniReadLine(const char* line) {
|
||||
auto [name, value] = wpi::split(line, '=');
|
||||
name = wpi::trim(name);
|
||||
value = wpi::trim(value);
|
||||
|
||||
if (name == "name") {
|
||||
m_name = value;
|
||||
} else if (name == "visible") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_visible = num.value();
|
||||
}
|
||||
m_visible = num;
|
||||
} else if (name == "enabled") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_enabled = num.value();
|
||||
}
|
||||
m_enabled = num;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
#include "glass/WindowManager.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <fmt/format.h>
|
||||
#include <wpigui.h>
|
||||
|
||||
using namespace glass;
|
||||
|
||||
WindowManager::WindowManager(const wpi::Twine& iniName)
|
||||
WindowManager::WindowManager(std::string_view iniName)
|
||||
: m_iniSaver{iniName, this} {}
|
||||
|
||||
// read/write open state to ini file
|
||||
@@ -31,42 +31,42 @@ void WindowManager::IniSaver::IniWriteAll(ImGuiTextBuffer* out_buf) {
|
||||
}
|
||||
}
|
||||
|
||||
Window* WindowManager::AddWindow(wpi::StringRef id,
|
||||
Window* WindowManager::AddWindow(std::string_view id,
|
||||
wpi::unique_function<void()> display) {
|
||||
auto win = GetOrAddWindow(id, false);
|
||||
if (!win) {
|
||||
return nullptr;
|
||||
}
|
||||
if (win->HasView()) {
|
||||
wpi::errs() << "GUI: ignoring duplicate window '" << id << "'\n";
|
||||
fmt::print(stderr, "GUI: ignoring duplicate window '{}'\n", id);
|
||||
return nullptr;
|
||||
}
|
||||
win->SetView(MakeFunctionView(std::move(display)));
|
||||
return win;
|
||||
}
|
||||
|
||||
Window* WindowManager::AddWindow(wpi::StringRef id,
|
||||
Window* WindowManager::AddWindow(std::string_view id,
|
||||
std::unique_ptr<View> view) {
|
||||
auto win = GetOrAddWindow(id, false);
|
||||
if (!win) {
|
||||
return nullptr;
|
||||
}
|
||||
if (win->HasView()) {
|
||||
wpi::errs() << "GUI: ignoring duplicate window '" << id << "'\n";
|
||||
fmt::print(stderr, "GUI: ignoring duplicate window '{}'\n", id);
|
||||
return nullptr;
|
||||
}
|
||||
win->SetView(std::move(view));
|
||||
return win;
|
||||
}
|
||||
|
||||
Window* WindowManager::GetOrAddWindow(wpi::StringRef id, bool duplicateOk) {
|
||||
Window* WindowManager::GetOrAddWindow(std::string_view id, bool duplicateOk) {
|
||||
// binary search
|
||||
auto it = std::lower_bound(
|
||||
m_windows.begin(), m_windows.end(), id,
|
||||
[](const auto& elem, wpi::StringRef s) { return elem->GetId() < s; });
|
||||
[](const auto& elem, std::string_view s) { return elem->GetId() < s; });
|
||||
if (it != m_windows.end() && (*it)->GetId() == id) {
|
||||
if (!duplicateOk) {
|
||||
wpi::errs() << "GUI: ignoring duplicate window '" << id << "'\n";
|
||||
fmt::print(stderr, "GUI: ignoring duplicate window '{}'\n", id);
|
||||
return nullptr;
|
||||
}
|
||||
return it->get();
|
||||
@@ -75,11 +75,11 @@ Window* WindowManager::GetOrAddWindow(wpi::StringRef id, bool duplicateOk) {
|
||||
return m_windows.emplace(it, std::make_unique<Window>(id))->get();
|
||||
}
|
||||
|
||||
Window* WindowManager::GetWindow(wpi::StringRef id) {
|
||||
Window* WindowManager::GetWindow(std::string_view id) {
|
||||
// binary search
|
||||
auto it = std::lower_bound(
|
||||
m_windows.begin(), m_windows.end(), id,
|
||||
[](const auto& elem, wpi::StringRef s) { return elem->GetId() < s; });
|
||||
[](const auto& elem, std::string_view s) { return elem->GetId() < s; });
|
||||
if (it == m_windows.end() || (*it)->GetId() != id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ void glass::DisplayAnalogInput(AnalogInputModel* model, int index) {
|
||||
}
|
||||
|
||||
void glass::DisplayAnalogInputs(AnalogInputsModel* model,
|
||||
wpi::StringRef noneMsg) {
|
||||
std::string_view noneMsg) {
|
||||
ImGui::Text("(Use Ctrl+Click to edit value)");
|
||||
bool hasAny = false;
|
||||
bool first = true;
|
||||
@@ -65,6 +65,6 @@ void glass::DisplayAnalogInputs(AnalogInputsModel* model,
|
||||
hasAny = true;
|
||||
});
|
||||
if (!hasAny && !noneMsg.empty()) {
|
||||
ImGui::TextUnformatted(noneMsg.begin(), noneMsg.end());
|
||||
ImGui::TextUnformatted(noneMsg.data(), noneMsg.data() + noneMsg.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ void glass::DisplayDIO(DIOModel* model, int index, bool outputsEnabled) {
|
||||
}
|
||||
|
||||
void glass::DisplayDIOs(DIOsModel* model, bool outputsEnabled,
|
||||
wpi::StringRef noneMsg) {
|
||||
std::string_view noneMsg) {
|
||||
bool hasAny = false;
|
||||
|
||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
|
||||
@@ -116,6 +116,6 @@ void glass::DisplayDIOs(DIOsModel* model, bool outputsEnabled,
|
||||
});
|
||||
ImGui::PopItemWidth();
|
||||
if (!hasAny && !noneMsg.empty()) {
|
||||
ImGui::TextUnformatted(noneMsg.begin(), noneMsg.end());
|
||||
ImGui::TextUnformatted(noneMsg.data(), noneMsg.data() + noneMsg.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "glass/hardware/Encoder.h"
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <imgui.h>
|
||||
|
||||
#include "glass/Context.h"
|
||||
@@ -11,8 +12,8 @@
|
||||
|
||||
using namespace glass;
|
||||
|
||||
void EncoderModel::SetName(const wpi::Twine& name) {
|
||||
if (name.str().empty()) {
|
||||
void EncoderModel::SetName(std::string_view name) {
|
||||
if (name.empty()) {
|
||||
if (auto distancePerPulse = GetDistancePerPulseData()) {
|
||||
distancePerPulse->SetName("");
|
||||
}
|
||||
@@ -33,22 +34,22 @@ void EncoderModel::SetName(const wpi::Twine& name) {
|
||||
}
|
||||
} else {
|
||||
if (auto distancePerPulse = GetDistancePerPulseData()) {
|
||||
distancePerPulse->SetName(name + " Distance/Count");
|
||||
distancePerPulse->SetName(fmt::format("{} Distance/Count", name));
|
||||
}
|
||||
if (auto count = GetCountData()) {
|
||||
count->SetName(name + " Count");
|
||||
count->SetName(fmt::format("{} Count", name));
|
||||
}
|
||||
if (auto period = GetPeriodData()) {
|
||||
period->SetName(name + " Period");
|
||||
period->SetName(fmt::format("{} Period", name));
|
||||
}
|
||||
if (auto direction = GetDirectionData()) {
|
||||
direction->SetName(name + " Direction");
|
||||
direction->SetName(fmt::format("{} Direction", name));
|
||||
}
|
||||
if (auto distance = GetDistanceData()) {
|
||||
distance->SetName(name + " Distance");
|
||||
distance->SetName(fmt::format("{} Distance", name));
|
||||
}
|
||||
if (auto rate = GetRateData()) {
|
||||
rate->SetName(name + " Rate");
|
||||
rate->SetName(fmt::format("{} Rate", name));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -153,7 +154,7 @@ void glass::DisplayEncoder(EncoderModel* model) {
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
void glass::DisplayEncoders(EncodersModel* model, wpi::StringRef noneMsg) {
|
||||
void glass::DisplayEncoders(EncodersModel* model, std::string_view noneMsg) {
|
||||
bool hasAny = false;
|
||||
model->ForEachEncoder([&](EncoderModel& encoder, int i) {
|
||||
hasAny = true;
|
||||
@@ -162,6 +163,6 @@ void glass::DisplayEncoders(EncodersModel* model, wpi::StringRef noneMsg) {
|
||||
PopID();
|
||||
});
|
||||
if (!hasAny && !noneMsg.empty()) {
|
||||
ImGui::TextUnformatted(noneMsg.begin(), noneMsg.end());
|
||||
ImGui::TextUnformatted(noneMsg.data(), noneMsg.data() + noneMsg.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ bool glass::DisplayPCMSolenoids(PCMModel* model, int index,
|
||||
}
|
||||
|
||||
void glass::DisplayPCMsSolenoids(PCMsModel* model, bool outputsEnabled,
|
||||
wpi::StringRef noneMsg) {
|
||||
std::string_view noneMsg) {
|
||||
bool hasAny = false;
|
||||
model->ForEachPCM([&](PCMModel& pcm, int i) {
|
||||
PushID(i);
|
||||
@@ -93,7 +93,7 @@ void glass::DisplayPCMsSolenoids(PCMsModel* model, bool outputsEnabled,
|
||||
PopID();
|
||||
});
|
||||
if (!hasAny && !noneMsg.empty()) {
|
||||
ImGui::TextUnformatted(noneMsg.begin(), noneMsg.end());
|
||||
ImGui::TextUnformatted(noneMsg.data(), noneMsg.data() + noneMsg.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ void glass::DisplayPDP(PDPModel* model, int index) {
|
||||
}
|
||||
}
|
||||
|
||||
void glass::DisplayPDPs(PDPsModel* model, wpi::StringRef noneMsg) {
|
||||
void glass::DisplayPDPs(PDPsModel* model, std::string_view noneMsg) {
|
||||
bool hasAny = false;
|
||||
model->ForEachPDP([&](PDPModel& pdp, int i) {
|
||||
hasAny = true;
|
||||
@@ -88,6 +88,6 @@ void glass::DisplayPDPs(PDPsModel* model, wpi::StringRef noneMsg) {
|
||||
PopID();
|
||||
});
|
||||
if (!hasAny && !noneMsg.empty()) {
|
||||
ImGui::TextUnformatted(noneMsg.begin(), noneMsg.end());
|
||||
ImGui::TextUnformatted(noneMsg.data(), noneMsg.data() + noneMsg.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ void glass::DisplayPWM(PWMModel* model, int index, bool outputsEnabled) {
|
||||
}
|
||||
|
||||
void glass::DisplayPWMs(PWMsModel* model, bool outputsEnabled,
|
||||
wpi::StringRef noneMsg) {
|
||||
std::string_view noneMsg) {
|
||||
bool hasAny = false;
|
||||
bool first = true;
|
||||
model->ForEachPWM([&](PWMModel& pwm, int i) {
|
||||
@@ -58,6 +58,6 @@ void glass::DisplayPWMs(PWMsModel* model, bool outputsEnabled,
|
||||
PopID();
|
||||
});
|
||||
if (!hasAny && !noneMsg.empty()) {
|
||||
ImGui::TextUnformatted(noneMsg.begin(), noneMsg.end());
|
||||
ImGui::TextUnformatted(noneMsg.data(), noneMsg.data() + noneMsg.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ void glass::DisplayRelay(RelayModel* model, int index, bool outputsEnabled) {
|
||||
}
|
||||
|
||||
void glass::DisplayRelays(RelaysModel* model, bool outputsEnabled,
|
||||
wpi::StringRef noneMsg) {
|
||||
std::string_view noneMsg) {
|
||||
bool hasAny = false;
|
||||
bool first = true;
|
||||
model->ForEachRelay([&](RelayModel& relay, int i) {
|
||||
@@ -77,6 +77,6 @@ void glass::DisplayRelays(RelaysModel* model, bool outputsEnabled,
|
||||
PopID();
|
||||
});
|
||||
if (!hasAny && !noneMsg.empty()) {
|
||||
ImGui::TextUnformatted(noneMsg.begin(), noneMsg.end());
|
||||
ImGui::TextUnformatted(noneMsg.data(), noneMsg.data() + noneMsg.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,12 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <frc/geometry/Pose2d.h>
|
||||
#include <frc/geometry/Rotation2d.h>
|
||||
#include <frc/geometry/Translation2d.h>
|
||||
@@ -21,11 +24,11 @@
|
||||
#include <units/angle.h>
|
||||
#include <units/length.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/StringMap.h>
|
||||
#include <wpi/fs.h>
|
||||
#include <wpi/json.h>
|
||||
#include <wpi/raw_istream.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <wpigui.h>
|
||||
|
||||
#include "glass/Context.h"
|
||||
@@ -229,7 +232,7 @@ class FieldInfo {
|
||||
private:
|
||||
void Reset();
|
||||
bool LoadImageImpl(const char* fn);
|
||||
void LoadJson(const wpi::Twine& jsonfile);
|
||||
void LoadJson(std::string_view jsonfile);
|
||||
|
||||
std::unique_ptr<pfd::open_file> m_fileOpener;
|
||||
|
||||
@@ -377,7 +380,7 @@ void FieldInfo::LoadImage() {
|
||||
if (m_fileOpener && m_fileOpener->ready(0)) {
|
||||
auto result = m_fileOpener->result();
|
||||
if (!result.empty()) {
|
||||
if (wpi::StringRef(result[0]).endswith(".json")) {
|
||||
if (wpi::ends_with(result[0], ".json")) {
|
||||
LoadJson(result[0]);
|
||||
} else {
|
||||
LoadImageImpl(result[0].c_str());
|
||||
@@ -396,11 +399,11 @@ void FieldInfo::LoadImage() {
|
||||
}
|
||||
}
|
||||
|
||||
void FieldInfo::LoadJson(const wpi::Twine& jsonfile) {
|
||||
void FieldInfo::LoadJson(std::string_view jsonfile) {
|
||||
std::error_code ec;
|
||||
wpi::raw_fd_istream f(jsonfile, ec);
|
||||
if (ec) {
|
||||
wpi::errs() << "GUI: could not open field JSON file\n";
|
||||
std::fputs("GUI: could not open field JSON file\n", stderr);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -409,12 +412,12 @@ void FieldInfo::LoadJson(const wpi::Twine& jsonfile) {
|
||||
try {
|
||||
j = wpi::json::parse(f);
|
||||
} catch (const wpi::json::parse_error& e) {
|
||||
wpi::errs() << "GUI: JSON: could not parse: " << e.what() << '\n';
|
||||
fmt::print(stderr, "GUI: JSON: could not parse: {}\n", e.what());
|
||||
}
|
||||
|
||||
// top level must be an object
|
||||
if (!j.is_object()) {
|
||||
wpi::errs() << "GUI: JSON: does not contain a top object\n";
|
||||
std::fputs("GUI: JSON: does not contain a top object\n", stderr);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -423,8 +426,7 @@ void FieldInfo::LoadJson(const wpi::Twine& jsonfile) {
|
||||
try {
|
||||
image = j.at("field-image").get<std::string>();
|
||||
} catch (const wpi::json::exception& e) {
|
||||
wpi::errs() << "GUI: JSON: could not read field-image: " << e.what()
|
||||
<< '\n';
|
||||
fmt::print(stderr, "GUI: JSON: could not read field-image: {}\n", e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -436,8 +438,8 @@ void FieldInfo::LoadJson(const wpi::Twine& jsonfile) {
|
||||
bottom = j.at("field-corners").at("bottom-right").at(1).get<int>();
|
||||
right = j.at("field-corners").at("bottom-right").at(0).get<int>();
|
||||
} catch (const wpi::json::exception& e) {
|
||||
wpi::errs() << "GUI: JSON: could not read field-corners: " << e.what()
|
||||
<< '\n';
|
||||
fmt::print(stderr, "GUI: JSON: could not read field-corners: {}\n",
|
||||
e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -448,7 +450,7 @@ void FieldInfo::LoadJson(const wpi::Twine& jsonfile) {
|
||||
width = j.at("field-size").at(0).get<float>();
|
||||
height = j.at("field-size").at(1).get<float>();
|
||||
} catch (const wpi::json::exception& e) {
|
||||
wpi::errs() << "GUI: JSON: could not read field-size: " << e.what() << '\n';
|
||||
fmt::print(stderr, "GUI: JSON: could not read field-size: {}\n", e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -457,7 +459,7 @@ void FieldInfo::LoadJson(const wpi::Twine& jsonfile) {
|
||||
try {
|
||||
unit = j.at("field-unit").get<std::string>();
|
||||
} catch (const wpi::json::exception& e) {
|
||||
wpi::errs() << "GUI: JSON: could not read field-unit: " << e.what() << '\n';
|
||||
fmt::print(stderr, "GUI: JSON: could not read field-unit: {}\n", e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -468,7 +470,7 @@ void FieldInfo::LoadJson(const wpi::Twine& jsonfile) {
|
||||
}
|
||||
|
||||
// the image filename is relative to the json file
|
||||
auto pathname = fs::path{jsonfile.str()}.replace_filename(image).string();
|
||||
auto pathname = fs::path{jsonfile}.replace_filename(image).string();
|
||||
|
||||
// load field image
|
||||
if (!LoadImageImpl(pathname.c_str())) {
|
||||
@@ -486,10 +488,10 @@ void FieldInfo::LoadJson(const wpi::Twine& jsonfile) {
|
||||
}
|
||||
|
||||
bool FieldInfo::LoadImageImpl(const char* fn) {
|
||||
wpi::outs() << "GUI: loading field image '" << fn << "'\n";
|
||||
fmt::print("GUI: loading field image '{}'\n", fn);
|
||||
auto texture = gui::Texture::CreateFromFile(fn);
|
||||
if (!texture) {
|
||||
wpi::errs() << "GUI: could not read field image\n";
|
||||
std::puts("GUI: could not read field image");
|
||||
return false;
|
||||
}
|
||||
m_texture = std::move(texture);
|
||||
@@ -679,10 +681,10 @@ void ObjectInfo::LoadImage() {
|
||||
}
|
||||
|
||||
bool ObjectInfo::LoadImageImpl(const char* fn) {
|
||||
wpi::outs() << "GUI: loading object image '" << fn << "'\n";
|
||||
fmt::print("GUI: loading object image '{}'\n", fn);
|
||||
auto texture = gui::Texture::CreateFromFile(fn);
|
||||
if (!texture) {
|
||||
wpi::errs() << "GUI: could not read object image\n";
|
||||
std::fputs("GUI: could not read object image\n", stderr);
|
||||
return false;
|
||||
}
|
||||
m_texture = std::move(texture);
|
||||
@@ -883,7 +885,7 @@ void glass::DisplayField2DSettings(Field2DModel* model) {
|
||||
}
|
||||
auto obj = objRef.get();
|
||||
|
||||
wpi::SmallString<64> nameBuf = name;
|
||||
wpi::SmallString<64> nameBuf{name};
|
||||
if (ImGui::CollapsingHeader(nameBuf.c_str())) {
|
||||
obj->DisplaySettings();
|
||||
}
|
||||
@@ -899,7 +901,7 @@ class FieldDisplay {
|
||||
const ImVec2& contentSize);
|
||||
|
||||
private:
|
||||
void DisplayObject(FieldObjectModel& model, wpi::StringRef name);
|
||||
void DisplayObject(FieldObjectModel& model, std::string_view name);
|
||||
|
||||
FieldInfo* m_field;
|
||||
ImVec2 m_mousePos;
|
||||
@@ -1018,7 +1020,8 @@ void FieldDisplay::Display(FieldInfo* field, Field2DModel* model,
|
||||
}
|
||||
}
|
||||
|
||||
void FieldDisplay::DisplayObject(FieldObjectModel& model, wpi::StringRef name) {
|
||||
void FieldDisplay::DisplayObject(FieldObjectModel& model,
|
||||
std::string_view name) {
|
||||
PushID(name);
|
||||
auto& objRef = m_field->m_objects[name];
|
||||
if (!objRef) {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "glass/other/Log.h"
|
||||
|
||||
#include <imgui.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
using namespace glass;
|
||||
|
||||
@@ -17,14 +16,13 @@ void LogData::Clear() {
|
||||
m_lineOffsets.push_back(0);
|
||||
}
|
||||
|
||||
void LogData::Append(const wpi::Twine& msg) {
|
||||
void LogData::Append(std::string_view msg) {
|
||||
if (m_lineOffsets.size() >= m_maxLines) {
|
||||
Clear();
|
||||
}
|
||||
|
||||
size_t oldSize = m_buf.size();
|
||||
wpi::raw_string_ostream os{m_buf};
|
||||
msg.print(os);
|
||||
m_buf.append(msg);
|
||||
for (size_t newSize = m_buf.size(); oldSize < newSize; ++oldSize) {
|
||||
if (m_buf[oldSize] == '\n') {
|
||||
m_lineOffsets.push_back(oldSize + 1);
|
||||
|
||||
@@ -6,9 +6,12 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <frc/geometry/Pose2d.h>
|
||||
#include <frc/geometry/Rotation2d.h>
|
||||
#include <frc/geometry/Transform2d.h>
|
||||
@@ -21,7 +24,6 @@
|
||||
#include <portable-file-dialogs.h>
|
||||
#include <units/angle.h>
|
||||
#include <units/length.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <wpigui.h>
|
||||
|
||||
#include "glass/Context.h"
|
||||
@@ -125,10 +127,10 @@ void BackgroundInfo::LoadImage() {
|
||||
}
|
||||
|
||||
bool BackgroundInfo::LoadImageImpl(const char* fn) {
|
||||
wpi::outs() << "GUI: loading background image '" << fn << "'\n";
|
||||
fmt::print("GUI: loading background image '{}'\n", fn);
|
||||
auto texture = gui::Texture::CreateFromFile(fn);
|
||||
if (!texture) {
|
||||
wpi::errs() << "GUI: could not read background image\n";
|
||||
std::puts("GUI: could not read background image");
|
||||
return false;
|
||||
}
|
||||
m_texture = std::move(texture);
|
||||
@@ -182,7 +184,7 @@ void glass::DisplayMechanism2DSettings(Mechanism2DModel* model) {
|
||||
void FrameData::DrawObject(ImDrawList* drawList, MechanismObjectModel& objModel,
|
||||
const frc::Pose2d& pose) const {
|
||||
const char* type = objModel.GetType();
|
||||
if (wpi::StringRef{type} == "line") {
|
||||
if (std::string_view{type} == "line") {
|
||||
auto startPose =
|
||||
pose + frc::Transform2d{frc::Translation2d{}, objModel.GetAngle()};
|
||||
auto endPose =
|
||||
|
||||
@@ -12,8 +12,11 @@
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
@@ -23,6 +26,7 @@
|
||||
#include <wpi/Signal.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/timestamp.h>
|
||||
|
||||
#include "glass/Context.h"
|
||||
@@ -42,7 +46,7 @@ struct PlotSeriesRef {
|
||||
|
||||
class PlotSeries {
|
||||
public:
|
||||
explicit PlotSeries(wpi::StringRef id);
|
||||
explicit PlotSeries(std::string_view id);
|
||||
explicit PlotSeries(DataSource* source, int yAxis = 0);
|
||||
|
||||
const std::string& GetId() const { return m_id; }
|
||||
@@ -52,7 +56,7 @@ class PlotSeries {
|
||||
void SetSource(DataSource* source);
|
||||
DataSource* GetSource() const { return m_source; }
|
||||
|
||||
bool ReadIni(wpi::StringRef name, wpi::StringRef value);
|
||||
bool ReadIni(std::string_view name, std::string_view value);
|
||||
void WriteIni(ImGuiTextBuffer* out);
|
||||
|
||||
enum Action { kNone, kMoveUp, kMoveDown, kDelete };
|
||||
@@ -102,7 +106,7 @@ class Plot {
|
||||
public:
|
||||
Plot();
|
||||
|
||||
bool ReadIni(wpi::StringRef name, wpi::StringRef value);
|
||||
bool ReadIni(std::string_view name, std::string_view value);
|
||||
void WriteIni(ImGuiTextBuffer* out);
|
||||
|
||||
void DragDropTarget(PlotView& view, size_t i, bool inPlot);
|
||||
@@ -164,7 +168,7 @@ class PlotView : public View {
|
||||
|
||||
} // namespace
|
||||
|
||||
PlotSeries::PlotSeries(wpi::StringRef id) : m_id(id) {
|
||||
PlotSeries::PlotSeries(std::string_view id) : m_id(id) {
|
||||
if (DataSource* source = DataSource::Find(id)) {
|
||||
SetSource(source);
|
||||
return;
|
||||
@@ -241,55 +245,45 @@ void PlotSeries::AppendValue(double value, uint64_t timeUs) {
|
||||
}
|
||||
}
|
||||
|
||||
bool PlotSeries::ReadIni(wpi::StringRef name, wpi::StringRef value) {
|
||||
bool PlotSeries::ReadIni(std::string_view name, std::string_view value) {
|
||||
if (name == "name") {
|
||||
m_name = value;
|
||||
return true;
|
||||
}
|
||||
if (name == "yAxis") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_yAxis = num.value();
|
||||
}
|
||||
m_yAxis = num;
|
||||
return true;
|
||||
} else if (name == "color") {
|
||||
unsigned int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<unsigned int>(value, 10)) {
|
||||
m_color = ImColor(num.value());
|
||||
}
|
||||
m_color = ImColor(num);
|
||||
return true;
|
||||
} else if (name == "marker") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_marker = num.value();
|
||||
}
|
||||
m_marker = num;
|
||||
return true;
|
||||
} else if (name == "weight") {
|
||||
std::sscanf(value.data(), "%f", &m_weight);
|
||||
if (auto num = wpi::parse_float<float>(value)) {
|
||||
m_weight = num.value();
|
||||
}
|
||||
return true;
|
||||
} else if (name == "digital") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_digital = num.value();
|
||||
}
|
||||
m_digital = num;
|
||||
return true;
|
||||
} else if (name == "digitalBitHeight") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_digitalBitHeight = num.value();
|
||||
}
|
||||
m_digitalBitHeight = num;
|
||||
return true;
|
||||
} else if (name == "digitalBitGap") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_digitalBitGap = num.value();
|
||||
}
|
||||
m_digitalBitGap = num;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -478,121 +472,93 @@ Plot::Plot() {
|
||||
}
|
||||
}
|
||||
|
||||
bool Plot::ReadIni(wpi::StringRef name, wpi::StringRef value) {
|
||||
bool Plot::ReadIni(std::string_view name, std::string_view value) {
|
||||
if (name == "name") {
|
||||
m_name = value;
|
||||
return true;
|
||||
} else if (name == "visible") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_visible = num.value() != 0;
|
||||
}
|
||||
m_visible = num != 0;
|
||||
return true;
|
||||
} else if (name == "showPause") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_showPause = num.value() != 0;
|
||||
}
|
||||
m_showPause = num != 0;
|
||||
return true;
|
||||
} else if (name == "lockPrevX") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_lockPrevX = num.value() != 0;
|
||||
}
|
||||
m_lockPrevX = num != 0;
|
||||
return true;
|
||||
} else if (name == "legend") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
}
|
||||
if (num == 0) {
|
||||
m_plotFlags |= ImPlotFlags_NoLegend;
|
||||
} else {
|
||||
m_plotFlags &= ~ImPlotFlags_NoLegend;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
if (num.value() == 0) {
|
||||
m_plotFlags |= ImPlotFlags_NoLegend;
|
||||
} else {
|
||||
m_plotFlags &= ~ImPlotFlags_NoLegend;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (name == "yaxis2") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
}
|
||||
if (num == 0) {
|
||||
m_plotFlags &= ~ImPlotFlags_YAxis2;
|
||||
} else {
|
||||
m_plotFlags |= ImPlotFlags_YAxis2;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
if (num.value() == 0) {
|
||||
m_plotFlags &= ~ImPlotFlags_YAxis2;
|
||||
} else {
|
||||
m_plotFlags |= ImPlotFlags_YAxis2;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (name == "yaxis3") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
}
|
||||
if (num == 0) {
|
||||
m_plotFlags &= ~ImPlotFlags_YAxis3;
|
||||
} else {
|
||||
m_plotFlags |= ImPlotFlags_YAxis3;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
if (num.value() == 0) {
|
||||
m_plotFlags &= ~ImPlotFlags_YAxis3;
|
||||
} else {
|
||||
m_plotFlags |= ImPlotFlags_YAxis3;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (name == "viewTime") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_viewTime = num.value() / 1000.0;
|
||||
}
|
||||
m_viewTime = num / 1000.0;
|
||||
return true;
|
||||
} else if (name == "autoHeight") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_autoHeight = num.value() != 0;
|
||||
}
|
||||
m_autoHeight = num != 0;
|
||||
return true;
|
||||
} else if (name == "height") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_height = num.value();
|
||||
}
|
||||
m_height = num;
|
||||
return true;
|
||||
} else if (name.startswith("y")) {
|
||||
auto [yAxisStr, yName] = name.split('_');
|
||||
int yAxis;
|
||||
if (yAxisStr.substr(1).getAsInteger(10, yAxis)) {
|
||||
return false;
|
||||
}
|
||||
} else if (wpi::starts_with(name, 'y')) {
|
||||
auto [yAxisStr, yName] = wpi::split(name, '_');
|
||||
int yAxis =
|
||||
wpi::parse_integer<int>(wpi::drop_front(yAxisStr), 10).value_or(-1);
|
||||
if (yAxis < 0 || yAxis > 3) {
|
||||
return false;
|
||||
}
|
||||
if (yName == "min") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_axisRange[yAxis].min = num.value() / 1000.0;
|
||||
}
|
||||
m_axisRange[yAxis].min = num / 1000.0;
|
||||
return true;
|
||||
} else if (yName == "max") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_axisRange[yAxis].max = num.value() / 1000.0;
|
||||
}
|
||||
m_axisRange[yAxis].max = num / 1000.0;
|
||||
return true;
|
||||
} else if (yName == "lockMin") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_axisRange[yAxis].lockMin = num.value() != 0;
|
||||
}
|
||||
m_axisRange[yAxis].lockMin = num != 0;
|
||||
return true;
|
||||
} else if (yName == "lockMax") {
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_axisRange[yAxis].lockMax = num.value() != 0;
|
||||
}
|
||||
m_axisRange[yAxis].lockMax = num != 0;
|
||||
return true;
|
||||
} else if (yName == "label") {
|
||||
m_axisLabel[yAxis] = value;
|
||||
@@ -960,10 +926,10 @@ void PlotView::MovePlotSeries(PlotView* fromView, size_t fromPlotIndex,
|
||||
}
|
||||
}
|
||||
|
||||
PlotProvider::PlotProvider(const wpi::Twine& iniName)
|
||||
: WindowManager{iniName + "Window"},
|
||||
PlotProvider::PlotProvider(std::string_view iniName)
|
||||
: WindowManager{fmt::format("{}Window", iniName)},
|
||||
m_plotSaver{iniName, this, false},
|
||||
m_seriesSaver{iniName + "Series", this, true} {}
|
||||
m_seriesSaver{fmt::format("{}Series", iniName), this, true} {}
|
||||
|
||||
PlotProvider::~PlotProvider() = default;
|
||||
|
||||
@@ -1021,21 +987,23 @@ void PlotProvider::DisplayWindows() {
|
||||
WindowManager::DisplayWindows();
|
||||
}
|
||||
|
||||
PlotProvider::IniSaver::IniSaver(const wpi::Twine& typeName,
|
||||
PlotProvider::IniSaver::IniSaver(std::string_view typeName,
|
||||
PlotProvider* provider, bool forSeries)
|
||||
: IniSaverBase{typeName}, m_provider{provider}, m_forSeries{forSeries} {}
|
||||
|
||||
void* PlotProvider::IniSaver::IniReadOpen(const char* name) {
|
||||
auto [viewId, plotNumStr] = wpi::StringRef{name}.split('#');
|
||||
wpi::StringRef seriesId;
|
||||
auto [viewId, plotNumStr] = wpi::split(name, '#');
|
||||
std::string_view seriesId;
|
||||
if (m_forSeries) {
|
||||
std::tie(plotNumStr, seriesId) = plotNumStr.split('#');
|
||||
std::tie(plotNumStr, seriesId) = wpi::split(plotNumStr, '#');
|
||||
if (seriesId.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
unsigned int plotNum;
|
||||
if (plotNumStr.getAsInteger(10, plotNum)) {
|
||||
if (auto plotNumOpt = wpi::parse_integer<unsigned int>(plotNumStr, 10)) {
|
||||
plotNum = plotNumOpt.value();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1071,10 +1039,10 @@ void* PlotProvider::IniSaver::IniReadOpen(const char* name) {
|
||||
.get();
|
||||
}
|
||||
|
||||
void PlotProvider::IniSaver::IniReadLine(void* entry, const char* lineStr) {
|
||||
auto [name, value] = wpi::StringRef{lineStr}.split('=');
|
||||
name = name.trim();
|
||||
value = value.trim();
|
||||
void PlotProvider::IniSaver::IniReadLine(void* entry, const char* line) {
|
||||
auto [name, value] = wpi::split(line, '=');
|
||||
name = wpi::trim(name);
|
||||
value = wpi::trim(value);
|
||||
if (m_forSeries) {
|
||||
static_cast<PlotSeries*>(entry)->ReadIni(name, value);
|
||||
} else {
|
||||
|
||||
@@ -54,9 +54,8 @@ static ImGuiSaver* GetSaverInstance() {
|
||||
return inst;
|
||||
}
|
||||
|
||||
IniSaverBase::IniSaverBase(const wpi::Twine& typeName, IniSaverBackend* backend)
|
||||
: m_typeName(typeName.str()),
|
||||
m_backend{backend ? backend : GetSaverInstance()} {}
|
||||
IniSaverBase::IniSaverBase(std::string_view typeName, IniSaverBackend* backend)
|
||||
: m_typeName(typeName), m_backend{backend ? backend : GetSaverInstance()} {}
|
||||
|
||||
IniSaverBase::~IniSaverBase() {
|
||||
m_backend->Unregister(this);
|
||||
|
||||
@@ -8,15 +8,13 @@
|
||||
#include <cstring>
|
||||
|
||||
#include <imgui_internal.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
|
||||
using namespace glass;
|
||||
|
||||
void NameInfo::SetName(const wpi::Twine& name) {
|
||||
wpi::SmallString<64> nameBuf;
|
||||
auto nameStr = name.toStringRef(nameBuf);
|
||||
size_t len = (std::min)(nameStr.size(), sizeof(m_name) - 1);
|
||||
std::memcpy(m_name, nameStr.data(), len);
|
||||
void NameInfo::SetName(std::string_view name) {
|
||||
size_t len = (std::min)(name.size(), sizeof(m_name) - 1);
|
||||
std::memcpy(m_name, name.data(), len);
|
||||
m_name[len] = '\0';
|
||||
}
|
||||
|
||||
@@ -74,7 +72,7 @@ void NameInfo::GetLabel(char* buf, size_t size, const char* defaultName,
|
||||
}
|
||||
}
|
||||
|
||||
bool NameInfo::ReadIni(wpi::StringRef name, wpi::StringRef value) {
|
||||
bool NameInfo::ReadIni(std::string_view name, std::string_view value) {
|
||||
if (name != "name") {
|
||||
return false;
|
||||
}
|
||||
@@ -140,15 +138,13 @@ bool NameInfo::InputTextName(const char* label_id, ImGuiInputTextFlags flags) {
|
||||
return ImGui::InputText(label_id, m_name, sizeof(m_name), flags);
|
||||
}
|
||||
|
||||
bool OpenInfo::ReadIni(wpi::StringRef name, wpi::StringRef value) {
|
||||
bool OpenInfo::ReadIni(std::string_view name, std::string_view value) {
|
||||
if (name != "open") {
|
||||
return false;
|
||||
}
|
||||
int num;
|
||||
if (value.getAsInteger(10, num)) {
|
||||
return true;
|
||||
if (auto num = wpi::parse_integer<int>(value, 10)) {
|
||||
m_open = num.value();
|
||||
}
|
||||
m_open = num;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -156,7 +152,7 @@ void OpenInfo::WriteIni(ImGuiTextBuffer* out) {
|
||||
out->appendf("open=%d\n", m_open ? 1 : 0);
|
||||
}
|
||||
|
||||
bool NameOpenInfo::ReadIni(wpi::StringRef name, wpi::StringRef value) {
|
||||
bool NameOpenInfo::ReadIni(std::string_view name, std::string_view value) {
|
||||
if (NameInfo::ReadIni(name, value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6,12 +6,11 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
namespace glass {
|
||||
|
||||
@@ -48,7 +47,7 @@ class Storage {
|
||||
public:
|
||||
struct Value {
|
||||
Value() = default;
|
||||
explicit Value(const wpi::Twine& str) : stringVal{str.str()} {}
|
||||
explicit Value(std::string_view str) : stringVal{str} {}
|
||||
|
||||
enum Type { kNone, kInt, kInt64, kBool, kFloat, kDouble, kString };
|
||||
Type type = kNone;
|
||||
@@ -62,29 +61,30 @@ class Storage {
|
||||
std::string stringVal;
|
||||
};
|
||||
|
||||
int GetInt(wpi::StringRef key, int defaultVal = 0) const;
|
||||
int64_t GetInt64(wpi::StringRef key, int64_t defaultVal = 0) const;
|
||||
bool GetBool(wpi::StringRef key, bool defaultVal = false) const;
|
||||
float GetFloat(wpi::StringRef key, float defaultVal = 0.0f) const;
|
||||
double GetDouble(wpi::StringRef key, double defaultVal = 0.0) const;
|
||||
std::string GetString(wpi::StringRef key,
|
||||
const std::string& defaultVal = {}) const;
|
||||
int GetInt(std::string_view key, int defaultVal = 0) const;
|
||||
int64_t GetInt64(std::string_view key, int64_t defaultVal = 0) const;
|
||||
bool GetBool(std::string_view key, bool defaultVal = false) const;
|
||||
float GetFloat(std::string_view key, float defaultVal = 0.0f) const;
|
||||
double GetDouble(std::string_view key, double defaultVal = 0.0) const;
|
||||
std::string GetString(std::string_view key,
|
||||
std::string_view defaultVal = {}) const;
|
||||
|
||||
void SetInt(wpi::StringRef key, int val);
|
||||
void SetInt64(wpi::StringRef key, int64_t val);
|
||||
void SetBool(wpi::StringRef key, bool val);
|
||||
void SetFloat(wpi::StringRef key, float val);
|
||||
void SetDouble(wpi::StringRef key, double val);
|
||||
void SetString(wpi::StringRef key, const wpi::Twine& val);
|
||||
void SetInt(std::string_view key, int val);
|
||||
void SetInt64(std::string_view key, int64_t val);
|
||||
void SetBool(std::string_view key, bool val);
|
||||
void SetFloat(std::string_view key, float val);
|
||||
void SetDouble(std::string_view key, double val);
|
||||
void SetString(std::string_view key, std::string_view val);
|
||||
|
||||
int* GetIntRef(wpi::StringRef key, int defaultVal = 0);
|
||||
int64_t* GetInt64Ref(wpi::StringRef key, int64_t defaultVal = 0);
|
||||
bool* GetBoolRef(wpi::StringRef key, bool defaultVal = false);
|
||||
float* GetFloatRef(wpi::StringRef key, float defaultVal = 0.0f);
|
||||
double* GetDoubleRef(wpi::StringRef key, double defaultVal = 0.0);
|
||||
std::string* GetStringRef(wpi::StringRef key, wpi::StringRef defaultVal = {});
|
||||
int* GetIntRef(std::string_view key, int defaultVal = 0);
|
||||
int64_t* GetInt64Ref(std::string_view key, int64_t defaultVal = 0);
|
||||
bool* GetBoolRef(std::string_view key, bool defaultVal = false);
|
||||
float* GetFloatRef(std::string_view key, float defaultVal = 0.0f);
|
||||
double* GetDoubleRef(std::string_view key, double defaultVal = 0.0);
|
||||
std::string* GetStringRef(std::string_view key,
|
||||
std::string_view defaultVal = {});
|
||||
|
||||
Value& GetValue(wpi::StringRef key);
|
||||
Value& GetValue(std::string_view key);
|
||||
|
||||
void SetData(std::shared_ptr<void>&& data) { m_data = std::move(data); }
|
||||
|
||||
@@ -111,7 +111,7 @@ class Storage {
|
||||
};
|
||||
|
||||
Storage& GetStorage();
|
||||
Storage& GetStorage(wpi::StringRef id);
|
||||
Storage& GetStorage(std::string_view id);
|
||||
|
||||
bool Begin(const char* name, bool* p_open = nullptr,
|
||||
ImGuiWindowFlags flags = 0);
|
||||
@@ -141,8 +141,8 @@ void PushID(const char* str_id);
|
||||
void PushID(const char* str_id_begin, const char* str_id_end);
|
||||
|
||||
// push string into the ID stack (will hash string).
|
||||
inline void PushID(wpi::StringRef str) {
|
||||
PushID(str.begin(), str.end());
|
||||
inline void PushID(std::string_view str) {
|
||||
PushID(str.data(), str.data() + str.size());
|
||||
}
|
||||
|
||||
// push integer into the ID stack (will hash integer).
|
||||
|
||||
@@ -26,7 +26,7 @@ class DataSourceName {
|
||||
DataSourceName() = default;
|
||||
explicit DataSourceName(DataSource* source) : source{source} {}
|
||||
|
||||
bool ReadIni(wpi::StringRef name_, wpi::StringRef value) {
|
||||
bool ReadIni(std::string_view name_, std::string_view value) {
|
||||
return name->ReadIni(name_, value);
|
||||
}
|
||||
void WriteIni(ImGuiTextBuffer* out) { name->WriteIni(out); }
|
||||
|
||||
@@ -8,11 +8,10 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <wpi/Signal.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/spinlock.h>
|
||||
|
||||
namespace glass {
|
||||
@@ -24,9 +23,9 @@ class NameInfo;
|
||||
*/
|
||||
class DataSource {
|
||||
public:
|
||||
explicit DataSource(const wpi::Twine& id);
|
||||
DataSource(const wpi::Twine& id, int index);
|
||||
DataSource(const wpi::Twine& id, int index, int index2);
|
||||
explicit DataSource(std::string_view id);
|
||||
DataSource(std::string_view id, int index);
|
||||
DataSource(std::string_view id, int index, int index2);
|
||||
virtual ~DataSource();
|
||||
|
||||
DataSource(const DataSource&) = delete;
|
||||
@@ -34,7 +33,7 @@ class DataSource {
|
||||
|
||||
const char* GetId() const { return m_id.c_str(); }
|
||||
|
||||
void SetName(const wpi::Twine& name);
|
||||
void SetName(std::string_view name);
|
||||
const char* GetName() const;
|
||||
NameInfo& GetNameInfo() { return *m_name; }
|
||||
|
||||
@@ -69,7 +68,7 @@ class DataSource {
|
||||
|
||||
wpi::sig::SignalBase<wpi::spinlock, double, uint64_t> valueChanged;
|
||||
|
||||
static DataSource* Find(wpi::StringRef id);
|
||||
static DataSource* Find(std::string_view id);
|
||||
|
||||
static wpi::sig::Signal<const char*, DataSource*> sourceCreated;
|
||||
|
||||
|
||||
@@ -8,11 +8,10 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpigui.h>
|
||||
|
||||
#include "glass/Model.h"
|
||||
@@ -52,7 +51,7 @@ class Provider : public WindowManager {
|
||||
*
|
||||
* @param iniName Group name to use in ini file
|
||||
*/
|
||||
explicit Provider(const wpi::Twine& iniName) : WindowManager{iniName} {}
|
||||
explicit Provider(std::string_view iniName) : WindowManager{iniName} {}
|
||||
|
||||
Provider(const Provider&) = delete;
|
||||
Provider& operator=(const Provider&) = delete;
|
||||
@@ -69,7 +68,7 @@ class Provider : public WindowManager {
|
||||
*
|
||||
* @param name View name
|
||||
*/
|
||||
void ShowDefault(wpi::StringRef name);
|
||||
void ShowDefault(std::string_view name);
|
||||
|
||||
/**
|
||||
* Register a model and view combination. Equivalent to calling both
|
||||
@@ -80,7 +79,7 @@ class Provider : public WindowManager {
|
||||
* @param createModel Functor for creating model
|
||||
* @param createView Functor for creating view
|
||||
*/
|
||||
void Register(wpi::StringRef name, ExistsFunc exists,
|
||||
void Register(std::string_view name, ExistsFunc exists,
|
||||
CreateModelFunc createModel, CreateViewFunc createView);
|
||||
|
||||
/**
|
||||
@@ -90,7 +89,7 @@ class Provider : public WindowManager {
|
||||
* @param exists Functor, returns true if model can be created
|
||||
* @param createModel Functor for creating model
|
||||
*/
|
||||
void RegisterModel(wpi::StringRef name, ExistsFunc exists,
|
||||
void RegisterModel(std::string_view name, ExistsFunc exists,
|
||||
CreateModelFunc createModel);
|
||||
|
||||
/**
|
||||
@@ -101,14 +100,14 @@ class Provider : public WindowManager {
|
||||
* @param exists Functor, returns true if view can be created
|
||||
* @param createView Functor for creating view
|
||||
*/
|
||||
void RegisterView(wpi::StringRef name, wpi::StringRef modelName,
|
||||
void RegisterView(std::string_view name, std::string_view modelName,
|
||||
ViewExistsFunc exists, CreateViewFunc createView);
|
||||
|
||||
protected:
|
||||
virtual void Update();
|
||||
|
||||
struct ModelEntry {
|
||||
ModelEntry(wpi::StringRef name, ExistsFunc exists,
|
||||
ModelEntry(std::string_view name, ExistsFunc exists,
|
||||
CreateModelFunc createModel)
|
||||
: name{name},
|
||||
exists{std::move(exists)},
|
||||
@@ -122,7 +121,7 @@ class Provider : public WindowManager {
|
||||
};
|
||||
|
||||
struct ViewEntry {
|
||||
ViewEntry(wpi::StringRef name, ModelEntry* modelEntry,
|
||||
ViewEntry(std::string_view name, ModelEntry* modelEntry,
|
||||
ViewExistsFunc exists, CreateViewFunc createView)
|
||||
: name{name},
|
||||
modelEntry{modelEntry},
|
||||
@@ -143,16 +142,16 @@ class Provider : public WindowManager {
|
||||
using ViewEntries = std::vector<std::unique_ptr<ViewEntry>>;
|
||||
ViewEntries m_viewEntries;
|
||||
|
||||
typename ModelEntries::iterator FindModelEntry(wpi::StringRef name);
|
||||
typename ViewEntries::iterator FindViewEntry(wpi::StringRef name);
|
||||
typename ModelEntries::iterator FindModelEntry(std::string_view name);
|
||||
typename ViewEntries::iterator FindViewEntry(std::string_view name);
|
||||
|
||||
virtual std::unique_ptr<ModelEntry> MakeModelEntry(
|
||||
wpi::StringRef name, ExistsFunc exists, CreateModelFunc createModel) {
|
||||
std::string_view name, ExistsFunc exists, CreateModelFunc createModel) {
|
||||
return std::make_unique<ModelEntry>(name, std::move(exists),
|
||||
std::move(createModel));
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<ViewEntry> MakeViewEntry(wpi::StringRef name,
|
||||
virtual std::unique_ptr<ViewEntry> MakeViewEntry(std::string_view name,
|
||||
ModelEntry* modelEntry,
|
||||
ViewExistsFunc exists,
|
||||
CreateViewFunc createView) {
|
||||
|
||||
@@ -17,7 +17,7 @@ void Provider<Functions>::GlobalInit() {
|
||||
}
|
||||
|
||||
template <typename Functions>
|
||||
void Provider<Functions>::ShowDefault(wpi::StringRef name) {
|
||||
void Provider<Functions>::ShowDefault(std::string_view name) {
|
||||
auto win = GetWindow(name);
|
||||
if (win) {
|
||||
return;
|
||||
@@ -30,7 +30,7 @@ void Provider<Functions>::ShowDefault(wpi::StringRef name) {
|
||||
}
|
||||
|
||||
template <typename Functions>
|
||||
void Provider<Functions>::Register(wpi::StringRef name, ExistsFunc exists,
|
||||
void Provider<Functions>::Register(std::string_view name, ExistsFunc exists,
|
||||
CreateModelFunc createModel,
|
||||
CreateViewFunc createView) {
|
||||
RegisterModel(name, std::move(exists), std::move(createModel));
|
||||
@@ -38,7 +38,8 @@ void Provider<Functions>::Register(wpi::StringRef name, ExistsFunc exists,
|
||||
}
|
||||
|
||||
template <typename Functions>
|
||||
void Provider<Functions>::RegisterModel(wpi::StringRef name, ExistsFunc exists,
|
||||
void Provider<Functions>::RegisterModel(std::string_view name,
|
||||
ExistsFunc exists,
|
||||
CreateModelFunc createModel) {
|
||||
auto it = FindModelEntry(name);
|
||||
// ignore if exists
|
||||
@@ -51,8 +52,8 @@ void Provider<Functions>::RegisterModel(wpi::StringRef name, ExistsFunc exists,
|
||||
}
|
||||
|
||||
template <typename Functions>
|
||||
void Provider<Functions>::RegisterView(wpi::StringRef name,
|
||||
wpi::StringRef modelName,
|
||||
void Provider<Functions>::RegisterView(std::string_view name,
|
||||
std::string_view modelName,
|
||||
ViewExistsFunc exists,
|
||||
CreateViewFunc createView) {
|
||||
// find model; if model doesn't exist, ignore
|
||||
@@ -84,18 +85,18 @@ void Provider<Functions>::Update() {
|
||||
|
||||
template <typename Functions>
|
||||
typename Provider<Functions>::ModelEntries::iterator
|
||||
Provider<Functions>::FindModelEntry(wpi::StringRef name) {
|
||||
Provider<Functions>::FindModelEntry(std::string_view name) {
|
||||
return std::lower_bound(
|
||||
m_modelEntries.begin(), m_modelEntries.end(), name,
|
||||
[](const auto& elem, wpi::StringRef s) { return elem->name < s; });
|
||||
[](const auto& elem, std::string_view s) { return elem->name < s; });
|
||||
}
|
||||
|
||||
template <typename Functions>
|
||||
typename Provider<Functions>::ViewEntries::iterator
|
||||
Provider<Functions>::FindViewEntry(wpi::StringRef name) {
|
||||
Provider<Functions>::FindViewEntry(std::string_view name) {
|
||||
return std::lower_bound(
|
||||
m_viewEntries.begin(), m_viewEntries.end(), name,
|
||||
[](const auto& elem, wpi::StringRef s) { return elem->name < s; });
|
||||
[](const auto& elem, std::string_view s) { return elem->name < s; });
|
||||
}
|
||||
|
||||
} // namespace glass
|
||||
|
||||
@@ -6,11 +6,10 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
#include "glass/View.h"
|
||||
|
||||
@@ -23,9 +22,9 @@ namespace glass {
|
||||
class Window {
|
||||
public:
|
||||
Window() = default;
|
||||
explicit Window(wpi::StringRef id) : m_id{id}, m_defaultName{id} {}
|
||||
explicit Window(std::string_view id) : m_id{id}, m_defaultName{id} {}
|
||||
|
||||
wpi::StringRef GetId() const { return m_id; }
|
||||
std::string_view GetId() const { return m_id; }
|
||||
|
||||
enum Visibility { kHide = 0, kShow, kDisabled };
|
||||
|
||||
@@ -43,8 +42,8 @@ class Window {
|
||||
|
||||
void SetFlags(ImGuiWindowFlags flags) { m_flags = flags; }
|
||||
|
||||
void SetName(const wpi::Twine& name) { m_name = name.str(); }
|
||||
void SetDefaultName(const wpi::Twine& name) { m_defaultName = name.str(); }
|
||||
void SetName(std::string_view name) { m_name = name; }
|
||||
void SetDefaultName(std::string_view name) { m_defaultName = name; }
|
||||
|
||||
/**
|
||||
* Normally windows provide a right-click popup menu on the title bar to
|
||||
|
||||
@@ -6,13 +6,12 @@
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <wpi/FunctionExtras.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
|
||||
#include "glass/Window.h"
|
||||
#include "glass/support/IniSaverBase.h"
|
||||
@@ -34,7 +33,7 @@ class WindowManager {
|
||||
*
|
||||
* @param iniName Group name to use in ini file
|
||||
*/
|
||||
explicit WindowManager(const wpi::Twine& iniName);
|
||||
explicit WindowManager(std::string_view iniName);
|
||||
virtual ~WindowManager() = default;
|
||||
|
||||
WindowManager(const WindowManager&) = delete;
|
||||
@@ -67,7 +66,7 @@ class WindowManager {
|
||||
* @param id unique identifier of the window (title bar)
|
||||
* @param display window contents display function
|
||||
*/
|
||||
Window* AddWindow(wpi::StringRef id, wpi::unique_function<void()> display);
|
||||
Window* AddWindow(std::string_view id, wpi::unique_function<void()> display);
|
||||
|
||||
/**
|
||||
* Adds window to GUI. The view's display function is called from within a
|
||||
@@ -85,7 +84,7 @@ class WindowManager {
|
||||
* @param view view object
|
||||
* @return Window, or nullptr on duplicate window
|
||||
*/
|
||||
Window* AddWindow(wpi::StringRef id, std::unique_ptr<View> view);
|
||||
Window* AddWindow(std::string_view id, std::unique_ptr<View> view);
|
||||
|
||||
/**
|
||||
* Adds window to GUI. A View must be assigned to the returned Window
|
||||
@@ -102,7 +101,7 @@ class WindowManager {
|
||||
* @param id unique identifier of the window (default title bar)
|
||||
* @return Window, or nullptr on duplicate window
|
||||
*/
|
||||
Window* GetOrAddWindow(wpi::StringRef id, bool duplicateOk = false);
|
||||
Window* GetOrAddWindow(std::string_view id, bool duplicateOk = false);
|
||||
|
||||
/**
|
||||
* Gets existing window. If none exists, returns nullptr.
|
||||
@@ -110,7 +109,7 @@ class WindowManager {
|
||||
* @param id unique identifier of the window (default title bar)
|
||||
* @return Window, or nullptr if window does not exist
|
||||
*/
|
||||
Window* GetWindow(wpi::StringRef id);
|
||||
Window* GetWindow(std::string_view id);
|
||||
|
||||
protected:
|
||||
virtual void DisplayWindows();
|
||||
@@ -121,7 +120,7 @@ class WindowManager {
|
||||
private:
|
||||
class IniSaver : public IniSaverBase {
|
||||
public:
|
||||
explicit IniSaver(const wpi::Twine& typeName, WindowManager* manager)
|
||||
explicit IniSaver(std::string_view typeName, WindowManager* manager)
|
||||
: IniSaverBase{typeName}, m_manager{manager} {}
|
||||
|
||||
void* IniReadOpen(const char* name) override;
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
#include "glass/Model.h"
|
||||
|
||||
@@ -31,6 +32,6 @@ class AnalogInputsModel : public Model {
|
||||
|
||||
void DisplayAnalogInput(AnalogInputModel* model, int index);
|
||||
void DisplayAnalogInputs(AnalogInputsModel* model,
|
||||
wpi::StringRef noneMsg = "No analog inputs");
|
||||
std::string_view noneMsg = "No analog inputs");
|
||||
|
||||
} // namespace glass
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
#include "glass/Model.h"
|
||||
|
||||
@@ -57,6 +58,6 @@ class DIOsModel : public Model {
|
||||
|
||||
void DisplayDIO(DIOModel* model, int index, bool outputsEnabled);
|
||||
void DisplayDIOs(DIOsModel* model, bool outputsEnabled,
|
||||
wpi::StringRef noneMsg = "No Digital I/O");
|
||||
std::string_view noneMsg = "No Digital I/O");
|
||||
|
||||
} // namespace glass
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
#include "glass/Model.h"
|
||||
|
||||
@@ -15,7 +16,7 @@ class DataSource;
|
||||
|
||||
class EncoderModel : public Model {
|
||||
public:
|
||||
virtual void SetName(const wpi::Twine& name);
|
||||
virtual void SetName(std::string_view name);
|
||||
|
||||
virtual const char* GetSimDevice() const = 0;
|
||||
|
||||
@@ -51,6 +52,6 @@ class EncodersModel : public Model {
|
||||
|
||||
void DisplayEncoder(EncoderModel* model);
|
||||
void DisplayEncoders(EncodersModel* model,
|
||||
wpi::StringRef noneMsg = "No encoders");
|
||||
std::string_view noneMsg = "No encoders");
|
||||
|
||||
} // namespace glass
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
#include "glass/Model.h"
|
||||
|
||||
namespace glass {
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
#include "glass/Model.h"
|
||||
|
||||
@@ -49,7 +50,7 @@ class PCMsModel : public Model {
|
||||
|
||||
bool DisplayPCMSolenoids(PCMModel* model, int index, bool outputsEnabled);
|
||||
void DisplayPCMsSolenoids(PCMsModel* model, bool outputsEnabled,
|
||||
wpi::StringRef noneMsg = "No solenoids");
|
||||
std::string_view noneMsg = "No solenoids");
|
||||
|
||||
void DisplayCompressorDevice(PCMModel* model, int index, bool outputsEnabled);
|
||||
void DisplayCompressorDevice(CompressorModel* model, int index,
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
#include "glass/Model.h"
|
||||
|
||||
@@ -33,6 +34,6 @@ class PDPsModel : public Model {
|
||||
};
|
||||
|
||||
void DisplayPDP(PDPModel* model, int index);
|
||||
void DisplayPDPs(PDPsModel* model, wpi::StringRef noneMsg = "No PDPs");
|
||||
void DisplayPDPs(PDPsModel* model, std::string_view noneMsg = "No PDPs");
|
||||
|
||||
} // namespace glass
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
#include "glass/Model.h"
|
||||
|
||||
@@ -31,6 +32,6 @@ class PWMsModel : public Model {
|
||||
|
||||
void DisplayPWM(PWMModel* model, int index, bool outputsEnabled);
|
||||
void DisplayPWMs(PWMsModel* model, bool outputsEnabled,
|
||||
wpi::StringRef noneMsg = "No PWM outputs");
|
||||
std::string_view noneMsg = "No PWM outputs");
|
||||
|
||||
} // namespace glass
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
#include "glass/Model.h"
|
||||
|
||||
@@ -30,6 +31,6 @@ class RelaysModel : public Model {
|
||||
|
||||
void DisplayRelay(RelayModel* model, int index, bool outputsEnabled);
|
||||
void DisplayRelays(RelaysModel* model, bool outputsEnabled,
|
||||
wpi::StringRef noneMsg = "No relays");
|
||||
std::string_view noneMsg = "No relays");
|
||||
|
||||
} // namespace glass
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <wpi/STLExtras.h>
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
#include "glass/Model.h"
|
||||
|
||||
namespace glass {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user