Add braces to C++ single-line loops and conditionals (NFC) (#2973)

This makes code easier to read and more consistent between C++ and Java.
Also update clang-format settings to always add a line break (even if no braces are used).
This commit is contained in:
Peter Johnson
2020-12-28 12:58:06 -08:00
committed by GitHub
parent 0291a3ff56
commit 2aed432b4b
634 changed files with 10716 additions and 3938 deletions

View File

@@ -14,10 +14,10 @@ AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortFunctionsOnASingleLine: Inline
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true

View File

@@ -143,7 +143,9 @@ bool ReadConfig() {
// cameras
try {
for (auto&& camera : j.at("cameras")) {
if (!ReadCameraConfig(camera)) return false;
if (!ReadCameraConfig(camera)) {
return false;
}
}
} catch (const wpi::json::exception& e) {
ParseError() << "could not read cameras: " << e.what() << '\n';
@@ -164,10 +166,14 @@ void StartCamera(const CameraConfig& config) {
} // namespace
int main(int argc, char* argv[]) {
if (argc >= 2) configFile = argv[1];
if (argc >= 2) {
configFile = argv[1];
}
// read configuration
if (!ReadConfig()) return EXIT_FAILURE;
if (!ReadConfig()) {
return EXIT_FAILURE;
}
// start NetworkTables
auto ntinst = nt::NetworkTableInstance::GetDefault();
@@ -180,8 +186,12 @@ int main(int argc, char* argv[]) {
}
// start cameras
for (auto&& camera : cameras) StartCamera(camera);
for (auto&& camera : cameras) {
StartCamera(camera);
}
// loop forever
for (;;) std::this_thread::sleep_for(std::chrono::seconds(10));
for (;;) {
std::this_thread::sleep_for(std::chrono::seconds(10));
}
}

View File

@@ -71,7 +71,9 @@ static wpi::StringRef MakeSourceValue(CS_Source source,
wpi::StringRef prefix{"ip:"};
buf.append(prefix.begin(), prefix.end());
auto urls = cs::GetHttpCameraUrls(source, &status);
if (!urls.empty()) buf.append(urls[0].begin(), urls[0].end());
if (!urls.empty()) {
buf.append(urls[0].begin(), urls[0].end());
}
break;
}
case CS_SOURCE_CV:
@@ -99,8 +101,9 @@ std::vector<std::string> CameraServer::Impl::GetSinkStreamValues(CS_Sink sink) {
CS_Status status = 0;
// Ignore all but MjpegServer
if (cs::GetSinkKind(sink, &status) != CS_SINK_MJPEG)
return std::vector<std::string>{};
if (cs::GetSinkKind(sink, &status) != CS_SINK_MJPEG) {
return {};
}
// Get port
int port = cs::GetMjpegServerPort(sink, &status);
@@ -116,7 +119,9 @@ std::vector<std::string> CameraServer::Impl::GetSinkStreamValues(CS_Sink sink) {
values.emplace_back(MakeStreamValue(cs::GetHostname() + ".local", port));
for (const auto& addr : m_addresses) {
if (addr == "127.0.0.1") continue; // ignore localhost
if (addr == "127.0.0.1") {
continue; // ignore localhost
}
values.emplace_back(MakeStreamValue(addr, port));
}
}
@@ -129,12 +134,15 @@ std::vector<std::string> CameraServer::Impl::GetSourceStreamValues(
CS_Status status = 0;
// Ignore all but HttpCamera
if (cs::GetSourceKind(source, &status) != CS_SOURCE_HTTP)
return std::vector<std::string>{};
if (cs::GetSourceKind(source, &status) != CS_SOURCE_HTTP) {
return {};
}
// Generate values
auto values = cs::GetHttpCameraUrls(source, &status);
for (auto& value : values) value = "mjpg:" + value;
for (auto& value : values) {
value = "mjpg:" + value;
}
#ifdef __FRC_ROBORIO__
// Look to see if we have a passthrough server for this source
@@ -165,16 +173,24 @@ void CameraServer::Impl::UpdateStreamValues() {
// Get the source's subtable (if none exists, we're done)
CS_Source source = m_fixedSources.lookup(sink);
if (source == 0) source = cs::GetSinkSource(sink, &status);
if (source == 0) continue;
if (source == 0) {
source = cs::GetSinkSource(sink, &status);
}
if (source == 0) {
continue;
}
auto table = m_tables.lookup(source);
if (table) {
// Don't set stream values if this is a HttpCamera passthrough
if (cs::GetSourceKind(source, &status) == CS_SOURCE_HTTP) continue;
if (cs::GetSourceKind(source, &status) == CS_SOURCE_HTTP) {
continue;
}
// Set table value
auto values = GetSinkStreamValues(sink);
if (!values.empty()) table->GetEntry("streams").SetStringArray(values);
if (!values.empty()) {
table->GetEntry("streams").SetStringArray(values);
}
}
}
@@ -187,7 +203,9 @@ void CameraServer::Impl::UpdateStreamValues() {
if (table) {
// Set table value
auto values = GetSourceStreamValues(source);
if (!values.empty()) table->GetEntry("streams").SetStringArray(values);
if (!values.empty()) {
table->GetEntry("streams").SetStringArray(values);
}
}
}
}
@@ -221,8 +239,9 @@ static std::string VideoModeToString(const cs::VideoMode& mode) {
static std::vector<std::string> GetSourceModeValues(int source) {
std::vector<std::string> rv;
CS_Status status = 0;
for (const auto& mode : cs::EnumerateSourceVideoModes(source, &status))
for (const auto& mode : cs::EnumerateSourceVideoModes(source, &status)) {
rv.emplace_back(VideoModeToString(mode));
}
return rv;
}
@@ -247,10 +266,11 @@ static void PutSourcePropertyValue(nt::NetworkTable* table,
nt::NetworkTableEntry entry = table->GetEntry(name);
switch (event.propertyKind) {
case CS_PROP_BOOLEAN:
if (isNew)
if (isNew) {
entry.SetDefaultBoolean(event.value != 0);
else
} else {
entry.SetBoolean(event.value != 0);
}
break;
case CS_PROP_INTEGER:
case CS_PROP_ENUM:
@@ -269,10 +289,11 @@ static void PutSourcePropertyValue(nt::NetworkTable* table,
}
break;
case CS_PROP_STRING:
if (isNew)
if (isNew) {
entry.SetDefaultString(event.valueStr);
else
} else {
entry.SetString(event.valueStr);
}
break;
default:
break;
@@ -348,30 +369,38 @@ CameraServer::Impl::Impl()
}
case cs::VideoEvent::kSourceDisconnected: {
auto table = GetSourceTable(event.sourceHandle);
if (table) table->GetEntry("connected").SetBoolean(false);
if (table) {
table->GetEntry("connected").SetBoolean(false);
}
break;
}
case cs::VideoEvent::kSourceVideoModesUpdated: {
auto table = GetSourceTable(event.sourceHandle);
if (table)
if (table) {
table->GetEntry("modes").SetStringArray(
GetSourceModeValues(event.sourceHandle));
}
break;
}
case cs::VideoEvent::kSourceVideoModeChanged: {
auto table = GetSourceTable(event.sourceHandle);
if (table)
if (table) {
table->GetEntry("mode").SetString(VideoModeToString(event.mode));
}
break;
}
case cs::VideoEvent::kSourcePropertyCreated: {
auto table = GetSourceTable(event.sourceHandle);
if (table) PutSourcePropertyValue(table.get(), event, true);
if (table) {
PutSourcePropertyValue(table.get(), event, true);
}
break;
}
case cs::VideoEvent::kSourcePropertyValueUpdated: {
auto table = GetSourceTable(event.sourceHandle);
if (table) PutSourcePropertyValue(table.get(), event, false);
if (table) {
PutSourcePropertyValue(table.get(), event, false);
}
break;
}
case cs::VideoEvent::kSourcePropertyChoicesUpdated: {
@@ -413,10 +442,14 @@ CameraServer::Impl::Impl()
// get source (sourceName/...)
auto subKeyIndex = relativeKey.find('/');
if (subKeyIndex == wpi::StringRef::npos) return;
if (subKeyIndex == wpi::StringRef::npos) {
return;
}
wpi::StringRef sourceName = relativeKey.slice(0, subKeyIndex);
auto sourceIt = m_sources.find(sourceName);
if (sourceIt == m_sources.end()) return;
if (sourceIt == m_sources.end()) {
return;
}
// get subkey
relativeKey = relativeKey.substr(subKeyIndex + 1);
@@ -689,7 +722,9 @@ cs::VideoSink CameraServer::GetServer(const wpi::Twine& name) {
void CameraServer::AddCamera(const cs::VideoSource& camera) {
std::string name = camera.GetName();
std::scoped_lock lock(m_impl->m_mutex);
if (m_impl->m_primarySourceName.empty()) m_impl->m_primarySourceName = name;
if (m_impl->m_primarySourceName.empty()) {
m_impl->m_primarySourceName = name;
}
m_impl->m_sources.try_emplace(name, camera);
}
@@ -701,13 +736,18 @@ void CameraServer::RemoveCamera(const wpi::Twine& name) {
void CameraServer::SetSize(int size) {
std::scoped_lock lock(m_impl->m_mutex);
if (m_impl->m_primarySourceName.empty()) return;
if (m_impl->m_primarySourceName.empty()) {
return;
}
auto it = m_impl->m_sources.find(m_impl->m_primarySourceName);
if (it == m_impl->m_sources.end()) return;
if (size == kSize160x120)
if (it == m_impl->m_sources.end()) {
return;
}
if (size == kSize160x120) {
it->second.SetResolution(160, 120);
else if (size == kSize320x240)
} else if (size == kSize320x240) {
it->second.SetResolution(320, 240);
else if (size == kSize640x480)
} else if (size == kSize640x480) {
it->second.SetResolution(640, 480);
}
}

View File

@@ -53,4 +53,6 @@ void VisionRunnerBase::RunForever() {
}
}
void VisionRunnerBase::Stop() { m_enabled = false; }
void VisionRunnerBase::Stop() {
m_enabled = false;
}

View File

@@ -20,7 +20,8 @@ inline cs::AxisCamera CameraServer::AddAxisCamera(
const wpi::Twine& name, std::initializer_list<T> hosts) {
std::vector<std::string> vec;
vec.reserve(hosts.size());
for (const auto& host : hosts) vec.emplace_back(host);
for (const auto& host : hosts)
vec.emplace_back(host);
return AddAxisCamera(name, vec);
}

View File

@@ -2,4 +2,6 @@
// 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.
int main() { return 0; }
int main() {
return 0;
}

View File

@@ -16,8 +16,9 @@ int main() {
<< ")\n";
if (!caminfo.otherPaths.empty()) {
wpi::outs() << "Other device paths:\n";
for (auto&& path : caminfo.otherPaths)
for (auto&& path : caminfo.otherPaths) {
wpi::outs() << " " << path << '\n';
}
}
cs::UsbCamera camera{"usbcam", caminfo.dev};
@@ -45,7 +46,9 @@ int main() {
<< "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()) {
continue;
}
wpi::outs() << "\n " << i << ": " << choices[i];
}
break;

View File

@@ -34,18 +34,22 @@ int main(int argc, char** argv) {
} else {
wpi::StringRef propVal{argv[arg]};
int intVal;
if (propVal.getAsInteger(10, intVal))
if (propVal.getAsInteger(10, intVal)) {
camera.GetProperty(propName).SetString(propVal);
else
} else {
camera.GetProperty(propName).Set(intVal);
}
propName = wpi::StringRef{};
}
}
if (arg < argc && wpi::StringRef{argv[arg]} == "--") ++arg;
if (arg < argc && wpi::StringRef{argv[arg]} == "--") {
++arg;
}
// Wait to connect
while (!camera.IsConnected())
while (!camera.IsConnected()) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
// Set rest
propName = wpi::StringRef{};
@@ -55,10 +59,11 @@ int main(int argc, char** argv) {
} else {
wpi::StringRef propVal{argv[arg]};
int intVal;
if (propVal.getAsInteger(10, intVal))
if (propVal.getAsInteger(10, intVal)) {
camera.GetProperty(propName).SetString(propVal);
else
} else {
camera.GetProperty(propName).Set(intVal);
}
propName = wpi::StringRef{};
}
}
@@ -88,7 +93,9 @@ int main(int argc, char** argv) {
<< "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()) {
continue;
}
wpi::outs() << "\n " << i << ": " << choices[i];
}
break;

View File

@@ -11,8 +11,9 @@
int main() {
wpi::outs() << "hostname: " << cs::GetHostname() << '\n';
wpi::outs() << "IPv4 network addresses:\n";
for (const auto& addr : cs::GetNetworkInterfaces())
for (const auto& addr : cs::GetNetworkInterfaces()) {
wpi::outs() << " " << addr << '\n';
}
cs::UsbCamera camera{"usbcam", 0};
camera.SetVideoMode(cs::VideoMode::kMJPEG, 320, 240, 30);
cs::MjpegServer mjpegServer{"httpserver", 8081};

View File

@@ -50,7 +50,9 @@ int main() {
} else {
{
std::scoped_lock lock(sharedFreeListMutex);
for (auto mat : sharedFreeList) sourceFreeList.emplace_back(mat);
for (auto mat : sharedFreeList) {
sourceFreeList.emplace_back(mat);
}
sharedFreeList.clear();
}
if (!sourceFreeList.empty()) {
@@ -68,7 +70,9 @@ int main() {
auto prev = latestFrame.exchange(out);
// put prev on free list
if (prev) sourceFreeList.emplace_back(prev);
if (prev) {
sourceFreeList.emplace_back(prev);
}
}
});

View File

@@ -6,4 +6,6 @@
#include "cscore.h"
int main() { std::cout << cs::GetHostname() << std::endl; }
int main() {
std::cout << cs::GetHostname() << std::endl;
}

View File

@@ -30,16 +30,22 @@ CvSinkImpl::CvSinkImpl(const wpi::Twine& name, wpi::Logger& logger,
std::function<void(uint64_t time)> processFrame)
: SinkImpl{name, logger, notifier, telemetry} {}
CvSinkImpl::~CvSinkImpl() { Stop(); }
CvSinkImpl::~CvSinkImpl() {
Stop();
}
void CvSinkImpl::Stop() {
m_active = false;
// wake up any waiters by forcing an empty frame to be sent
if (auto source = GetSource()) source->Wakeup();
if (auto source = GetSource()) {
source->Wakeup();
}
// join thread
if (m_thread.joinable()) m_thread.join();
if (m_thread.joinable()) {
m_thread.join();
}
}
uint64_t CvSinkImpl::GrabFrame(cv::Mat& image) {
@@ -106,7 +112,9 @@ void CvSinkImpl::ThreadMain() {
}
SDEBUG4("waiting for frame");
Frame frame = source->GetNextFrame(); // blocks
if (!m_active) break;
if (!m_active) {
break;
}
if (!frame) {
// Bad frame; sleep for 10 ms so we don't consume all processor time.
std::this_thread::sleep_for(std::chrono::milliseconds(10));
@@ -240,7 +248,9 @@ uint64_t CS_GrabSinkFrameTimeoutCpp(CS_Sink sink, cv::Mat* image,
char* CS_GetSinkError(CS_Sink sink, CS_Status* status) {
wpi::SmallString<128> buf;
auto str = cs::GetSinkError(sink, buf, status);
if (*status != 0) return nullptr;
if (*status != 0) {
return nullptr;
}
return cs::ConvertToC(str);
}

View File

@@ -29,10 +29,11 @@ CvSourceImpl::~CvSourceImpl() {}
void CvSourceImpl::PutFrame(cv::Mat& image) {
// We only support 8-bit images; convert if necessary.
cv::Mat finalImage;
if (image.depth() == CV_8U)
if (image.depth() == CV_8U) {
finalImage = image;
else
} else {
image.convertTo(finalImage, CV_8U);
}
std::unique_ptr<Image> dest;
switch (image.channels()) {
@@ -224,7 +225,9 @@ void CS_SetSourceEnumPropertyChoices(CS_Source source, CS_Property property,
CS_Status* status) {
wpi::SmallVector<std::string, 8> vec;
vec.reserve(count);
for (int i = 0; i < count; ++i) vec.push_back(choices[i]);
for (int i = 0; i < count; ++i) {
vec.push_back(choices[i]);
}
return cs::SetSourceEnumPropertyChoices(source, property, vec, status);
}

View File

@@ -32,22 +32,31 @@ Frame::Frame(SourceImpl& source, std::unique_ptr<Image> image, Time time)
}
Image* Frame::GetNearestImage(int width, int height) const {
if (!m_impl) return nullptr;
if (!m_impl) {
return nullptr;
}
std::scoped_lock lock(m_impl->mutex);
Image* found = nullptr;
// Ideally we want the smallest image at least width/height in size
for (auto i : m_impl->images) {
if (i->IsLarger(width, height) && (!found || (i->IsSmaller(*found))))
if (i->IsLarger(width, height) && (!found || (i->IsSmaller(*found)))) {
found = i;
}
}
if (found) {
return found;
}
if (found) return found;
// Find the largest image (will be less than width/height)
for (auto i : m_impl->images) {
if (!found || (i->IsLarger(*found))) found = i;
if (!found || (i->IsLarger(*found))) {
found = i;
}
}
if (found) {
return found;
}
if (found) return found;
// Shouldn't reach this, but just in case...
return m_impl->images.empty() ? nullptr : m_impl->images[0];
@@ -56,7 +65,9 @@ Image* Frame::GetNearestImage(int width, int height) const {
Image* Frame::GetNearestImage(int width, int height,
VideoMode::PixelFormat pixelFormat,
int jpegQuality) const {
if (!m_impl) return nullptr;
if (!m_impl) {
return nullptr;
}
std::scoped_lock lock(m_impl->mutex);
Image* found = nullptr;
@@ -71,19 +82,25 @@ Image* Frame::GetNearestImage(int width, int height,
// 1) Same width, height, pixelFormat, and (possibly) JPEG quality
// (e.g. exactly what we want)
for (auto i : m_impl->images) {
if (i->Is(width, height, pixelFormat, jpegQuality)) return i;
if (i->Is(width, height, pixelFormat, jpegQuality)) {
return i;
}
}
// 2) Same width, height, different (but non-JPEG) pixelFormat (color conv)
// 2a) If we want JPEG output, prefer BGR over other pixel formats
if (pixelFormat == VideoMode::kMJPEG) {
for (auto i : m_impl->images) {
if (i->Is(width, height, VideoMode::kBGR)) return i;
if (i->Is(width, height, VideoMode::kBGR)) {
return i;
}
}
}
for (auto i : m_impl->images) {
if (i->Is(width, height) && i->pixelFormat != VideoMode::kMJPEG) return i;
if (i->Is(width, height) && i->pixelFormat != VideoMode::kMJPEG) {
return i;
}
}
// 3) Different width, height, same pixelFormat (only if non-JPEG) (resample)
@@ -91,17 +108,23 @@ Image* Frame::GetNearestImage(int width, int height,
// 3a) Smallest image at least width/height in size
for (auto i : m_impl->images) {
if (i->IsLarger(width, height) && i->pixelFormat == pixelFormat &&
(!found || (i->IsSmaller(*found))))
(!found || (i->IsSmaller(*found)))) {
found = i;
}
}
if (found) {
return found;
}
if (found) return found;
// 3b) Largest image (less than width/height)
for (auto i : m_impl->images) {
if (i->pixelFormat == pixelFormat && (!found || (i->IsLarger(*found))))
if (i->pixelFormat == pixelFormat && (!found || (i->IsLarger(*found)))) {
found = i;
}
}
if (found) {
return found;
}
if (found) return found;
}
// 4) Different width, height, different (but non-JPEG) pixelFormat
@@ -109,18 +132,24 @@ Image* Frame::GetNearestImage(int width, int height,
// 4a) Smallest image at least width/height in size
for (auto i : m_impl->images) {
if (i->IsLarger(width, height) && i->pixelFormat != VideoMode::kMJPEG &&
(!found || (i->IsSmaller(*found))))
(!found || (i->IsSmaller(*found)))) {
found = i;
}
}
if (found) {
return found;
}
if (found) return found;
// 4b) Largest image (less than width/height)
for (auto i : m_impl->images) {
if (i->pixelFormat != VideoMode::kMJPEG &&
(!found || (i->IsLarger(*found))))
(!found || (i->IsLarger(*found)))) {
found = i;
}
}
if (found) {
return found;
}
if (found) return found;
// 5) Same width, height, JPEG pixelFormat (decompression). As there may be
// multiple JPEG images, find the highest quality one.
@@ -130,27 +159,37 @@ Image* Frame::GetNearestImage(int width, int height,
found = i;
// consider one without a quality setting to be the highest quality
// (e.g. directly from the camera)
if (i->jpegQuality == -1) break;
if (i->jpegQuality == -1) {
break;
}
}
}
if (found) return found;
if (found) {
return found;
}
// 6) Different width, height, JPEG pixelFormat (decompression)
// 6a) Smallest image at least width/height in size
for (auto i : m_impl->images) {
if (i->IsLarger(width, height) && i->pixelFormat == VideoMode::kMJPEG &&
(!found || (i->IsSmaller(*found))))
(!found || (i->IsSmaller(*found)))) {
found = i;
}
}
if (found) {
return found;
}
if (found) return found;
// 6b) Largest image (less than width/height)
for (auto i : m_impl->images) {
if (i->pixelFormat != VideoMode::kMJPEG &&
(!found || (i->IsLarger(*found))))
(!found || (i->IsLarger(*found)))) {
found = i;
}
}
if (found) {
return found;
}
if (found) return found;
// Shouldn't reach this, but just in case...
return m_impl->images.empty() ? nullptr : m_impl->images[0];
@@ -158,9 +197,10 @@ Image* Frame::GetNearestImage(int width, int height,
Image* Frame::ConvertImpl(Image* image, VideoMode::PixelFormat pixelFormat,
int requiredJpegQuality, int defaultJpegQuality) {
if (!image ||
image->Is(image->width, image->height, pixelFormat, requiredJpegQuality))
if (!image || image->Is(image->width, image->height, pixelFormat,
requiredJpegQuality)) {
return image;
}
Image* cur = image;
// If the source image is a JPEG, we need to decode it before we can do
@@ -169,7 +209,9 @@ Image* Frame::ConvertImpl(Image* image, VideoMode::PixelFormat pixelFormat,
// would have returned above).
if (cur->pixelFormat == VideoMode::kMJPEG) {
cur = ConvertMJPEGToBGR(cur);
if (pixelFormat == VideoMode::kBGR) return cur;
if (pixelFormat == VideoMode::kBGR) {
return cur;
}
}
// Color convert
@@ -179,17 +221,19 @@ Image* Frame::ConvertImpl(Image* image, VideoMode::PixelFormat pixelFormat,
if (cur->pixelFormat == VideoMode::kYUYV) {
// Check to see if BGR version already exists...
if (Image* newImage =
GetExistingImage(cur->width, cur->height, VideoMode::kBGR))
GetExistingImage(cur->width, cur->height, VideoMode::kBGR)) {
cur = newImage;
else
} else {
cur = ConvertYUYVToBGR(cur);
}
} else if (cur->pixelFormat == VideoMode::kGray) {
// Check to see if BGR version already exists...
if (Image* newImage =
GetExistingImage(cur->width, cur->height, VideoMode::kBGR))
GetExistingImage(cur->width, cur->height, VideoMode::kBGR)) {
cur = newImage;
else
} else {
cur = ConvertGrayToBGR(cur);
}
}
return ConvertBGRToRGB565(cur);
case VideoMode::kGray:
@@ -197,17 +241,19 @@ Image* Frame::ConvertImpl(Image* image, VideoMode::PixelFormat pixelFormat,
if (cur->pixelFormat == VideoMode::kYUYV) {
// Check to see if BGR version already exists...
if (Image* newImage =
GetExistingImage(cur->width, cur->height, VideoMode::kBGR))
GetExistingImage(cur->width, cur->height, VideoMode::kBGR)) {
cur = newImage;
else
} else {
cur = ConvertYUYVToBGR(cur);
}
} else if (cur->pixelFormat == VideoMode::kRGB565) {
// Check to see if BGR version already exists...
if (Image* newImage =
GetExistingImage(cur->width, cur->height, VideoMode::kBGR))
GetExistingImage(cur->width, cur->height, VideoMode::kBGR)) {
cur = newImage;
else
} else {
cur = ConvertRGB565ToBGR(cur);
}
}
return ConvertBGRToGray(cur);
case VideoMode::kBGR:
@@ -217,10 +263,11 @@ Image* Frame::ConvertImpl(Image* image, VideoMode::PixelFormat pixelFormat,
} else if (cur->pixelFormat == VideoMode::kRGB565) {
cur = ConvertRGB565ToBGR(cur);
} else if (cur->pixelFormat == VideoMode::kGray) {
if (pixelFormat == VideoMode::kBGR)
if (pixelFormat == VideoMode::kBGR) {
return ConvertGrayToBGR(cur);
else
} else {
return ConvertGrayToMJPEG(cur, defaultJpegQuality);
}
}
break;
case VideoMode::kYUYV:
@@ -229,14 +276,17 @@ Image* Frame::ConvertImpl(Image* image, VideoMode::PixelFormat pixelFormat,
}
// Compress if destination is JPEG
if (pixelFormat == VideoMode::kMJPEG)
if (pixelFormat == VideoMode::kMJPEG) {
cur = ConvertBGRToMJPEG(cur, defaultJpegQuality);
}
return cur;
}
Image* Frame::ConvertMJPEGToBGR(Image* image) {
if (!image || image->pixelFormat != VideoMode::kMJPEG) return nullptr;
if (!image || image->pixelFormat != VideoMode::kMJPEG) {
return nullptr;
}
// Allocate an BGR image
auto newImage =
@@ -257,7 +307,9 @@ Image* Frame::ConvertMJPEGToBGR(Image* image) {
}
Image* Frame::ConvertMJPEGToGray(Image* image) {
if (!image || image->pixelFormat != VideoMode::kMJPEG) return nullptr;
if (!image || image->pixelFormat != VideoMode::kMJPEG) {
return nullptr;
}
// Allocate an grayscale image
auto newImage =
@@ -278,7 +330,9 @@ Image* Frame::ConvertMJPEGToGray(Image* image) {
}
Image* Frame::ConvertYUYVToBGR(Image* image) {
if (!image || image->pixelFormat != VideoMode::kYUYV) return nullptr;
if (!image || image->pixelFormat != VideoMode::kYUYV) {
return nullptr;
}
// Allocate a BGR image
auto newImage =
@@ -298,7 +352,9 @@ Image* Frame::ConvertYUYVToBGR(Image* image) {
}
Image* Frame::ConvertBGRToRGB565(Image* image) {
if (!image || image->pixelFormat != VideoMode::kBGR) return nullptr;
if (!image || image->pixelFormat != VideoMode::kBGR) {
return nullptr;
}
// Allocate a RGB565 image
auto newImage =
@@ -318,7 +374,9 @@ Image* Frame::ConvertBGRToRGB565(Image* image) {
}
Image* Frame::ConvertRGB565ToBGR(Image* image) {
if (!image || image->pixelFormat != VideoMode::kRGB565) return nullptr;
if (!image || image->pixelFormat != VideoMode::kRGB565) {
return nullptr;
}
// Allocate a BGR image
auto newImage =
@@ -338,7 +396,9 @@ Image* Frame::ConvertRGB565ToBGR(Image* image) {
}
Image* Frame::ConvertBGRToGray(Image* image) {
if (!image || image->pixelFormat != VideoMode::kBGR) return nullptr;
if (!image || image->pixelFormat != VideoMode::kBGR) {
return nullptr;
}
// Allocate a Grayscale image
auto newImage =
@@ -358,7 +418,9 @@ Image* Frame::ConvertBGRToGray(Image* image) {
}
Image* Frame::ConvertGrayToBGR(Image* image) {
if (!image || image->pixelFormat != VideoMode::kGray) return nullptr;
if (!image || image->pixelFormat != VideoMode::kGray) {
return nullptr;
}
// Allocate a BGR image
auto newImage =
@@ -378,8 +440,12 @@ Image* Frame::ConvertGrayToBGR(Image* image) {
}
Image* Frame::ConvertBGRToMJPEG(Image* image, int quality) {
if (!image || image->pixelFormat != VideoMode::kBGR) return nullptr;
if (!m_impl) return nullptr;
if (!image || image->pixelFormat != VideoMode::kBGR) {
return nullptr;
}
if (!m_impl) {
return nullptr;
}
std::scoped_lock lock(m_impl->mutex);
// Allocate a JPEG image. We don't actually know what the resulting size
@@ -409,8 +475,12 @@ Image* Frame::ConvertBGRToMJPEG(Image* image, int quality) {
}
Image* Frame::ConvertGrayToMJPEG(Image* image, int quality) {
if (!image || image->pixelFormat != VideoMode::kGray) return nullptr;
if (!m_impl) return nullptr;
if (!image || image->pixelFormat != VideoMode::kGray) {
return nullptr;
}
if (!m_impl) {
return nullptr;
}
std::scoped_lock lock(m_impl->mutex);
// Allocate a JPEG image. We don't actually know what the resulting size
@@ -442,11 +512,14 @@ Image* Frame::ConvertGrayToMJPEG(Image* image, int quality) {
Image* Frame::GetImageImpl(int width, int height,
VideoMode::PixelFormat pixelFormat,
int requiredJpegQuality, int defaultJpegQuality) {
if (!m_impl) return nullptr;
if (!m_impl) {
return nullptr;
}
std::scoped_lock lock(m_impl->mutex);
Image* cur = GetNearestImage(width, height, pixelFormat, requiredJpegQuality);
if (!cur || cur->Is(width, height, pixelFormat, requiredJpegQuality))
if (!cur || cur->Is(width, height, pixelFormat, requiredJpegQuality)) {
return cur;
}
WPI_DEBUG4(Instance::GetInstance().logger,
"converting image from " << cur->width << "x" << cur->height
@@ -458,7 +531,9 @@ Image* Frame::GetImageImpl(int width, int height,
// anything else with it. Note that if the destination format is JPEG, we
// still need to do this (unless the width/height/compression were the same,
// in which case we already returned the existing JPEG above).
if (cur->pixelFormat == VideoMode::kMJPEG) cur = ConvertMJPEGToBGR(cur);
if (cur->pixelFormat == VideoMode::kMJPEG) {
cur = ConvertMJPEGToBGR(cur);
}
// Resize
if (!cur->Is(width, height)) {
@@ -482,14 +557,17 @@ Image* Frame::GetImageImpl(int width, int height,
bool Frame::GetCv(cv::Mat& image, int width, int height) {
Image* rawImage = GetImage(width, height, VideoMode::kBGR);
if (!rawImage) return false;
if (!rawImage) {
return false;
}
rawImage->AsMat().copyTo(image);
return true;
}
void Frame::ReleaseFrame() {
for (auto image : m_impl->images)
for (auto image : m_impl->images) {
m_impl->source.ReleaseImage(std::unique_ptr<Image>(image));
}
m_impl->images.clear();
m_impl->source.ReleaseFrameImpl(std::unique_ptr<Impl>(m_impl));
m_impl = nullptr;

View File

@@ -49,7 +49,9 @@ class Frame {
Frame(SourceImpl& source, std::unique_ptr<Image> image, Time time);
Frame(const Frame& frame) noexcept : m_impl{frame.m_impl} {
if (m_impl) ++m_impl->refcount;
if (m_impl) {
++m_impl->refcount;
}
}
Frame(Frame&& other) noexcept : Frame() { swap(*this, other); }
@@ -71,60 +73,90 @@ class Frame {
Time GetTime() const { return m_impl ? m_impl->time : 0; }
wpi::StringRef GetError() const {
if (!m_impl) return wpi::StringRef{};
if (!m_impl) {
return {};
}
return m_impl->error;
}
int GetOriginalWidth() const {
if (!m_impl) return 0;
if (!m_impl) {
return 0;
}
std::scoped_lock lock(m_impl->mutex);
if (m_impl->images.empty()) return 0;
if (m_impl->images.empty()) {
return 0;
}
return m_impl->images[0]->width;
}
int GetOriginalHeight() const {
if (!m_impl) return 0;
if (!m_impl) {
return 0;
}
std::scoped_lock lock(m_impl->mutex);
if (m_impl->images.empty()) return 0;
if (m_impl->images.empty()) {
return 0;
}
return m_impl->images[0]->height;
}
int GetOriginalPixelFormat() const {
if (!m_impl) return 0;
if (!m_impl) {
return 0;
}
std::scoped_lock lock(m_impl->mutex);
if (m_impl->images.empty()) return 0;
if (m_impl->images.empty()) {
return 0;
}
return m_impl->images[0]->pixelFormat;
}
int GetOriginalJpegQuality() const {
if (!m_impl) return 0;
if (!m_impl) {
return 0;
}
std::scoped_lock lock(m_impl->mutex);
if (m_impl->images.empty()) return 0;
if (m_impl->images.empty()) {
return 0;
}
return m_impl->images[0]->jpegQuality;
}
Image* GetExistingImage(size_t i = 0) const {
if (!m_impl) return nullptr;
if (!m_impl) {
return nullptr;
}
std::scoped_lock lock(m_impl->mutex);
if (i >= m_impl->images.size()) return nullptr;
if (i >= m_impl->images.size()) {
return nullptr;
}
return m_impl->images[i];
}
Image* GetExistingImage(int width, int height) const {
if (!m_impl) return nullptr;
if (!m_impl) {
return nullptr;
}
std::scoped_lock lock(m_impl->mutex);
for (auto i : m_impl->images) {
if (i->Is(width, height)) return i;
if (i->Is(width, height)) {
return i;
}
}
return nullptr;
}
Image* GetExistingImage(int width, int height,
VideoMode::PixelFormat pixelFormat) const {
if (!m_impl) return nullptr;
if (!m_impl) {
return nullptr;
}
std::scoped_lock lock(m_impl->mutex);
for (auto i : m_impl->images) {
if (i->Is(width, height, pixelFormat)) return i;
if (i->Is(width, height, pixelFormat)) {
return i;
}
}
return nullptr;
}
@@ -132,10 +164,14 @@ class Frame {
Image* GetExistingImage(int width, int height,
VideoMode::PixelFormat pixelFormat,
int jpegQuality) const {
if (!m_impl) return nullptr;
if (!m_impl) {
return nullptr;
}
std::scoped_lock lock(m_impl->mutex);
for (auto i : m_impl->images) {
if (i->Is(width, height, pixelFormat, jpegQuality)) return i;
if (i->Is(width, height, pixelFormat, jpegQuality)) {
return i;
}
}
return nullptr;
}
@@ -146,7 +182,9 @@ class Frame {
int jpegQuality = -1) const;
Image* Convert(Image* image, VideoMode::PixelFormat pixelFormat) {
if (pixelFormat == VideoMode::kMJPEG) return nullptr;
if (pixelFormat == VideoMode::kMJPEG) {
return nullptr;
}
return ConvertImpl(image, pixelFormat, -1, 80);
}
Image* ConvertToMJPEG(Image* image, int requiredQuality,
@@ -165,7 +203,9 @@ class Frame {
Image* ConvertGrayToMJPEG(Image* image, int quality);
Image* GetImage(int width, int height, VideoMode::PixelFormat pixelFormat) {
if (pixelFormat == VideoMode::kMJPEG) return nullptr;
if (pixelFormat == VideoMode::kMJPEG) {
return nullptr;
}
return GetImageImpl(width, height, pixelFormat, -1, 80);
}
Image* GetImageMJPEG(int width, int height, int requiredQuality,
@@ -185,7 +225,9 @@ class Frame {
Image* GetImageImpl(int width, int height, VideoMode::PixelFormat pixelFormat,
int requiredJpegQuality, int defaultJpegQuality);
void DecRef() {
if (m_impl && --(m_impl->refcount) == 0) ReleaseFrame();
if (m_impl && --(m_impl->refcount) == 0) {
ReleaseFrame();
}
}
void ReleaseFrame();

View File

@@ -30,26 +30,36 @@ HttpCameraImpl::~HttpCameraImpl() {
m_monitorCond.notify_one();
// join monitor thread
if (m_monitorThread.joinable()) m_monitorThread.join();
if (m_monitorThread.joinable()) {
m_monitorThread.join();
}
// Close file if it's open
{
std::scoped_lock lock(m_mutex);
if (m_streamConn) m_streamConn->stream->close();
if (m_settingsConn) m_settingsConn->stream->close();
if (m_streamConn) {
m_streamConn->stream->close();
}
if (m_settingsConn) {
m_settingsConn->stream->close();
}
}
// force wakeup of camera thread in case it's waiting on cv
m_sinkEnabledCond.notify_one();
// join camera thread
if (m_streamThread.joinable()) m_streamThread.join();
if (m_streamThread.joinable()) {
m_streamThread.join();
}
// force wakeup of settings thread
m_settingsCond.notify_one();
// join settings thread
if (m_settingsThread.joinable()) m_settingsThread.join();
if (m_settingsThread.joinable()) {
m_settingsThread.join();
}
}
void HttpCameraImpl::Start() {
@@ -66,7 +76,9 @@ void HttpCameraImpl::MonitorThreadMain() {
m_monitorCond.wait_for(lock, std::chrono::seconds(1),
[=] { return !m_active; });
if (!m_active) break;
if (!m_active) {
break;
}
// check to see if we got any frames, and close the stream if not
// (this will result in an error at the read point, and ultimately
@@ -93,20 +105,28 @@ void HttpCameraImpl::StreamThreadMain() {
// disconnect if not enabled
if (!IsEnabled()) {
std::unique_lock lock(m_mutex);
if (m_streamConn) m_streamConn->stream->close();
if (m_streamConn) {
m_streamConn->stream->close();
}
// Wait for enable
m_sinkEnabledCond.wait(lock, [=] { return !m_active || IsEnabled(); });
if (!m_active) return;
if (!m_active) {
return;
}
}
// connect
wpi::SmallString<64> boundary;
wpi::HttpConnection* conn = DeviceStreamConnect(boundary);
if (!m_active) break;
if (!m_active) {
break;
}
// keep retrying
if (!conn) continue;
if (!conn) {
continue;
}
// update connected since we're actually connected
SetConnected(true);
@@ -134,7 +154,9 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
std::this_thread::sleep_for(std::chrono::seconds(1));
return nullptr;
}
if (m_nextLocation >= m_locations.size()) m_nextLocation = 0;
if (m_nextLocation >= m_locations.size()) {
m_nextLocation = 0;
}
req = wpi::HttpRequest{m_locations[m_nextLocation++], m_streamSettings};
m_streamSettingsUpdated = false;
}
@@ -143,7 +165,9 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
auto stream =
wpi::TCPConnector::connect(req.host.c_str(), req.port, m_logger, 1);
if (!m_active || !stream) return nullptr;
if (!m_active || !stream) {
return nullptr;
}
auto connPtr = std::make_unique<wpi::HttpConnection>(std::move(stream), 1);
wpi::HttpConnection* conn = connPtr.get();
@@ -215,24 +239,33 @@ void HttpCameraImpl::DeviceStream(wpi::raw_istream& is,
// streaming loop
while (m_active && !is.has_error() && IsEnabled() && numErrors < 3 &&
!m_streamSettingsUpdated) {
if (!FindMultipartBoundary(is, boundary, nullptr)) break;
if (!FindMultipartBoundary(is, boundary, nullptr)) {
break;
}
// Read the next two characters after the boundary (normally \r\n)
// Handle just \n for LabVIEW however
char eol[2];
is.read(eol, 1);
if (!m_active || is.has_error()) break;
if (!m_active || is.has_error()) {
break;
}
if (eol[0] != '\n') {
is.read(eol + 1, 1);
if (!m_active || is.has_error()) break;
if (!m_active || is.has_error()) {
break;
}
// End-of-stream is indicated with trailing --
if (eol[0] == '-' && eol[1] == '-') break;
if (eol[0] == '-' && eol[1] == '-') {
break;
}
}
if (!DeviceStreamFrame(is, imageBuf))
if (!DeviceStreamFrame(is, imageBuf)) {
++numErrors;
else
} else {
numErrors = 0;
}
}
}
@@ -277,7 +310,9 @@ bool HttpCameraImpl::DeviceStreamFrame(wpi::raw_istream& is,
// the data directly into it.
auto image = AllocImage(VideoMode::PixelFormat::kMJPEG, 0, 0, contentLength);
is.read(image->data(), contentLength);
if (!m_active || is.has_error()) return false;
if (!m_active || is.has_error()) {
return false;
}
int width, height;
if (!GetJpegSize(image->str(), &width, &height)) {
SWARNING("did not receive a JPEG image");
@@ -299,7 +334,9 @@ void HttpCameraImpl::SettingsThreadMain() {
m_settingsCond.wait(lock, [=] {
return !m_active || (m_prefLocation != -1 && !m_settings.empty());
});
if (!m_active) break;
if (!m_active) {
break;
}
// Build the request
req = wpi::HttpRequest{m_locations[m_prefLocation], m_settings};
@@ -316,7 +353,9 @@ void HttpCameraImpl::DeviceSendSettings(wpi::HttpRequest& req) {
auto stream =
wpi::TCPConnector::connect(req.host.c_str(), req.port, m_logger, 1);
if (!m_active || !stream) return;
if (!m_active || !stream) {
return;
}
auto connPtr = std::make_unique<wpi::HttpConnection>(std::move(stream), 1);
wpi::HttpConnection* conn = connPtr.get();
@@ -329,7 +368,9 @@ 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);
if (!conn->Handshake(req, &warn)) {
SWARNING(GetName() << ": " << warn);
}
conn->stream->close();
}
@@ -363,7 +404,9 @@ bool HttpCameraImpl::SetUrls(wpi::ArrayRef<std::string> urls,
std::vector<std::string> HttpCameraImpl::GetUrls() const {
std::scoped_lock lock(m_mutex);
std::vector<std::string> urls;
for (const auto& loc : m_locations) urls.push_back(loc.url);
for (const auto& loc : m_locations) {
urls.push_back(loc.url);
}
return urls;
}
@@ -393,7 +436,9 @@ void HttpCameraImpl::CreateEnumProperty(
auto& enumChoices = m_propertyData.back()->enumChoices;
enumChoices.clear();
for (const auto& choice : choices) enumChoices.emplace_back(choice);
for (const auto& choice : choices) {
enumChoices.emplace_back(choice);
}
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CREATED, name,
m_propertyData.size() + 1, CS_PROP_ENUM,
@@ -468,7 +513,9 @@ void HttpCameraImpl::SetExposureManual(int value, CS_Status* status) {
}
bool HttpCameraImpl::SetVideoMode(const VideoMode& mode, CS_Status* status) {
if (mode.pixelFormat != VideoMode::kMJPEG) return false;
if (mode.pixelFormat != VideoMode::kMJPEG) {
return false;
}
std::scoped_lock lock(m_mutex);
m_mode = mode;
m_streamSettingsUpdated = true;
@@ -527,7 +574,9 @@ CS_Source CreateHttpCamera(const wpi::Twine& name, const wpi::Twine& url,
inst.notifier, inst.telemetry);
break;
}
if (!source->SetUrls(url.str(), status)) return 0;
if (!source->SetUrls(url.str(), status)) {
return 0;
}
return inst.CreateSource(CS_SOURCE_HTTP, source);
}
@@ -541,7 +590,9 @@ CS_Source CreateHttpCamera(const wpi::Twine& name,
}
auto source = std::make_shared<HttpCameraImpl>(name, kind, inst.logger,
inst.notifier, inst.telemetry);
if (!source->SetUrls(urls, status)) return 0;
if (!source->SetUrls(urls, status)) {
return 0;
}
return inst.CreateSource(CS_SOURCE_HTTP, source);
}
@@ -592,7 +643,9 @@ CS_Source CS_CreateHttpCameraMulti(const char* name, const char** urls,
CS_Status* status) {
wpi::SmallVector<std::string, 4> vec;
vec.reserve(count);
for (int i = 0; i < count; ++i) vec.push_back(urls[i]);
for (int i = 0; i < count; ++i) {
vec.push_back(urls[i]);
}
return cs::CreateHttpCamera(name, vec, kind, status);
}
@@ -604,7 +657,9 @@ void CS_SetHttpCameraUrls(CS_Source source, const char** urls, int count,
CS_Status* status) {
wpi::SmallVector<std::string, 4> vec;
vec.reserve(count);
for (int i = 0; i < count; ++i) vec.push_back(urls[i]);
for (int i = 0; i < count; ++i) {
vec.push_back(urls[i]);
}
cs::SetHttpCameraUrls(source, vec, status);
}
@@ -613,13 +668,19 @@ char** CS_GetHttpCameraUrls(CS_Source source, int* count, CS_Status* status) {
char** out =
static_cast<char**>(wpi::safe_malloc(urls.size() * sizeof(char*)));
*count = urls.size();
for (size_t i = 0; i < urls.size(); ++i) out[i] = cs::ConvertToC(urls[i]);
for (size_t i = 0; i < urls.size(); ++i) {
out[i] = cs::ConvertToC(urls[i]);
}
return out;
}
void CS_FreeHttpCameraUrls(char** urls, int count) {
if (!urls) return;
for (int i = 0; i < count; ++i) std::free(urls[i]);
if (!urls) {
return;
}
for (int i = 0; i < count; ++i) {
std::free(urls[i]);
}
std::free(urls);
}

View File

@@ -22,14 +22,15 @@ static void def_log_func(unsigned int level, const char* file,
}
wpi::StringRef levelmsg;
if (level >= 50)
if (level >= 50) {
levelmsg = "CRITICAL: ";
else if (level >= 40)
} else if (level >= 40) {
levelmsg = "ERROR: ";
else if (level >= 30)
} else if (level >= 30) {
levelmsg = "WARNING: ";
else
} else {
return;
}
oss << "CS: " << levelmsg << msg << " (" << wpi::sys::path::filename(file)
<< ':' << line << ")\n";
wpi::errs() << oss.str();
@@ -55,7 +56,9 @@ void Instance::Shutdown() {
notifier.Stop();
}
void Instance::SetDefaultLogger() { logger.SetLogger(def_log_func); }
void Instance::SetDefaultLogger() {
logger.SetLogger(def_log_func);
}
std::pair<CS_Source, std::shared_ptr<SourceData>> Instance::FindSource(
const SourceImpl& source) {
@@ -84,11 +87,13 @@ CS_Sink Instance::CreateSink(CS_SinkKind kind, std::shared_ptr<SinkImpl> sink) {
}
void Instance::DestroySource(CS_Source handle) {
if (auto data = m_sources.Free(handle))
if (auto data = m_sources.Free(handle)) {
notifier.NotifySource(data->source->GetName(), handle, CS_SOURCE_DESTROYED);
}
}
void Instance::DestroySink(CS_Sink handle) {
if (auto data = m_sinks.Free(handle))
if (auto data = m_sinks.Free(handle)) {
notifier.NotifySink(data->sink->GetName(), handle, CS_SINK_DESTROYED);
}
}

View File

@@ -98,7 +98,9 @@ class Instance {
CS_Source source, wpi::SmallVectorImpl<CS_Sink>& vec) {
vec.clear();
m_sinks.ForEach([&](CS_Sink sinkHandle, const SinkData& data) {
if (source == data.sourceHandle.load()) vec.push_back(sinkHandle);
if (source == data.sourceHandle.load()) {
vec.push_back(sinkHandle);
}
});
return vec;
}

View File

@@ -47,28 +47,44 @@ static const unsigned char dhtData[] = {
0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa};
bool IsJpeg(wpi::StringRef data) {
if (data.size() < 11) return false;
if (data.size() < 11) {
return false;
}
// Check for valid SOI
auto bytes = data.bytes_begin();
if (bytes[0] != 0xff || bytes[1] != 0xd8) return false;
if (bytes[0] != 0xff || bytes[1] != 0xd8) {
return false;
}
return true;
}
bool GetJpegSize(wpi::StringRef data, int* width, int* height) {
if (!IsJpeg(data)) return false;
if (!IsJpeg(data)) {
return false;
}
data = data.substr(2); // Get to the first block
auto bytes = data.bytes_begin();
for (;;) {
if (data.size() < 4) return false; // EOF
if (data.size() < 4) {
return false; // EOF
}
bytes = data.bytes_begin();
if (bytes[0] != 0xff) return false; // not a tag
if (bytes[1] == 0xd9) return false; // EOI without finding SOF?
if (bytes[1] == 0xda) return false; // SOS without finding SOF?
if (bytes[0] != 0xff) {
return false; // not a tag
}
if (bytes[1] == 0xd9) {
return false; // EOI without finding SOF?
}
if (bytes[1] == 0xda) {
return false; // SOS without finding SOF?
}
if (bytes[1] == 0xc0) {
// SOF contains the file size
if (data.size() < 9) return false;
if (data.size() < 9) {
return false;
}
*height = bytes[5] * 256 + bytes[6];
*width = bytes[7] * 256 + bytes[8];
return true;
@@ -80,7 +96,9 @@ 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);
if (!IsJpeg(sdata)) return false;
if (!IsJpeg(sdata)) {
return false;
}
*locSOF = *size;
@@ -88,12 +106,22 @@ bool JpegNeedsDHT(const char* data, size_t* size, size_t* locSOF) {
sdata = sdata.substr(2); // Get to the first block
auto bytes = sdata.bytes_begin();
for (;;) {
if (sdata.size() < 4) return false; // EOF
if (sdata.size() < 4) {
return false; // EOF
}
bytes = sdata.bytes_begin();
if (bytes[0] != 0xff) return false; // not a tag
if (bytes[1] == 0xda) break; // SOS
if (bytes[1] == 0xc4) return false; // DHT
if (bytes[1] == 0xc0) *locSOF = sdata.data() - data; // SOF
if (bytes[0] != 0xff) {
return false; // not a tag
}
if (bytes[1] == 0xda) {
break; // SOS
}
if (bytes[1] == 0xc4) {
return false; // DHT
}
if (bytes[1] == 0xc0) {
*locSOF = sdata.data() - data; // SOF
}
// Go to the next block
sdata = sdata.substr(bytes[2] * 256 + bytes[3] + 2);
}
@@ -126,18 +154,26 @@ bool ReadJpeg(wpi::raw_istream& is, std::string& buf, int* width, int* height) {
// read SOI and first marker
buf.resize(4);
is.read(&(*buf.begin()), 4);
if (is.has_error()) return false;
if (is.has_error()) {
return false;
}
// Check for valid SOI
auto bytes = reinterpret_cast<const unsigned char*>(buf.data());
if (bytes[0] != 0xff || bytes[1] != 0xd8) return false;
if (bytes[0] != 0xff || bytes[1] != 0xd8) {
return false;
}
size_t pos = 2; // point to first marker
for (;;) {
bytes = reinterpret_cast<const unsigned char*>(buf.data() + pos);
if (bytes[0] != 0xff) return false; // not a marker
if (bytes[0] != 0xff) {
return false; // not a marker
}
unsigned char marker = bytes[1];
if (marker == 0xd9) return true; // EOI, we're done
if (marker == 0xd9) {
return true; // EOI, we're done
}
if (marker == 0xda) {
// SOS: need to keep reading until we reach a normal marker.
@@ -147,12 +183,15 @@ bool ReadJpeg(wpi::raw_istream& is, std::string& buf, int* width, int* height) {
bool maybeMarker = false;
for (;;) {
ReadInto(is, buf, 1);
if (is.has_error()) return false;
if (is.has_error()) {
return false;
}
bytes = reinterpret_cast<const unsigned char*>(buf.data() + pos);
if (maybeMarker) {
if (bytes[0] != 0x00 && bytes[0] != 0xff &&
(bytes[0] < 0xd0 || bytes[0] > 0xd7))
(bytes[0] < 0xd0 || bytes[0] > 0xd7)) {
break;
}
maybeMarker = false;
} else if (bytes[0] == 0xff) {
maybeMarker = true;
@@ -165,7 +204,9 @@ bool ReadJpeg(wpi::raw_istream& is, std::string& buf, int* width, int* height) {
// A normal block. Read the length
ReadInto(is, buf, 2); // read length
if (is.has_error()) return false;
if (is.has_error()) {
return false;
}
// Point to length
pos += 2;
@@ -174,7 +215,9 @@ bool ReadJpeg(wpi::raw_istream& is, std::string& buf, int* width, int* height) {
// Read the block and the next marker
size_t blockLength = bytes[0] * 256 + bytes[1];
ReadInto(is, buf, blockLength);
if (is.has_error()) return false;
if (is.has_error()) {
return false;
}
bytes = reinterpret_cast<const unsigned char*>(buf.data() + pos);
// Special block processing

View File

@@ -108,13 +108,17 @@ class MjpegServerImpl::ConnThread : public wpi::SafeThread {
void StartStream() {
std::scoped_lock lock(m_mutex);
if (m_source) m_source->EnableSink();
if (m_source) {
m_source->EnableSink();
}
m_streaming = true;
}
void StopStream() {
std::scoped_lock lock(m_mutex);
if (m_source) m_source->DisableSink();
if (m_source) {
m_source->DisableSink();
}
m_streaming = false;
}
};
@@ -140,7 +144,9 @@ static void SendHeader(wpi::raw_ostream& os, int code,
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 (!extraStr.empty()) {
os << extraStr << "\r\n";
}
os << "\r\n"; // header ends with a blank line
}
@@ -198,9 +204,13 @@ bool MjpegServerImpl::ConnThread::ProcessCommand(wpi::raw_ostream& os,
// split out next param and value
wpi::StringRef rawParam, rawValue;
std::tie(rawParam, parameters) = parameters.split('&');
if (rawParam.empty()) continue; // ignore "&&"
if (rawParam.empty()) {
continue; // ignore "&&"
}
std::tie(rawParam, rawValue) = rawParam.split('=');
if (rawParam.empty() || rawValue.empty()) continue; // ignore "param="
if (rawParam.empty() || rawValue.empty()) {
continue; // ignore "param="
}
SDEBUG4("HTTP parameter \"" << rawParam << "\" value \"" << rawValue
<< "\"");
@@ -282,7 +292,9 @@ bool MjpegServerImpl::ConnThread::ProcessCommand(wpi::raw_ostream& os,
}
// ignore name parameter
if (param == "name") continue;
if (param == "name") {
continue;
}
// try to assign parameter
auto prop = source.GetPropertyIndex(param);
@@ -339,7 +351,9 @@ void MjpegServerImpl::ConnThread::SendHTMLHeadTitle(
// Send the root html file with controls for all the settable properties.
void MjpegServerImpl::ConnThread::SendHTML(wpi::raw_ostream& os,
SourceImpl& source, bool header) {
if (header) SendHeader(os, 200, "OK", "text/html");
if (header) {
SendHeader(os, 200, "OK", "text/html");
}
SendHTMLHeadTitle(os);
os << startRootPage;
@@ -348,7 +362,9 @@ 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_")) continue;
if (name.startswith("raw_")) {
continue;
}
auto kind = source.GetPropertyKind(prop);
os << "<p />"
<< "<label for=\"" << name << "\">" << name << "</label>\n";
@@ -357,10 +373,11 @@ void MjpegServerImpl::ConnThread::SendHTML(wpi::raw_ostream& os,
os << "<input id=\"" << name
<< "\" type=\"checkbox\" onclick=\"update('" << name
<< "', this.checked ? 1 : 0)\" ";
if (source.GetProperty(prop, &status) != 0)
if (source.GetProperty(prop, &status) != 0) {
os << "checked />\n";
else
} else {
os << " />\n";
}
break;
case CS_PROP_INTEGER: {
auto valI = source.GetProperty(prop, &status);
@@ -381,11 +398,14 @@ void MjpegServerImpl::ConnThread::SendHTML(wpi::raw_ostream& os,
int j = 0;
for (auto choice = choices.begin(), end = choices.end(); choice != end;
++j, ++choice) {
if (choice->empty()) continue; // skip empty choices
if (choice->empty()) {
continue; // skip empty choices
}
// replace any non-printable characters in name with spaces
wpi::SmallString<128> ch_name;
for (char ch : *choice)
for (char ch : *choice) {
ch_name.push_back(std::isprint(ch) ? ch : ' ');
}
os << "<input id=\"" << name << j << "\" type=\"radio\" name=\""
<< name << "\" value=\"" << ch_name << "\" onclick=\"update('"
<< name << "', " << j << ")\"";
@@ -416,8 +436,9 @@ void MjpegServerImpl::ConnThread::SendHTML(wpi::raw_ostream& os,
&status);
if (status == CS_OK) {
os << "<p>USB device path: " << info.path << '\n';
for (auto&& path : info.otherPaths)
for (auto&& path : info.otherPaths) {
os << "<p>Alternate device path: " << path << '\n';
}
}
os << "<p>Supported Video Modes:</p>\n";
@@ -461,17 +482,20 @@ void MjpegServerImpl::ConnThread::SendHTML(wpi::raw_ostream& os,
// Send a JSON file which is contains information about the source parameters.
void MjpegServerImpl::ConnThread::SendJSON(wpi::raw_ostream& os,
SourceImpl& source, bool header) {
if (header) SendHeader(os, 200, "OK", "application/json");
if (header) {
SendHeader(os, 200, "OK", "application/json");
}
os << "{\n\"controls\": [\n";
wpi::SmallVector<int, 32> properties_vec;
bool first = true;
CS_Status status = 0;
for (auto prop : source.EnumerateProperties(properties_vec, &status)) {
if (first)
if (first) {
first = false;
else
} else {
os << ",\n";
}
os << '{';
wpi::SmallString<128> name_buf;
auto name = source.GetPropertyName(prop, name_buf, &status);
@@ -511,10 +535,14 @@ void MjpegServerImpl::ConnThread::SendJSON(wpi::raw_ostream& os,
int j = 0;
for (auto choice = choices.begin(), end = choices.end(); choice != end;
++j, ++choice) {
if (j != 0) os << ", ";
if (j != 0) {
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 : ' ');
for (char ch : *choice) {
ch_name.push_back(std::isprint(ch) ? ch : ' ');
}
os << '"' << j << "\": \"" << ch_name << '"';
}
os << "}\n";
@@ -524,10 +552,11 @@ void MjpegServerImpl::ConnThread::SendJSON(wpi::raw_ostream& os,
os << "\n],\n\"modes\": [\n";
first = true;
for (auto mode : source.EnumerateVideoModes(&status)) {
if (first)
if (first) {
first = false;
else
} else {
os << ",\n";
}
os << '{';
os << "\n\"pixelFormat\": \"";
switch (mode.pixelFormat) {
@@ -596,7 +625,9 @@ MjpegServerImpl::MjpegServerImpl(const wpi::Twine& name, wpi::Logger& logger,
m_serverThread = std::thread(&MjpegServerImpl::ServerThreadMain, this);
}
MjpegServerImpl::~MjpegServerImpl() { Stop(); }
MjpegServerImpl::~MjpegServerImpl() {
Stop();
}
void MjpegServerImpl::Stop() {
m_active = false;
@@ -605,18 +636,24 @@ void MjpegServerImpl::Stop() {
m_acceptor->shutdown();
// join server thread
if (m_serverThread.joinable()) m_serverThread.join();
if (m_serverThread.joinable()) {
m_serverThread.join();
}
// close streams
for (auto& connThread : m_connThreads) {
if (auto thr = connThread.GetThread()) {
if (thr->m_stream) thr->m_stream->close();
if (thr->m_stream) {
thr->m_stream->close();
}
}
connThread.Stop();
}
// wake up connection threads by forcing an empty frame to be sent
if (auto source = GetSource()) source->Wakeup();
if (auto source = GetSource()) {
source->Wakeup();
}
}
// Send HTTP response and a stream of JPG-frames
@@ -639,10 +676,14 @@ void MjpegServerImpl::ConnThread::SendStream(wpi::raw_socket_ostream& os) {
Frame::Time lastFrameTime = 0;
Frame::Time timePerFrame = 0;
if (m_fps != 0) timePerFrame = 1000000.0 / m_fps;
if (m_fps != 0) {
timePerFrame = 1000000.0 / m_fps;
}
Frame::Time averageFrameTime = 0;
Frame::Time averagePeriod = 1000000; // 1 second window
if (averagePeriod < timePerFrame) averagePeriod = timePerFrame * 10;
if (averagePeriod < timePerFrame) {
averagePeriod = timePerFrame * 10;
}
StartStream();
while (m_active && !os.has_error()) {
@@ -655,7 +696,9 @@ void MjpegServerImpl::ConnThread::SendStream(wpi::raw_socket_ostream& os) {
}
SDEBUG4("waiting for frame");
Frame frame = source->GetNextFrame(0.225); // blocks
if (!m_active) break;
if (!m_active) {
break;
}
if (!frame) {
// Bad frame; sleep for 20 ms so we don't consume all processor time.
os << "\r\n"; // Keep connection alive
@@ -804,8 +847,12 @@ void MjpegServerImpl::ConnThread::ProcessRequest() {
// The end of the request is marked by a single, empty line
wpi::SmallString<128> lineBuf;
for (;;) {
if (is.getline(lineBuf, 4096).startswith("\n")) break;
if (is.has_error()) return;
if (is.getline(lineBuf, 4096).startswith("\n")) {
break;
}
if (is.has_error()) {
return;
}
}
// Send response
@@ -813,7 +860,9 @@ void MjpegServerImpl::ConnThread::ProcessRequest() {
case kStream:
if (auto source = GetSource()) {
SDEBUG("request for stream " << source->GetName());
if (!ProcessCommand(os, *source, parameters, false)) return;
if (!ProcessCommand(os, *source, parameters, false)) {
return;
}
}
SendStream(os);
break;
@@ -829,10 +878,11 @@ void MjpegServerImpl::ConnThread::ProcessRequest() {
break;
case kGetSettings:
SDEBUG("request for JSON file");
if (auto source = GetSource())
if (auto source = GetSource()) {
SendJSON(os, *source, true);
else
} else {
SendError(os, 404, "Resource not found");
}
break;
case kGetSourceConfig:
SDEBUG("request for JSON file");
@@ -866,7 +916,9 @@ void MjpegServerImpl::ConnThread::Main() {
while (m_active) {
while (!m_stream) {
m_cond.wait(lock);
if (!m_active) return;
if (!m_active) {
return;
}
}
lock.unlock();
ProcessRequest();
@@ -889,7 +941,9 @@ void MjpegServerImpl::ServerThreadMain() {
m_active = false;
return;
}
if (!m_active) return;
if (!m_active) {
return;
}
SDEBUG("client connection from " << stream->getPeerIP());
@@ -939,9 +993,13 @@ void MjpegServerImpl::SetSourceImpl(std::shared_ptr<SourceImpl> source) {
if (auto thr = connThread.GetThread()) {
if (thr->m_source != source) {
bool streaming = thr->m_streaming;
if (thr->m_source && streaming) thr->m_source->DisableSink();
if (thr->m_source && streaming) {
thr->m_source->DisableSink();
}
thr->m_source = source;
if (source && streaming) thr->m_source->EnableSink();
if (source && streaming) {
thr->m_source->EnableSink();
}
}
}
}

View File

@@ -49,7 +49,9 @@ class UidVector {
// one. The element is added to the freelist for later reuse.
void erase(unsigned int uid) {
--uid;
if (uid >= m_vector.size() || !m_vector[uid]) return;
if (uid >= m_vector.size() || !m_vector[uid]) {
return;
}
m_free.push_back(uid);
m_vector[uid] = T();
}
@@ -88,35 +90,53 @@ class Notifier::Thread : public wpi::SafeThread {
std::function<void()> m_on_exit;
};
Notifier::Notifier() { s_destroyed = false; }
Notifier::Notifier() {
s_destroyed = false;
}
Notifier::~Notifier() { s_destroyed = true; }
Notifier::~Notifier() {
s_destroyed = true;
}
void Notifier::Start() { m_owner.Start(m_on_start, m_on_exit); }
void Notifier::Start() {
m_owner.Start(m_on_start, m_on_exit);
}
void Notifier::Stop() { m_owner.Stop(); }
void Notifier::Stop() {
m_owner.Stop();
}
void Notifier::Thread::Main() {
if (m_on_start) m_on_start();
if (m_on_start) {
m_on_start();
}
std::unique_lock lock(m_mutex);
while (m_active) {
while (m_notifications.empty()) {
m_cond.wait(lock);
if (!m_active) goto done;
if (!m_active) {
goto done;
}
}
while (!m_notifications.empty()) {
if (!m_active) goto done;
if (!m_active) {
goto done;
}
auto item = std::move(m_notifications.front());
m_notifications.pop();
// Use index because iterator might get invalidated.
for (size_t i = 0; i < m_listeners.size(); ++i) {
if (!m_listeners[i]) continue; // removed
if (!m_listeners[i]) {
continue; // removed
}
// Event type must be within requested set for this listener.
if ((item.kind & m_listeners[i].eventMask) == 0) continue;
if ((item.kind & m_listeners[i].eventMask) == 0) {
continue;
}
// make a copy of the callback so we can safely release the mutex
auto callback = m_listeners[i].callback;
@@ -130,7 +150,9 @@ void Notifier::Thread::Main() {
}
done:
if (m_on_exit) m_on_exit();
if (m_on_exit) {
m_on_exit();
}
}
int Notifier::AddListener(std::function<void(const RawEvent& event)> callback,
@@ -142,14 +164,18 @@ int Notifier::AddListener(std::function<void(const RawEvent& event)> callback,
void Notifier::RemoveListener(int uid) {
auto thr = m_owner.GetThread();
if (!thr) return;
if (!thr) {
return;
}
thr->m_listeners.erase(uid);
}
void Notifier::NotifySource(const wpi::Twine& name, CS_Source source,
CS_EventKind kind) {
auto thr = m_owner.GetThread();
if (!thr) return;
if (!thr) {
return;
}
thr->m_notifications.emplace(name, source, static_cast<RawEvent::Kind>(kind));
thr->m_cond.notify_one();
}
@@ -162,7 +188,9 @@ void Notifier::NotifySource(const SourceImpl& source, CS_EventKind kind) {
void Notifier::NotifySourceVideoMode(const SourceImpl& source,
const VideoMode& mode) {
auto thr = m_owner.GetThread();
if (!thr) return;
if (!thr) {
return;
}
auto handleData = Instance::GetInstance().FindSource(source);
@@ -175,7 +203,9 @@ void Notifier::NotifySourceProperty(const SourceImpl& source, CS_EventKind kind,
int property, CS_PropertyKind propertyKind,
int value, const wpi::Twine& valueStr) {
auto thr = m_owner.GetThread();
if (!thr) return;
if (!thr) {
return;
}
auto handleData = Instance::GetInstance().FindSource(source);
@@ -189,7 +219,9 @@ void Notifier::NotifySourceProperty(const SourceImpl& source, CS_EventKind kind,
void Notifier::NotifySink(const wpi::Twine& name, CS_Sink sink,
CS_EventKind kind) {
auto thr = m_owner.GetThread();
if (!thr) return;
if (!thr) {
return;
}
thr->m_notifications.emplace(name, sink, static_cast<RawEvent::Kind>(kind));
thr->m_cond.notify_one();
@@ -203,7 +235,9 @@ void Notifier::NotifySink(const SinkImpl& sink, CS_EventKind kind) {
void Notifier::NotifySinkSourceChanged(const wpi::Twine& name, CS_Sink sink,
CS_Source source) {
auto thr = m_owner.GetThread();
if (!thr) return;
if (!thr) {
return;
}
RawEvent event{name, sink, RawEvent::kSinkSourceChanged};
event.sourceHandle = source;
@@ -217,7 +251,9 @@ void Notifier::NotifySinkProperty(const SinkImpl& sink, CS_EventKind kind,
CS_PropertyKind propertyKind, int value,
const wpi::Twine& valueStr) {
auto thr = m_owner.GetThread();
if (!thr) return;
if (!thr) {
return;
}
auto handleData = Instance::GetInstance().FindSink(sink);
@@ -230,7 +266,9 @@ void Notifier::NotifySinkProperty(const SinkImpl& sink, CS_EventKind kind,
void Notifier::NotifyNetworkInterfacesChanged() {
auto thr = m_owner.GetThread();
if (!thr) return;
if (!thr) {
return;
}
thr->m_notifications.emplace(RawEvent::kNetworkInterfacesChanged);
thr->m_cond.notify_one();
@@ -238,7 +276,9 @@ void Notifier::NotifyNetworkInterfacesChanged() {
void Notifier::NotifyTelemetryUpdated() {
auto thr = m_owner.GetThread();
if (!thr) return;
if (!thr) {
return;
}
thr->m_notifications.emplace(RawEvent::kTelemetryUpdated);
thr->m_cond.notify_one();

View File

@@ -14,7 +14,9 @@ using namespace cs;
int PropertyContainer::GetPropertyIndex(const wpi::Twine& 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);
if (!m_properties_cached) {
CacheProperties(&status);
}
std::scoped_lock lock(m_mutex);
wpi::SmallVector<char, 64> nameBuf;
int& ndx = m_properties[name.toStringRef(nameBuf)];
@@ -28,39 +30,50 @@ int PropertyContainer::GetPropertyIndex(const wpi::Twine& name) const {
wpi::ArrayRef<int> PropertyContainer::EnumerateProperties(
wpi::SmallVectorImpl<int>& vec, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status))
return wpi::ArrayRef<int>{};
if (!m_properties_cached && !CacheProperties(status)) {
return {};
}
std::scoped_lock lock(m_mutex);
for (int i = 0; i < static_cast<int>(m_propertyData.size()); ++i) {
if (m_propertyData[i]) vec.push_back(i + 1);
if (m_propertyData[i]) {
vec.push_back(i + 1);
}
}
return vec;
}
CS_PropertyKind PropertyContainer::GetPropertyKind(int property) const {
CS_Status status = 0;
if (!m_properties_cached && !CacheProperties(&status)) return CS_PROP_NONE;
if (!m_properties_cached && !CacheProperties(&status)) {
return CS_PROP_NONE;
}
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) return CS_PROP_NONE;
if (!prop) {
return CS_PROP_NONE;
}
return prop->propKind;
}
wpi::StringRef PropertyContainer::GetPropertyName(
int property, wpi::SmallVectorImpl<char>& buf, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return wpi::StringRef{};
if (!m_properties_cached && !CacheProperties(status)) {
return {};
}
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
return wpi::StringRef{};
return {};
}
// safe to not copy because we never modify it after caching
return prop->name;
}
int PropertyContainer::GetProperty(int property, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return 0;
if (!m_properties_cached && !CacheProperties(status)) {
return 0;
}
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
@@ -85,7 +98,9 @@ void PropertyContainer::SetProperty(int property, int value,
}
// Guess it's integer if we've set before get
if (prop->propKind == CS_PROP_NONE) prop->propKind = CS_PROP_INTEGER;
if (prop->propKind == CS_PROP_NONE) {
prop->propKind = CS_PROP_INTEGER;
}
if ((prop->propKind & (CS_PROP_BOOLEAN | CS_PROP_INTEGER | CS_PROP_ENUM)) ==
0) {
@@ -97,7 +112,9 @@ void PropertyContainer::SetProperty(int property, int value,
}
int PropertyContainer::GetPropertyMin(int property, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return 0;
if (!m_properties_cached && !CacheProperties(status)) {
return 0;
}
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
@@ -108,7 +125,9 @@ int PropertyContainer::GetPropertyMin(int property, CS_Status* status) const {
}
int PropertyContainer::GetPropertyMax(int property, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return 0;
if (!m_properties_cached && !CacheProperties(status)) {
return 0;
}
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
@@ -119,7 +138,9 @@ int PropertyContainer::GetPropertyMax(int property, CS_Status* status) const {
}
int PropertyContainer::GetPropertyStep(int property, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return 0;
if (!m_properties_cached && !CacheProperties(status)) {
return 0;
}
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
@@ -131,7 +152,9 @@ int PropertyContainer::GetPropertyStep(int property, CS_Status* status) const {
int PropertyContainer::GetPropertyDefault(int property,
CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return 0;
if (!m_properties_cached && !CacheProperties(status)) {
return 0;
}
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
@@ -143,16 +166,18 @@ int PropertyContainer::GetPropertyDefault(int property,
wpi::StringRef PropertyContainer::GetStringProperty(
int property, wpi::SmallVectorImpl<char>& buf, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return wpi::StringRef{};
if (!m_properties_cached && !CacheProperties(status)) {
return {};
}
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
return wpi::StringRef{};
return {};
}
if (prop->propKind != CS_PROP_STRING) {
*status = CS_WRONG_PROPERTY_TYPE;
return wpi::StringRef{};
return {};
}
buf.clear();
buf.append(prop->valueStr.begin(), prop->valueStr.end());
@@ -169,7 +194,9 @@ void PropertyContainer::SetStringProperty(int property, const wpi::Twine& value,
}
// Guess it's string if we've set before get
if (prop->propKind == CS_PROP_NONE) prop->propKind = CS_PROP_STRING;
if (prop->propKind == CS_PROP_NONE) {
prop->propKind = CS_PROP_STRING;
}
if (prop->propKind != CS_PROP_STRING) {
*status = CS_WRONG_PROPERTY_TYPE;
@@ -181,17 +208,18 @@ void PropertyContainer::SetStringProperty(int property, const wpi::Twine& value,
std::vector<std::string> PropertyContainer::GetEnumPropertyChoices(
int property, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status))
return std::vector<std::string>{};
if (!m_properties_cached && !CacheProperties(status)) {
return {};
}
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
return std::vector<std::string>{};
return {};
}
if (prop->propKind != CS_PROP_ENUM) {
*status = CS_WRONG_PROPERTY_TYPE;
return std::vector<std::string>{};
return {};
}
return prop->enumChoices;
}

View File

@@ -59,13 +59,17 @@ class PropertyContainer {
protected:
// Get a property; must be called with m_mutex held.
PropertyImpl* GetProperty(int property) {
if (property <= 0 || static_cast<size_t>(property) > m_propertyData.size())
if (property <= 0 ||
static_cast<size_t>(property) > m_propertyData.size()) {
return nullptr;
}
return m_propertyData[property - 1].get();
}
const PropertyImpl* GetProperty(int property) const {
if (property <= 0 || static_cast<size_t>(property) > m_propertyData.size())
if (property <= 0 ||
static_cast<size_t>(property) > m_propertyData.size()) {
return nullptr;
}
return m_propertyData[property - 1].get();
}
// Create or update a property; must be called with m_mutex held.

View File

@@ -29,15 +29,18 @@ PropertyImpl::PropertyImpl(const wpi::Twine& name_, CS_PropertyKind kind_,
void PropertyImpl::SetValue(int v) {
int oldValue = value;
if (hasMinimum && v < minimum)
if (hasMinimum && v < minimum) {
value = minimum;
else if (hasMaximum && v > maximum)
} else if (hasMaximum && v > maximum) {
value = maximum;
else
} else {
value = v;
}
bool wasValueSet = valueSet;
valueSet = true;
if (!wasValueSet || value != oldValue) changed();
if (!wasValueSet || value != oldValue) {
changed();
}
}
void PropertyImpl::SetValue(const wpi::Twine& v) {
@@ -49,14 +52,17 @@ void PropertyImpl::SetValue(const wpi::Twine& v) {
}
bool wasValueSet = valueSet;
valueSet = true;
if (!wasValueSet || valueChanged) changed();
if (!wasValueSet || valueChanged) {
changed();
}
}
void PropertyImpl::SetDefaultValue(int v) {
if (hasMinimum && v < minimum)
if (hasMinimum && v < minimum) {
defaultValue = minimum;
else if (hasMaximum && v > maximum)
} else if (hasMaximum && v > maximum) {
defaultValue = maximum;
else
} else {
defaultValue = v;
}
}

View File

@@ -22,16 +22,22 @@ RawSinkImpl::RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger,
std::function<void(uint64_t time)> processFrame)
: SinkImpl{name, logger, notifier, telemetry} {}
RawSinkImpl::~RawSinkImpl() { Stop(); }
RawSinkImpl::~RawSinkImpl() {
Stop();
}
void RawSinkImpl::Stop() {
m_active = false;
// wake up any waiters by forcing an empty frame to be sent
if (auto source = GetSource()) source->Wakeup();
if (auto source = GetSource()) {
source->Wakeup();
}
// join thread
if (m_thread.joinable()) m_thread.join();
if (m_thread.joinable()) {
m_thread.join();
}
}
uint64_t RawSinkImpl::GrabFrame(CS_RawFrame& image) {
@@ -123,7 +129,9 @@ void RawSinkImpl::ThreadMain() {
}
SDEBUG4("waiting for frame");
Frame frame = source->GetNextFrame(); // blocks
if (!m_active) break;
if (!m_active) {
break;
}
if (!frame) {
// Bad frame; sleep for 10 ms so we don't consume all processor time.
std::this_thread::sleep_for(std::chrono::milliseconds(10));

View File

@@ -21,7 +21,9 @@ SinkImpl::SinkImpl(const wpi::Twine& name, wpi::Logger& logger,
SinkImpl::~SinkImpl() {
if (m_source) {
if (m_enabledCount > 0) m_source->DisableSink();
if (m_enabledCount > 0) {
m_source->DisableSink();
}
m_source->RemoveSink();
}
}
@@ -41,7 +43,9 @@ void SinkImpl::Enable() {
std::scoped_lock lock(m_mutex);
++m_enabledCount;
if (m_enabledCount == 1) {
if (m_source) m_source->EnableSink();
if (m_source) {
m_source->EnableSink();
}
m_notifier.NotifySink(*this, CS_SINK_ENABLED);
}
}
@@ -50,7 +54,9 @@ void SinkImpl::Disable() {
std::scoped_lock lock(m_mutex);
--m_enabledCount;
if (m_enabledCount == 0) {
if (m_source) m_source->DisableSink();
if (m_source) {
m_source->DisableSink();
}
m_notifier.NotifySink(*this, CS_SINK_DISABLED);
}
}
@@ -58,11 +64,15 @@ void SinkImpl::Disable() {
void SinkImpl::SetEnabled(bool enabled) {
std::scoped_lock lock(m_mutex);
if (enabled && m_enabledCount == 0) {
if (m_source) m_source->EnableSink();
if (m_source) {
m_source->EnableSink();
}
m_enabledCount = 1;
m_notifier.NotifySink(*this, CS_SINK_ENABLED);
} else if (!enabled && m_enabledCount > 0) {
if (m_source) m_source->DisableSink();
if (m_source) {
m_source->DisableSink();
}
m_enabledCount = 0;
m_notifier.NotifySink(*this, CS_SINK_DISABLED);
}
@@ -71,15 +81,21 @@ void SinkImpl::SetEnabled(bool enabled) {
void SinkImpl::SetSource(std::shared_ptr<SourceImpl> source) {
{
std::scoped_lock lock(m_mutex);
if (m_source == source) return;
if (m_source == source) {
return;
}
if (m_source) {
if (m_enabledCount > 0) m_source->DisableSink();
if (m_enabledCount > 0) {
m_source->DisableSink();
}
m_source->RemoveSink();
}
m_source = source;
if (m_source) {
m_source->AddSink();
if (m_enabledCount > 0) m_source->EnableSink();
if (m_enabledCount > 0) {
m_source->EnableSink();
}
}
}
SetSourceImpl(source);
@@ -87,13 +103,17 @@ void SinkImpl::SetSource(std::shared_ptr<SourceImpl> source) {
std::string SinkImpl::GetError() const {
std::scoped_lock lock(m_mutex);
if (!m_source) return "no source connected";
if (!m_source) {
return "no source connected";
}
return m_source->GetCurFrame().GetError();
}
wpi::StringRef SinkImpl::GetError(wpi::SmallVectorImpl<char>& buf) const {
std::scoped_lock lock(m_mutex);
if (!m_source) return "no source connected";
if (!m_source) {
return "no source connected";
}
// Make a copy as it's shared data
wpi::StringRef error = m_source->GetCurFrame().GetError();
buf.clear();
@@ -115,8 +135,9 @@ bool SinkImpl::SetConfigJson(wpi::StringRef config, CS_Status* status) {
}
bool SinkImpl::SetConfigJson(const wpi::json& config, CS_Status* status) {
if (config.count("properties") != 0)
if (config.count("properties") != 0) {
SetPropertiesJson(config.at("properties"), m_logger, GetName(), status);
}
return true;
}
@@ -133,7 +154,9 @@ wpi::json SinkImpl::GetConfigJsonObject(CS_Status* status) {
wpi::json j;
wpi::json props = GetPropertiesJsonObject(status);
if (props.is_array()) j.emplace("properties", props);
if (props.is_array()) {
j.emplace("properties", props);
}
return j;
}
@@ -143,21 +166,25 @@ void SinkImpl::NotifyPropertyCreated(int propIndex, PropertyImpl& prop) {
propIndex, prop.propKind, prop.value,
prop.valueStr);
// also notify choices updated event for enum types
if (prop.propKind == CS_PROP_ENUM)
if (prop.propKind == CS_PROP_ENUM) {
m_notifier.NotifySinkProperty(*this, CS_SINK_PROPERTY_CHOICES_UPDATED,
prop.name, propIndex, prop.propKind,
prop.value, wpi::Twine{});
}
}
void SinkImpl::UpdatePropertyValue(int property, bool setString, int value,
const wpi::Twine& valueStr) {
auto prop = GetProperty(property);
if (!prop) return;
if (!prop) {
return;
}
if (setString)
if (setString) {
prop->SetValue(valueStr);
else
} else {
prop->SetValue(value);
}
// Only notify updates after we've notified created
if (m_properties_cached) {

View File

@@ -54,10 +54,11 @@ wpi::StringRef SourceImpl::GetDescription(
void SourceImpl::SetConnected(bool connected) {
bool wasConnected = m_connected.exchange(connected);
if (wasConnected && !connected)
if (wasConnected && !connected) {
m_notifier.NotifySource(*this, CS_SOURCE_DISCONNECTED);
else if (!wasConnected && connected)
} else if (!wasConnected && connected) {
m_notifier.NotifySource(*this, CS_SOURCE_CONNECTED);
}
}
uint64_t SourceImpl::GetCurFrameTime() {
@@ -130,7 +131,9 @@ void SourceImpl::SetExposureManual(int value, CS_Status* status) {
}
VideoMode SourceImpl::GetVideoMode(CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return VideoMode{};
if (!m_properties_cached && !CacheProperties(status)) {
return {};
}
std::scoped_lock lock(m_mutex);
return m_mode;
}
@@ -138,14 +141,18 @@ VideoMode SourceImpl::GetVideoMode(CS_Status* status) const {
bool SourceImpl::SetPixelFormat(VideoMode::PixelFormat pixelFormat,
CS_Status* status) {
auto mode = GetVideoMode(status);
if (!mode) return false;
if (!mode) {
return false;
}
mode.pixelFormat = pixelFormat;
return SetVideoMode(mode, status);
}
bool SourceImpl::SetResolution(int width, int height, CS_Status* status) {
auto mode = GetVideoMode(status);
if (!mode) return false;
if (!mode) {
return false;
}
mode.width = width;
mode.height = height;
return SetVideoMode(mode, status);
@@ -153,7 +160,9 @@ bool SourceImpl::SetResolution(int width, int height, CS_Status* status) {
bool SourceImpl::SetFPS(int fps, CS_Status* status) {
auto mode = GetVideoMode(status);
if (!mode) return false;
if (!mode) {
return false;
}
mode.fps = fps;
return SetVideoMode(mode, status);
}
@@ -315,8 +324,9 @@ bool SourceImpl::SetConfigJson(const wpi::json& config, CS_Status* status) {
}
// properties
if (config.count("properties") != 0)
if (config.count("properties") != 0) {
SetPropertiesJson(config.at("properties"), m_logger, GetName(), status);
}
return true;
}
@@ -353,30 +363,41 @@ wpi::json SourceImpl::GetConfigJsonObject(CS_Status* status) {
default:
break;
}
if (!pixelFormat.empty()) j.emplace("pixel format", pixelFormat);
if (!pixelFormat.empty()) {
j.emplace("pixel format", pixelFormat);
}
// width
if (m_mode.width != 0) j.emplace("width", m_mode.width);
if (m_mode.width != 0) {
j.emplace("width", m_mode.width);
}
// height
if (m_mode.height != 0) j.emplace("height", m_mode.height);
if (m_mode.height != 0) {
j.emplace("height", m_mode.height);
}
// fps
if (m_mode.fps != 0) j.emplace("fps", m_mode.fps);
if (m_mode.fps != 0) {
j.emplace("fps", m_mode.fps);
}
// TODO: output brightness, white balance, and exposure?
// properties
wpi::json props = GetPropertiesJsonObject(status);
if (props.is_array()) j.emplace("properties", props);
if (props.is_array()) {
j.emplace("properties", props);
}
return j;
}
std::vector<VideoMode> SourceImpl::EnumerateVideoModes(
CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status))
return std::vector<VideoMode>{};
if (!m_properties_cached && !CacheProperties(status)) {
return {};
}
std::scoped_lock lock(m_mutex);
return m_videoModes;
}
@@ -401,10 +422,11 @@ std::unique_ptr<Image> SourceImpl::AllocImage(
}
// if nothing found, allocate a new buffer
if (found < 0)
if (found < 0) {
image.reset(new Image{size});
else
} else {
image = std::move(m_imagesAvail[found]);
}
}
// Initialize image
@@ -461,21 +483,25 @@ void SourceImpl::NotifyPropertyCreated(int propIndex, PropertyImpl& prop) {
propIndex, prop.propKind, prop.value,
prop.valueStr);
// also notify choices updated event for enum types
if (prop.propKind == CS_PROP_ENUM)
if (prop.propKind == CS_PROP_ENUM) {
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CHOICES_UPDATED,
prop.name, propIndex, prop.propKind,
prop.value, wpi::Twine{});
}
}
void SourceImpl::UpdatePropertyValue(int property, bool setString, int value,
const wpi::Twine& valueStr) {
auto prop = GetProperty(property);
if (!prop) return;
if (!prop) {
return;
}
if (setString)
if (setString) {
prop->SetValue(valueStr);
else
} else {
prop->SetValue(value);
}
// Only notify updates after we've notified created
if (m_properties_cached) {
@@ -487,7 +513,9 @@ void SourceImpl::UpdatePropertyValue(int property, bool setString, int value,
void SourceImpl::ReleaseImage(std::unique_ptr<Image> image) {
std::scoped_lock lock{m_poolMutex};
if (m_destroyFrames) return;
if (m_destroyFrames) {
return;
}
// Return the frame to the pool. First try to find an empty slot, otherwise
// add it to the end.
auto it = std::find(m_imagesAvail.begin(), m_imagesAvail.end(), nullptr);
@@ -501,7 +529,9 @@ void SourceImpl::ReleaseImage(std::unique_ptr<Image> image) {
[](const std::unique_ptr<Image>& a, const std::unique_ptr<Image>& b) {
return a->capacity() < b->capacity();
});
if ((*it2)->capacity() < image->capacity()) *it2 = std::move(image);
if ((*it2)->capacity() < image->capacity()) {
*it2 = std::move(image);
}
} else {
m_imagesAvail.emplace_back(std::move(image));
}
@@ -510,7 +540,9 @@ void SourceImpl::ReleaseImage(std::unique_ptr<Image> image) {
std::unique_ptr<Frame::Impl> SourceImpl::AllocFrameImpl() {
std::scoped_lock lock{m_poolMutex};
if (m_framesAvail.empty()) return std::make_unique<Frame::Impl>(*this);
if (m_framesAvail.empty()) {
return std::make_unique<Frame::Impl>(*this);
}
auto impl = std::move(m_framesAvail.back());
m_framesAvail.pop_back();
@@ -519,6 +551,8 @@ std::unique_ptr<Frame::Impl> SourceImpl::AllocFrameImpl() {
void SourceImpl::ReleaseFrameImpl(std::unique_ptr<Frame::Impl> impl) {
std::scoped_lock lock{m_poolMutex};
if (m_destroyFrames) return;
if (m_destroyFrames) {
return;
}
m_framesAvail.push_back(std::move(impl));
}

View File

@@ -45,22 +45,31 @@ int64_t Telemetry::Thread::GetValue(CS_Handle handle, CS_TelemetryKind kind,
Telemetry::~Telemetry() {}
void Telemetry::Start() { m_owner.Start(m_notifier); }
void Telemetry::Start() {
m_owner.Start(m_notifier);
}
void Telemetry::Stop() { m_owner.Stop(); }
void Telemetry::Stop() {
m_owner.Stop();
}
void Telemetry::Thread::Main() {
std::unique_lock lock(m_mutex);
auto prevTime = std::chrono::steady_clock::now();
while (m_active) {
double period = m_period;
if (period == 0) period = 1000.0;
if (period == 0) {
period = 1000.0;
}
auto timeoutTime = prevTime + std::chrono::duration<double>(period);
while (m_active && !m_updated) {
if (m_cond.wait_until(lock, timeoutTime) == std::cv_status::timeout)
if (m_cond.wait_until(lock, timeoutTime) == std::cv_status::timeout) {
break;
}
}
if (!m_active) {
break;
}
if (!m_active) break;
if (m_updated) {
m_updated = false;
continue;
@@ -80,8 +89,12 @@ void Telemetry::Thread::Main() {
void Telemetry::SetPeriod(double seconds) {
auto thr = m_owner.GetThread();
if (!thr) return;
if (thr->m_period == seconds) return; // no change
if (!thr) {
return;
}
if (thr->m_period == seconds) {
return; // no change
}
thr->m_period = seconds;
thr->m_updated = true;
thr->m_cond.notify_one();
@@ -89,7 +102,9 @@ void Telemetry::SetPeriod(double seconds) {
double Telemetry::GetElapsedTime() {
auto thr = m_owner.GetThread();
if (!thr) return 0;
if (!thr) {
return 0;
}
return thr->m_elapsed;
}
@@ -110,13 +125,17 @@ double Telemetry::GetAverageValue(CS_Handle handle, CS_TelemetryKind kind,
*status = CS_TELEMETRY_NOT_ENABLED;
return 0;
}
if (thr->m_elapsed == 0) return 0.0;
if (thr->m_elapsed == 0) {
return 0.0;
}
return thr->GetValue(handle, kind, status) / thr->m_elapsed;
}
void Telemetry::RecordSourceBytes(const SourceImpl& source, int quantity) {
auto thr = m_owner.GetThread();
if (!thr) return;
if (!thr) {
return;
}
auto handleData = Instance::GetInstance().FindSource(source);
thr->m_current[std::make_pair(Handle{handleData.first, Handle::kSource},
static_cast<int>(CS_SOURCE_BYTES_RECEIVED))] +=
@@ -125,7 +144,9 @@ void Telemetry::RecordSourceBytes(const SourceImpl& source, int quantity) {
void Telemetry::RecordSourceFrames(const SourceImpl& source, int quantity) {
auto thr = m_owner.GetThread();
if (!thr) return;
if (!thr) {
return;
}
auto handleData = Instance::GetInstance().FindSource(source);
thr->m_current[std::make_pair(Handle{handleData.first, Handle::kSource},
static_cast<int>(CS_SOURCE_FRAMES_RECEIVED))] +=

View File

@@ -87,7 +87,9 @@ THandle UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Allocate(
return MakeHandle(i);
}
}
if (i >= THandle::kIndexMax) return 0;
if (i >= THandle::kIndexMax) {
return 0;
}
m_structures.emplace_back(
std::make_shared<TStruct>(std::forward<Args>(args)...));
@@ -105,7 +107,9 @@ THandle UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Allocate(
return MakeHandle(i);
}
}
if (i >= THandle::kIndexMax) return 0;
if (i >= THandle::kIndexMax) {
return 0;
}
m_structures.push_back(structure);
return MakeHandle(i);
@@ -117,9 +121,13 @@ UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Get(
THandle handle) {
auto index =
handle.GetTypedIndex(static_cast<typename THandle::Type>(typeValue));
if (index < 0) return nullptr;
if (index < 0) {
return nullptr;
}
std::scoped_lock sync(m_handleMutex);
if (index >= static_cast<int>(m_structures.size())) return nullptr;
if (index >= static_cast<int>(m_structures.size())) {
return nullptr;
}
return m_structures[index];
}
@@ -129,9 +137,13 @@ UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Free(
THandle handle) {
auto index =
handle.GetTypedIndex(static_cast<typename THandle::Type>(typeValue));
if (index < 0) return nullptr;
if (index < 0) {
return nullptr;
}
std::scoped_lock sync(m_handleMutex);
if (index >= static_cast<int>(m_structures.size())) return nullptr;
if (index >= static_cast<int>(m_structures.size())) {
return nullptr;
}
auto rv = std::move(m_structures[index]);
m_structures[index].reset();
return rv;
@@ -161,7 +173,9 @@ inline void
UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::ForEach(F func) {
std::scoped_lock sync(m_handleMutex);
for (size_t i = 0; i < m_structures.size(); i++) {
if (m_structures[i] != nullptr) func(MakeHandle(i), *(m_structures[i]));
if (m_structures[i] != nullptr) {
func(MakeHandle(i), *(m_structures[i]));
}
}
}
@@ -172,8 +186,9 @@ UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::FindIf(F func) {
std::scoped_lock sync(m_handleMutex);
for (size_t i = 0; i < m_structures.size(); i++) {
auto& structure = m_structures[i];
if (structure != nullptr && func(*structure))
if (structure != nullptr && func(*structure)) {
return std::make_pair(MakeHandle(i), structure);
}
}
return std::make_pair(0, nullptr);
}

View File

@@ -16,8 +16,9 @@ static void ConvertToC(CS_UsbCameraInfo* out, const UsbCameraInfo& in) {
out->otherPaths = static_cast<char**>(
wpi::safe_malloc(in.otherPaths.size() * sizeof(char*)));
out->otherPathsCount = in.otherPaths.size();
for (size_t i = 0; i < in.otherPaths.size(); ++i)
for (size_t i = 0; i < in.otherPaths.size(); ++i) {
out->otherPaths[i] = cs::ConvertToC(in.otherPaths[i]);
}
out->vendorId = in.vendorId;
out->productId = in.productId;
}
@@ -25,8 +26,9 @@ static void ConvertToC(CS_UsbCameraInfo* out, const UsbCameraInfo& in) {
static void FreeUsbCameraInfo(CS_UsbCameraInfo* info) {
std::free(info->path);
std::free(info->name);
for (int i = 0; i < info->otherPathsCount; ++i)
for (int i = 0; i < info->otherPathsCount; ++i) {
std::free(info->otherPaths[i]);
}
std::free(info->otherPaths);
}
@@ -52,7 +54,9 @@ char* CS_GetUsbCameraPath(CS_Source source, CS_Status* status) {
CS_UsbCameraInfo* CS_GetUsbCameraInfo(CS_Source source, CS_Status* status) {
auto info = cs::GetUsbCameraInfo(source, status);
if (*status != CS_OK) return nullptr;
if (*status != CS_OK) {
return nullptr;
}
CS_UsbCameraInfo* out = static_cast<CS_UsbCameraInfo*>(
wpi::safe_malloc(sizeof(CS_UsbCameraInfo)));
ConvertToC(out, info);
@@ -64,18 +68,26 @@ CS_UsbCameraInfo* CS_EnumerateUsbCameras(int* count, CS_Status* status) {
CS_UsbCameraInfo* out = static_cast<CS_UsbCameraInfo*>(
wpi::safe_malloc(cameras.size() * sizeof(CS_UsbCameraInfo)));
*count = cameras.size();
for (size_t i = 0; i < cameras.size(); ++i) ConvertToC(&out[i], cameras[i]);
for (size_t i = 0; i < cameras.size(); ++i) {
ConvertToC(&out[i], cameras[i]);
}
return out;
}
void CS_FreeEnumeratedUsbCameras(CS_UsbCameraInfo* cameras, int count) {
if (!cameras) return;
for (int i = 0; i < count; ++i) FreeUsbCameraInfo(&cameras[i]);
if (!cameras) {
return;
}
for (int i = 0; i < count; ++i) {
FreeUsbCameraInfo(&cameras[i]);
}
std::free(cameras);
}
void CS_FreeUsbCameraInfo(CS_UsbCameraInfo* info) {
if (!info) return;
if (!info) {
return;
}
FreeUsbCameraInfo(info);
std::free(info);
}

View File

@@ -24,7 +24,9 @@ CS_PropertyKind CS_GetPropertyKind(CS_Property property, CS_Status* status) {
char* CS_GetPropertyName(CS_Property property, CS_Status* status) {
wpi::SmallString<128> buf;
auto str = cs::GetPropertyName(property, buf, status);
if (*status != 0) return nullptr;
if (*status != 0) {
return nullptr;
}
return cs::ConvertToC(str);
}
@@ -55,7 +57,9 @@ int CS_GetPropertyDefault(CS_Property property, CS_Status* status) {
char* CS_GetStringProperty(CS_Property property, CS_Status* status) {
wpi::SmallString<128> buf;
auto str = cs::GetStringProperty(property, buf, status);
if (*status != 0) return nullptr;
if (*status != 0) {
return nullptr;
}
return cs::ConvertToC(str);
}
@@ -70,8 +74,9 @@ char** CS_GetEnumPropertyChoices(CS_Property property, int* count,
char** out =
static_cast<char**>(wpi::safe_malloc(choices.size() * sizeof(char*)));
*count = choices.size();
for (size_t i = 0; i < choices.size(); ++i)
for (size_t i = 0; i < choices.size(); ++i) {
out[i] = cs::ConvertToC(choices[i]);
}
return out;
}
@@ -82,14 +87,18 @@ CS_SourceKind CS_GetSourceKind(CS_Source source, CS_Status* status) {
char* CS_GetSourceName(CS_Source source, CS_Status* status) {
wpi::SmallString<128> buf;
auto str = cs::GetSourceName(source, buf, status);
if (*status != 0) return nullptr;
if (*status != 0) {
return nullptr;
}
return cs::ConvertToC(str);
}
char* CS_GetSourceDescription(CS_Source source, CS_Status* status) {
wpi::SmallString<128> buf;
auto str = cs::GetSourceDescription(source, buf, status);
if (*status != 0) return nullptr;
if (*status != 0) {
return nullptr;
}
return cs::ConvertToC(str);
}
@@ -248,14 +257,18 @@ CS_SinkKind CS_GetSinkKind(CS_Sink sink, CS_Status* status) {
char* CS_GetSinkName(CS_Sink sink, CS_Status* status) {
wpi::SmallString<128> buf;
auto str = cs::GetSinkName(sink, buf, status);
if (*status != 0) return nullptr;
if (*status != 0) {
return nullptr;
}
return cs::ConvertToC(str);
}
char* CS_GetSinkDescription(CS_Sink sink, CS_Status* status) {
wpi::SmallString<128> buf;
auto str = cs::GetSinkDescription(sink, buf, status);
if (*status != 0) return nullptr;
if (*status != 0) {
return nullptr;
}
return cs::ConvertToC(str);
}
@@ -338,9 +351,13 @@ void CS_RemoveListener(CS_Listener handle, CS_Status* status) {
return cs::RemoveListener(handle, status);
}
int CS_NotifierDestroyed(void) { return cs::NotifierDestroyed(); }
int CS_NotifierDestroyed(void) {
return cs::NotifierDestroyed();
}
void CS_SetTelemetryPeriod(double seconds) { cs::SetTelemetryPeriod(seconds); }
void CS_SetTelemetryPeriod(double seconds) {
cs::SetTelemetryPeriod(seconds);
}
double CS_GetTelemetryElapsedTime(void) {
return cs::GetTelemetryElapsedTime();
@@ -364,7 +381,9 @@ void CS_SetDefaultLogger(unsigned int min_level) {
cs::SetDefaultLogger(min_level);
}
void CS_Shutdown(void) { cs::Shutdown(); }
void CS_Shutdown(void) {
cs::Shutdown();
}
CS_Source* CS_EnumerateSources(int* count, CS_Status* status) {
wpi::SmallVector<CS_Source, 32> buf;
@@ -377,10 +396,14 @@ CS_Source* CS_EnumerateSources(int* count, CS_Status* status) {
}
void CS_ReleaseEnumeratedSources(CS_Source* sources, int count) {
if (!sources) return;
if (!sources) {
return;
}
for (int i = 0; i < count; ++i) {
CS_Status status = 0;
if (sources[i] != 0) cs::ReleaseSource(sources[i], &status);
if (sources[i] != 0) {
cs::ReleaseSource(sources[i], &status);
}
}
std::free(sources);
}
@@ -396,19 +419,29 @@ CS_Sink* CS_EnumerateSinks(int* count, CS_Status* status) {
}
void CS_ReleaseEnumeratedSinks(CS_Sink* sinks, int count) {
if (!sinks) return;
if (!sinks) {
return;
}
for (int i = 0; i < count; ++i) {
CS_Status status = 0;
if (sinks[i] != 0) cs::ReleaseSink(sinks[i], &status);
if (sinks[i] != 0) {
cs::ReleaseSink(sinks[i], &status);
}
}
std::free(sinks);
}
void CS_FreeString(char* str) { std::free(str); }
void CS_FreeString(char* str) {
std::free(str);
}
void CS_FreeEnumPropertyChoices(char** choices, int count) {
if (!choices) return;
for (int i = 0; i < count; ++i) std::free(choices[i]);
if (!choices) {
return;
}
for (int i = 0; i < count; ++i) {
std::free(choices[i]);
}
std::free(choices);
}
@@ -420,26 +453,35 @@ void CS_FreeEnumeratedVideoModes(CS_VideoMode* modes, int count) {
std::free(modes);
}
char* CS_GetHostname() { return cs::ConvertToC(cs::GetHostname()); }
char* CS_GetHostname() {
return cs::ConvertToC(cs::GetHostname());
}
char** CS_GetNetworkInterfaces(int* count) {
auto interfaces = cs::GetNetworkInterfaces();
char** out =
static_cast<char**>(wpi::safe_malloc(interfaces.size() * sizeof(char*)));
*count = interfaces.size();
for (size_t i = 0; i < interfaces.size(); ++i)
for (size_t i = 0; i < interfaces.size(); ++i) {
out[i] = cs::ConvertToC(interfaces[i]);
}
return out;
}
void CS_FreeNetworkInterfaces(char** interfaces, int count) {
if (!interfaces) return;
for (int i = 0; i < count; ++i) std::free(interfaces[i]);
if (!interfaces) {
return;
}
for (int i = 0; i < count; ++i) {
std::free(interfaces[i]);
}
std::free(interfaces);
}
void CS_AllocateRawFrameData(CS_RawFrame* frame, int requestedSize) {
if (frame->dataLength >= requestedSize) return;
if (frame->dataLength >= requestedSize) {
return;
}
if (frame->data) {
frame->data =
static_cast<char*>(wpi::safe_realloc(frame->data, requestedSize));

View File

@@ -57,7 +57,9 @@ namespace cs {
CS_PropertyKind GetPropertyKind(CS_Property property, CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
if (!container) return CS_PROP_NONE;
if (!container) {
return CS_PROP_NONE;
}
return container->GetPropertyKind(propertyIndex);
}
@@ -65,7 +67,9 @@ std::string GetPropertyName(CS_Property property, CS_Status* status) {
wpi::SmallString<128> buf;
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
if (!container) return std::string{};
if (!container) {
return {};
}
return container->GetPropertyName(propertyIndex, buf, status);
}
@@ -74,49 +78,63 @@ wpi::StringRef GetPropertyName(CS_Property property,
CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
if (!container) return wpi::StringRef{};
if (!container) {
return {};
}
return container->GetPropertyName(propertyIndex, buf, status);
}
int GetProperty(CS_Property property, CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
if (!container) return false;
if (!container) {
return false;
}
return container->GetProperty(propertyIndex, status);
}
void SetProperty(CS_Property property, int value, CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
if (!container) return;
if (!container) {
return;
}
container->SetProperty(propertyIndex, value, status);
}
int GetPropertyMin(CS_Property property, CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
if (!container) return 0.0;
if (!container) {
return 0.0;
}
return container->GetPropertyMin(propertyIndex, status);
}
int GetPropertyMax(CS_Property property, CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
if (!container) return 0.0;
if (!container) {
return 0.0;
}
return container->GetPropertyMax(propertyIndex, status);
}
int GetPropertyStep(CS_Property property, CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
if (!container) return 0.0;
if (!container) {
return 0.0;
}
return container->GetPropertyStep(propertyIndex, status);
}
int GetPropertyDefault(CS_Property property, CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
if (!container) return 0.0;
if (!container) {
return 0.0;
}
return container->GetPropertyDefault(propertyIndex, status);
}
@@ -124,7 +142,9 @@ std::string GetStringProperty(CS_Property property, CS_Status* status) {
wpi::SmallString<128> buf;
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
if (!container) return std::string{};
if (!container) {
return {};
}
return container->GetStringProperty(propertyIndex, buf, status);
}
@@ -133,7 +153,9 @@ wpi::StringRef GetStringProperty(CS_Property property,
CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
if (!container) return wpi::StringRef{};
if (!container) {
return {};
}
return container->GetStringProperty(propertyIndex, buf, status);
}
@@ -141,7 +163,9 @@ void SetStringProperty(CS_Property property, const wpi::Twine& value,
CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
if (!container) return;
if (!container) {
return;
}
container->SetStringProperty(propertyIndex, value, status);
}
@@ -149,7 +173,9 @@ std::vector<std::string> GetEnumPropertyChoices(CS_Property property,
CS_Status* status) {
int propertyIndex;
auto container = GetPropertyContainer(property, &propertyIndex, status);
if (!container) return std::vector<std::string>{};
if (!container) {
return {};
}
return container->GetEnumPropertyChoices(propertyIndex, status);
}
@@ -269,8 +295,9 @@ wpi::ArrayRef<CS_Property> EnumerateSourceProperties(
}
wpi::SmallVector<int, 32> properties_buf;
for (auto property :
data->source->EnumerateProperties(properties_buf, status))
data->source->EnumerateProperties(properties_buf, status)) {
vec.push_back(Handle{source, property, Handle::kProperty});
}
return vec;
}
@@ -383,7 +410,9 @@ wpi::ArrayRef<CS_Sink> EnumerateSourceSinks(CS_Source source,
}
CS_Source CopySource(CS_Source source, CS_Status* status) {
if (source == 0) return 0;
if (source == 0) {
return 0;
}
auto data = Instance::GetInstance().GetSource(source);
if (!data) {
*status = CS_INVALID_HANDLE;
@@ -394,14 +423,18 @@ CS_Source CopySource(CS_Source source, CS_Status* status) {
}
void ReleaseSource(CS_Source source, CS_Status* status) {
if (source == 0) return;
if (source == 0) {
return;
}
auto& inst = Instance::GetInstance();
auto data = inst.GetSource(source);
if (!data) {
*status = CS_INVALID_HANDLE;
return;
}
if (data->refCount-- == 0) inst.DestroySource(source);
if (data->refCount-- == 0) {
inst.DestroySource(source);
}
}
//
@@ -556,8 +589,10 @@ wpi::ArrayRef<CS_Property> EnumerateSinkProperties(
return 0;
}
wpi::SmallVector<int, 32> properties_buf;
for (auto property : data->sink->EnumerateProperties(properties_buf, status))
for (auto property :
data->sink->EnumerateProperties(properties_buf, status)) {
vec.push_back(Handle{sink, property, Handle::kSinkProperty});
}
return vec;
}
@@ -639,7 +674,9 @@ CS_Property GetSinkSourceProperty(CS_Sink sink, const wpi::Twine& name,
}
CS_Sink CopySink(CS_Sink sink, CS_Status* status) {
if (sink == 0) return 0;
if (sink == 0) {
return 0;
}
auto data = Instance::GetInstance().GetSink(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
@@ -650,14 +687,18 @@ CS_Sink CopySink(CS_Sink sink, CS_Status* status) {
}
void ReleaseSink(CS_Sink sink, CS_Status* status) {
if (sink == 0) return;
if (sink == 0) {
return;
}
auto& inst = Instance::GetInstance();
auto data = inst.GetSink(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
return;
}
if (data->refCount-- == 0) inst.DestroySink(sink);
if (data->refCount-- == 0) {
inst.DestroySink(sink);
}
}
//
@@ -680,7 +721,9 @@ CS_Listener AddListener(std::function<void(const RawEvent& event)> callback,
if ((eventMask & CS_NETWORK_INTERFACES_CHANGED) != 0) {
// start network interface event listener
inst.networkListener.Start();
if (immediateNotify) inst.notifier.NotifyNetworkInterfacesChanged();
if (immediateNotify) {
inst.notifier.NotifyNetworkInterfacesChanged();
}
}
if (immediateNotify) {
// TODO
@@ -697,7 +740,9 @@ void RemoveListener(CS_Listener handle, CS_Status* status) {
Instance::GetInstance().notifier.RemoveListener(uid);
}
bool NotifierDestroyed() { return Notifier::destroyed(); }
bool NotifierDestroyed() {
return Notifier::destroyed();
}
//
// Telemetry Functions
@@ -741,7 +786,9 @@ void SetDefaultLogger(unsigned int min_level) {
//
// Shutdown Function
//
void Shutdown() { Instance::GetInstance().Shutdown(); }
void Shutdown() {
Instance::GetInstance().Shutdown();
}
//
// Utility Functions
@@ -757,6 +804,8 @@ wpi::ArrayRef<CS_Sink> EnumerateSinkHandles(wpi::SmallVectorImpl<CS_Sink>& vec,
return Instance::GetInstance().EnumerateSinkHandles(vec);
}
std::string GetHostname() { return wpi::GetHostname(); }
std::string GetHostname() {
return wpi::GetHostname();
}
} // namespace cs

View File

@@ -25,8 +25,9 @@ std::vector<VideoProperty> VideoSource::EnumerateProperties() const {
std::vector<VideoProperty> properties;
properties.reserve(handles.size());
for (CS_Property handle : handles)
for (CS_Property handle : handles) {
properties.emplace_back(VideoProperty{handle});
}
return properties;
}
@@ -37,7 +38,9 @@ std::vector<VideoSink> VideoSource::EnumerateSinks() {
std::vector<VideoSink> sinks;
sinks.reserve(handles.size());
for (int handle : handles) sinks.emplace_back(VideoSink{handle});
for (int handle : handles) {
sinks.emplace_back(VideoSink{handle});
}
return sinks;
}
@@ -48,7 +51,9 @@ std::vector<VideoSource> VideoSource::EnumerateSources() {
std::vector<VideoSource> sources;
sources.reserve(handles.size());
for (int handle : handles) sources.emplace_back(VideoSource{handle});
for (int handle : handles) {
sources.emplace_back(VideoSource{handle});
}
return sources;
}
@@ -59,8 +64,9 @@ std::vector<VideoProperty> VideoSink::EnumerateProperties() const {
std::vector<VideoProperty> properties;
properties.reserve(handles.size());
for (CS_Property handle : handles)
for (CS_Property handle : handles) {
properties.emplace_back(VideoProperty{handle});
}
return properties;
}
@@ -71,6 +77,8 @@ std::vector<VideoSink> VideoSink::EnumerateSinks() {
std::vector<VideoSink> sinks;
sinks.reserve(handles.size());
for (int handle : handles) sinks.emplace_back(VideoSink{handle});
for (int handle : handles) {
sinks.emplace_back(VideoSink{handle});
}
return sinks;
}

View File

@@ -50,22 +50,29 @@ static const JExceptionInit exceptions[] = {
{"java/lang/Exception", &exceptionEx}};
static void ListenerOnStart() {
if (!jvm) return;
if (!jvm) {
return;
}
JNIEnv* env;
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_2;
args.name = const_cast<char*>("CSListener");
args.group = nullptr;
if (jvm->AttachCurrentThreadAsDaemon(reinterpret_cast<void**>(&env), &args) !=
JNI_OK)
JNI_OK) {
return;
if (!env || !env->functions) return;
}
if (!env || !env->functions) {
return;
}
listenerEnv = env;
}
static void ListenerOnExit() {
listenerEnv = nullptr;
if (!jvm) return;
if (!jvm) {
return;
}
jvm->DetachCurrentThread();
}
@@ -89,7 +96,9 @@ static void ThrowJavaException(JNIEnv* env, const std::exception* e) {
what = "unknown exception";
}
if (!je) je = exceptionEx;
if (!je) {
je = exceptionEx;
}
env->ThrowNew(je, what.c_str());
}
@@ -99,18 +108,23 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
jvm = vm;
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK)
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR;
}
// Cache references to classes
for (auto& c : classes) {
*c.cls = JClass(env, c.name);
if (!*c.cls) return JNI_ERR;
if (!*c.cls) {
return JNI_ERR;
}
}
for (auto& c : exceptions) {
*c.cls = JException(env, c.name);
if (!*c.cls) return JNI_ERR;
if (!*c.cls) {
return JNI_ERR;
}
}
// Initial configuration of listener start/exit
@@ -124,8 +138,9 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved) {
cs::Shutdown();
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK)
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return;
}
// Delete global references
for (auto& c : classes) {
c.cls->free(env);
@@ -147,20 +162,27 @@ class JCSGlobal {
JCSGlobal(JNIEnv* env, T obj)
: m_obj(static_cast<T>(env->NewGlobalRef(obj))) {}
~JCSGlobal() {
if (!jvm || cs::NotifierDestroyed()) return;
if (!jvm || cs::NotifierDestroyed()) {
return;
}
JNIEnv* env;
bool attached = false;
// don't attach and de-attach if already attached to a thread.
if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) ==
JNI_EDETACHED) {
if (jvm->AttachCurrentThread(reinterpret_cast<void**>(&env), nullptr) !=
JNI_OK)
JNI_OK) {
return;
}
attached = true;
}
if (!env || !env->functions) return;
if (!env || !env->functions) {
return;
}
env->DeleteGlobalRef(m_obj);
if (attached) jvm->DetachCurrentThread();
if (attached) {
jvm->DetachCurrentThread();
}
}
operator T() { return m_obj; }
T obj() { return m_obj; }
@@ -170,7 +192,9 @@ class JCSGlobal {
};
static void ReportError(JNIEnv* env, CS_Status status) {
if (status == CS_OK) return;
if (status == CS_OK) {
return;
}
wpi::SmallString<64> msg;
switch (status) {
case CS_PROPERTY_WRITE_FAILED:
@@ -213,7 +237,9 @@ static void ReportError(JNIEnv* env, CS_Status status) {
}
static inline bool CheckStatus(JNIEnv* env, CS_Status status) {
if (status != CS_OK) ReportError(env, status);
if (status != CS_OK) {
ReportError(env, status);
}
return status == CS_OK;
}
@@ -293,7 +319,9 @@ Java_edu_wpi_cscore_CameraServerJNI_getPropertyName
CS_Status status = 0;
wpi::SmallString<128> buf;
auto str = cs::GetPropertyName(property, buf, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJString(env, str);
}
@@ -398,7 +426,9 @@ Java_edu_wpi_cscore_CameraServerJNI_getStringProperty
CS_Status status = 0;
wpi::SmallString<128> buf;
auto str = cs::GetStringProperty(property, buf, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJString(env, str);
}
@@ -431,7 +461,9 @@ Java_edu_wpi_cscore_CameraServerJNI_getEnumPropertyChoices
{
CS_Status status = 0;
auto arr = cs::GetEnumPropertyChoices(property, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJStringArray(env, arr);
}
@@ -617,7 +649,9 @@ Java_edu_wpi_cscore_CameraServerJNI_getSourceName
CS_Status status = 0;
wpi::SmallString<128> buf;
auto str = cs::GetSourceName(source, buf, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJString(env, str);
}
@@ -633,7 +667,9 @@ Java_edu_wpi_cscore_CameraServerJNI_getSourceDescription
CS_Status status = 0;
wpi::SmallString<128> buf;
auto str = cs::GetSourceDescription(source, buf, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJString(env, str);
}
@@ -729,7 +765,9 @@ Java_edu_wpi_cscore_CameraServerJNI_enumerateSourceProperties
CS_Status status = 0;
wpi::SmallVector<CS_Property, 32> buf;
auto arr = cs::EnumerateSourceProperties(source, buf, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJIntArray(env, arr);
}
@@ -744,7 +782,9 @@ Java_edu_wpi_cscore_CameraServerJNI_getSourceVideoMode
{
CS_Status status = 0;
auto val = cs::GetSourceVideoMode(source, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJObject(env, val);
}
@@ -855,9 +895,13 @@ Java_edu_wpi_cscore_CameraServerJNI_enumerateSourceVideoModes
{
CS_Status status = 0;
auto arr = cs::EnumerateSourceVideoModes(source, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
jobjectArray jarr = env->NewObjectArray(arr.size(), videoModeCls, nullptr);
if (!jarr) return nullptr;
if (!jarr) {
return nullptr;
}
for (size_t i = 0; i < arr.size(); ++i) {
JLocal<jobject> jelem{env, MakeJObject(env, arr[i])};
env->SetObjectArrayElement(jarr, i, jelem);
@@ -877,7 +921,9 @@ Java_edu_wpi_cscore_CameraServerJNI_enumerateSourceSinks
CS_Status status = 0;
wpi::SmallVector<CS_Sink, 16> buf;
auto arr = cs::EnumerateSourceSinks(source, buf, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJIntArray(env, arr);
}
@@ -1048,7 +1094,9 @@ Java_edu_wpi_cscore_CameraServerJNI_getUsbCameraPath
{
CS_Status status = 0;
auto str = cs::GetUsbCameraPath(source, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJString(env, str);
}
@@ -1063,7 +1111,9 @@ Java_edu_wpi_cscore_CameraServerJNI_getUsbCameraInfo
{
CS_Status status = 0;
auto info = cs::GetUsbCameraInfo(source, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJObject(env, info);
}
@@ -1078,7 +1128,9 @@ Java_edu_wpi_cscore_CameraServerJNI_getHttpCameraKind
{
CS_Status status = 0;
auto kind = cs::GetHttpCameraKind(source, &status);
if (!CheckStatus(env, status)) return 0;
if (!CheckStatus(env, status)) {
return 0;
}
return kind;
}
@@ -1123,7 +1175,9 @@ Java_edu_wpi_cscore_CameraServerJNI_getHttpCameraUrls
{
CS_Status status = 0;
auto arr = cs::GetHttpCameraUrls(source, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJStringArray(env, arr);
}
@@ -1381,7 +1435,9 @@ Java_edu_wpi_cscore_CameraServerJNI_getSinkName
CS_Status status = 0;
wpi::SmallString<128> buf;
auto str = cs::GetSinkName(sink, buf, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJString(env, str);
}
@@ -1397,7 +1453,9 @@ Java_edu_wpi_cscore_CameraServerJNI_getSinkDescription
CS_Status status = 0;
wpi::SmallString<128> buf;
auto str = cs::GetSinkDescription(sink, buf, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJString(env, str);
}
@@ -1432,7 +1490,9 @@ Java_edu_wpi_cscore_CameraServerJNI_enumerateSinkProperties
CS_Status status = 0;
wpi::SmallVector<CS_Property, 32> buf;
auto arr = cs::EnumerateSinkProperties(source, buf, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJIntArray(env, arr);
}
@@ -1555,7 +1615,9 @@ Java_edu_wpi_cscore_CameraServerJNI_getMjpegServerListenAddress
{
CS_Status status = 0;
auto str = cs::GetMjpegServerListenAddress(sink, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJString(env, str);
}
@@ -1721,7 +1783,9 @@ Java_edu_wpi_cscore_CameraServerJNI_getSinkError
CS_Status status = 0;
wpi::SmallString<128> buf;
auto str = cs::GetSinkError(sink, buf, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJString(env, str);
}
@@ -1760,17 +1824,23 @@ Java_edu_wpi_cscore_CameraServerJNI_addListener
// cls is a temporary here; cannot be used within callback functor
jclass cls = envouter->GetObjectClass(listener);
if (!cls) return 0;
if (!cls) {
return 0;
}
// method ids, on the other hand, are safe to retain
jmethodID mid = envouter->GetMethodID(cls, "accept", "(Ljava/lang/Object;)V");
if (!mid) return 0;
if (!mid) {
return 0;
}
CS_Status status = 0;
CS_Listener handle = cs::AddListener(
[=](const cs::RawEvent& event) {
JNIEnv* env = listenerEnv;
if (!env || !env->functions) return;
if (!env || !env->functions) {
return;
}
// get the handler
auto handler = listener_global->obj();
@@ -1782,7 +1852,9 @@ Java_edu_wpi_cscore_CameraServerJNI_addListener
env->ExceptionClear();
return;
}
if (!jobj) return;
if (!jobj) {
return;
}
env->CallVoidMethod(handler, mid, jobj.obj());
if (env->ExceptionCheck()) {
@@ -1876,10 +1948,14 @@ Java_edu_wpi_cscore_CameraServerJNI_enumerateUsbCameras
{
CS_Status status = 0;
auto arr = cs::EnumerateUsbCameras(&status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
jobjectArray jarr =
env->NewObjectArray(arr.size(), usbCameraInfoCls, nullptr);
if (!jarr) return nullptr;
if (!jarr) {
return nullptr;
}
for (size_t i = 0; i < arr.size(); ++i) {
JLocal<jobject> jelem{env, MakeJObject(env, arr[i])};
env->SetObjectArrayElement(jarr, i, jelem);
@@ -1899,7 +1975,9 @@ Java_edu_wpi_cscore_CameraServerJNI_enumerateSources
CS_Status status = 0;
wpi::SmallVector<CS_Source, 16> buf;
auto arr = cs::EnumerateSourceHandles(buf, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJIntArray(env, arr);
}
@@ -1915,7 +1993,9 @@ Java_edu_wpi_cscore_CameraServerJNI_enumerateSinks
CS_Status status = 0;
wpi::SmallVector<CS_Sink, 16> buf;
auto arr = cs::EnumerateSinkHandles(buf, &status);
if (!CheckStatus(env, status)) return nullptr;
if (!CheckStatus(env, status)) {
return nullptr;
}
return MakeJIntArray(env, arr);
}
@@ -1991,12 +2071,16 @@ Java_edu_wpi_cscore_CameraServerJNI_setLogger
}
// cls is a temporary here; cannot be used within callback functor
jclass cls = env->GetObjectClass(func);
if (!cls) return;
if (!cls) {
return;
}
// method ids, on the other hand, are safe to retain
jmethodID mid = env->GetMethodID(cls, "apply",
"(ILjava/lang/String;ILjava/lang/String;)V");
if (!mid) return;
if (!mid) {
return;
}
auto& logger = LoggerJNI::GetInstance();
logger.Start();

View File

@@ -124,10 +124,11 @@ struct RawEvent {
RawEvent(const wpi::Twine& name_, CS_Handle handle_, RawEvent::Kind kind_)
: kind{kind_}, name{name_.str()} {
if (kind_ == kSinkCreated || kind_ == kSinkDestroyed ||
kind_ == kSinkEnabled || kind_ == kSinkDisabled)
kind_ == kSinkEnabled || kind_ == kSinkDisabled) {
sinkHandle = handle_;
else
} else {
sourceHandle = handle_;
}
}
RawEvent(const wpi::Twine& name_, CS_Source source_, const VideoMode& mode_)
: kind{kSourceVideoModeChanged},

View File

@@ -94,7 +94,8 @@ inline VideoSource& VideoSource::operator=(VideoSource other) noexcept {
inline VideoSource::~VideoSource() {
m_status = 0;
if (m_handle != 0) ReleaseSource(m_handle, &m_status);
if (m_handle != 0)
ReleaseSource(m_handle, &m_status);
}
inline VideoSource::Kind VideoSource::GetKind() const {
@@ -309,7 +310,8 @@ inline HttpCamera::HttpCamera(const wpi::Twine& name,
HttpCameraKind kind) {
std::vector<std::string> vec;
vec.reserve(urls.size());
for (const auto& url : urls) vec.emplace_back(url);
for (const auto& url : urls)
vec.emplace_back(url);
m_handle = CreateHttpCamera(
name, vec, static_cast<CS_HttpCameraKind>(static_cast<int>(kind)),
&m_status);
@@ -330,7 +332,8 @@ template <typename T>
inline void HttpCamera::SetUrls(std::initializer_list<T> urls) {
std::vector<std::string> vec;
vec.reserve(urls.size());
for (const auto& url : urls) vec.emplace_back(url);
for (const auto& url : urls)
vec.emplace_back(url);
m_status = 0;
::cs::SetHttpCameraUrls(m_handle, vec, &m_status);
}
@@ -457,7 +460,8 @@ inline void ImageSource::SetEnumPropertyChoices(
const VideoProperty& property, std::initializer_list<T> choices) {
std::vector<std::string> vec;
vec.reserve(choices.size());
for (const auto& choice : choices) vec.emplace_back(choice);
for (const auto& choice : choices)
vec.emplace_back(choice);
m_status = 0;
SetSourceEnumPropertyChoices(m_handle, property.m_handle, vec, &m_status);
}
@@ -476,7 +480,8 @@ inline VideoSink& VideoSink::operator=(VideoSink other) noexcept {
inline VideoSink::~VideoSink() {
m_status = 0;
if (m_handle != 0) ReleaseSink(m_handle, &m_status);
if (m_handle != 0)
ReleaseSink(m_handle, &m_status);
}
inline VideoSink::Kind VideoSink::GetKind() const {
@@ -625,7 +630,8 @@ inline VideoListener& VideoListener::operator=(VideoListener&& other) noexcept {
inline VideoListener::~VideoListener() {
CS_Status status = 0;
if (m_handle != 0) RemoveListener(m_handle, &status);
if (m_handle != 0)
RemoveListener(m_handle, &status);
}
} // namespace cs

View File

@@ -171,22 +171,22 @@ inline RawCvSink::RawCvSink(const wpi::Twine& name,
: RawSink{name, processFrame} {}
inline uint64_t RawCvSink::GrabFrame(cv::Mat& image, double timeout) {
cv::Mat tmpMat;
auto retVal = GrabFrameDirect(tmpMat);
cv::Mat tmpnam;
auto retVal = GrabFrameDirect(tmpnam);
if (retVal <= 0) {
return retVal;
}
tmpMat.copyTo(image);
tmpnam.copyTo(image);
return retVal;
}
inline uint64_t RawCvSink::GrabFrameNoTimeout(cv::Mat& image) {
cv::Mat tmpMat;
auto retVal = GrabFrameNoTimeoutDirect(tmpMat);
cv::Mat tmpnam;
auto retVal = GrabFrameNoTimeoutDirect(tmpnam);
if (retVal <= 0) {
return retVal;
}
tmpMat.copyTo(image);
tmpnam.copyTo(image);
return retVal;
}
@@ -195,7 +195,9 @@ inline uint64_t RawCvSink::GrabFrameDirect(cv::Mat& image, double timeout) {
rawFrame.width = 0;
rawFrame.pixelFormat = CS_PixelFormat::CS_PIXFMT_BGR;
m_status = RawSink::GrabFrame(rawFrame, timeout);
if (m_status <= 0) return m_status;
if (m_status <= 0) {
return m_status;
}
image = cv::Mat{rawFrame.height, rawFrame.width, CV_8UC3, rawFrame.data};
return m_status;
}
@@ -205,7 +207,9 @@ inline uint64_t RawCvSink::GrabFrameNoTimeoutDirect(cv::Mat& image) {
rawFrame.width = 0;
rawFrame.pixelFormat = CS_PixelFormat::CS_PIXFMT_BGR;
m_status = RawSink::GrabFrameNoTimeout(rawFrame);
if (m_status <= 0) return m_status;
if (m_status <= 0) {
return m_status;
}
image = cv::Mat{rawFrame.height, rawFrame.width, CV_8UC3, rawFrame.data};
return m_status;
}

View File

@@ -47,7 +47,9 @@ class NetworkListener::Impl {
NetworkListener::NetworkListener(wpi::Logger& logger, Notifier& notifier)
: m_impl(std::make_unique<Impl>(logger, notifier)) {}
NetworkListener::~NetworkListener() { Stop(); }
NetworkListener::~NetworkListener() {
Stop();
}
void NetworkListener::Start() {
m_impl->m_owner.Start(m_impl->m_logger, m_impl->m_notifier);
@@ -57,7 +59,9 @@ void NetworkListener::Stop() {
// Wake up thread
if (auto thr = m_impl->m_owner.GetThread()) {
thr->m_active = false;
if (thr->m_command_fd >= 0) eventfd_write(thr->m_command_fd, 1);
if (thr->m_command_fd >= 0) {
eventfd_write(thr->m_command_fd, 1);
}
}
m_impl->m_owner.Stop();
}
@@ -114,25 +118,35 @@ void NetworkListener::Impl::Thread::Main() {
}
// Double-check to see if we're shutting down
if (!m_active) break;
if (!m_active) {
break;
}
if (!FD_ISSET(sd, &readfds)) continue;
if (!FD_ISSET(sd, &readfds)) {
continue;
}
std::memset(&addr, 0, sizeof(addr));
struct iovec iov = {buf, sizeof(buf)};
struct msghdr msg = {&addr, sizeof(addr), &iov, 1, nullptr, 0, 0};
int len = ::recvmsg(sd, &msg, 0);
if (len < 0) {
if (errno == EWOULDBLOCK || errno == EAGAIN) continue;
if (errno == EWOULDBLOCK || errno == EAGAIN) {
continue;
}
ERROR(
"NetworkListener: could not read netlink: " << std::strerror(errno));
break; // XXX: is this the right thing to do here?
}
if (len == 0) continue; // EOF?
if (len == 0) {
continue; // EOF?
}
unsigned int ulen = static_cast<unsigned int>(len);
for (struct nlmsghdr* nh = reinterpret_cast<struct nlmsghdr*>(buf);
NLMSG_OK(nh, ulen); nh = NLMSG_NEXT(nh, ulen)) {
if (nh->nlmsg_type == NLMSG_DONE) break;
if (nh->nlmsg_type == NLMSG_DONE) {
break;
}
if (nh->nlmsg_type == RTM_NEWLINK || nh->nlmsg_type == RTM_DELLINK ||
nh->nlmsg_type == RTM_NEWADDR || nh->nlmsg_type == RTM_DELADDR) {
m_notifier.NotifyNetworkInterfacesChanged();

View File

@@ -13,17 +13,25 @@ namespace cs {
std::vector<std::string> GetNetworkInterfaces() {
struct ifaddrs* ifa;
if (::getifaddrs(&ifa) != 0) return std::vector<std::string>{};
if (::getifaddrs(&ifa) != 0) {
return {};
}
std::vector<std::string> rv;
char buf[256];
for (struct ifaddrs* i = ifa; i; i = i->ifa_next) {
if (!i->ifa_addr) continue; // no address
if (i->ifa_addr->sa_family != AF_INET) continue; // only return IPv4
if (!i->ifa_addr) {
continue; // no address
}
if (i->ifa_addr->sa_family != AF_INET) {
continue; // only return IPv4
}
struct sockaddr_in* addr_in = reinterpret_cast<sockaddr_in*>(i->ifa_addr);
const char* addr =
::inet_ntop(addr_in->sin_family, &addr_in->sin_addr, buf, sizeof(buf));
if (!addr) continue; // error converting address
if (!addr) {
continue; // error converting address
}
rv.emplace_back(addr);
}

View File

@@ -35,7 +35,9 @@ class UsbCameraBuffer {
}
~UsbCameraBuffer() {
if (m_data) munmap(m_data, m_length);
if (m_data) {
munmap(m_data, m_length);
}
}
friend void swap(UsbCameraBuffer& first, UsbCameraBuffer& second) noexcept {

View File

@@ -96,7 +96,9 @@ static __u32 FromPixelFormat(VideoMode::PixelFormat pixelFormat) {
}
static bool IsPercentageProperty(wpi::StringRef name) {
if (name.startswith("raw_")) name = name.substr(4);
if (name.startswith("raw_")) {
name = name.substr(4);
}
return name == "brightness" || name == "contrast" || name == "saturation" ||
name == "hue" || name == "sharpness" || name == "gain" ||
name == "exposure_absolute" || name == "exposure_time_absolute";
@@ -122,7 +124,9 @@ int UsbCameraImpl::RawToPercentage(const UsbCameraProperty& rawProp,
rawProp.minimum == 5 && rawProp.maximum == 20000) {
int nelems = wpi::array_lengthof(quirkLifeCamHd3000);
for (int i = 0; i < nelems; ++i) {
if (rawValue < quirkLifeCamHd3000[i]) return 100.0 * i / nelems;
if (rawValue < quirkLifeCamHd3000[i]) {
return 100.0 * i / nelems;
}
}
return 100;
}
@@ -137,8 +141,12 @@ int UsbCameraImpl::PercentageToRaw(const UsbCameraProperty& rawProp,
rawProp.minimum == 5 && rawProp.maximum == 20000) {
int nelems = wpi::array_lengthof(quirkLifeCamHd3000);
int ndx = nelems * percentValue / 100.0;
if (ndx < 0) ndx = 0;
if (ndx >= nelems) ndx = nelems - 1;
if (ndx < 0) {
ndx = 0;
}
if (ndx >= nelems) {
ndx = nelems - 1;
}
return quirkLifeCamHd3000[ndx];
}
return rawProp.minimum +
@@ -153,18 +161,28 @@ static bool GetVendorProduct(int dev, int* vendor, int* product) {
}
int fd = open(ifpath.c_str(), O_RDONLY);
if (fd < 0) return false;
if (fd < 0) {
return false;
}
char readBuf[128];
ssize_t n = read(fd, readBuf, sizeof(readBuf));
close(fd);
if (n <= 0) return false;
if (n <= 0) {
return false;
}
wpi::StringRef readStr{readBuf};
if (readStr.substr(readStr.find('v')).substr(1, 4).getAsInteger(16, *vendor))
if (readStr.substr(readStr.find('v'))
.substr(1, 4)
.getAsInteger(16, *vendor)) {
return false;
if (readStr.substr(readStr.find('p')).substr(1, 4).getAsInteger(16, *product))
}
if (readStr.substr(readStr.find('p'))
.substr(1, 4)
.getAsInteger(16, *product)) {
return false;
}
return true;
}
@@ -177,13 +195,17 @@ static bool GetDescriptionSysV4L(int dev, std::string* desc) {
}
int fd = open(ifpath.c_str(), O_RDONLY);
if (fd < 0) return false;
if (fd < 0) {
return false;
}
char readBuf[128];
ssize_t n = read(fd, readBuf, sizeof(readBuf));
close(fd);
if (n <= 0) return false;
if (n <= 0) {
return false;
}
*desc = wpi::StringRef(readBuf, n).rtrim();
return true;
@@ -191,7 +213,9 @@ static bool GetDescriptionSysV4L(int dev, std::string* desc) {
static bool GetDescriptionIoctl(const char* cpath, std::string* desc) {
int fd = open(cpath, O_RDWR);
if (fd < 0) return false;
if (fd < 0) {
return false;
}
struct v4l2_capability vcap;
std::memset(&vcap, 0, sizeof(vcap));
@@ -222,7 +246,9 @@ static bool GetDescriptionIoctl(const char* cpath, std::string* desc) {
static bool IsVideoCaptureDevice(const char* cpath) {
int fd = open(cpath, O_RDWR);
if (fd < 0) return false;
if (fd < 0) {
return false;
}
struct v4l2_capability vcap;
std::memset(&vcap, 0, sizeof(vcap));
@@ -255,9 +281,13 @@ static int GetDeviceNum(const char* cpath) {
}
path = wpi::sys::path::filename(path);
if (!path.startswith("video")) return -1;
if (!path.startswith("video")) {
return -1;
}
int dev = -1;
if (path.substr(5).getAsInteger(10, dev)) return -1;
if (path.substr(5).getAsInteger(10, dev)) {
return -1;
}
return dev;
}
@@ -267,11 +297,15 @@ static std::string GetDescriptionImpl(const char* cpath) {
int dev = GetDeviceNum(cpath);
if (dev >= 0) {
// Sometimes the /sys tree gives a better name.
if (GetDescriptionSysV4L(dev, &rv)) return rv;
if (GetDescriptionSysV4L(dev, &rv)) {
return rv;
}
}
// Otherwise use an ioctl to query the caps and get the card name
if (GetDescriptionIoctl(cpath, &rv)) return rv;
if (GetDescriptionIoctl(cpath, &rv)) {
return rv;
}
return std::string{};
}
@@ -305,17 +339,23 @@ UsbCameraImpl::~UsbCameraImpl() {
Send(Message{Message::kNone});
// join camera thread
if (m_cameraThread.joinable()) m_cameraThread.join();
if (m_cameraThread.joinable()) {
m_cameraThread.join();
}
// close command fd
int fd = m_command_fd.exchange(-1);
if (fd >= 0) close(fd);
if (fd >= 0) {
close(fd);
}
}
static inline void DoFdSet(int fd, fd_set* set, int* nfds) {
if (fd >= 0) {
FD_SET(fd, set);
if ((fd + 1) > *nfds) *nfds = fd + 1;
if ((fd + 1) > *nfds) {
*nfds = fd + 1;
}
}
}
@@ -357,12 +397,16 @@ void UsbCameraImpl::CameraThreadMain() {
while (m_active) {
// If not connected, try to reconnect
if (m_fd < 0) DeviceConnect();
if (m_fd < 0) {
DeviceConnect();
}
// Make copies of fd's in case they go away
int command_fd = m_command_fd.load();
int fd = m_fd.load();
if (!m_active) break;
if (!m_active) {
break;
}
// Reset notified flag and restart streaming if necessary
if (fd >= 0) {
@@ -395,7 +439,9 @@ void UsbCameraImpl::CameraThreadMain() {
fd_set readfds;
FD_ZERO(&readfds);
DoFdSet(command_fd, &readfds, &nfds);
if (m_streaming) DoFdSet(fd, &readfds, &nfds);
if (m_streaming) {
DoFdSet(fd, &readfds, &nfds);
}
DoFdSet(notify_fd, &readfds, &nfds);
if (select(nfds, &readfds, nullptr, nullptr, &tv) < 0) {
@@ -404,7 +450,9 @@ void UsbCameraImpl::CameraThreadMain() {
}
// Double-check to see if we're shutting down
if (!m_active) break;
if (!m_active) {
break;
}
// Handle notify events
if (notify_fd >= 0 && FD_ISSET(notify_fd, &readfds)) {
@@ -508,10 +556,14 @@ void UsbCameraImpl::CameraThreadMain() {
void UsbCameraImpl::DeviceDisconnect() {
int fd = m_fd.exchange(-1);
if (fd < 0) return; // already disconnected
if (fd < 0) {
return; // already disconnected
}
// Unmap buffers
for (int i = 0; i < kNumBuffers; ++i) m_buffers[i] = UsbCameraBuffer{};
for (int i = 0; i < kNumBuffers; ++i) {
m_buffers[i] = UsbCameraBuffer{};
}
// Close device
close(fd);
@@ -521,14 +573,20 @@ void UsbCameraImpl::DeviceDisconnect() {
}
void UsbCameraImpl::DeviceConnect() {
if (m_fd >= 0) return;
if (m_fd >= 0) {
return;
}
if (m_connectVerbose) SINFO("Connecting to USB camera on " << m_path);
if (m_connectVerbose) {
SINFO("Connecting to USB camera on " << m_path);
}
// Try to open the device
SDEBUG3("opening device");
int fd = open(m_path.c_str(), O_RDWR);
if (fd < 0) return;
if (fd < 0) {
return;
}
m_fd = fd;
// Get capabilities
@@ -537,8 +595,9 @@ void UsbCameraImpl::DeviceConnect() {
std::memset(&vcap, 0, sizeof(vcap));
if (DoIoctl(fd, VIDIOC_QUERYCAP, &vcap) >= 0) {
m_capabilities = vcap.capabilities;
if (m_capabilities & V4L2_CAP_DEVICE_CAPS)
if (m_capabilities & V4L2_CAP_DEVICE_CAPS) {
m_capabilities = vcap.device_caps;
}
}
// Get or restore video mode
@@ -559,10 +618,12 @@ void UsbCameraImpl::DeviceConnect() {
for (size_t i = 0; i < m_propertyData.size(); ++i) {
const auto prop =
static_cast<const UsbCameraProperty*>(m_propertyData[i].get());
if (!prop || !prop->valueSet || !prop->device || prop->percentage)
if (!prop || !prop->valueSet || !prop->device || prop->percentage) {
continue;
if (!prop->DeviceSet(lock2, m_fd))
}
if (!prop->DeviceSet(lock2, m_fd)) {
SWARNING("failed to set property " << prop->name);
}
}
}
@@ -601,7 +662,9 @@ void UsbCameraImpl::DeviceConnect() {
if (!m_buffers[i].m_data) {
SWARNING("could not map buffer " << i);
// release other buffers
for (int j = 0; j < i; ++j) m_buffers[j] = UsbCameraBuffer{};
for (int j = 0; j < i; ++j) {
m_buffers[j] = UsbCameraBuffer{};
}
close(fd);
m_fd = -1;
return;
@@ -621,9 +684,13 @@ void UsbCameraImpl::DeviceConnect() {
}
bool UsbCameraImpl::DeviceStreamOn() {
if (m_streaming) return false; // ignore if already enabled
if (m_streaming) {
return false; // ignore if already enabled
}
int fd = m_fd.load();
if (fd < 0) return false;
if (fd < 0) {
return false;
}
// Queue buffers
SDEBUG3("queuing buffers");
@@ -660,11 +727,17 @@ bool UsbCameraImpl::DeviceStreamOn() {
}
bool UsbCameraImpl::DeviceStreamOff() {
if (!m_streaming) return false; // ignore if already disabled
if (!m_streaming) {
return false; // ignore if already disabled
}
int fd = m_fd.load();
if (fd < 0) return false;
if (fd < 0) {
return false;
}
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (DoIoctl(fd, VIDIOC_STREAMOFF, &type) != 0) return false;
if (DoIoctl(fd, VIDIOC_STREAMOFF, &type) != 0) {
return false;
}
SDEBUG4("disabled streaming");
m_streaming = false;
return true;
@@ -703,12 +776,16 @@ CS_StatusValue UsbCameraImpl::DeviceCmdSetMode(
m_mode = newMode;
lock.unlock();
bool wasStreaming = m_streaming;
if (wasStreaming) DeviceStreamOff();
if (wasStreaming) {
DeviceStreamOff();
}
if (m_fd >= 0) {
DeviceDisconnect();
DeviceConnect();
}
if (wasStreaming) DeviceStreamOn();
if (wasStreaming) {
DeviceStreamOn();
}
m_notifier.NotifySourceVideoMode(*this, newMode);
lock.lock();
} else if (newMode.fps != m_mode.fps) {
@@ -716,9 +793,13 @@ CS_StatusValue UsbCameraImpl::DeviceCmdSetMode(
lock.unlock();
// Need to stop streaming to set FPS
bool wasStreaming = m_streaming;
if (wasStreaming) DeviceStreamOff();
if (wasStreaming) {
DeviceStreamOff();
}
DeviceSetFPS();
if (wasStreaming) DeviceStreamOn();
if (wasStreaming) {
DeviceStreamOn();
}
m_notifier.NotifySourceVideoMode(*this, newMode);
lock.lock();
}
@@ -735,21 +816,25 @@ CS_StatusValue UsbCameraImpl::DeviceCmdSetProperty(
// Look up
auto prop = static_cast<UsbCameraProperty*>(GetProperty(property));
if (!prop) return CS_INVALID_PROPERTY;
if (!prop) {
return CS_INVALID_PROPERTY;
}
// If setting before we get, guess initial type based on set
if (prop->propKind == CS_PROP_NONE) {
if (setString)
if (setString) {
prop->propKind = CS_PROP_STRING;
else
} else {
prop->propKind = CS_PROP_INTEGER;
}
}
// Check kind match
if ((setString && prop->propKind != CS_PROP_STRING) ||
(!setString && (prop->propKind &
(CS_PROP_BOOLEAN | CS_PROP_INTEGER | CS_PROP_ENUM)) == 0))
(!setString && (prop->propKind & (CS_PROP_BOOLEAN | CS_PROP_INTEGER |
CS_PROP_ENUM)) == 0)) {
return CS_WRONG_PROPERTY_TYPE;
}
// Handle percentage property
int percentageProperty = prop->propPair;
@@ -766,17 +851,21 @@ CS_StatusValue UsbCameraImpl::DeviceCmdSetProperty(
// Actually set the new value on the device (if possible)
if (!prop->device) {
if (prop->id == kPropConnectVerboseId) m_connectVerbose = value;
if (prop->id == kPropConnectVerboseId) {
m_connectVerbose = value;
}
} else {
if (!prop->DeviceSet(lock, m_fd, value, valueStr))
if (!prop->DeviceSet(lock, m_fd, value, valueStr)) {
return CS_PROPERTY_WRITE_FAILED;
}
}
// Cache the set values
UpdatePropertyValue(property, setString, value, valueStr);
if (percentageProperty != 0)
if (percentageProperty != 0) {
UpdatePropertyValue(percentageProperty, setString, percentageValue,
valueStr);
}
return CS_OK;
}
@@ -787,12 +876,16 @@ CS_StatusValue UsbCameraImpl::DeviceCmdSetPath(
lock.unlock();
// disconnect and reconnect
bool wasStreaming = m_streaming;
if (wasStreaming) DeviceStreamOff();
if (wasStreaming) {
DeviceStreamOff();
}
if (m_fd >= 0) {
DeviceDisconnect();
DeviceConnect();
}
if (wasStreaming) DeviceStreamOn();
if (wasStreaming) {
DeviceStreamOn();
}
lock.lock();
return CS_OK;
}
@@ -819,15 +912,18 @@ CS_StatusValue UsbCameraImpl::DeviceProcessCommand(
void UsbCameraImpl::DeviceProcessCommands() {
std::unique_lock lock(m_mutex);
if (m_commands.empty()) return;
if (m_commands.empty()) {
return;
}
while (!m_commands.empty()) {
auto msg = std::move(m_commands.back());
m_commands.pop_back();
CS_StatusValue status = DeviceProcessCommand(lock, msg);
if (msg.kind != Message::kNumSinksChanged &&
msg.kind != Message::kNumSinksEnabledChanged)
msg.kind != Message::kNumSinksEnabledChanged) {
m_responses.emplace_back(msg.from, status);
}
}
lock.unlock();
m_responseCv.notify_all();
@@ -835,7 +931,9 @@ void UsbCameraImpl::DeviceProcessCommands() {
void UsbCameraImpl::DeviceSetMode() {
int fd = m_fd.load();
if (fd < 0) return;
if (fd < 0) {
return;
}
struct v4l2_format vfmt;
std::memset(&vfmt, 0, sizeof(vfmt));
@@ -866,25 +964,34 @@ void UsbCameraImpl::DeviceSetMode() {
void UsbCameraImpl::DeviceSetFPS() {
int fd = m_fd.load();
if (fd < 0) return;
if (fd < 0) {
return;
}
struct v4l2_streamparm parm;
std::memset(&parm, 0, sizeof(parm));
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (DoIoctl(fd, VIDIOC_G_PARM, &parm) != 0) return;
if ((parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) return;
if (DoIoctl(fd, VIDIOC_G_PARM, &parm) != 0) {
return;
}
if ((parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) == 0) {
return;
}
std::memset(&parm, 0, sizeof(parm));
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
parm.parm.capture.timeperframe = FPSToFract(m_mode.fps);
if (DoIoctl(fd, VIDIOC_S_PARM, &parm) != 0)
if (DoIoctl(fd, VIDIOC_S_PARM, &parm) != 0) {
SWARNING("could not set FPS to " << m_mode.fps);
else
} else {
SINFO("set FPS to " << m_mode.fps);
}
}
void UsbCameraImpl::DeviceCacheMode() {
int fd = m_fd.load();
if (fd < 0) return;
if (fd < 0) {
return;
}
// Get format
struct v4l2_format vfmt;
@@ -911,8 +1018,9 @@ void UsbCameraImpl::DeviceCacheMode() {
std::memset(&parm, 0, sizeof(parm));
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (TryIoctl(fd, VIDIOC_G_PARM, &parm) == 0) {
if (parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)
if (parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
fps = FractToFPS(parm.parm.capture.timeperframe);
}
}
// Update format with user changes.
@@ -943,7 +1051,9 @@ void UsbCameraImpl::DeviceCacheMode() {
// Default to lowest known resolution (based on number of total pixels)
int numPixels = width * height;
for (const auto& mode : m_videoModes) {
if (mode.pixelFormat != pixelFormat) continue;
if (mode.pixelFormat != pixelFormat) {
continue;
}
int numPixelsHere = mode.width * mode.height;
if (numPixelsHere < numPixels) {
formatChanged = true;
@@ -970,8 +1080,12 @@ void UsbCameraImpl::DeviceCacheMode() {
m_mode.fps = fps;
}
if (formatChanged) DeviceSetMode();
if (fpsChanged) DeviceSetFPS();
if (formatChanged) {
DeviceSetMode();
}
if (fpsChanged) {
DeviceSetFPS();
}
m_notifier.NotifySourceVideoMode(*this, m_mode);
}
@@ -1024,8 +1138,9 @@ void UsbCameraImpl::DeviceCacheProperty(
rawProp->valueStr = perProp->valueStr; // copy
} else {
// Read current raw value and set percentage from it
if (!rawProp->DeviceGet(lock, m_fd))
if (!rawProp->DeviceGet(lock, m_fd)) {
SWARNING("failed to get property " << rawProp->name);
}
if (perProp) {
perProp->SetValue(RawToPercentage(*rawProp, rawProp->value));
@@ -1035,8 +1150,9 @@ void UsbCameraImpl::DeviceCacheProperty(
// Set value on device if user-configured
if (rawProp->valueSet) {
if (!rawProp->DeviceSet(lock, m_fd))
if (!rawProp->DeviceSet(lock, m_fd)) {
SWARNING("failed to set property " << rawProp->name);
}
}
// Update pointers since we released the lock
@@ -1076,12 +1192,16 @@ void UsbCameraImpl::DeviceCacheProperty(
}
NotifyPropertyCreated(*rawIndex, *rawPropPtr);
if (perPropPtr) NotifyPropertyCreated(*perIndex, *perPropPtr);
if (perPropPtr) {
NotifyPropertyCreated(*perIndex, *perPropPtr);
}
}
void UsbCameraImpl::DeviceCacheProperties() {
int fd = m_fd.load();
if (fd < 0) return;
if (fd < 0) {
return;
}
#ifdef V4L2_CTRL_FLAG_NEXT_COMPOUND
constexpr __u32 nextFlags =
@@ -1099,20 +1219,24 @@ void UsbCameraImpl::DeviceCacheProperties() {
if (id == nextFlags) {
// try just enumerating standard...
for (id = V4L2_CID_BASE; id < V4L2_CID_LASTP1; ++id) {
if (auto prop = UsbCameraProperty::DeviceQuery(fd, &id))
if (auto prop = UsbCameraProperty::DeviceQuery(fd, &id)) {
DeviceCacheProperty(std::move(prop));
}
}
// ... and custom controls
std::unique_ptr<UsbCameraProperty> prop;
for (id = V4L2_CID_PRIVATE_BASE;
(prop = UsbCameraProperty::DeviceQuery(fd, &id)); ++id)
(prop = UsbCameraProperty::DeviceQuery(fd, &id)); ++id) {
DeviceCacheProperty(std::move(prop));
}
}
}
void UsbCameraImpl::DeviceCacheVideoModes() {
int fd = m_fd.load();
if (fd < 0) return;
if (fd < 0) {
return;
}
std::vector<VideoMode> modes;
@@ -1122,7 +1246,9 @@ void UsbCameraImpl::DeviceCacheVideoModes() {
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
for (fmt.index = 0; TryIoctl(fd, VIDIOC_ENUM_FMT, &fmt) >= 0; ++fmt.index) {
VideoMode::PixelFormat pixelFormat = ToPixelFormat(fmt.pixelformat);
if (pixelFormat == VideoMode::kUnknown) continue;
if (pixelFormat == VideoMode::kUnknown) {
continue;
}
// Frame sizes
struct v4l2_frmsizeenum frmsize;
@@ -1130,7 +1256,9 @@ void UsbCameraImpl::DeviceCacheVideoModes() {
frmsize.pixel_format = fmt.pixelformat;
for (frmsize.index = 0; TryIoctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0;
++frmsize.index) {
if (frmsize.type != V4L2_FRMSIZE_TYPE_DISCRETE) continue;
if (frmsize.type != V4L2_FRMSIZE_TYPE_DISCRETE) {
continue;
}
// Frame intervals
struct v4l2_frmivalenum frmival;
@@ -1141,7 +1269,9 @@ void UsbCameraImpl::DeviceCacheVideoModes() {
for (frmival.index = 0;
TryIoctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival) >= 0;
++frmival.index) {
if (frmival.type != V4L2_FRMIVAL_TYPE_DISCRETE) continue;
if (frmival.type != V4L2_FRMIVAL_TYPE_DISCRETE) {
continue;
}
modes.emplace_back(pixelFormat,
static_cast<int>(frmsize.discrete.width),
@@ -1180,7 +1310,9 @@ void UsbCameraImpl::DeviceCacheVideoModes() {
CS_StatusValue UsbCameraImpl::SendAndWait(Message&& msg) const {
int fd = m_command_fd.load();
// exit early if not possible to signal
if (fd < 0) return CS_SOURCE_IS_DISCONNECTED;
if (fd < 0) {
return CS_SOURCE_IS_DISCONNECTED;
}
auto from = msg.from;
@@ -1191,7 +1323,9 @@ CS_StatusValue UsbCameraImpl::SendAndWait(Message&& msg) const {
}
// Signal the camera thread
if (eventfd_write(fd, 1) < 0) return CS_SOURCE_IS_DISCONNECTED;
if (eventfd_write(fd, 1) < 0) {
return CS_SOURCE_IS_DISCONNECTED;
}
std::unique_lock lock(m_mutex);
while (m_active) {
@@ -1217,7 +1351,9 @@ CS_StatusValue UsbCameraImpl::SendAndWait(Message&& msg) const {
void UsbCameraImpl::Send(Message&& msg) const {
int fd = m_command_fd.load();
// exit early if not possible to signal
if (fd < 0) return;
if (fd < 0) {
return;
}
// Add the message to the command queue
{
@@ -1237,7 +1373,9 @@ std::unique_ptr<PropertyImpl> UsbCameraImpl::CreateEmptyProperty(
bool UsbCameraImpl::CacheProperties(CS_Status* status) const {
// Wake up camera thread; this will try to reconnect
*status = SendAndWait(Message{Message::kNone});
if (*status != CS_OK) return false;
if (*status != CS_OK) {
return false;
}
if (!m_properties_cached) {
*status = CS_SOURCE_IS_DISCONNECTED;
return false;
@@ -1473,7 +1611,9 @@ UsbCameraInfo GetUsbCameraInfo(CS_Source source, CS_Status* status) {
path += ep->d_name;
char* target = ::realpath(path.c_str(), nullptr);
if (target) {
if (keypath == target) info.otherPaths.emplace_back(path.str());
if (keypath == target) {
info.otherPaths.emplace_back(path.str());
}
std::free(target);
}
}
@@ -1496,10 +1636,14 @@ 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")) continue;
if (!fname.startswith("video")) {
continue;
}
unsigned int dev = 0;
if (fname.substr(5).getAsInteger(10, dev)) continue;
if (fname.substr(5).getAsInteger(10, dev)) {
continue;
}
UsbCameraInfo info;
info.dev = dev;
@@ -1508,14 +1652,20 @@ std::vector<UsbCameraInfo> EnumerateUsbCameras(CS_Status* status) {
path += fname;
info.path = path.str();
if (!IsVideoCaptureDevice(path.c_str())) continue;
if (!IsVideoCaptureDevice(path.c_str())) {
continue;
}
info.name = GetDescriptionImpl(path.c_str());
if (info.name.empty()) continue;
if (info.name.empty()) {
continue;
}
GetVendorProduct(dev, &info.vendorId, &info.productId);
if (dev >= retval.size()) retval.resize(info.dev + 1);
if (dev >= retval.size()) {
retval.resize(info.dev + 1);
}
retval[info.dev] = std::move(info);
}
::closedir(dp);

View File

@@ -26,7 +26,9 @@ static int GetIntCtrlIoctl(int fd, unsigned id, int type, int64_t* value) {
ctrls.count = 1;
ctrls.controls = &ctrl;
int rc = DoIoctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls);
if (rc < 0) return rc;
if (rc < 0) {
return rc;
}
*value = ctrl.value;
} else {
// Use normal control
@@ -34,7 +36,9 @@ static int GetIntCtrlIoctl(int fd, unsigned id, int type, int64_t* value) {
std::memset(&ctrl, 0, sizeof(ctrl));
ctrl.id = id;
int rc = DoIoctl(fd, VIDIOC_G_CTRL, &ctrl);
if (rc < 0) return rc;
if (rc < 0) {
return rc;
}
*value = ctrl.value;
}
return 0;
@@ -51,10 +55,11 @@ static int SetIntCtrlIoctl(int fd, unsigned id, int type, int64_t value) {
std::memset(&ctrl, 0, sizeof(ctrl));
std::memset(&ctrls, 0, sizeof(ctrls));
ctrl.id = id;
if (type == V4L2_CTRL_TYPE_INTEGER64)
if (type == V4L2_CTRL_TYPE_INTEGER64) {
ctrl.value64 = value;
else
} else {
ctrl.value = static_cast<__s32>(value);
}
ctrls.ctrl_class = ctrl_class;
ctrls.count = 1;
ctrls.controls = &ctrl;
@@ -117,7 +122,9 @@ static wpi::StringRef NormalizeName(wpi::StringRef name,
bool newWord = false;
for (auto ch : name) {
if (std::isalnum(ch)) {
if (newWord) buf.push_back('_');
if (newWord) {
buf.push_back('_');
}
newWord = false;
buf.push_back(std::tolower(ch));
} else if (!buf.empty()) {
@@ -163,7 +170,9 @@ UsbCameraProperty::UsbCameraProperty(const struct v4l2_query_ext_ctrl& ctrl)
// name
size_t len = 0;
while (len < sizeof(ctrl.name) && ctrl.name[len] != '\0') ++len;
while (len < sizeof(ctrl.name) && ctrl.name[len] != '\0') {
++len;
}
wpi::SmallString<64> name_buf;
name = NormalizeName(wpi::StringRef(ctrl.name, len), name_buf);
}
@@ -201,7 +210,9 @@ UsbCameraProperty::UsbCameraProperty(const struct v4l2_queryctrl& ctrl)
// name
size_t len = 0;
while (len < sizeof(ctrl.name) && ctrl.name[len] != '\0') ++len;
while (len < sizeof(ctrl.name) && ctrl.name[len] != '\0') {
++len;
}
wpi::SmallString<64> name_buf;
name = NormalizeName(
wpi::StringRef(reinterpret_cast<const char*>(ctrl.name), len), name_buf);
@@ -219,7 +230,9 @@ std::unique_ptr<UsbCameraProperty> UsbCameraProperty::DeviceQuery(int fd,
if (rc == 0) {
*id = qc_ext.id; // copy back
// We don't support array types
if (qc_ext.elems > 1 || qc_ext.nr_of_dims > 0) return nullptr;
if (qc_ext.elems > 1 || qc_ext.nr_of_dims > 0) {
return nullptr;
}
prop = std::make_unique<UsbCameraProperty>(qc_ext);
}
#endif
@@ -230,7 +243,9 @@ std::unique_ptr<UsbCameraProperty> UsbCameraProperty::DeviceQuery(int fd,
qc.id = *id;
rc = TryIoctl(fd, VIDIOC_QUERYCTRL, &qc);
*id = qc.id; // copy back
if (rc != 0) return nullptr;
if (rc != 0) {
return nullptr;
}
prop = std::make_unique<UsbCameraProperty>(qc);
}
@@ -242,7 +257,9 @@ std::unique_ptr<UsbCameraProperty> UsbCameraProperty::DeviceQuery(int fd,
qmenu.id = *id;
for (int i = prop->minimum; i <= prop->maximum; ++i) {
qmenu.index = static_cast<__u32>(i);
if (TryIoctl(fd, VIDIOC_QUERYMENU, &qmenu) != 0) continue;
if (TryIoctl(fd, VIDIOC_QUERYMENU, &qmenu) != 0) {
continue;
}
if (prop->intMenu) {
wpi::raw_string_ostream os(prop->enumChoices[i]);
os << qmenu.value;
@@ -256,7 +273,9 @@ std::unique_ptr<UsbCameraProperty> UsbCameraProperty::DeviceQuery(int fd,
}
bool UsbCameraProperty::DeviceGet(std::unique_lock<wpi::mutex>& lock, int fd) {
if (fd < 0) return true;
if (fd < 0) {
return true;
}
unsigned idCopy = id;
int rv = 0;
@@ -269,7 +288,9 @@ bool UsbCameraProperty::DeviceGet(std::unique_lock<wpi::mutex>& lock, int fd) {
lock.unlock();
rv = GetIntCtrlIoctl(fd, idCopy, typeCopy, &newValue);
lock.lock();
if (rv >= 0) value = newValue;
if (rv >= 0) {
value = newValue;
}
break;
}
case CS_PROP_STRING: {
@@ -278,7 +299,9 @@ bool UsbCameraProperty::DeviceGet(std::unique_lock<wpi::mutex>& lock, int fd) {
lock.unlock();
rv = GetStringCtrlIoctl(fd, idCopy, maximumCopy, &newValueStr);
lock.lock();
if (rv >= 0) valueStr = std::move(newValueStr);
if (rv >= 0) {
valueStr = std::move(newValueStr);
}
break;
}
default:
@@ -298,7 +321,9 @@ bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock, int fd,
int newValue,
const wpi::Twine& newValueStr) const {
if (!device || fd < 0) return true;
if (!device || fd < 0) {
return true;
}
unsigned idCopy = id;
int rv = 0;

View File

@@ -21,7 +21,9 @@ namespace cs {
static wpi::StringRef GetUsbNameFromFile(int vendor, int product,
wpi::SmallVectorImpl<char>& buf) {
int fd = open("/var/lib/usbutils/usb.ids", O_RDONLY);
if (fd < 0) return wpi::StringRef{};
if (fd < 0) {
return {};
}
wpi::raw_svector_ostream os{buf};
wpi::raw_fd_istream is{fd, true};
@@ -37,9 +39,13 @@ static wpi::StringRef GetUsbNameFromFile(int vendor, int product,
bool foundVendor = false;
for (;;) {
auto line = is.getline(lineBuf, 4096);
if (is.has_error()) break;
if (is.has_error()) {
break;
}
if (line.empty()) continue;
if (line.empty()) {
continue;
}
// look for vendor at start of line
if (line.startswith(vendorStr)) {
@@ -63,14 +69,16 @@ static wpi::StringRef GetUsbNameFromFile(int vendor, int product,
}
}
return wpi::StringRef{};
return {};
}
wpi::StringRef GetUsbNameFromId(int vendor, int product,
wpi::SmallVectorImpl<char>& buf) {
// try reading usb.ids
wpi::StringRef rv = GetUsbNameFromFile(vendor, product, buf);
if (!rv.empty()) return rv;
if (!rv.empty()) {
return rv;
}
// Fall back to internal database
wpi::raw_svector_ostream os{buf};

View File

@@ -56,9 +56,13 @@ STDMETHODIMP_(ULONG) SourceReaderCB::Release() {
return uCount;
}
STDMETHODIMP SourceReaderCB::OnEvent(DWORD, IMFMediaEvent*) { return S_OK; }
STDMETHODIMP SourceReaderCB::OnEvent(DWORD, IMFMediaEvent*) {
return S_OK;
}
STDMETHODIMP SourceReaderCB::OnFlush(DWORD) { return S_OK; }
STDMETHODIMP SourceReaderCB::OnFlush(DWORD) {
return S_OK;
}
void SourceReaderCB::NotifyError(HRESULT hr) {
wprintf(L"Source Reader error: 0x%X\n", hr);
@@ -70,7 +74,8 @@ STDMETHODIMP SourceReaderCB::OnReadSample(HRESULT hrStatus, DWORD dwStreamIndex,
IMFSample* pSample // Can be NULL
) {
auto source = m_source.lock();
if (!source) return S_OK;
if (!source)
return S_OK;
if (SUCCEEDED(hrStatus)) {
if (pSample) {
// Prcoess sample

View File

@@ -44,7 +44,9 @@ static void WINAPI OnInterfaceChange(PVOID callerContext,
NetworkListener::NetworkListener(wpi::Logger& logger, Notifier& notifier)
: m_impl(std::make_unique<Impl>(logger, notifier)) {}
NetworkListener::~NetworkListener() { Stop(); }
NetworkListener::~NetworkListener() {
Stop();
}
void NetworkListener::Start() {
NotifyIpInterfaceChange(AF_INET, OnInterfaceChange, &m_impl->m_notifier, true,

View File

@@ -21,7 +21,9 @@ std::vector<std::string> GetNetworkInterfaces() {
char ip[50];
for (int i = 0; i < counts; i++) {
if (adrs[i].is_internal) continue;
if (adrs[i].is_internal) {
continue;
}
InetNtop(PF_INET, &(adrs[i].netmask.netmask4.sin_addr.s_addr), ip,
sizeof(ip) - 1);
ip[49] = '\0';

View File

@@ -86,7 +86,9 @@ UsbCameraImpl::UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger,
StartMessagePump();
}
UsbCameraImpl::~UsbCameraImpl() { m_messagePump = nullptr; }
UsbCameraImpl::~UsbCameraImpl() {
m_messagePump = nullptr;
}
void UsbCameraImpl::SetProperty(int property, int value, CS_Status* status) {
Message msg{Message::kCmdSetProperty};
@@ -254,7 +256,8 @@ bool UsbCameraImpl::CheckDeviceChange(WPARAM wParam, DEV_BROADCAST_HDR* pHdr,
}
void UsbCameraImpl::DeviceDisconnect() {
if (m_connectVerbose) SINFO("Disconnected from " << m_path);
if (m_connectVerbose)
SINFO("Disconnected from " << m_path);
m_sourceReader.Reset();
m_mediaSource.Reset();
if (m_imageCallback) {
@@ -266,7 +269,8 @@ void UsbCameraImpl::DeviceDisconnect() {
}
static bool IsPercentageProperty(wpi::StringRef name) {
if (name.startswith("raw_")) name = name.substr(4);
if (name.startswith("raw_"))
name = name.substr(4);
return name == "Brightness" || name == "Contrast" || name == "Saturation" ||
name == "Hue" || name == "Sharpness" || name == "Gain" ||
name == "Exposure";
@@ -274,14 +278,17 @@ static bool IsPercentageProperty(wpi::StringRef name) {
void UsbCameraImpl::ProcessFrame(IMFSample* videoSample,
const VideoMode& mode) {
if (!videoSample) return;
if (!videoSample)
return;
ComPtr<IMFMediaBuffer> buf;
if (!SUCCEEDED(videoSample->ConvertToContiguousBuffer(buf.GetAddressOf()))) {
DWORD bcnt = 0;
if (!SUCCEEDED(videoSample->GetBufferCount(&bcnt))) return;
if (bcnt == 0) return;
if (!SUCCEEDED(videoSample->GetBufferCount(&bcnt)))
return;
if (bcnt == 0)
return;
if (!SUCCEEDED(videoSample->GetBufferByIndex(0, buf.GetAddressOf())))
return;
}
@@ -310,7 +317,8 @@ void UsbCameraImpl::ProcessFrame(IMFSample* videoSample,
return;
}
}
if (!ptr) return;
if (!ptr)
return;
cv::Mat tmpMat;
std::unique_ptr<Image> dest;
@@ -451,16 +459,19 @@ static cs::VideoMode::PixelFormat GetFromGUID(const GUID& guid) {
}
bool UsbCameraImpl::DeviceConnect() {
if (m_mediaSource && m_sourceReader) return true;
if (m_mediaSource && m_sourceReader)
return true;
if (m_connectVerbose) SINFO("Connecting to USB camera on " << m_path);
if (m_connectVerbose)
SINFO("Connecting to USB camera on " << m_path);
SDEBUG3("opening device");
const wchar_t* path = m_widePath.c_str();
m_mediaSource = CreateVideoCaptureDevice(path);
if (!m_mediaSource) return false;
if (!m_mediaSource)
return false;
m_imageCallback = CreateSourceReaderCB(shared_from_this(), m_mode);
m_sourceReader =
@@ -510,7 +521,8 @@ bool UsbCameraImpl::CacheProperties(CS_Status* status) const {
auto result = m_messagePump->SendWindowMessage<CS_Status>(
WaitForStartupMessage, nullptr, nullptr);
*status = result;
if (*status != CS_OK) return false;
if (*status != CS_OK)
return false;
if (!m_properties_cached) {
*status = CS_SOURCE_IS_DISCONNECTED;
return false;
@@ -545,7 +557,8 @@ template void UsbCameraImpl::DeviceAddProperty(const wpi::Twine& name_,
DeviceAddProperty(#val, CameraControl_##val, pCamControl);
void UsbCameraImpl::DeviceCacheProperties() {
if (!m_sourceReader) return;
if (!m_sourceReader)
return;
IAMVideoProcAmp* pProcAmp = NULL;
@@ -693,7 +706,8 @@ void UsbCameraImpl::DeviceCacheProperty(
}
NotifyPropertyCreated(*rawIndex, *rawPropPtr);
if (perPropPtr && perIndex) NotifyPropertyCreated(*perIndex, *perPropPtr);
if (perPropPtr && perIndex)
NotifyPropertyCreated(*perIndex, *perPropPtr);
}
CS_StatusValue UsbCameraImpl::DeviceProcessCommand(
@@ -740,7 +754,8 @@ CS_StatusValue UsbCameraImpl::DeviceCmdSetProperty(
// Look up
auto prop = static_cast<UsbCameraProperty*>(GetProperty(property));
if (!prop) return CS_INVALID_PROPERTY;
if (!prop)
return CS_INVALID_PROPERTY;
// If setting before we get, guess initial type based on set
if (prop->propKind == CS_PROP_NONE) {
@@ -771,7 +786,8 @@ CS_StatusValue UsbCameraImpl::DeviceCmdSetProperty(
// Actually set the new value on the device (if possible)
if (!prop->device) {
if (prop->id == kPropConnectVerboseId) m_connectVerbose = value;
if (prop->id == kPropConnectVerboseId)
m_connectVerbose = value;
} else {
if (!prop->DeviceSet(lock, m_sourceReader.Get())) {
return CS_PROPERTY_WRITE_FAILED;
@@ -855,8 +871,10 @@ CS_StatusValue UsbCameraImpl::DeviceCmdSetMode(
}
bool UsbCameraImpl::DeviceStreamOn() {
if (m_streaming) return false;
if (!m_deviceValid) return false;
if (m_streaming)
return false;
if (!m_deviceValid)
return false;
m_streaming = true;
m_sourceReader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, NULL,
NULL, NULL);
@@ -869,9 +887,11 @@ bool UsbCameraImpl::DeviceStreamOff() {
}
void UsbCameraImpl::DeviceCacheMode() {
if (!m_sourceReader) return;
if (!m_sourceReader)
return;
if (m_windowsVideoModes.size() == 0) return;
if (m_windowsVideoModes.size() == 0)
return;
if (!m_currentMode) {
// First, see if our set mode is valid
@@ -936,7 +956,8 @@ CS_StatusValue UsbCameraImpl::DeviceSetMode() {
}
void UsbCameraImpl::DeviceCacheVideoModes() {
if (!m_sourceReader) return;
if (!m_sourceReader)
return;
std::vector<VideoMode> modes;
m_windowsVideoModes.clear();

View File

@@ -38,7 +38,8 @@ UsbCameraProperty::UsbCameraProperty(const wpi::Twine& name_,
bool UsbCameraProperty::DeviceGet(std::unique_lock<wpi::mutex>& lock,
IAMVideoProcAmp* pProcAmp) {
if (!pProcAmp) return true;
if (!pProcAmp)
return true;
lock.unlock();
long newValue = 0, paramFlag = 0; // NOLINT(runtime/int)
@@ -57,7 +58,8 @@ bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
IAMVideoProcAmp* pProcAmp,
int newValue) const {
if (!pProcAmp) return true;
if (!pProcAmp)
return true;
lock.unlock();
if (SUCCEEDED(
@@ -100,7 +102,8 @@ UsbCameraProperty::UsbCameraProperty(const wpi::Twine& name_,
bool UsbCameraProperty::DeviceGet(std::unique_lock<wpi::mutex>& lock,
IAMCameraControl* pProcAmp) {
if (!pProcAmp) return true;
if (!pProcAmp)
return true;
lock.unlock();
long newValue = 0, paramFlag = 0; // NOLINT(runtime/int)
@@ -119,7 +122,8 @@ bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
IAMCameraControl* pProcAmp,
int newValue) const {
if (!pProcAmp) return true;
if (!pProcAmp)
return true;
lock.unlock();
if (SUCCEEDED(pProcAmp->Set(tagCameraControl, newValue,
@@ -133,7 +137,8 @@ bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
bool UsbCameraProperty::DeviceGet(std::unique_lock<wpi::mutex>& lock,
IMFSourceReader* sourceReader) {
if (!sourceReader) return true;
if (!sourceReader)
return true;
if (isControlProperty) {
ComPtr<IAMCameraControl> pProcAmp;
@@ -162,7 +167,8 @@ bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
IMFSourceReader* sourceReader,
int newValue) const {
if (!sourceReader) return true;
if (!sourceReader)
return true;
if (isControlProperty) {
ComPtr<IAMCameraControl> pProcAmp;

View File

@@ -99,7 +99,8 @@ WindowsMessagePump::WindowsMessagePump(
WindowsMessagePump::~WindowsMessagePump() {
auto res = SendMessage(hwnd, WM_CLOSE, NULL, NULL);
if (m_mainThread.joinable()) m_mainThread.join();
if (m_mainThread.joinable())
m_mainThread.join();
}
void WindowsMessagePump::ThreadMain(HANDLE eventHandle) {

View File

@@ -26,7 +26,9 @@ NetworkTablesSettings::NetworkTablesSettings(NT_Inst inst,
}
void NetworkTablesSettings::Update() {
if (!m_restart) return;
if (!m_restart) {
return;
}
m_restart = false;
nt::StopClient(m_inst);
nt::StopServer(m_inst);
@@ -40,8 +42,9 @@ void NetworkTablesSettings::Update() {
wpi::SmallVector<wpi::StringRef, 4> serverNames;
wpi::SmallVector<std::pair<wpi::StringRef, unsigned int>, 4> servers;
serverTeam.split(serverNames, ',', -1, false);
for (auto&& serverName : serverNames)
for (auto&& serverName : serverNames) {
servers.emplace_back(serverName, NT_DEFAULT_PORT);
}
nt::StartClient(m_inst, servers);
}
} else if (*m_pMode == 2) {
@@ -64,5 +67,7 @@ void NetworkTablesSettings::Display() {
default:
break;
}
if (ImGui::Button("Apply")) m_restart = true;
if (ImGui::Button("Apply")) {
m_restart = true;
}
}

View File

@@ -45,7 +45,9 @@ static void NtInitialize() {
nt::AddPolledConnectionListener(poller, true);
gui::AddEarlyExecute([poller] {
auto win = gui::GetSystemWindow();
if (!win) return;
if (!win) {
return;
}
bool timedOut;
for (auto&& event : nt::PollConnectionListener(poller, 0, &timedOut)) {
if (event.connected) {
@@ -118,14 +120,18 @@ int main() {
ImGui::BeginMainMenuBar();
gui::EmitViewMenu();
if (ImGui::BeginMenu("View")) {
if (ImGui::MenuItem("Reset Time")) glass::ResetTime();
if (ImGui::MenuItem("Reset Time")) {
glass::ResetTime();
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("NetworkTables")) {
if (gNetworkTablesSettingsWindow)
if (gNetworkTablesSettingsWindow) {
gNetworkTablesSettingsWindow->DisplayMenuItem("NetworkTables Settings");
if (gNetworkTablesWindow)
}
if (gNetworkTablesWindow) {
gNetworkTablesWindow->DisplayMenuItem("NetworkTables View");
}
ImGui::Separator();
gNtProvider->DisplayMenu();
ImGui::EndMenu();

View File

@@ -26,8 +26,9 @@ static bool ConvertInt(Storage::Value* value) {
if (value->stringVal.empty()) {
return false;
} else {
if (wpi::StringRef{value->stringVal}.getAsInteger(10, value->intVal))
if (wpi::StringRef{value->stringVal}.getAsInteger(10, value->intVal)) {
return false;
}
}
return true;
}
@@ -37,8 +38,9 @@ static bool ConvertInt64(Storage::Value* value) {
if (value->stringVal.empty()) {
return false;
} else {
if (wpi::StringRef{value->stringVal}.getAsInteger(10, value->int64Val))
if (wpi::StringRef{value->stringVal}.getAsInteger(10, value->int64Val)) {
return false;
}
}
return true;
}
@@ -62,8 +64,9 @@ static bool ConvertFloat(Storage::Value* value) {
if (value->stringVal.empty()) {
return false;
} else {
if (std::sscanf(value->stringVal.c_str(), "%f", &value->floatVal) != 1)
if (std::sscanf(value->stringVal.c_str(), "%f", &value->floatVal) != 1) {
return false;
}
}
return true;
}
@@ -73,8 +76,9 @@ static bool ConvertDouble(Storage::Value* value) {
if (value->stringVal.empty()) {
return false;
} else {
if (std::sscanf(value->stringVal.c_str(), "%lf", &value->doubleVal) != 1)
if (std::sscanf(value->stringVal.c_str(), "%lf", &value->doubleVal) != 1) {
return false;
}
}
return true;
}
@@ -83,7 +87,9 @@ static void* GlassStorageReadOpen(ImGuiContext*, ImGuiSettingsHandler* handler,
const char* name) {
auto ctx = static_cast<Context*>(handler->UserData);
auto& storage = ctx->storage[name];
if (!storage) storage = std::make_unique<Storage>();
if (!storage) {
storage = std::make_unique<Storage>();
}
return storage.get();
}
@@ -193,25 +199,39 @@ static void Shutdown(Context* ctx) {}
Context* glass::CreateContext() {
Context* ctx = new Context;
if (!gContext) SetCurrentContext(ctx);
if (!gContext) {
SetCurrentContext(ctx);
}
Initialize(ctx);
return ctx;
}
void glass::DestroyContext(Context* ctx) {
if (!ctx) ctx = gContext;
if (!ctx) {
ctx = gContext;
}
Shutdown(ctx);
if (gContext == ctx) SetCurrentContext(nullptr);
if (gContext == ctx) {
SetCurrentContext(nullptr);
}
delete ctx;
}
Context* glass::GetCurrentContext() { return gContext; }
Context* glass::GetCurrentContext() {
return gContext;
}
void glass::SetCurrentContext(Context* ctx) { gContext = ctx; }
void glass::SetCurrentContext(Context* ctx) {
gContext = ctx;
}
void glass::ResetTime() { gContext->zeroTime = wpi::Now(); }
void glass::ResetTime() {
gContext->zeroTime = wpi::Now();
}
uint64_t glass::GetZeroTime() { return gContext->zeroTime; }
uint64_t glass::GetZeroTime() {
return gContext->zeroTime;
}
Storage::Value& Storage::GetValue(wpi::StringRef key) {
auto it = std::find(m_keys.begin(), m_keys.end(), key);
@@ -227,10 +247,12 @@ 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; \
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; \
if (!Convert##CapsName(&value)) \
value.LowerName##Val = defaultVal; \
} \
return value.LowerName##Val; \
} \
@@ -260,7 +282,8 @@ Storage::Value& Storage::GetValue(wpi::StringRef key) {
} else { \
Value& value = *m_values[it - m_keys.begin()]; \
if (value.type != Value::k##CapsName) { \
if (!Convert##CapsName(&value)) value.LowerName##Val = defaultVal; \
if (!Convert##CapsName(&value)) \
value.LowerName##Val = defaultVal; \
} \
return &value.LowerName##Val; \
} \
@@ -275,7 +298,9 @@ DEFUN(Double, double, double)
std::string Storage::GetString(wpi::StringRef key,
const std::string& defaultVal) const {
auto it = std::find(m_keys.begin(), m_keys.end(), key);
if (it == m_keys.end()) return defaultVal;
if (it == m_keys.end()) {
return defaultVal;
}
Value& value = *m_values[it - m_keys.begin()];
value.type = Value::kString;
return value.stringVal;
@@ -311,13 +336,17 @@ std::string* Storage::GetStringRef(wpi::StringRef key,
Storage& glass::GetStorage() {
auto& storage = gContext->storage[gContext->curId];
if (!storage) storage = std::make_unique<Storage>();
if (!storage) {
storage = std::make_unique<Storage>();
}
return *storage;
}
Storage& glass::GetStorage(wpi::StringRef id) {
auto& storage = gContext->storage[id];
if (!storage) storage = std::make_unique<Storage>();
if (!storage) {
storage = std::make_unique<Storage>();
}
return *storage;
}
@@ -326,8 +355,12 @@ static void PushIDStack(wpi::StringRef label_id) {
auto [label, id] = wpi::StringRef{label_id}.split("###");
// if no ###id, use label as id
if (id.empty()) id = label;
if (!gContext->curId.empty()) gContext->curId += "###";
if (id.empty()) {
id = label;
}
if (!gContext->curId.empty()) {
gContext->curId += "###";
}
gContext->curId += id;
}
@@ -361,7 +394,9 @@ bool glass::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) {
wpi::SmallString<64> openKey;
auto [name, id] = wpi::StringRef{label}.split("###");
// if no ###id, use name as id
if (id.empty()) id = name;
if (id.empty()) {
id = name;
}
openKey = id;
openKey += "###open";
@@ -376,7 +411,9 @@ bool glass::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags) {
bool* open = GetStorage().GetBoolRef("open");
*open = ImGui::TreeNodeEx(
label, flags | (*open ? ImGuiTreeNodeFlags_DefaultOpen : 0));
if (!*open) PopIDStack();
if (!*open) {
PopIDStack();
}
return *open;
}

View File

@@ -14,7 +14,9 @@ DataSource::DataSource(const wpi::Twine& id) : m_id{id.str()} {
auto it = gContext->sources.try_emplace(m_id, this);
auto& srcName = it.first->getValue();
m_name = srcName.name.get();
if (!srcName.source) srcName.source = this;
if (!srcName.source) {
srcName.source = this;
}
sourceCreated(m_id.c_str(), this);
}
@@ -26,18 +28,30 @@ DataSource::DataSource(const wpi::Twine& id, int index, int index2)
wpi::Twine(index2) + wpi::Twine(']')} {}
DataSource::~DataSource() {
if (!gContext) return;
if (!gContext) {
return;
}
auto it = gContext->sources.find(m_id);
if (it == gContext->sources.end()) return;
if (it == gContext->sources.end()) {
return;
}
auto& srcName = it->getValue();
if (srcName.source == this) srcName.source = nullptr;
if (srcName.source == this) {
srcName.source = nullptr;
}
}
void DataSource::SetName(const wpi::Twine& name) { m_name->SetName(name); }
void DataSource::SetName(const wpi::Twine& name) {
m_name->SetName(name);
}
const char* DataSource::GetName() const { return m_name->GetName(); }
const char* DataSource::GetName() const {
return m_name->GetName();
}
void DataSource::PushEditNameId(int index) { m_name->PushEditNameId(index); }
void DataSource::PushEditNameId(int index) {
m_name->PushEditNameId(index);
}
void DataSource::PushEditNameId(const char* name) {
m_name->PushEditNameId(name);
@@ -134,6 +148,8 @@ void DataSource::EmitDrag(ImGuiDragDropFlags flags) const {
DataSource* DataSource::Find(wpi::StringRef id) {
auto it = gContext->sources.find(id);
if (it == gContext->sources.end()) return nullptr;
if (it == gContext->sources.end()) {
return nullptr;
}
return it->getValue().source;
}

View File

@@ -11,11 +11,15 @@
using namespace glass;
void MainMenuBar::AddMainMenu(std::function<void()> menu) {
if (menu) m_menus.emplace_back(std::move(menu));
if (menu) {
m_menus.emplace_back(std::move(menu));
}
}
void MainMenuBar::AddOptionMenu(std::function<void()> menu) {
if (menu) m_optionMenus.emplace_back(std::move(menu));
if (menu) {
m_optionMenus.emplace_back(std::move(menu));
}
}
void MainMenuBar::Display() {
@@ -24,7 +28,9 @@ void MainMenuBar::Display() {
if (!m_optionMenus.empty()) {
if (ImGui::BeginMenu("Options")) {
for (auto&& menu : m_optionMenus) {
if (menu) menu();
if (menu) {
menu();
}
}
ImGui::EndMenu();
}
@@ -33,7 +39,9 @@ void MainMenuBar::Display() {
wpi::gui::EmitViewMenu();
for (auto&& menu : m_menus) {
if (menu) menu();
if (menu) {
menu();
}
}
#if 0

View File

@@ -6,4 +6,6 @@
using namespace glass;
bool Model::IsReadOnly() { return false; }
bool Model::IsReadOnly() {
return false;
}

View File

@@ -28,7 +28,9 @@ void Window::SetVisibility(Visibility visibility) {
}
void Window::Display() {
if (!m_view) return;
if (!m_view) {
return;
}
if (!m_visible || !m_enabled) {
PushID(m_id);
m_view->Hidden();
@@ -36,22 +38,32 @@ void Window::Display() {
return;
}
if (m_posCond != 0) ImGui::SetNextWindowPos(m_pos, m_posCond);
if (m_sizeCond != 0) ImGui::SetNextWindowSize(m_size, m_sizeCond);
if (m_setPadding) ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, m_padding);
if (m_posCond != 0) {
ImGui::SetNextWindowPos(m_pos, m_posCond);
}
if (m_sizeCond != 0) {
ImGui::SetNextWindowSize(m_size, m_sizeCond);
}
if (m_setPadding) {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, m_padding);
}
char label[128];
std::snprintf(label, sizeof(label), "%s###%s",
m_name.empty() ? m_id.c_str() : m_name.c_str(), m_id.c_str());
if (Begin(label, &m_visible, m_flags)) {
if (m_renamePopupEnabled) PopupEditName(nullptr, &m_name);
if (m_renamePopupEnabled) {
PopupEditName(nullptr, &m_name);
}
m_view->Display();
} else {
m_view->Hidden();
}
End();
if (m_setPadding) ImGui::PopStyleVar();
if (m_setPadding) {
ImGui::PopStyleVar();
}
}
bool Window::DisplayMenuItem(const char* label) {
@@ -83,11 +95,15 @@ void Window::IniReadLine(const char* lineStr) {
m_name = value;
} else if (name == "visible") {
int num;
if (value.getAsInteger(10, num)) return;
if (value.getAsInteger(10, num)) {
return;
}
m_visible = num;
} else if (name == "enabled") {
int num;
if (value.getAsInteger(10, num)) return;
if (value.getAsInteger(10, num)) {
return;
}
m_enabled = num;
}
}

View File

@@ -34,7 +34,9 @@ void WindowManager::IniSaver::IniWriteAll(ImGuiTextBuffer* out_buf) {
Window* WindowManager::AddWindow(wpi::StringRef id,
wpi::unique_function<void()> display) {
auto win = GetOrAddWindow(id, false);
if (!win) return nullptr;
if (!win) {
return nullptr;
}
if (win->HasView()) {
wpi::errs() << "GUI: ignoring duplicate window '" << id << "'\n";
return nullptr;
@@ -46,7 +48,9 @@ Window* WindowManager::AddWindow(wpi::StringRef id,
Window* WindowManager::AddWindow(wpi::StringRef id,
std::unique_ptr<View> view) {
auto win = GetOrAddWindow(id, false);
if (!win) return nullptr;
if (!win) {
return nullptr;
}
if (win->HasView()) {
wpi::errs() << "GUI: ignoring duplicate window '" << id << "'\n";
return nullptr;
@@ -76,7 +80,9 @@ Window* WindowManager::GetWindow(wpi::StringRef id) {
auto it = std::lower_bound(
m_windows.begin(), m_windows.end(), id,
[](const auto& elem, wpi::StringRef s) { return elem->GetId() < s; });
if (it == m_windows.end() || (*it)->GetId() != id) return nullptr;
if (it == m_windows.end() || (*it)->GetId() != id) {
return nullptr;
}
return it->get();
}

View File

@@ -10,7 +10,9 @@
using namespace glass;
void glass::DisplayAccelerometerDevice(AccelerometerModel* model) {
if (!model->Exists()) return;
if (!model->Exists()) {
return;
}
if (BeginDevice("BuiltInAccel")) {
// Range
{

View File

@@ -13,7 +13,9 @@ using namespace glass;
void glass::DisplayAnalogInput(AnalogInputModel* model, int index) {
auto voltageData = model->GetVoltageData();
if (!voltageData) return;
if (!voltageData) {
return;
}
// build label
std::string* name = GetStorage().GetStringRef("name");
@@ -34,11 +36,15 @@ void glass::DisplayAnalogInput(AnalogInputModel* model, int index) {
ImGui::PopStyleColor();
} else {
float val = voltageData->GetValue();
if (voltageData->SliderFloat(label, &val, 0.0, 5.0)) model->SetVoltage(val);
if (voltageData->SliderFloat(label, &val, 0.0, 5.0)) {
model->SetVoltage(val);
}
}
// context menu to change name
if (PopupEditName("name", name)) voltageData->SetName(name->c_str());
if (PopupEditName("name", name)) {
voltageData->SetName(name->c_str());
}
}
void glass::DisplayAnalogInputs(AnalogInputsModel* model,
@@ -58,6 +64,7 @@ void glass::DisplayAnalogInputs(AnalogInputsModel* model,
PopID();
hasAny = true;
});
if (!hasAny && !noneMsg.empty())
if (!hasAny && !noneMsg.empty()) {
ImGui::TextUnformatted(noneMsg.begin(), noneMsg.end());
}
}

View File

@@ -13,12 +13,16 @@ using namespace glass;
void glass::DisplayAnalogOutputsDevice(AnalogOutputsModel* model) {
int count = 0;
model->ForEachAnalogOutput([&](auto&, int) { ++count; });
if (count == 0) return;
if (count == 0) {
return;
}
if (BeginDevice("Analog Outputs")) {
model->ForEachAnalogOutput([&](auto& analogOut, int i) {
auto analogOutData = analogOut.GetVoltageData();
if (!analogOutData) return;
if (!analogOutData) {
return;
}
PushID(i);
// build label
@@ -34,7 +38,9 @@ void glass::DisplayAnalogOutputsDevice(AnalogOutputsModel* model) {
DeviceDouble(label, true, &value, analogOutData);
if (PopupEditName("name", name)) {
if (analogOutData) analogOutData->SetName(name->c_str());
if (analogOutData) {
analogOutData->SetName(name->c_str());
}
}
PopID();
});

View File

@@ -59,11 +59,12 @@ void DisplayDIOImpl(DIOModel* model, int index, bool outputsEnabled) {
}
} else {
const char* name = model->GetName();
if (name[0] != '\0')
if (name[0] != '\0') {
info.GetLabel(label, sizeof(label), name);
else
} else {
info.GetLabel(label, sizeof(label), model->IsInput() ? " In" : "Out",
index);
}
if (auto simDevice = model->GetSimDevice()) {
LabelSimDevice(label, simDevice);
} else {
@@ -87,8 +88,12 @@ void DisplayDIOImpl(DIOModel* model, int index, bool outputsEnabled) {
}
}
if (info.PopupEditName(index)) {
if (dpwmData) dpwmData->SetName(info.GetName());
if (dutyCycleData) dutyCycleData->SetName(info.GetName());
if (dpwmData) {
dpwmData->SetName(info.GetName());
}
if (dutyCycleData) {
dutyCycleData->SetName(info.GetName());
}
}
}
@@ -110,6 +115,7 @@ void glass::DisplayDIOs(DIOsModel* model, bool outputsEnabled,
ImGui::PopID();
});
ImGui::PopItemWidth();
if (!hasAny && !noneMsg.empty())
if (!hasAny && !noneMsg.empty()) {
ImGui::TextUnformatted(noneMsg.begin(), noneMsg.end());
}
}

View File

@@ -82,7 +82,9 @@ void glass::DisplayEncoder(EncoderModel* model) {
model->SetName(name->c_str());
}
if (!open) return;
if (!open) {
return;
}
ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
// distance per pulse
@@ -94,7 +96,9 @@ void glass::DisplayEncoder(EncoderModel* model) {
// count
if (auto countData = model->GetCountData()) {
int value = countData->GetValue();
if (ImGui::InputInt("##input", &value)) model->SetCount(value);
if (ImGui::InputInt("##input", &value)) {
model->SetCount(value);
}
ImGui::SameLine();
if (ImGui::Button("Reset")) {
model->SetCount(0);
@@ -157,6 +161,7 @@ void glass::DisplayEncoders(EncodersModel* model, wpi::StringRef noneMsg) {
DisplayEncoder(&encoder);
PopID();
});
if (!hasAny && !noneMsg.empty())
if (!hasAny && !noneMsg.empty()) {
ImGui::TextUnformatted(noneMsg.begin(), noneMsg.end());
}
}

View File

@@ -36,8 +36,9 @@ void glass::DisplayGyro(GyroModel* m) {
m->IsReadOnly() ? ImGuiInputTextFlags_ReadOnly : ImGuiInputTextFlags_None;
auto value = angle->GetValue();
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
if (ImGui::InputDouble("Gyro Angle (Deg)", &value, 0.0, 0.0, "%.4f", flags))
if (ImGui::InputDouble("Gyro Angle (Deg)", &value, 0.0, 0.0, "%.4f", flags)) {
m->SetAngle(value);
}
// Draw the gyro indicator.
ImDrawList* draw = ImGui::GetWindowDrawList();

View File

@@ -42,7 +42,9 @@ void glass::DisplayLEDDisplay(LEDDisplayModel* model, int index) {
ImGui::Combo("Start", start, options, 4);
}
ImGui::Checkbox("Serpentine", serpentine);
if (*numColumns < 1) *numColumns = 1;
if (*numColumns < 1) {
*numColumns = 1;
}
ImGui::PopItemWidth();
// show as LED indicators
@@ -51,13 +53,17 @@ void glass::DisplayLEDDisplay(LEDDisplayModel* model, int index) {
storage.SetData(std::make_shared<IndicatorData>());
iData = storage.GetData<IndicatorData>();
}
if (length > static_cast<int>(iData->values.size()))
if (length > static_cast<int>(iData->values.size())) {
iData->values.resize(length);
if (length > static_cast<int>(iData->colors.size()))
}
if (length > static_cast<int>(iData->colors.size())) {
iData->colors.resize(length);
}
if (!running) {
iData->colors[0] = IM_COL32(128, 128, 128, 255);
for (int j = 0; j < length; ++j) iData->values[j] = -1;
for (int j = 0; j < length; ++j) {
iData->values[j] = -1;
}
} else {
for (int j = 0; j < length; ++j) {
iData->values[j] = j + 1;
@@ -79,10 +85,14 @@ void glass::DisplayLEDDisplays(LEDDisplaysModel* model) {
model->ForEachLEDDisplay([&](LEDDisplayModel& display, int i) {
hasAny = true;
if (model->GetNumLEDDisplays() > 1) ImGui::Text("LEDs[%d]", i);
if (model->GetNumLEDDisplays() > 1) {
ImGui::Text("LEDs[%d]", i);
}
PushID(i);
DisplayLEDDisplay(&display, i);
PopID();
});
if (!hasAny) ImGui::Text("No addressable LEDs");
if (!hasAny) {
ImGui::Text("No addressable LEDs");
}
}

View File

@@ -23,16 +23,22 @@ bool glass::DisplayPCMSolenoids(PCMModel* model, int index,
wpi::SmallVector<int, 16> channels;
model->ForEachSolenoid([&](SolenoidModel& solenoid, int j) {
if (auto data = solenoid.GetOutputData()) {
if (j >= static_cast<int>(channels.size())) channels.resize(j + 1);
if (j >= static_cast<int>(channels.size())) {
channels.resize(j + 1);
}
channels[j] = (outputsEnabled && data->GetValue()) ? 1 : -1;
}
});
if (channels.empty()) return false;
if (channels.empty()) {
return false;
}
// show nonexistent channels as empty
for (auto&& ch : channels) {
if (ch == 0) ch = -2;
if (ch == 0) {
ch = -2;
}
}
// build header label
@@ -81,17 +87,22 @@ void glass::DisplayPCMsSolenoids(PCMsModel* model, bool outputsEnabled,
bool hasAny = false;
model->ForEachPCM([&](PCMModel& pcm, int i) {
PushID(i);
if (DisplayPCMSolenoids(&pcm, i, outputsEnabled)) hasAny = true;
if (DisplayPCMSolenoids(&pcm, i, outputsEnabled)) {
hasAny = true;
}
PopID();
});
if (!hasAny && !noneMsg.empty())
if (!hasAny && !noneMsg.empty()) {
ImGui::TextUnformatted(noneMsg.begin(), noneMsg.end());
}
}
void glass::DisplayCompressorDevice(PCMModel* model, int index,
bool outputsEnabled) {
auto compressor = model->GetCompressor();
if (!compressor || !compressor->Exists()) return;
if (!compressor || !compressor->Exists()) {
return;
}
DisplayCompressorDevice(compressor, index, outputsEnabled);
}

View File

@@ -24,8 +24,9 @@ static float DisplayChannel(PDPModel& pdp, int channel) {
leftInfo.GetLabel(name, sizeof(name), "", channel);
double val = currentData->GetValue();
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 4);
if (currentData->InputDouble(name, &val, 0, 0, "%.3f"))
if (currentData->InputDouble(name, &val, 0, 0, "%.3f")) {
pdp.SetCurrent(channel, val);
}
width = ImGui::GetItemRectSize().x;
leftInfo.PopupEditName(channel);
ImGui::PopID();
@@ -69,7 +70,9 @@ void glass::DisplayPDP(PDPModel* model, int index) {
float width =
(std::max)(leftWidth, rightWidth) * 2 + ImGui::GetFontSize() * 4;
if (width > maxWidth) maxWidth = width;
if (width > maxWidth) {
maxWidth = width;
}
}
ImGui::Columns(1);
ImGui::Dummy(ImVec2(maxWidth, 0));
@@ -84,6 +87,7 @@ void glass::DisplayPDPs(PDPsModel* model, wpi::StringRef noneMsg) {
DisplayPDP(&pdp, i);
PopID();
});
if (!hasAny && !noneMsg.empty())
if (!hasAny && !noneMsg.empty()) {
ImGui::TextUnformatted(noneMsg.begin(), noneMsg.end());
}
}

View File

@@ -13,7 +13,9 @@ using namespace glass;
void glass::DisplayPWM(PWMModel* model, int index, bool outputsEnabled) {
auto data = model->GetSpeedData();
if (!data) return;
if (!data) {
return;
}
// build label
std::string* name = GetStorage().GetStringRef("name");
@@ -46,14 +48,16 @@ void glass::DisplayPWMs(PWMsModel* model, bool outputsEnabled,
hasAny = true;
PushID(i);
if (!first)
if (!first) {
ImGui::Separator();
else
} else {
first = false;
}
DisplayPWM(&pwm, i, outputsEnabled);
PopID();
});
if (!hasAny && !noneMsg.empty())
if (!hasAny && !noneMsg.empty()) {
ImGui::TextUnformatted(noneMsg.begin(), noneMsg.end());
}
}

View File

@@ -23,20 +23,29 @@ void glass::DisplayRelay(RelayModel* model, int index, bool outputsEnabled) {
bool forward = false;
bool reverse = false;
if (outputsEnabled) {
if (forwardData) forward = forwardData->GetValue();
if (reverseData) reverse = reverseData->GetValue();
if (forwardData) {
forward = forwardData->GetValue();
}
if (reverseData) {
reverse = reverseData->GetValue();
}
}
std::string* name = GetStorage().GetStringRef("name");
ImGui::PushID("name");
if (!name->empty())
if (!name->empty()) {
ImGui::Text("%s [%d]", name->c_str(), index);
else
} else {
ImGui::Text("Relay[%d]", index);
}
ImGui::PopID();
if (PopupEditName("name", name)) {
if (forwardData) forwardData->SetName(name->c_str());
if (reverseData) reverseData->SetName(name->c_str());
if (forwardData) {
forwardData->SetName(name->c_str());
}
if (reverseData) {
reverseData->SetName(name->c_str());
}
}
ImGui::SameLine();
@@ -57,15 +66,17 @@ void glass::DisplayRelays(RelaysModel* model, bool outputsEnabled,
model->ForEachRelay([&](RelayModel& relay, int i) {
hasAny = true;
if (!first)
if (!first) {
ImGui::Separator();
else
} else {
first = false;
}
PushID(i);
DisplayRelay(&relay, i, outputsEnabled);
PopID();
});
if (!hasAny && !noneMsg.empty())
if (!hasAny && !noneMsg.empty()) {
ImGui::TextUnformatted(noneMsg.begin(), noneMsg.end());
}
}

View File

@@ -23,11 +23,15 @@ void glass::DisplaySpeedController(SpeedControllerModel* m) {
}
// Add button to zero output.
if (ImGui::Button("Zero")) m->SetPercent(0.0);
if (ImGui::Button("Zero")) {
m->SetPercent(0.0);
}
ImGui::SameLine();
// Display a slider for the data.
float value = dc->GetValue();
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
if (dc->SliderFloat("% Output", &value, -1.0f, 1.0f)) m->SetPercent(value);
if (dc->SliderFloat("% Output", &value, -1.0f, 1.0f)) {
m->SetPercent(value);
}
}

View File

@@ -27,7 +27,9 @@ void glass::DisplayCommandScheduler(CommandSchedulerModel* m) {
ImGui::SameLine(pos);
ImGui::PushID(i);
if (ImGui::Button("Cancel")) m->CancelCommand(i);
if (ImGui::Button("Cancel")) {
m->CancelCommand(i);
}
ImGui::PopID();
}
} else {

View File

@@ -12,7 +12,9 @@
using namespace glass;
void glass::DisplayCommandSelector(CommandSelectorModel* m) {
if (auto name = m->GetName()) ImGui::Text("%s", name);
if (auto name = m->GetName()) {
ImGui::Text("%s", name);
}
if (m->Exists()) {
if (auto run = m->GetRunningData()) {
bool running = run->GetValue();
@@ -21,7 +23,9 @@ void glass::DisplayCommandSelector(CommandSelectorModel* m) {
m->SetRunning(running);
}
ImGui::SameLine();
if (running) ImGui::Text("Running...");
if (running) {
ImGui::Text("Running...");
}
}
} else {
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(96, 96, 96, 255));

View File

@@ -16,27 +16,37 @@ using namespace glass;
void DeviceTreeModel::Update() {
for (auto&& display : m_displays) {
if (display.first) display.first->Update();
if (display.first) {
display.first->Update();
}
}
}
bool DeviceTreeModel::Exists() {
for (auto&& display : m_displays) {
if (display.first && display.first->Exists()) return true;
if (display.first && display.first->Exists()) {
return true;
}
}
return false;
}
void DeviceTreeModel::Display() {
for (auto&& display : m_displays) {
if (display.second) display.second(display.first);
if (display.second) {
display.second(display.first);
}
}
}
void glass::HideDevice(const char* id) { gContext->deviceHidden[id] = true; }
void glass::HideDevice(const char* id) {
gContext->deviceHidden[id] = true;
}
bool glass::BeginDevice(const char* id, ImGuiTreeNodeFlags flags) {
if (gContext->deviceHidden[id]) return false;
if (gContext->deviceHidden[id]) {
return false;
}
PushID(id);
@@ -49,11 +59,15 @@ bool glass::BeginDevice(const char* id, ImGuiTreeNodeFlags flags) {
bool open = CollapsingHeader(label, flags);
PopupEditName("name", name);
if (!open) PopID();
if (!open) {
PopID();
}
return open;
}
void glass::EndDevice() { PopID(); }
void glass::EndDevice() {
PopID();
}
static bool DeviceBooleanImpl(const char* name, bool readonly, bool* value) {
if (readonly) {
@@ -82,10 +96,11 @@ static bool DeviceDoubleImpl(const char* name, bool readonly, double* value) {
static bool DeviceEnumImpl(const char* name, bool readonly, int* value,
const char** options, int32_t numOptions) {
if (readonly) {
if (*value < 0 || *value >= numOptions)
if (*value < 0 || *value >= numOptions) {
ImGui::LabelText(name, "%d (unknown)", *value);
else
} else {
ImGui::LabelText(name, "%s", options[*value]);
}
return false;
} else {
return ImGui::Combo(name, value, options, numOptions);

View File

@@ -15,19 +15,25 @@ static const char* stations[] = {"Red 1", "Red 2", "Red 3",
"Blue 1", "Blue 2", "Blue 3"};
void glass::DisplayFMS(FMSModel* model, bool* matchTimeEnabled) {
if (!model->Exists() || model->IsReadOnly()) return DisplayFMSReadOnly(model);
if (!model->Exists() || model->IsReadOnly()) {
return DisplayFMSReadOnly(model);
}
// FMS Attached
if (auto data = model->GetFmsAttachedData()) {
bool val = data->GetValue();
if (ImGui::Checkbox("FMS Attached", &val)) model->SetFmsAttached(val);
if (ImGui::Checkbox("FMS Attached", &val)) {
model->SetFmsAttached(val);
}
data->EmitDrag();
}
// DS Attached
if (auto data = model->GetDsAttachedData()) {
bool val = data->GetValue();
if (ImGui::Checkbox("DS Attached", &val)) model->SetDsAttached(val);
if (ImGui::Checkbox("DS Attached", &val)) {
model->SetDsAttached(val);
}
data->EmitDrag();
}
@@ -35,15 +41,17 @@ void glass::DisplayFMS(FMSModel* model, bool* matchTimeEnabled) {
if (auto data = model->GetAllianceStationIdData()) {
int val = data->GetValue();
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
if (ImGui::Combo("Alliance Station", &val, stations, 6))
if (ImGui::Combo("Alliance Station", &val, stations, 6)) {
model->SetAllianceStationId(val);
}
data->EmitDrag();
}
// Match Time
if (auto data = model->GetMatchTimeData()) {
if (matchTimeEnabled)
if (matchTimeEnabled) {
ImGui::Checkbox("Match Time Enabled", matchTimeEnabled);
}
double val = data->GetValue();
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
@@ -74,7 +82,9 @@ void glass::DisplayFMS(FMSModel* model, bool* matchTimeEnabled) {
void glass::DisplayFMSReadOnly(FMSModel* model) {
bool exists = model->Exists();
if (!exists) ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(96, 96, 96, 255));
if (!exists) {
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(96, 96, 96, 255));
}
if (auto data = model->GetEStopData()) {
ImGui::Selectable("E-Stopped: ");
@@ -123,15 +133,18 @@ void glass::DisplayFMSReadOnly(FMSModel* model) {
ImGui::Selectable("Match Time: ");
data->EmitDrag();
ImGui::SameLine();
if (exists)
if (exists) {
ImGui::Text("%.1f", data->GetValue());
else
} else {
ImGui::TextUnformatted("?");
}
}
wpi::SmallString<64> gameSpecificMessage;
model->GetGameSpecificMessage(gameSpecificMessage);
ImGui::Text("Game Specific: %s", exists ? gameSpecificMessage.c_str() : "?");
if (!exists) ImGui::PopStyleColor();
if (!exists) {
ImGui::PopStyleColor();
}
}

View File

@@ -182,7 +182,9 @@ void FieldInfo::LoadImage() {
m_fileOpener.reset();
}
if (!m_texture && !m_pFilename->empty()) {
if (!LoadImageImpl(m_pFilename->c_str())) m_pFilename->clear();
if (!LoadImageImpl(m_pFilename->c_str())) {
m_pFilename->clear();
}
}
}
@@ -264,7 +266,9 @@ void FieldInfo::LoadJson(const wpi::Twine& jsonfile) {
wpi::sys::path::append(pathname, image);
// load field image
if (!LoadImageImpl(pathname.c_str())) return;
if (!LoadImageImpl(pathname.c_str())) {
return;
}
// save to field info
*m_pFilename = pathname.str();
@@ -292,8 +296,9 @@ bool FieldInfo::LoadImageImpl(const char* fn) {
FieldFrameData FieldInfo::GetFrameData(ImVec2 min, ImVec2 max) const {
// fit the image into the window
if (m_texture && m_imageHeight != 0 && m_imageWidth != 0)
if (m_texture && m_imageHeight != 0 && m_imageWidth != 0) {
gui::MaxFit(&min, &max, m_imageWidth, m_imageHeight);
}
FieldFrameData ffd;
ffd.imageMin = min;
@@ -340,11 +345,15 @@ void ObjectGroupInfo::Reset() {
void ObjectGroupInfo::LoadImage() {
if (m_fileOpener && m_fileOpener->ready(0)) {
auto result = m_fileOpener->result();
if (!result.empty()) LoadImageImpl(result[0].c_str());
if (!result.empty()) {
LoadImageImpl(result[0].c_str());
}
m_fileOpener.reset();
}
if (!m_texture && !m_pFilename->empty()) {
if (!LoadImageImpl(m_pFilename->c_str())) m_pFilename->clear();
if (!LoadImageImpl(m_pFilename->c_str())) {
m_pFilename->clear();
}
}
}
@@ -368,10 +377,15 @@ ObjectFrameData::ObjectFrameData(FieldObjectModel& model,
m_width2(ffd.scale * width / 2),
m_length2(ffd.scale * length / 2),
m_hitRadius((std::min)(m_width2, m_length2) / 2) {
if (auto xData = model.GetXData()) m_x = xData->GetValue();
if (auto yData = model.GetYData()) m_y = yData->GetValue();
if (auto rotationData = model.GetRotationData())
if (auto xData = model.GetXData()) {
m_x = xData->GetValue();
}
if (auto yData = model.GetYData()) {
m_y = yData->GetValue();
}
if (auto rotationData = model.GetRotationData()) {
m_rot = rotationData->GetValue();
}
UpdateFrameData();
}
@@ -418,22 +432,25 @@ int ObjectFrameData::IsHovered(const ImVec2& cursor) const {
// only allow initiation of dragging when invisible button is hovered;
// this prevents the window resize handles from simultaneously activating
// the drag functionality
if (!ImGui::IsItemHovered()) return 0;
if (!ImGui::IsItemHovered()) {
return 0;
}
float hitRadiusSquared = m_hitRadius * m_hitRadius;
// it's within the hit radius of the center?
if (gui::GetDistSquared(cursor, m_center) < hitRadiusSquared)
if (gui::GetDistSquared(cursor, m_center) < hitRadiusSquared) {
return 1;
else if (gui::GetDistSquared(cursor, m_corners[0]) < hitRadiusSquared)
} else if (gui::GetDistSquared(cursor, m_corners[0]) < hitRadiusSquared) {
return 2;
else if (gui::GetDistSquared(cursor, m_corners[1]) < hitRadiusSquared)
} else if (gui::GetDistSquared(cursor, m_corners[1]) < hitRadiusSquared) {
return 3;
else if (gui::GetDistSquared(cursor, m_corners[2]) < hitRadiusSquared)
} else if (gui::GetDistSquared(cursor, m_corners[2]) < hitRadiusSquared) {
return 4;
else if (gui::GetDistSquared(cursor, m_corners[3]) < hitRadiusSquared)
} else if (gui::GetDistSquared(cursor, m_corners[3]) < hitRadiusSquared) {
return 5;
else
} else {
return 0;
}
}
bool ObjectFrameData::HandleDrag(const ImVec2& cursor, int hitCorner,
@@ -525,10 +542,14 @@ void glass::DisplayField2DSettings(Field2DModel* model) {
}
model->ForEachFieldObjectGroup([&](auto& groupModel, auto name) {
if (!groupModel.Exists()) return;
if (!groupModel.Exists()) {
return;
}
PushID(name);
auto& objGroupRef = field->m_objectGroups[name];
if (!objGroupRef) objGroupRef = std::make_unique<ObjectGroupInfo>();
if (!objGroupRef) {
objGroupRef = std::make_unique<ObjectGroupInfo>();
}
auto objGroup = objGroupRef.get();
wpi::SmallString<64> nameBuf = name;
@@ -565,7 +586,9 @@ void glass::DisplayField2D(Field2DModel* model, const ImVec2& contentSize) {
// for dragging to work, there needs to be a button (otherwise the window is
// dragged)
if (contentSize.x <= 0 || contentSize.y <= 0) return;
if (contentSize.x <= 0 || contentSize.y <= 0) {
return;
}
ImVec2 cursorPos = windowPos + ImGui::GetCursorPos(); // screen coords
ImGui::InvisibleButton("field", contentSize);
@@ -576,10 +599,14 @@ void glass::DisplayField2D(Field2DModel* model, const ImVec2& contentSize) {
field->Draw(drawList, ffd);
model->ForEachFieldObjectGroup([&](auto& groupModel, auto name) {
if (!groupModel.Exists()) return;
if (!groupModel.Exists()) {
return;
}
PushID(name);
auto& objGroupRef = field->m_objectGroups[name];
if (!objGroupRef) objGroupRef = std::make_unique<ObjectGroupInfo>();
if (!objGroupRef) {
objGroupRef = std::make_unique<ObjectGroupInfo>();
}
auto objGroup = objGroupRef.get();
objGroup->LoadImage();
@@ -593,8 +620,9 @@ void glass::DisplayField2D(Field2DModel* model, const ImVec2& contentSize) {
if (objGroup->m_dragState.object == 0 ||
objGroup->m_dragState.object == i) {
hitCorner = ofd.IsHovered(mousePos);
if (ofd.HandleDrag(mousePos, hitCorner, &objGroup->m_dragState))
if (ofd.HandleDrag(mousePos, hitCorner, &objGroup->m_dragState)) {
objGroup->m_dragState.object = i;
}
}
// draw

View File

@@ -23,7 +23,9 @@ void glass::DisplayPIDController(PIDControllerModel* m) {
auto createTuningParameter = [](const char* name, double* v,
std::function<void(double)> callback) {
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 4);
if (ImGui::InputDouble(name, v, 0.0, 0.0, "%.3f")) callback(*v);
if (ImGui::InputDouble(name, v, 0.0, 0.0, "%.3f")) {
callback(*v);
}
};
if (auto p = m->GetPData()) {

View File

@@ -237,17 +237,23 @@ bool PlotSeries::ReadIni(wpi::StringRef name, wpi::StringRef value) {
}
if (name == "yAxis") {
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_yAxis = num;
return true;
} else if (name == "color") {
unsigned int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_color = ImColor(num);
return true;
} else if (name == "marker") {
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_marker = num;
return true;
} else if (name == "weight") {
@@ -255,17 +261,23 @@ bool PlotSeries::ReadIni(wpi::StringRef name, wpi::StringRef value) {
return true;
} else if (name == "digital") {
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_digital = num;
return true;
} else if (name == "digitalBitHeight") {
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_digitalBitHeight = num;
return true;
} else if (name == "digitalBitGap") {
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_digitalBitGap = num;
return true;
}
@@ -281,10 +293,14 @@ void PlotSeries::WriteIni(ImGuiTextBuffer* out) {
}
const char* PlotSeries::GetName() const {
if (!m_name.empty()) return m_name.c_str();
if (!m_name.empty()) {
return m_name.c_str();
}
if (m_newValueConn.connected()) {
auto sourceName = m_source->GetName();
if (sourceName[0] != '\0') return sourceName;
if (sourceName[0] != '\0') {
return sourceName;
}
}
return m_id.c_str();
}
@@ -311,19 +327,23 @@ PlotSeries::Action PlotSeries::EmitPlot(PlotView& view, double now, size_t i,
GetterData getterData = {now, GetZeroTime() * 1.0e-6, m_data, size, offset};
auto getter = [](void* data, int idx) {
auto d = static_cast<GetterData*>(data);
if (idx == d->size)
if (idx == d->size) {
return ImPlotPoint{
d->now - d->zeroTime,
d->data[d->offset == 0 ? d->size - 1 : d->offset - 1].y};
}
ImPlotPoint* point;
if (d->offset + idx < d->size)
if (d->offset + idx < d->size) {
point = &d->data[d->offset + idx];
else
} else {
point = &d->data[d->offset + idx - d->size];
}
return ImPlotPoint{point->x - d->zeroTime, point->y};
};
if (m_color.w == IMPLOT_AUTO_COL.w) m_color = ImPlot::GetColormapColor(i);
if (m_color.w == IMPLOT_AUTO_COL.w) {
m_color = ImPlot::GetColormapColor(i);
}
ImPlot::SetNextLineStyle(m_color, m_weight);
if (IsDigital()) {
ImPlot::PushStyleVar(ImPlotStyleVar_DigitalBitHeight, m_digitalBitHeight);
@@ -346,7 +366,9 @@ PlotSeries::Action PlotSeries::EmitPlot(PlotView& view, double now, size_t i,
// Edit settings via popup
Action rv = kNone;
if (ImPlot::BeginLegendPopup(label)) {
if (ImGui::Button("Close")) ImGui::CloseCurrentPopup();
if (ImGui::Button("Close")) {
ImGui::CloseCurrentPopup();
}
ImGui::Text("Edit series name:");
ImGui::InputText("##editname", &m_name);
if (ImGui::Button("Move Up")) {
@@ -382,7 +404,9 @@ void PlotSeries::EmitSettings(size_t i) {
{
ImGui::ColorEdit3("Color", &m_color.x, ImGuiColorEditFlags_NoInputs);
ImGui::SameLine();
if (ImGui::Button("Default")) m_color = ImPlot::GetColormapColor(i);
if (ImGui::Button("Default")) {
m_color = ImPlot::GetColormapColor(i);
}
}
// Line weight
@@ -443,76 +467,107 @@ bool Plot::ReadIni(wpi::StringRef name, wpi::StringRef value) {
return true;
} else if (name == "visible") {
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_visible = num != 0;
return true;
} else if (name == "showPause") {
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_showPause = num != 0;
return true;
} else if (name == "lockPrevX") {
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_lockPrevX = num != 0;
return true;
} else if (name == "legend") {
int num;
if (value.getAsInteger(10, num)) return true;
if (num == 0)
if (value.getAsInteger(10, num)) {
return true;
}
if (num == 0) {
m_plotFlags &= ~ImPlotFlags_Legend;
else
} else {
m_plotFlags |= ImPlotFlags_Legend;
}
return true;
} else if (name == "yaxis2") {
int num;
if (value.getAsInteger(10, num)) return true;
if (num == 0)
if (value.getAsInteger(10, num)) {
return true;
}
if (num == 0) {
m_plotFlags &= ~ImPlotFlags_YAxis2;
else
} else {
m_plotFlags |= ImPlotFlags_YAxis2;
}
return true;
} else if (name == "yaxis3") {
int num;
if (value.getAsInteger(10, num)) return true;
if (num == 0)
if (value.getAsInteger(10, num)) {
return true;
}
if (num == 0) {
m_plotFlags &= ~ImPlotFlags_YAxis3;
else
} else {
m_plotFlags |= ImPlotFlags_YAxis3;
}
return true;
} else if (name == "viewTime") {
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_viewTime = num / 1000.0;
return true;
} else if (name == "height") {
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
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;
if (yAxis < 0 || yAxis > 3) return false;
if (yAxisStr.substr(1).getAsInteger(10, yAxis)) {
return false;
}
if (yAxis < 0 || yAxis > 3) {
return false;
}
if (yName == "min") {
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_axisRange[yAxis].min = num / 1000.0;
return true;
} else if (yName == "max") {
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_axisRange[yAxis].max = num / 1000.0;
return true;
} else if (yName == "lockMin") {
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_axisRange[yAxis].lockMin = num != 0;
return true;
} else if (yName == "lockMax") {
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_axisRange[yAxis].lockMax = num != 0;
return true;
}
@@ -539,7 +594,9 @@ void Plot::WriteIni(ImGuiTextBuffer* out) {
}
void Plot::DragDropTarget(PlotView& view, size_t i, bool inPlot) {
if (!ImGui::BeginDragDropTarget()) return;
if (!ImGui::BeginDragDropTarget()) {
return;
}
// handle dragging onto a specific Y axis
int yAxis = -1;
if (inPlot) {
@@ -576,12 +633,15 @@ void Plot::DragDropTarget(PlotView& view, size_t i, bool inPlot) {
}
void Plot::EmitPlot(PlotView& view, double now, bool paused, size_t i) {
if (!m_visible) return;
if (!m_visible) {
return;
}
bool lockX = (i != 0 && m_lockPrevX);
if (!lockX && m_showPause && ImGui::Button(m_paused ? "Resume" : "Pause"))
if (!lockX && m_showPause && ImGui::Button(m_paused ? "Resume" : "Pause")) {
m_paused = !m_paused;
}
char label[128];
std::snprintf(label, sizeof(label), "%s##plot", m_name.c_str());
@@ -606,8 +666,12 @@ void Plot::EmitPlot(PlotView& view, double now, bool paused, size_t i) {
m_axisRange[i].min, m_axisRange[i].max,
m_axisRange[i].apply ? ImGuiCond_Always : ImGuiCond_Once, i);
m_axisRange[i].apply = false;
if (m_axisRange[i].lockMin) yFlags[i] |= ImPlotAxisFlags_LockMin;
if (m_axisRange[i].lockMax) yFlags[i] |= ImPlotAxisFlags_LockMax;
if (m_axisRange[i].lockMin) {
yFlags[i] |= ImPlotAxisFlags_LockMin;
}
if (m_axisRange[i].lockMax) {
yFlags[i] |= ImPlotAxisFlags_LockMax;
}
}
if (ImPlot::BeginPlot(label, nullptr, nullptr, ImVec2(-1, m_height),
@@ -617,11 +681,14 @@ void Plot::EmitPlot(PlotView& view, double now, bool paused, size_t i) {
ImGui::PushID(j);
switch (m_series[j]->EmitPlot(view, now, j, i)) {
case PlotSeries::kMoveUp:
if (j > 0) std::swap(m_series[j - 1], m_series[j]);
if (j > 0) {
std::swap(m_series[j - 1], m_series[j]);
}
break;
case PlotSeries::kMoveDown:
if (j < (m_series.size() - 1))
if (j < (m_series.size() - 1)) {
std::swap(m_series[j], m_series[j + 1]);
}
break;
case PlotSeries::kDelete:
m_series.erase(m_series.begin() + j);
@@ -647,7 +714,9 @@ void Plot::EmitSettingsLimits(int axis) {
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 3.5);
ImGui::InputDouble("Max", &m_axisRange[axis].max, 0, 0, "%.3f");
ImGui::SameLine();
if (ImGui::Button("Apply")) m_axisRange[axis].apply = true;
if (ImGui::Button("Apply")) {
m_axisRange[axis].apply = true;
}
ImGui::TextUnformatted("Lock Axis");
ImGui::SameLine();
@@ -665,35 +734,45 @@ void Plot::EmitSettings(size_t i) {
ImGui::Checkbox("Visible", &m_visible);
ImGui::Checkbox("Show Pause Button", &m_showPause);
ImGui::CheckboxFlags("Show Legend", &m_plotFlags, ImPlotFlags_Legend);
if (i != 0) ImGui::Checkbox("Lock X-axis to previous plot", &m_lockPrevX);
if (i != 0) {
ImGui::Checkbox("Lock X-axis to previous plot", &m_lockPrevX);
}
ImGui::TextUnformatted("Primary Y-Axis");
EmitSettingsLimits(0);
ImGui::CheckboxFlags("2nd Y-Axis", &m_plotFlags, ImPlotFlags_YAxis2);
if ((m_plotFlags & ImPlotFlags_YAxis2) != 0) EmitSettingsLimits(1);
if ((m_plotFlags & ImPlotFlags_YAxis2) != 0) {
EmitSettingsLimits(1);
}
ImGui::CheckboxFlags("3rd Y-Axis", &m_plotFlags, ImPlotFlags_YAxis3);
if ((m_plotFlags & ImPlotFlags_YAxis3) != 0) EmitSettingsLimits(2);
if ((m_plotFlags & ImPlotFlags_YAxis3) != 0) {
EmitSettingsLimits(2);
}
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 6);
ImGui::InputFloat("View Time (s)", &m_viewTime, 0.1f, 1.0f, "%.1f");
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 6);
if (ImGui::InputInt("Height", &m_height, 10)) {
if (m_height < 0) m_height = 0;
if (m_height < 0) {
m_height = 0;
}
}
}
void PlotView::Display() {
if (ImGui::BeginPopupContextItem()) {
if (ImGui::Button("Add plot"))
if (ImGui::Button("Add plot")) {
m_plots.emplace_back(std::make_unique<Plot>());
}
for (size_t i = 0; i < m_plots.size(); ++i) {
auto& plot = m_plots[i];
ImGui::PushID(i);
char name[64];
if (!plot->GetName().empty())
if (!plot->GetName().empty()) {
std::snprintf(name, sizeof(name), "%s", plot->GetName().c_str());
else
} else {
std::snprintf(name, sizeof(name), "Plot %d", static_cast<int>(i));
}
char label[90];
std::snprintf(label, sizeof(label), "%s###header%d", name,
@@ -712,12 +791,16 @@ void PlotView::Display() {
if (open) {
if (ImGui::Button("Move Up")) {
if (i > 0) std::swap(m_plots[i - 1], plot);
if (i > 0) {
std::swap(m_plots[i - 1], plot);
}
}
ImGui::SameLine();
if (ImGui::Button("Move Down")) {
if (i < (m_plots.size() - 1)) std::swap(plot, m_plots[i + 1]);
if (i < (m_plots.size() - 1)) {
std::swap(plot, m_plots[i + 1]);
}
}
ImGui::SameLine();
@@ -737,11 +820,14 @@ void PlotView::Display() {
}
if (m_plots.empty()) {
if (ImGui::Button("Add plot"))
if (ImGui::Button("Add plot")) {
m_plots.emplace_back(std::make_unique<Plot>());
}
// Make "add plot" button a DND target for Plot
if (!ImGui::BeginDragDropTarget()) return;
if (!ImGui::BeginDragDropTarget()) {
return;
}
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("Plot")) {
auto ref = static_cast<const PlotSeriesRef*>(payload->Data);
MovePlot(ref->view, ref->plotIndex, 0);
@@ -758,7 +844,9 @@ void PlotView::Display() {
void PlotView::MovePlot(PlotView* fromView, size_t fromIndex, size_t toIndex) {
if (fromView == this) {
if (fromIndex == toIndex) return;
if (fromIndex == toIndex) {
return;
}
auto val = std::move(m_plots[fromIndex]);
m_plots.insert(m_plots.begin() + toIndex, std::move(val));
m_plots.erase(m_plots.begin() + fromIndex + (fromIndex > toIndex ? 1 : 0));
@@ -778,7 +866,9 @@ void PlotView::MovePlotSeries(PlotView* fromView, size_t fromPlotIndex,
auto& plotSeries = m_plots[fromPlotIndex]->m_series;
auto val = std::move(plotSeries[fromSeriesIndex]);
// only set Y-axis if actually set
if (yAxis != -1) val->SetYAxis(yAxis);
if (yAxis != -1) {
val->SetYAxis(yAxis);
}
plotSeries.insert(plotSeries.begin() + toSeriesIndex, std::move(val));
plotSeries.erase(plotSeries.begin() + fromSeriesIndex +
(fromSeriesIndex > toSeriesIndex ? 1 : 0));
@@ -833,7 +923,9 @@ void PlotProvider::DisplayMenu() {
void PlotProvider::DisplayWindows() {
// create views if not already created
for (auto&& window : m_windows) {
if (!window->HasView()) window->SetView(std::make_unique<PlotView>(this));
if (!window->HasView()) {
window->SetView(std::make_unique<PlotView>(this));
}
}
WindowManager::DisplayWindows();
}
@@ -847,14 +939,20 @@ void* PlotProvider::IniSaver::IniReadOpen(const char* name) {
wpi::StringRef seriesId;
if (m_forSeries) {
std::tie(plotNumStr, seriesId) = plotNumStr.split('#');
if (seriesId.empty()) return nullptr;
if (seriesId.empty()) {
return nullptr;
}
}
unsigned int plotNum;
if (plotNumStr.getAsInteger(10, plotNum)) return nullptr;
if (plotNumStr.getAsInteger(10, plotNum)) {
return nullptr;
}
// get or create window
auto win = m_provider->GetOrAddWindow(viewId, true);
if (!win) return nullptr;
if (!win) {
return nullptr;
}
// get or create view
auto view = static_cast<PlotView*>(win->GetView());
@@ -864,12 +962,18 @@ void* PlotProvider::IniSaver::IniReadOpen(const char* name) {
}
// get or create plot
if (view->m_plots.size() <= plotNum) view->m_plots.resize(plotNum + 1);
if (view->m_plots.size() <= plotNum) {
view->m_plots.resize(plotNum + 1);
}
auto& plot = view->m_plots[plotNum];
if (!plot) plot = std::make_unique<Plot>();
if (!plot) {
plot = std::make_unique<Plot>();
}
// early exit for plot data
if (!m_forSeries) return plot.get();
if (!m_forSeries) {
return plot.get();
}
// get or create series
return plot->m_series.emplace_back(std::make_unique<PlotSeries>(seriesId))
@@ -880,10 +984,11 @@ void PlotProvider::IniSaver::IniReadLine(void* entry, const char* lineStr) {
auto [name, value] = wpi::StringRef{lineStr}.split('=');
name = name.trim();
value = value.trim();
if (m_forSeries)
if (m_forSeries) {
static_cast<PlotSeries*>(entry)->ReadIni(name, value);
else
} else {
static_cast<Plot*>(entry)->ReadIni(name, value);
}
}
void PlotProvider::IniSaver::IniWriteAll(ImGuiTextBuffer* out_buf) {

View File

@@ -31,7 +31,9 @@ void glass::DisplayStringChooser(StringChooserModel* model) {
if (ImGui::Selectable(option.c_str(), isSelected)) {
model->SetSelected(option);
}
if (isSelected) ImGui::SetItemDefaultFocus();
if (isSelected) {
ImGui::SetItemDefaultFocus();
}
ImGui::PopID();
}
ImGui::EndCombo();

View File

@@ -14,9 +14,15 @@ namespace glass {
void DrawLEDSources(const int* values, DataSource** sources, int numValues,
int cols, const ImU32* colors, float size, float spacing,
const LEDConfig& config) {
if (numValues == 0 || cols < 1) return;
if (size == 0) size = ImGui::GetFontSize() / 2.0;
if (spacing == 0) spacing = ImGui::GetFontSize() / 3.0;
if (numValues == 0 || cols < 1) {
return;
}
if (size == 0) {
size = ImGui::GetFontSize() / 2.0;
}
if (spacing == 0) {
spacing = ImGui::GetFontSize() / 3.0;
}
int rows = (numValues + cols - 1) / cols;
float inc = size + spacing;
@@ -73,12 +79,13 @@ void DrawLEDSources(const int* values, DataSource** sources, int numValues,
x += xinc;
}
}
if (values[i] > 0)
if (values[i] > 0) {
drawList->AddRectFilled(ImVec2(x, y), ImVec2(x + size, y + size),
colors[values[i] - 1]);
else if (values[i] < 0)
} else if (values[i] < 0) {
drawList->AddRect(ImVec2(x, y), ImVec2(x + size, y + size),
colors[-values[i] - 1], 0.0f, 0, 1.0);
}
if (sources) {
ImGui::SetCursorScreenPos(ImVec2(x - sized2, y - sized2));
if (sources[i]) {
@@ -97,7 +104,9 @@ void DrawLEDSources(const int* values, DataSource** sources, int numValues,
}
}
if (!sources) ImGui::Dummy(ImVec2(inc * cols, inc * rows));
if (!sources) {
ImGui::Dummy(ImVec2(inc * cols, inc * rows));
}
}
void DrawLEDs(const int* values, int numValues, int cols, const ImU32* colors,
@@ -120,15 +129,18 @@ bool DeleteButton(ImGuiID id, const ImVec2& pos) {
bool hovered, held;
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held);
if (is_clipped) return pressed;
if (is_clipped) {
return pressed;
}
// Render
ImU32 col =
ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered);
ImVec2 center = bb.GetCenter();
if (hovered)
if (hovered) {
window->DrawList->AddCircleFilled(
center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col, 12);
}
ImU32 cross_col = ImGui::GetColorU32(ImGuiCol_Text);
window->DrawList->AddCircle(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f),

View File

@@ -58,4 +58,6 @@ IniSaverBase::IniSaverBase(const wpi::Twine& typeName, IniSaverBackend* backend)
: m_typeName(typeName.str()),
m_backend{backend ? backend : GetSaverInstance()} {}
IniSaverBase::~IniSaverBase() { m_backend->Unregister(this); }
IniSaverBase::~IniSaverBase() {
m_backend->Unregister(this);
}

View File

@@ -75,7 +75,9 @@ void NameInfo::GetLabel(char* buf, size_t size, const char* defaultName,
}
bool NameInfo::ReadIni(wpi::StringRef name, wpi::StringRef value) {
if (name != "name") return false;
if (name != "name") {
return false;
}
size_t len = (std::min)(value.size(), sizeof(m_name) - 1);
std::memcpy(m_name, value.data(), len);
m_name[len] = '\0';
@@ -139,9 +141,13 @@ bool NameInfo::InputTextName(const char* label_id, ImGuiInputTextFlags flags) {
}
bool OpenInfo::ReadIni(wpi::StringRef name, wpi::StringRef value) {
if (name != "open") return false;
if (name != "open") {
return false;
}
int num;
if (value.getAsInteger(10, num)) return true;
if (value.getAsInteger(10, num)) {
return true;
}
m_open = num;
return true;
}
@@ -151,8 +157,12 @@ void OpenInfo::WriteIni(ImGuiTextBuffer* out) {
}
bool NameOpenInfo::ReadIni(wpi::StringRef name, wpi::StringRef value) {
if (NameInfo::ReadIni(name, value)) return true;
if (OpenInfo::ReadIni(name, value)) return true;
if (NameInfo::ReadIni(name, value)) {
return true;
}
if (OpenInfo::ReadIni(name, value)) {
return true;
}
return false;
}

View File

@@ -141,7 +141,9 @@ 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(wpi::StringRef str) {
PushID(str.begin(), str.end());
}
// push integer into the ID stack (will hash integer).
void PushID(int int_id);

View File

@@ -17,9 +17,11 @@ void Provider<Functions>::GlobalInit() {
template <typename Functions>
void Provider<Functions>::ShowDefault(wpi::StringRef name) {
auto win = GetWindow(name);
if (win) return;
if (win)
return;
auto it = FindViewEntry(name);
if (it == m_viewEntries.end() || (*it)->name != name) return;
if (it == m_viewEntries.end() || (*it)->name != name)
return;
this->Show(it->get(), (*it)->window);
}
@@ -36,7 +38,8 @@ void Provider<Functions>::RegisterModel(wpi::StringRef name, ExistsFunc exists,
CreateModelFunc createModel) {
auto it = FindModelEntry(name);
// ignore if exists
if (it != m_modelEntries.end() && (*it)->name == name) return;
if (it != m_modelEntries.end() && (*it)->name == name)
return;
// insert in sorted location
m_modelEntries.emplace(
it, MakeModelEntry(name, std::move(exists), std::move(createModel)));
@@ -49,11 +52,13 @@ void Provider<Functions>::RegisterView(wpi::StringRef name,
CreateViewFunc createView) {
// find model; if model doesn't exist, ignore
auto modelIt = FindModelEntry(modelName);
if (modelIt == m_modelEntries.end() || (*modelIt)->name != modelName) return;
if (modelIt == m_modelEntries.end() || (*modelIt)->name != modelName)
return;
auto viewIt = FindViewEntry(name);
// ignore if exists
if (viewIt != m_viewEntries.end() && (*viewIt)->name == name) return;
if (viewIt != m_viewEntries.end() && (*viewIt)->name == name)
return;
// insert in sorted location
m_viewEntries.emplace(viewIt,
MakeViewEntry(name, modelIt->get(), std::move(exists),
@@ -64,7 +69,8 @@ template <typename Functions>
void Provider<Functions>::Update() {
// update entries
for (auto&& entry : m_modelEntries) {
if (entry->model) entry->model->Update();
if (entry->model)
entry->model->Update();
}
}

View File

@@ -11,7 +11,8 @@ namespace glass {
template <typename Info>
void* IniSaver<Info>::IniReadOpen(const char* name) {
int num;
if (wpi::StringRef{name}.getAsInteger(10, num)) return nullptr;
if (wpi::StringRef{name}.getAsInteger(10, num))
return nullptr;
return &m_map[num];
}

View File

@@ -11,8 +11,10 @@ namespace glass {
template <typename Info>
void* IniSaverVector<Info>::IniReadOpen(const char* name) {
unsigned int num;
if (wpi::StringRef{name}.getAsInteger(10, num)) return nullptr;
if (num >= this->size()) this->resize(num + 1);
if (wpi::StringRef{name}.getAsInteger(10, num))
return nullptr;
if (num >= this->size())
this->resize(num + 1);
return &(*this)[num];
}

View File

@@ -27,22 +27,26 @@ NTCommandSchedulerModel::NTCommandSchedulerModel(NT_Inst instance,
}
void NTCommandSchedulerModel::CancelCommand(size_t index) {
if (index < m_idsValue.size())
if (index < m_idsValue.size()) {
nt::SetEntryValue(
m_cancel, nt::NetworkTableValue::MakeDoubleArray({m_idsValue[index]}));
}
}
void NTCommandSchedulerModel::Update() {
for (auto&& event : m_nt.PollListener()) {
if (event.entry == m_name) {
if (event.value && event.value->IsString())
if (event.value && event.value->IsString()) {
m_nameValue = event.value->GetString();
}
} else if (event.entry == m_commands) {
if (event.value && event.value->IsStringArray())
if (event.value && event.value->IsStringArray()) {
m_commandsValue = event.value->GetStringArray();
}
} else if (event.entry == m_ids) {
if (event.value && event.value->IsDoubleArray())
if (event.value && event.value->IsDoubleArray()) {
m_idsValue = event.value->GetDoubleArray();
}
}
}
}

View File

@@ -29,11 +29,13 @@ void NTCommandSelectorModel::SetRunning(bool run) {
void NTCommandSelectorModel::Update() {
for (auto&& event : m_nt.PollListener()) {
if (event.entry == m_running) {
if (event.value && event.value->IsBoolean())
if (event.value && event.value->IsBoolean()) {
m_runningData.SetValue(event.value->GetBoolean());
}
} else if (event.entry == m_name) {
if (event.value && event.value->IsString())
if (event.value && event.value->IsString()) {
m_nameValue = event.value->GetString();
}
}
}
}

View File

@@ -24,7 +24,9 @@ class NTField2DModel::GroupModel : public FieldObjectGroupModel {
void NTUpdate(const nt::Value& value);
void Update() override {
if (auto value = nt::GetEntryValue(m_entry)) NTUpdate(*value);
if (auto value = nt::GetEntryValue(m_entry)) {
NTUpdate(*value);
}
}
bool Exists() override { return nt::GetEntryType(m_entry) != NT_UNASSIGNED; }
bool IsReadOnly() override { return false; }
@@ -96,12 +98,14 @@ void NTField2DModel::GroupModel::NTUpdate(const nt::Value& value) {
m_count = arr.size() / 3;
if (m_count > m_objects.size()) {
m_objects.reserve(m_count);
for (size_t i = m_objects.size(); i < m_count; ++i)
for (size_t i = m_objects.size(); i < m_count; ++i) {
m_objects.emplace_back(std::make_unique<ObjectModel>(m_name, m_entry, i));
}
}
if (m_count < m_objects.size()) {
for (size_t i = m_count; i < m_objects.size(); ++i)
for (size_t i = m_count; i < m_objects.size(); ++i) {
m_objects[i]->SetExists(false);
}
}
for (size_t i = 0; i < m_count; ++i) {
@@ -139,19 +143,31 @@ void NTField2DModel::GroupModel::ObjectModel::SetPoseImpl(double x, double y,
bool setRot) {
// get from NT, validate type and size
auto value = nt::GetEntryValue(m_entry);
if (!value || !value->IsDoubleArray()) return;
if (!value || !value->IsDoubleArray()) {
return;
}
auto origArr = value->GetDoubleArray();
if (origArr.size() < static_cast<size_t>((m_index + 1) * 3)) return;
if (origArr.size() < static_cast<size_t>((m_index + 1) * 3)) {
return;
}
// copy existing array
wpi::SmallVector<double, 8> arr;
arr.reserve(origArr.size());
for (auto&& elem : origArr) arr.emplace_back(elem);
for (auto&& elem : origArr) {
arr.emplace_back(elem);
}
// update value
if (setX) arr[m_index * 3 + 0] = x;
if (setY) arr[m_index * 3 + 1] = y;
if (setRot) arr[m_index * 3 + 2] = rot;
if (setX) {
arr[m_index * 3 + 0] = x;
}
if (setY) {
arr[m_index * 3 + 1] = y;
}
if (setRot) {
arr[m_index * 3 + 2] = rot;
}
// set back to NT
nt::SetEntryValue(m_entry, nt::Value::MakeDoubleArray(arr));
@@ -194,19 +210,24 @@ void NTField2DModel::Update() {
// handle create/delete
if (wpi::StringRef{event.name}.startswith(m_path)) {
auto name = wpi::StringRef{event.name}.drop_front(m_path.size());
if (name.empty() || name[0] == '.') continue;
if (name.empty() || name[0] == '.') {
continue;
}
auto it = std::lower_bound(m_groups.begin(), m_groups.end(), name,
[](const auto& e, wpi::StringRef name) {
return e->GetName() < name;
});
bool match = (it != m_groups.end() && (*it)->GetName() == name);
if (event.flags & NT_NOTIFY_DELETE) {
if (match) m_groups.erase(it);
if (match) {
m_groups.erase(it);
}
continue;
} else if (event.flags & NT_NOTIFY_NEW) {
if (!match)
if (!match) {
it = m_groups.emplace(
it, std::make_unique<GroupModel>(event.name, event.entry));
}
} else if (!match) {
continue;
}
@@ -221,13 +242,16 @@ bool NTField2DModel::Exists() {
return m_nt.IsConnected() && nt::GetEntryType(m_name) != NT_UNASSIGNED;
}
bool NTField2DModel::IsReadOnly() { return false; }
bool NTField2DModel::IsReadOnly() {
return false;
}
void NTField2DModel::ForEachFieldObjectGroup(
wpi::function_ref<void(FieldObjectGroupModel& model, wpi::StringRef name)>
func) {
for (auto&& group : m_groups) {
if (group->Exists())
if (group->Exists()) {
func(*group, wpi::StringRef{group->GetName()}.drop_front(m_path.size()));
}
}
}

View File

@@ -23,11 +23,13 @@ NTGyroModel::NTGyroModel(NT_Inst instance, wpi::StringRef path)
void NTGyroModel::Update() {
for (auto&& event : m_nt.PollListener()) {
if (event.entry == m_angle) {
if (event.value && event.value->IsDouble())
if (event.value && event.value->IsDouble()) {
m_angleData.SetValue(event.value->GetDouble());
}
} else if (event.entry == m_name) {
if (event.value && event.value->IsString())
if (event.value && event.value->IsString()) {
m_nameValue = event.value->GetString();
}
}
}
}

View File

@@ -49,20 +49,25 @@ void NTPIDControllerModel::SetSetpoint(double value) {
void NTPIDControllerModel::Update() {
for (auto&& event : m_nt.PollListener()) {
if (event.entry == m_name) {
if (event.value && event.value->IsString())
if (event.value && event.value->IsString()) {
m_nameValue = event.value->GetString();
}
} else if (event.entry == m_p) {
if (event.value && event.value->IsDouble())
if (event.value && event.value->IsDouble()) {
m_pData.SetValue(event.value->GetDouble());
}
} else if (event.entry == m_i) {
if (event.value && event.value->IsDouble())
if (event.value && event.value->IsDouble()) {
m_iData.SetValue(event.value->GetDouble());
}
} else if (event.entry == m_d) {
if (event.value && event.value->IsDouble())
if (event.value && event.value->IsDouble()) {
m_dData.SetValue(event.value->GetDouble());
}
} else if (event.entry == m_setpoint) {
if (event.value && event.value->IsDouble())
if (event.value && event.value->IsDouble()) {
m_setpointData.SetValue(event.value->GetDouble());
}
}
}
}

View File

@@ -28,11 +28,13 @@ void NTSpeedControllerModel::SetPercent(double value) {
void NTSpeedControllerModel::Update() {
for (auto&& event : m_nt.PollListener()) {
if (event.entry == m_value) {
if (event.value && event.value->IsDouble())
if (event.value && event.value->IsDouble()) {
m_valueData.SetValue(event.value->GetDouble());
}
} else if (event.entry == m_name) {
if (event.value && event.value->IsString())
if (event.value && event.value->IsString()) {
m_nameValue = event.value->GetString();
}
}
}
}

View File

@@ -23,11 +23,13 @@ NTSubsystemModel::NTSubsystemModel(NT_Inst instance, wpi::StringRef path)
void NTSubsystemModel::Update() {
for (auto&& event : m_nt.PollListener()) {
if (event.entry == m_name) {
if (event.value && event.value->IsString())
if (event.value && event.value->IsString()) {
m_nameValue = event.value->GetString();
}
} else if (event.entry == m_defaultCommand) {
if (event.value && event.value->IsString())
if (event.value && event.value->IsString()) {
m_defaultCommandValue = event.value->GetString();
}
} else if (event.entry == m_currentCommand) {
if (event.value && event.value->IsString()) {
m_currentCommandValue = event.value->GetString();

View File

@@ -32,12 +32,15 @@ static std::string BooleanArrayToString(wpi::ArrayRef<int> in) {
os << '[';
bool first = true;
for (auto v : in) {
if (!first) os << ',';
if (!first) {
os << ',';
}
first = false;
if (v)
if (v) {
os << "true";
else
} else {
os << "false";
}
}
os << ']';
return rv;
@@ -49,7 +52,9 @@ static std::string DoubleArrayToString(wpi::ArrayRef<double> in) {
os << '[';
bool first = true;
for (auto v : in) {
if (!first) os << ',';
if (!first) {
os << ',';
}
first = false;
os << wpi::format("%.6f", v);
}
@@ -63,7 +68,9 @@ static std::string StringArrayToString(wpi::ArrayRef<std::string> in) {
os << '[';
bool first = true;
for (auto&& v : in) {
if (!first) os << ',';
if (!first) {
os << ',';
}
first = false;
os << '"';
os.write_escaped(v);
@@ -99,14 +106,16 @@ NetworkTablesModel::Entry::Entry(nt::EntryNotification&& event)
void NetworkTablesModel::Entry::UpdateValue() {
switch (value->type()) {
case NT_BOOLEAN:
if (!source)
if (!source) {
source = std::make_unique<DataSource>(wpi::Twine{"NT:"} + name);
}
source->SetValue(value->GetBoolean() ? 1 : 0);
source->SetDigital(true);
break;
case NT_DOUBLE:
if (!source)
if (!source) {
source = std::make_unique<DataSource>(wpi::Twine{"NT:"} + name);
}
source->SetValue(value->GetDouble());
source->SetDigital(false);
break;
@@ -136,12 +145,16 @@ void NetworkTablesModel::Update() {
updateTree = true;
}
}
if (!entry) continue;
if (!entry) {
continue;
}
if (event.flags & NT_NOTIFY_DELETE) {
auto it = std::find(m_sortedEntries.begin(), m_sortedEntries.end(),
entry.get());
// will be removed completely below
if (it != m_sortedEntries.end()) *it = nullptr;
if (it != m_sortedEntries.end()) {
*it = nullptr;
}
m_entries.erase(event.entry);
updateTree = true;
continue;
@@ -156,7 +169,9 @@ void NetworkTablesModel::Update() {
}
// shortcut common case (updates)
if (!updateTree) return;
if (!updateTree) {
return;
}
// remove deleted entries
m_sortedEntries.erase(
@@ -204,15 +219,22 @@ void NetworkTablesModel::Update() {
}
}
bool NetworkTablesModel::Exists() { return nt::IsConnected(m_inst); }
bool NetworkTablesModel::Exists() {
return nt::IsConnected(m_inst);
}
static std::shared_ptr<nt::Value> StringToBooleanArray(wpi::StringRef in) {
in = in.trim();
if (in.empty())
if (in.empty()) {
return nt::NetworkTableValue::MakeBooleanArray(
std::initializer_list<bool>{});
if (in.front() == '[') in = in.drop_front();
if (in.back() == ']') in = in.drop_back();
}
if (in.front() == '[') {
in = in.drop_front();
}
if (in.back() == ']') {
in = in.drop_back();
}
in = in.trim();
wpi::SmallVector<wpi::StringRef, 16> inSplit;
@@ -237,11 +259,16 @@ static std::shared_ptr<nt::Value> StringToBooleanArray(wpi::StringRef in) {
static std::shared_ptr<nt::Value> StringToDoubleArray(wpi::StringRef in) {
in = in.trim();
if (in.empty())
if (in.empty()) {
return nt::NetworkTableValue::MakeBooleanArray(
std::initializer_list<bool>{});
if (in.front() == '[') in = in.drop_front();
if (in.back() == ']') in = in.drop_back();
}
if (in.front() == '[') {
in = in.drop_front();
}
if (in.back() == ']') {
in = in.drop_back();
}
in = in.trim();
wpi::SmallVector<wpi::StringRef, 16> inSplit;
@@ -265,12 +292,13 @@ static std::shared_ptr<nt::Value> StringToDoubleArray(wpi::StringRef in) {
}
static int fromxdigit(char ch) {
if (ch >= 'a' && ch <= 'f')
if (ch >= 'a' && ch <= 'f') {
return (ch - 'a' + 10);
else if (ch >= 'A' && ch <= 'F')
} else if (ch >= 'A' && ch <= 'F') {
return (ch - 'A' + 10);
else
} else {
return ch - '0';
}
}
static wpi::StringRef UnescapeString(wpi::StringRef source,
@@ -313,11 +341,16 @@ static wpi::StringRef UnescapeString(wpi::StringRef source,
static std::shared_ptr<nt::Value> StringToStringArray(wpi::StringRef in) {
in = in.trim();
if (in.empty())
if (in.empty()) {
return nt::NetworkTableValue::MakeStringArray(
std::initializer_list<std::string>{});
if (in.front() == '[') in = in.drop_front();
if (in.back() == ']') in = in.drop_back();
}
if (in.front() == '[') {
in = in.drop_front();
}
if (in.back() == ']') {
in = in.drop_back();
}
in = in.trim();
wpi::SmallVector<wpi::StringRef, 16> inSplit;
@@ -327,7 +360,9 @@ static std::shared_ptr<nt::Value> StringToStringArray(wpi::StringRef in) {
in.split(inSplit, ',', -1, false);
for (auto val : inSplit) {
val = val.trim();
if (val.empty()) continue;
if (val.empty()) {
continue;
}
if (val.front() != '"' || val.back() != '"') {
wpi::errs() << "GUI: NetworkTables: Could not understand value '" << val
<< "'\n";
@@ -341,7 +376,9 @@ static std::shared_ptr<nt::Value> StringToStringArray(wpi::StringRef in) {
static void EmitEntryValueReadonly(NetworkTablesModel::Entry& entry) {
auto& val = entry.value;
if (!val) return;
if (!val) {
return;
}
switch (val->type()) {
case NT_BOOLEAN:
@@ -388,37 +425,43 @@ static char* GetTextBuffer(wpi::StringRef in) {
static void EmitEntryValueEditable(NetworkTablesModel::Entry& entry) {
auto& val = entry.value;
if (!val) return;
if (!val) {
return;
}
ImGui::PushID(entry.name.c_str());
switch (val->type()) {
case NT_BOOLEAN: {
static const char* boolOptions[] = {"false", "true"};
int v = val->GetBoolean() ? 1 : 0;
if (ImGui::Combo("boolean", &v, boolOptions, 2))
if (ImGui::Combo("boolean", &v, boolOptions, 2)) {
nt::SetEntryValue(entry.entry, nt::NetworkTableValue::MakeBoolean(v));
}
break;
}
case NT_DOUBLE: {
double v = val->GetDouble();
if (ImGui::InputDouble("double", &v, 0, 0, "%.6f",
ImGuiInputTextFlags_EnterReturnsTrue))
ImGuiInputTextFlags_EnterReturnsTrue)) {
nt::SetEntryValue(entry.entry, nt::NetworkTableValue::MakeDouble(v));
}
break;
}
case NT_STRING: {
char* v = GetTextBuffer(val->GetString());
if (ImGui::InputText("string", v, kTextBufferSize,
ImGuiInputTextFlags_EnterReturnsTrue))
ImGuiInputTextFlags_EnterReturnsTrue)) {
nt::SetEntryValue(entry.entry, nt::NetworkTableValue::MakeString(v));
}
break;
}
case NT_BOOLEAN_ARRAY: {
char* v = GetTextBuffer(entry.valueStr);
if (ImGui::InputText("boolean[]", v, kTextBufferSize,
ImGuiInputTextFlags_EnterReturnsTrue)) {
if (auto outv = StringToBooleanArray(v))
if (auto outv = StringToBooleanArray(v)) {
nt::SetEntryValue(entry.entry, std::move(outv));
}
}
break;
}
@@ -426,8 +469,9 @@ static void EmitEntryValueEditable(NetworkTablesModel::Entry& entry) {
char* v = GetTextBuffer(entry.valueStr);
if (ImGui::InputText("double[]", v, kTextBufferSize,
ImGuiInputTextFlags_EnterReturnsTrue)) {
if (auto outv = StringToDoubleArray(v))
if (auto outv = StringToDoubleArray(v)) {
nt::SetEntryValue(entry.entry, std::move(outv));
}
}
break;
}
@@ -435,8 +479,9 @@ static void EmitEntryValueEditable(NetworkTablesModel::Entry& entry) {
char* v = GetTextBuffer(entry.valueStr);
if (ImGui::InputText("string[]", v, kTextBufferSize,
ImGuiInputTextFlags_EnterReturnsTrue)) {
if (auto outv = StringToStringArray(v))
if (auto outv = StringToStringArray(v)) {
nt::SetEntryValue(entry.entry, std::move(outv));
}
}
break;
}
@@ -463,26 +508,29 @@ static void EmitEntry(NetworkTablesModel::Entry& entry, const char* name,
}
ImGui::NextColumn();
if (flags & NetworkTablesFlags_ReadOnly)
if (flags & NetworkTablesFlags_ReadOnly) {
EmitEntryValueReadonly(entry);
else
} else {
EmitEntryValueEditable(entry);
}
ImGui::NextColumn();
if (flags & NetworkTablesFlags_ShowFlags) {
if ((entry.flags & NT_PERSISTENT) != 0)
if ((entry.flags & NT_PERSISTENT) != 0) {
ImGui::Text("Persistent");
else if (entry.flags != 0)
} else if (entry.flags != 0) {
ImGui::Text("%02x", entry.flags);
}
ImGui::NextColumn();
}
if (flags & NetworkTablesFlags_ShowTimestamp) {
if (entry.value)
if (entry.value) {
ImGui::Text("%f", (entry.value->last_change() * 1.0e-6) -
(GetZeroTime() * 1.0e-6));
else
} else {
ImGui::TextUnformatted("");
}
ImGui::NextColumn();
}
ImGui::Separator();
@@ -500,8 +548,12 @@ static void EmitTree(const std::vector<NetworkTablesModel::TreeNode>& tree,
TreeNodeEx(node.name.c_str(), ImGuiTreeNodeFlags_SpanFullWidth);
ImGui::NextColumn();
ImGui::NextColumn();
if (flags & NetworkTablesFlags_ShowFlags) ImGui::NextColumn();
if (flags & NetworkTablesFlags_ShowTimestamp) ImGui::NextColumn();
if (flags & NetworkTablesFlags_ShowFlags) {
ImGui::NextColumn();
}
if (flags & NetworkTablesFlags_ShowTimestamp) {
ImGui::NextColumn();
}
ImGui::Separator();
if (open) {
EmitTree(node.children, flags);
@@ -543,7 +595,9 @@ void glass::DisplayNetworkTables(NetworkTablesModel* model,
ImGui::Columns();
}
if (!CollapsingHeader("Values", ImGuiTreeNodeFlags_DefaultOpen)) return;
if (!CollapsingHeader("Values", ImGuiTreeNodeFlags_DefaultOpen)) {
return;
}
}
const bool showFlags = (flags & NetworkTablesFlags_ShowFlags);
@@ -551,13 +605,17 @@ void glass::DisplayNetworkTables(NetworkTablesModel* model,
static bool first = true;
ImGui::Columns(2 + (showFlags ? 1 : 0) + (showTimestamp ? 1 : 0), "values");
if (first) ImGui::SetColumnWidth(-1, 0.5f * ImGui::GetWindowWidth());
if (first) {
ImGui::SetColumnWidth(-1, 0.5f * ImGui::GetWindowWidth());
}
ImGui::Text("Name");
ImGui::NextColumn();
ImGui::Text("Value");
ImGui::NextColumn();
if (showFlags) {
if (first) ImGui::SetColumnWidth(-1, 12 * ImGui::GetFontSize());
if (first) {
ImGui::SetColumnWidth(-1, 12 * ImGui::GetFontSize());
}
ImGui::Text("Flags");
ImGui::NextColumn();
}

View File

@@ -57,7 +57,9 @@ void NetworkTablesProvider::DisplayMenu() {
}
}
for (; depth > 0; --depth) ImGui::EndMenu();
for (; depth > 0; --depth) {
ImGui::EndMenu();
}
}
}
@@ -69,13 +71,16 @@ void NetworkTablesProvider::Update() {
// look for .type fields
wpi::StringRef eventName{event.name};
if (!eventName.endswith("/.type") || !event.value ||
!event.value->IsString())
!event.value->IsString()) {
continue;
}
auto tableName = eventName.drop_back(6);
// only handle ones where we have a builder
auto builderIt = m_typeMap.find(event.value->GetString());
if (builderIt == m_typeMap.end()) continue;
if (builderIt == m_typeMap.end()) {
continue;
}
if (event.flags & NT_NOTIFY_DELETE) {
auto it = std::find_if(
@@ -96,18 +101,26 @@ void NetworkTablesProvider::Update() {
// check for visible windows that need displays (typically this is due to
// file loading)
for (auto&& window : m_windows) {
if (!window->IsVisible() || window->HasView()) continue;
if (!window->IsVisible() || window->HasView()) {
continue;
}
auto id = window->GetId();
auto typeIt = m_typeCache.find(id);
if (typeIt == m_typeCache.end()) continue;
if (typeIt == m_typeCache.end()) {
continue;
}
// only handle ones where we have a builder
auto builderIt = m_typeMap.find(typeIt->second.GetName());
if (builderIt == m_typeMap.end()) continue;
if (builderIt == m_typeMap.end()) {
continue;
}
auto entry = GetOrCreateView(
builderIt->second, nt::GetEntry(m_nt.GetInstance(), id + "/.type"), id);
if (entry) Show(entry, window.get());
if (entry) {
Show(entry, window.get());
}
}
}
@@ -125,20 +138,29 @@ void NetworkTablesProvider::Show(ViewEntry* entry, Window* window) {
}
// get or create model
if (!entry->modelEntry->model)
if (!entry->modelEntry->model) {
entry->modelEntry->model =
entry->modelEntry->createModel(m_nt.GetInstance(), entry->name.c_str());
if (!entry->modelEntry->model) return;
}
if (!entry->modelEntry->model) {
return;
}
// the window might exist and we're just not associated to it yet
if (!window) window = GetOrAddWindow(entry->name, true);
if (!window) return;
if (!window) {
window = GetOrAddWindow(entry->name, true);
}
if (!window) {
return;
}
entry->window = window;
// create view
auto view = entry->createView(window, entry->modelEntry->model.get(),
entry->name.c_str());
if (!view) return;
if (!view) {
return;
}
window->SetView(std::move(view));
entry->window->SetVisible(true);

View File

@@ -123,7 +123,8 @@ static void writeRegister(Register reg, uint8_t data) {
// Execute and wait until it's done (up to a millisecond)
initialTime = HAL_GetFPGATime(&status);
while (accel->readSTAT(&status) & 1) {
if (HAL_GetFPGATime(&status) > initialTime + 1000) break;
if (HAL_GetFPGATime(&status) > initialTime + 1000)
break;
}
// Send a stop transmit/receive message with the data
@@ -134,7 +135,8 @@ static void writeRegister(Register reg, uint8_t data) {
// Execute and wait until it's done (up to a millisecond)
initialTime = HAL_GetFPGATime(&status);
while (accel->readSTAT(&status) & 1) {
if (HAL_GetFPGATime(&status) > initialTime + 1000) break;
if (HAL_GetFPGATime(&status) > initialTime + 1000)
break;
}
}
@@ -151,7 +153,8 @@ static uint8_t readRegister(Register reg) {
// Execute and wait until it's done (up to a millisecond)
initialTime = HAL_GetFPGATime(&status);
while (accel->readSTAT(&status) & 1) {
if (HAL_GetFPGATime(&status) > initialTime + 1000) break;
if (HAL_GetFPGATime(&status) > initialTime + 1000)
break;
}
// Receive a message with the data and stop
@@ -162,7 +165,8 @@ static uint8_t readRegister(Register reg) {
// Execute and wait until it's done (up to a millisecond)
initialTime = HAL_GetFPGATime(&status);
while (accel->readSTAT(&status) & 1) {
if (HAL_GetFPGATime(&status) > initialTime + 1000) break;
if (HAL_GetFPGATime(&status) > initialTime + 1000)
break;
}
return accel->readDATI(&status);

View File

@@ -25,7 +25,8 @@ HAL_Bool HAL_IsAccumulatorChannel(HAL_AnalogInputHandle analogPortHandle,
return false;
}
for (int32_t i = 0; i < kNumAccumulators; i++) {
if (port->channel == kAccumulatorChannels[i]) return true;
if (port->channel == kAccumulatorChannels[i])
return true;
}
return false;
}

View File

@@ -48,7 +48,9 @@ void InitializeAnalogGyro() {
} // namespace hal
static void Wait(double seconds) {
if (seconds < 0.0) return;
if (seconds < 0.0) {
return;
}
std::this_thread::sleep_for(std::chrono::duration<double>(seconds));
}
@@ -69,8 +71,9 @@ HAL_GyroHandle HAL_InitializeAnalogGyro(HAL_AnalogInputHandle analogHandle,
auto handle = analogGyroHandles->Allocate(channel, status);
if (*status != 0)
if (*status != 0) {
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
}
// Initialize port structure
auto gyro = analogGyroHandles->Get(handle);
@@ -97,17 +100,25 @@ void HAL_SetupAnalogGyro(HAL_GyroHandle handle, int32_t* status) {
gyro->voltsPerDegreePerSecond = kDefaultVoltsPerDegreePerSecond;
HAL_SetAnalogAverageBits(gyro->handle, kAverageBits, status);
if (*status != 0) return;
if (*status != 0) {
return;
}
HAL_SetAnalogOversampleBits(gyro->handle, kOversampleBits, status);
if (*status != 0) return;
if (*status != 0) {
return;
}
double sampleRate =
kSamplesPerSecond * (1 << (kAverageBits + kOversampleBits));
HAL_SetAnalogSampleRate(sampleRate, status);
if (*status != 0) return;
if (*status != 0) {
return;
}
Wait(0.1);
HAL_SetAnalogGyroDeadband(handle, 0.0, status);
if (*status != 0) return;
if (*status != 0) {
return;
}
}
void HAL_FreeAnalogGyro(HAL_GyroHandle handle) {
@@ -148,14 +159,18 @@ void HAL_ResetAnalogGyro(HAL_GyroHandle handle, int32_t* status) {
return;
}
HAL_ResetAccumulator(gyro->handle, status);
if (*status != 0) return;
if (*status != 0) {
return;
}
const double sampleTime = 1.0 / HAL_GetAnalogSampleRate(status);
const double overSamples =
1 << HAL_GetAnalogOversampleBits(gyro->handle, status);
const double averageSamples =
1 << HAL_GetAnalogAverageBits(gyro->handle, status);
if (*status != 0) return;
if (*status != 0) {
return;
}
Wait(sampleTime * overSamples * averageSamples);
}
@@ -167,7 +182,9 @@ void HAL_CalibrateAnalogGyro(HAL_GyroHandle handle, int32_t* status) {
}
HAL_InitAccumulator(gyro->handle, status);
if (*status != 0) return;
if (*status != 0) {
return;
}
wpi::outs() << "Calibrating analog gyro for " << kCalibrationSampleTime
<< " seconds." << '\n';
Wait(kCalibrationSampleTime);
@@ -175,7 +192,9 @@ void HAL_CalibrateAnalogGyro(HAL_GyroHandle handle, int32_t* status) {
int64_t value;
int64_t count;
HAL_GetAccumulatorOutput(gyro->handle, &value, &count, status);
if (*status != 0) return;
if (*status != 0) {
return;
}
gyro->center = static_cast<int32_t>(
static_cast<double>(value) / static_cast<double>(count) + 0.5);
@@ -183,7 +202,9 @@ void HAL_CalibrateAnalogGyro(HAL_GyroHandle handle, int32_t* status) {
gyro->offset = static_cast<double>(value) / static_cast<double>(count) -
static_cast<double>(gyro->center);
HAL_SetAccumulatorCenter(gyro->handle, gyro->center, status);
if (*status != 0) return;
if (*status != 0) {
return;
}
HAL_ResetAnalogGyro(handle, status);
}
@@ -197,7 +218,9 @@ void HAL_SetAnalogGyroDeadband(HAL_GyroHandle handle, double volts,
int32_t deadband = static_cast<int32_t>(
volts * 1e9 / HAL_GetAnalogLSBWeight(gyro->handle, status) *
(1 << HAL_GetAnalogOversampleBits(gyro->handle, status)));
if (*status != 0) return;
if (*status != 0) {
return;
}
HAL_SetAccumulatorDeadband(gyro->handle, deadband, status);
}

View File

@@ -28,7 +28,9 @@ HAL_AnalogInputHandle HAL_InitializeAnalogInputPort(HAL_PortHandle portHandle,
hal::init::CheckInit();
initializeAnalog(status);
if (*status != 0) return HAL_kInvalidHandle;
if (*status != 0) {
return HAL_kInvalidHandle;
}
int16_t channel = getPortHandleChannel(portHandle);
if (channel == InvalidHandleIndex) {
@@ -38,8 +40,9 @@ HAL_AnalogInputHandle HAL_InitializeAnalogInputPort(HAL_PortHandle portHandle,
HAL_AnalogInputHandle handle = analogInputHandles->Allocate(channel, status);
if (*status != 0)
if (*status != 0) {
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
}
// Initialize port structure
auto analog_port = analogInputHandles->Get(handle);
@@ -66,7 +69,9 @@ void HAL_FreeAnalogInputPort(HAL_AnalogInputHandle analogPortHandle) {
analogInputHandles->Free(analogPortHandle);
}
HAL_Bool HAL_CheckAnalogModule(int32_t module) { return module == 1; }
HAL_Bool HAL_CheckAnalogModule(int32_t module) {
return module == 1;
}
HAL_Bool HAL_CheckAnalogInputChannel(int32_t channel) {
return channel < kNumAnalogInputs && channel >= 0;
@@ -80,13 +85,17 @@ void HAL_SetAnalogSampleRate(double samplesPerSecond, int32_t* status) {
// TODO: Need double comparison with epsilon.
// wpi_assert(!sampleRateSet || GetSampleRate() == samplesPerSecond);
initializeAnalog(status);
if (*status != 0) return;
if (*status != 0) {
return;
}
setAnalogSampleRate(samplesPerSecond, status);
}
double HAL_GetAnalogSampleRate(int32_t* status) {
initializeAnalog(status);
if (*status != 0) return 0;
if (*status != 0) {
return 0;
}
uint32_t ticksPerConversion = analogInputSystem->readLoopTiming(status);
uint32_t ticksPerSample =
ticksPerConversion * getAnalogNumActiveChannels(status);

View File

@@ -40,9 +40,13 @@ void InitializeAnalogInternal() {
void initializeAnalog(int32_t* status) {
hal::init::CheckInit();
if (analogSystemInitialized) return;
if (analogSystemInitialized) {
return;
}
std::scoped_lock lock(analogRegisterWindowMutex);
if (analogSystemInitialized) return;
if (analogSystemInitialized) {
return;
}
analogInputSystem.reset(tAI::create(status));
analogOutputSystem.reset(tAO::create(status));
setAnalogNumChannelsToActivate(kNumAnalogInputs);
@@ -52,7 +56,9 @@ void initializeAnalog(int32_t* status) {
int32_t getAnalogNumActiveChannels(int32_t* status) {
int32_t scanSize = analogInputSystem->readConfig_ScanSize(status);
if (scanSize == 0) return 8;
if (scanSize == 0) {
return 8;
}
return scanSize;
}
@@ -61,8 +67,9 @@ void setAnalogNumChannelsToActivate(int32_t channels) {
}
int32_t getAnalogNumChannelsToActivate(int32_t* status) {
if (analogNumChannelsToActivate == 0)
if (analogNumChannelsToActivate == 0) {
return getAnalogNumActiveChannels(status);
}
return analogNumChannelsToActivate;
}
@@ -79,7 +86,9 @@ void setAnalogSampleRate(double samplesPerSecond, int32_t* status) {
ticksPerSample / getAnalogNumChannelsToActivate(status);
// ticksPerConversion must be at least 80
if (ticksPerConversion < 80) {
if ((*status) >= 0) *status = SAMPLE_RATE_TOO_HIGH;
if ((*status) >= 0) {
*status = SAMPLE_RATE_TOO_HIGH;
}
ticksPerConversion = 80;
}

View File

@@ -43,7 +43,9 @@ HAL_AnalogOutputHandle HAL_InitializeAnalogOutputPort(HAL_PortHandle portHandle,
hal::init::CheckInit();
initializeAnalog(status);
if (*status != 0) return HAL_kInvalidHandle;
if (*status != 0) {
return HAL_kInvalidHandle;
}
int16_t channel = getPortHandleChannel(portHandle);
if (channel == InvalidHandleIndex) {
@@ -54,8 +56,9 @@ HAL_AnalogOutputHandle HAL_InitializeAnalogOutputPort(HAL_PortHandle portHandle,
HAL_AnalogOutputHandle handle =
analogOutputHandles->Allocate(channel, status);
if (*status != 0)
if (*status != 0) {
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
}
auto port = analogOutputHandles->Get(handle);
if (port == nullptr) { // would only error on thread issue
@@ -82,10 +85,11 @@ void HAL_SetAnalogOutput(HAL_AnalogOutputHandle analogOutputHandle,
uint16_t rawValue = static_cast<uint16_t>(voltage / 5.0 * 0x1000);
if (voltage < 0.0)
if (voltage < 0.0) {
rawValue = 0;
else if (voltage > 5.0)
} else if (voltage > 5.0) {
rawValue = 0x1000;
}
analogOutputSystem->writeMXP(port->channel, rawValue, status);
}

View File

@@ -359,10 +359,11 @@ void HAL_SetCounterReverseDirection(HAL_CounterHandle counterHandle,
}
if (counter->counter->readConfig_Mode(status) ==
HAL_Counter_kExternalDirection) {
if (reverseDirection)
if (reverseDirection) {
HAL_SetCounterDownSourceEdge(counterHandle, true, true, status);
else
} else {
HAL_SetCounterDownSourceEdge(counterHandle, false, true, status);
}
}
}

Some files were not shown because too many files have changed in this diff Show More