Use std::string_view and fmtlib across all libraries (#3402)

- Twine, StringRef, Format, and NativeFormatting have been removed
- Logging now uses fmtlib style formatting
- Nearly all uses of wpi::outs/errs have been replaced with fmt::print() or
std::puts()/std::fputs() (for unformatted strings).
- A wpi/fmt/raw_ostream.h header has been added to enable
fmt::print() with wpi::raw_ostream
This commit is contained in:
Peter Johnson
2021-06-06 16:13:58 -07:00
committed by GitHub
parent 4f1cecb8e7
commit b2c3b2dd8e
441 changed files with 5061 additions and 9749 deletions

View File

@@ -70,15 +70,15 @@ void NetworkListener::Impl::Thread::Main() {
// Create event socket so we can be shut down
m_command_fd = ::eventfd(0, 0);
if (m_command_fd < 0) {
ERROR(
"NetworkListener: could not create eventfd: " << std::strerror(errno));
ERROR("NetworkListener: could not create eventfd: {}",
std::strerror(errno));
return;
}
// Create netlink socket
int sd = ::socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (sd < 0) {
ERROR("NetworkListener: could not create socket: " << std::strerror(errno));
ERROR("NetworkListener: could not create socket: {}", std::strerror(errno));
::close(m_command_fd);
m_command_fd = -1;
return;
@@ -90,7 +90,7 @@ void NetworkListener::Impl::Thread::Main() {
addr.nl_family = AF_NETLINK;
addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
if (bind(sd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
ERROR("NetworkListener: could not create socket: " << std::strerror(errno));
ERROR("NetworkListener: could not create socket: {}", std::strerror(errno));
::close(sd);
::close(m_command_fd);
m_command_fd = -1;
@@ -113,7 +113,7 @@ void NetworkListener::Impl::Thread::Main() {
int nfds = std::max(m_command_fd, sd) + 1;
if (::select(nfds, &readfds, nullptr, nullptr, &tv) < 0) {
ERROR("NetworkListener: select(): " << std::strerror(errno));
ERROR("NetworkListener: select(): {}", std::strerror(errno));
break; // XXX: is this the right thing to do here?
}
@@ -134,8 +134,8 @@ void NetworkListener::Impl::Thread::Main() {
if (errno == EWOULDBLOCK || errno == EAGAIN) {
continue;
}
ERROR(
"NetworkListener: could not read netlink: " << std::strerror(errno));
ERROR("NetworkListener: could not read netlink: {}",
std::strerror(errno));
break; // XXX: is this the right thing to do here?
}
if (len == 0) {

View File

@@ -22,8 +22,10 @@
#include <algorithm>
#include <memory>
#include <fmt/format.h>
#include <wpi/MemAlloc.h>
#include <wpi/SmallString.h>
#include <wpi/StringExtras.h>
#include <wpi/fs.h>
#include <wpi/raw_ostream.h>
#include <wpi/timestamp.h>
@@ -95,8 +97,8 @@ static __u32 FromPixelFormat(VideoMode::PixelFormat pixelFormat) {
}
}
static bool IsPercentageProperty(wpi::StringRef name) {
if (name.startswith("raw_")) {
static bool IsPercentageProperty(std::string_view name) {
if (wpi::starts_with(name, "raw_")) {
name = name.substr(4);
}
return name == "brightness" || name == "contrast" || name == "saturation" ||
@@ -154,11 +156,8 @@ int UsbCameraImpl::PercentageToRaw(const UsbCameraProperty& rawProp,
}
static bool GetVendorProduct(int dev, int* vendor, int* product) {
wpi::SmallString<64> ifpath;
{
wpi::raw_svector_ostream oss{ifpath};
oss << "/sys/class/video4linux/video" << dev << "/device/modalias";
}
auto ifpath =
fmt::format("/sys/class/video4linux/video{}/device/modalias", dev);
int fd = open(ifpath.c_str(), O_RDONLY);
if (fd < 0) {
@@ -172,15 +171,17 @@ static bool GetVendorProduct(int dev, int* vendor, int* product) {
if (n <= 0) {
return false;
}
wpi::StringRef readStr{readBuf};
if (readStr.substr(readStr.find('v'))
.substr(1, 4)
.getAsInteger(16, *vendor)) {
std::string_view readStr{readBuf};
if (auto v = wpi::parse_integer<int>(
readStr.substr(readStr.find('v')).substr(1, 4), 16)) {
*vendor = v.value();
} else {
return false;
}
if (readStr.substr(readStr.find('p'))
.substr(1, 4)
.getAsInteger(16, *product)) {
if (auto v = wpi::parse_integer<int>(
readStr.substr(readStr.find('p')).substr(1, 4), 16)) {
*product = v.value();
} else {
return false;
}
@@ -188,11 +189,8 @@ static bool GetVendorProduct(int dev, int* vendor, int* product) {
}
static bool GetDescriptionSysV4L(int dev, std::string* desc) {
wpi::SmallString<64> ifpath;
{
wpi::raw_svector_ostream oss{ifpath};
oss << "/sys/class/video4linux/video" << dev << "/device/interface";
}
auto ifpath =
fmt::format("/sys/class/video4linux/video{}/device/interface", dev);
int fd = open(ifpath.c_str(), O_RDONLY);
if (fd < 0) {
@@ -207,7 +205,7 @@ static bool GetDescriptionSysV4L(int dev, std::string* desc) {
return false;
}
*desc = wpi::StringRef(readBuf, n).rtrim();
*desc = wpi::rtrim(std::string_view(readBuf, n));
return true;
}
@@ -225,17 +223,16 @@ static bool GetDescriptionIoctl(const char* cpath, std::string* desc) {
}
close(fd);
wpi::StringRef card{reinterpret_cast<const char*>(vcap.card)};
std::string_view card{reinterpret_cast<const char*>(vcap.card)};
// try to convert "UVC Camera (0000:0000)" into a better name
int vendor = 0;
int product = 0;
if (card.startswith("UVC Camera (") &&
!card.substr(12, 4).getAsInteger(16, vendor) &&
!card.substr(17, 4).getAsInteger(16, product)) {
wpi::SmallString<64> card2Buf;
wpi::StringRef card2 = GetUsbNameFromId(vendor, product, card2Buf);
std::optional<int> vendor;
std::optional<int> product;
if (wpi::starts_with(card, "UVC Camera (") &&
(vendor = wpi::parse_integer<int>(card.substr(12, 4), 16)) &&
(product = wpi::parse_integer<int>(card.substr(17, 4), 16))) {
std::string card2 = GetUsbNameFromId(vendor.value(), product.value());
if (!card2.empty()) {
*desc = card2;
*desc = std::move(card2);
return true;
}
}
@@ -274,15 +271,14 @@ static int GetDeviceNum(const char* cpath) {
path = fs::canonical(path);
}
auto fn = path.filename();
if (!wpi::StringRef{fn}.startswith("video")) {
std::string fn = path.filename();
if (!wpi::starts_with(fn, "video")) {
return -1;
}
int dev = -1;
if (wpi::StringRef{fn}.substr(5).getAsInteger(10, dev)) {
return -1;
if (auto dev = wpi::parse_integer<int>(fn.substr(5), 10)) {
return dev.value();
}
return dev;
return -1;
}
static std::string GetDescriptionImpl(const char* cpath) {
@@ -304,14 +300,14 @@ static std::string GetDescriptionImpl(const char* cpath) {
return std::string{};
}
UsbCameraImpl::UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger,
UsbCameraImpl::UsbCameraImpl(std::string_view name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
const wpi::Twine& path)
std::string_view path)
: SourceImpl{name, logger, notifier, telemetry},
m_fd{-1},
m_command_fd{eventfd(0, 0)},
m_active{true},
m_path{path.str()} {
m_path{path} {
SetDescription(GetDescriptionImpl(m_path.c_str()));
SetQuirks();
@@ -439,7 +435,7 @@ void UsbCameraImpl::CameraThreadMain() {
DoFdSet(notify_fd, &readfds, &nfds);
if (select(nfds, &readfds, nullptr, nullptr, &tv) < 0) {
SERROR("select(): " << std::strerror(errno));
SERROR("select(): {}", std::strerror(errno));
break; // XXX: is this the right thing to do here?
}
@@ -450,7 +446,7 @@ void UsbCameraImpl::CameraThreadMain() {
// Handle notify events
if (notify_fd >= 0 && FD_ISSET(notify_fd, &readfds)) {
SDEBUG4("notify event");
SDEBUG4("{}", "notify event");
struct inotify_event event;
do {
// Read the event structure
@@ -460,10 +456,9 @@ void UsbCameraImpl::CameraThreadMain() {
raw_name.resize(event.len);
notify_is->read(raw_name.data(), event.len);
// If the name is what we expect...
wpi::StringRef name{raw_name.c_str()};
SDEBUG4("got event on '" << name << "' (" << name.size()
<< ") compare to '" << base << "' ("
<< base.size() << ") mask " << event.mask);
std::string_view name{raw_name.c_str()};
SDEBUG4("got event on '{}' ({}) compare to '{}' ({}) mask {}", name,
name.size(), base, base.size(), event.mask);
if (name == base) {
if ((event.mask & IN_DELETE) != 0) {
wasStreaming = m_streaming;
@@ -480,7 +475,7 @@ void UsbCameraImpl::CameraThreadMain() {
// Handle commands
if (command_fd >= 0 && FD_ISSET(command_fd, &readfds)) {
SDEBUG4("got command");
SDEBUG4("{}", "got command");
// Read it to clear
eventfd_t val;
eventfd_read(command_fd, &val);
@@ -490,7 +485,7 @@ void UsbCameraImpl::CameraThreadMain() {
// Handle frames
if (m_streaming && fd >= 0 && FD_ISSET(fd, &readfds)) {
SDEBUG4("grabbing image");
SDEBUG4("{}", "grabbing image");
// Dequeue buffer
struct v4l2_buffer buf;
@@ -498,7 +493,7 @@ void UsbCameraImpl::CameraThreadMain() {
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (DoIoctl(fd, VIDIOC_DQBUF, &buf) != 0) {
SWARNING("could not dequeue buffer");
SWARNING("{}", "could not dequeue buffer");
wasStreaming = m_streaming;
DeviceStreamOff();
DeviceDisconnect();
@@ -507,14 +502,14 @@ void UsbCameraImpl::CameraThreadMain() {
}
if ((buf.flags & V4L2_BUF_FLAG_ERROR) == 0) {
SDEBUG4("got image size=" << buf.bytesused << " index=" << buf.index);
SDEBUG4("got image size={} index={}", buf.bytesused, buf.index);
if (buf.index >= kNumBuffers || !m_buffers[buf.index].m_data) {
SWARNING("invalid buffer" << buf.index);
SWARNING("invalid buffer {}", buf.index);
continue;
}
wpi::StringRef image{
std::string_view image{
static_cast<const char*>(m_buffers[buf.index].m_data),
static_cast<size_t>(buf.bytesused)};
int width = m_mode.width;
@@ -522,7 +517,7 @@ void UsbCameraImpl::CameraThreadMain() {
bool good = true;
if (m_mode.pixelFormat == VideoMode::kMJPEG &&
!GetJpegSize(image, &width, &height)) {
SWARNING("invalid JPEG image received from camera");
SWARNING("{}", "invalid JPEG image received from camera");
good = false;
}
if (good) {
@@ -533,7 +528,7 @@ void UsbCameraImpl::CameraThreadMain() {
// Requeue buffer
if (DoIoctl(fd, VIDIOC_QBUF, &buf) != 0) {
SWARNING("could not requeue buffer");
SWARNING("{}", "could not requeue buffer");
wasStreaming = m_streaming;
DeviceStreamOff();
DeviceDisconnect();
@@ -572,11 +567,11 @@ void UsbCameraImpl::DeviceConnect() {
}
if (m_connectVerbose) {
SINFO("Connecting to USB camera on " << m_path);
SINFO("Connecting to USB camera on {}", m_path);
}
// Try to open the device
SDEBUG3("opening device");
SDEBUG3("{}", "opening device");
int fd = open(m_path.c_str(), O_RDWR);
if (fd < 0) {
return;
@@ -584,7 +579,7 @@ void UsbCameraImpl::DeviceConnect() {
m_fd = fd;
// Get capabilities
SDEBUG3("getting capabilities");
SDEBUG3("{}", "getting capabilities");
struct v4l2_capability vcap;
std::memset(&vcap, 0, sizeof(vcap));
if (DoIoctl(fd, VIDIOC_QUERYCAP, &vcap) >= 0) {
@@ -596,18 +591,18 @@ void UsbCameraImpl::DeviceConnect() {
// Get or restore video mode
if (!m_properties_cached) {
SDEBUG3("caching properties");
SDEBUG3("{}", "caching properties");
DeviceCacheProperties();
DeviceCacheVideoModes();
DeviceCacheMode();
m_properties_cached = true;
} else {
SDEBUG3("restoring video mode");
SDEBUG3("{}", "restoring video mode");
DeviceSetMode();
DeviceSetFPS();
// Restore settings
SDEBUG3("restoring settings");
SDEBUG3("{}", "restoring settings");
std::unique_lock lock2(m_mutex);
for (size_t i = 0; i < m_propertyData.size(); ++i) {
const auto prop =
@@ -616,27 +611,27 @@ void UsbCameraImpl::DeviceConnect() {
continue;
}
if (!prop->DeviceSet(lock2, m_fd)) {
SWARNING("failed to set property " << prop->name);
SWARNING("failed to set property {}", prop->name);
}
}
}
// Request buffers
SDEBUG3("allocating buffers");
SDEBUG3("{}", "allocating buffers");
struct v4l2_requestbuffers rb;
std::memset(&rb, 0, sizeof(rb));
rb.count = kNumBuffers;
rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
rb.memory = V4L2_MEMORY_MMAP;
if (DoIoctl(fd, VIDIOC_REQBUFS, &rb) != 0) {
SWARNING("could not allocate buffers");
SWARNING("{}", "could not allocate buffers");
close(fd);
m_fd = -1;
return;
}
// Map buffers
SDEBUG3("mapping buffers");
SDEBUG3("{}", "mapping buffers");
for (int i = 0; i < kNumBuffers; ++i) {
struct v4l2_buffer buf;
std::memset(&buf, 0, sizeof(buf));
@@ -644,17 +639,16 @@ void UsbCameraImpl::DeviceConnect() {
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (DoIoctl(fd, VIDIOC_QUERYBUF, &buf) != 0) {
SWARNING("could not query buffer " << i);
SWARNING("could not query buffer {}", i);
close(fd);
m_fd = -1;
return;
}
SDEBUG4("buf " << i << " length=" << buf.length
<< " offset=" << buf.m.offset);
SDEBUG4("buf {} length={} offset={}", i, buf.length, buf.m.offset);
m_buffers[i] = UsbCameraBuffer(fd, buf.length, buf.m.offset);
if (!m_buffers[i].m_data) {
SWARNING("could not map buffer " << i);
SWARNING("could not map buffer {}", i);
// release other buffers
for (int j = 0; j < i; ++j) {
m_buffers[j] = UsbCameraBuffer{};
@@ -664,7 +658,7 @@ void UsbCameraImpl::DeviceConnect() {
return;
}
SDEBUG4("buf " << i << " address=" << m_buffers[i].m_data);
SDEBUG4("buf {} address={}", i, m_buffers[i].m_data);
}
// Update description (as it may have changed)
@@ -687,7 +681,7 @@ bool UsbCameraImpl::DeviceStreamOn() {
}
// Queue buffers
SDEBUG3("queuing buffers");
SDEBUG3("{}", "queuing buffers");
for (int i = 0; i < kNumBuffers; ++i) {
struct v4l2_buffer buf;
std::memset(&buf, 0, sizeof(buf));
@@ -695,7 +689,7 @@ bool UsbCameraImpl::DeviceStreamOn() {
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (DoIoctl(fd, VIDIOC_QBUF, &buf) != 0) {
SWARNING("could not queue buffer " << i);
SWARNING("could not queue buffer {}", i);
return false;
}
}
@@ -706,16 +700,17 @@ bool UsbCameraImpl::DeviceStreamOn() {
if (errno == ENOSPC) {
// indicates too much USB bandwidth requested
SERROR(
"{}",
"could not start streaming due to USB bandwidth limitations; try a "
"lower resolution or a different pixel format (VIDIOC_STREAMON: "
"No space left on device)");
} else {
// some other error
SERROR("ioctl VIDIOC_STREAMON failed: " << std::strerror(errno));
SERROR("ioctl VIDIOC_STREAMON failed: {}", std::strerror(errno));
}
return false;
}
SDEBUG4("enabled streaming");
SDEBUG4("{}", "enabled streaming");
m_streaming = true;
return true;
}
@@ -732,7 +727,7 @@ bool UsbCameraImpl::DeviceStreamOff() {
if (DoIoctl(fd, VIDIOC_STREAMOFF, &type) != 0) {
return false;
}
SDEBUG4("disabled streaming");
SDEBUG4("{}", "disabled streaming");
m_streaming = false;
return true;
}
@@ -806,7 +801,7 @@ CS_StatusValue UsbCameraImpl::DeviceCmdSetProperty(
bool setString = (msg.kind == Message::kCmdSetPropertyStr);
int property = msg.data[0];
int value = msg.data[1];
wpi::StringRef valueStr = msg.dataStr;
std::string_view valueStr = msg.dataStr;
// Look up
auto prop = static_cast<UsbCameraProperty*>(GetProperty(property));
@@ -940,19 +935,19 @@ void UsbCameraImpl::DeviceSetMode() {
vfmt.fmt.pix.pixelformat =
FromPixelFormat(static_cast<VideoMode::PixelFormat>(m_mode.pixelFormat));
if (vfmt.fmt.pix.pixelformat == 0) {
SWARNING("could not set format " << m_mode.pixelFormat
<< ", defaulting to MJPEG");
SWARNING("could not set format {}, defaulting to MJPEG",
m_mode.pixelFormat);
vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
}
vfmt.fmt.pix.width = m_mode.width;
vfmt.fmt.pix.height = m_mode.height;
vfmt.fmt.pix.field = V4L2_FIELD_ANY;
if (DoIoctl(fd, VIDIOC_S_FMT, &vfmt) != 0) {
SWARNING("could not set format " << m_mode.pixelFormat << " res "
<< m_mode.width << "x" << m_mode.height);
SWARNING("could not set format {} res {}x{}", m_mode.pixelFormat,
m_mode.width, m_mode.height);
} else {
SINFO("set format " << m_mode.pixelFormat << " res " << m_mode.width << "x"
<< m_mode.height);
SINFO("set format {} res {}x{}", m_mode.pixelFormat, m_mode.width,
m_mode.height);
}
}
@@ -975,9 +970,9 @@ void UsbCameraImpl::DeviceSetFPS() {
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
parm.parm.capture.timeperframe = FPSToFract(m_mode.fps);
if (DoIoctl(fd, VIDIOC_S_PARM, &parm) != 0) {
SWARNING("could not set FPS to " << m_mode.fps);
SWARNING("could not set FPS to {}", m_mode.fps);
} else {
SINFO("set FPS to " << m_mode.fps);
SINFO("set FPS to {}", m_mode.fps);
}
}
@@ -997,7 +992,7 @@ void UsbCameraImpl::DeviceCacheMode() {
#endif
vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (DoIoctl(fd, VIDIOC_G_FMT, &vfmt) != 0) {
SERROR("could not read current video mode");
SERROR("{}", "could not read current video mode");
std::scoped_lock lock(m_mutex);
m_mode = VideoMode{VideoMode::kMJPEG, 320, 240, 30};
return;
@@ -1133,7 +1128,7 @@ void UsbCameraImpl::DeviceCacheProperty(
} else {
// Read current raw value and set percentage from it
if (!rawProp->DeviceGet(lock, m_fd)) {
SWARNING("failed to get property " << rawProp->name);
SWARNING("failed to get property {}", rawProp->name);
}
if (perProp) {
@@ -1145,7 +1140,7 @@ void UsbCameraImpl::DeviceCacheProperty(
// Set value on device if user-configured
if (rawProp->valueSet) {
if (!rawProp->DeviceSet(lock, m_fd)) {
SWARNING("failed to set property " << rawProp->name);
SWARNING("failed to set property {}", rawProp->name);
}
}
@@ -1360,7 +1355,7 @@ void UsbCameraImpl::Send(Message&& msg) const {
}
std::unique_ptr<PropertyImpl> UsbCameraImpl::CreateEmptyProperty(
const wpi::Twine& name) const {
std::string_view name) const {
return std::make_unique<UsbCameraProperty>(name);
}
@@ -1379,10 +1374,10 @@ bool UsbCameraImpl::CacheProperties(CS_Status* status) const {
void UsbCameraImpl::SetQuirks() {
wpi::SmallString<128> descbuf;
wpi::StringRef desc = GetDescription(descbuf);
m_lifecam_exposure =
desc.endswith("LifeCam HD-3000") || desc.endswith("LifeCam Cinema (TM)");
m_picamera = desc.startswith("mmal service");
std::string_view desc = GetDescription(descbuf);
m_lifecam_exposure = wpi::ends_with(desc, "LifeCam HD-3000") ||
wpi::ends_with(desc, "LifeCam Cinema (TM)");
m_picamera = wpi::ends_with(desc, "mmal service");
int deviceNum = GetDeviceNum(m_path.c_str());
if (deviceNum >= 0) {
@@ -1400,11 +1395,11 @@ void UsbCameraImpl::SetProperty(int property, int value, CS_Status* status) {
*status = SendAndWait(std::move(msg));
}
void UsbCameraImpl::SetStringProperty(int property, const wpi::Twine& value,
void UsbCameraImpl::SetStringProperty(int property, std::string_view value,
CS_Status* status) {
Message msg{Message::kCmdSetPropertyStr};
msg.data[0] = property;
msg.dataStr = value.str();
msg.dataStr = value;
*status = SendAndWait(std::move(msg));
}
@@ -1524,9 +1519,9 @@ void UsbCameraImpl::NumSinksEnabledChanged() {
Send(Message{Message::kNumSinksEnabledChanged});
}
void UsbCameraImpl::SetPath(const wpi::Twine& path, CS_Status* status) {
void UsbCameraImpl::SetPath(std::string_view path, CS_Status* status) {
Message msg{Message::kCmdSetPath};
msg.dataStr = path.str();
msg.dataStr = path;
*status = SendAndWait(std::move(msg));
}
@@ -1537,15 +1532,12 @@ std::string UsbCameraImpl::GetPath() const {
namespace cs {
CS_Source CreateUsbCameraDev(const wpi::Twine& name, int dev,
CS_Source CreateUsbCameraDev(std::string_view name, int dev,
CS_Status* status) {
wpi::SmallString<32> path;
wpi::raw_svector_ostream oss{path};
oss << "/dev/video" << dev;
return CreateUsbCameraPath(name, oss.str(), status);
return CreateUsbCameraPath(name, fmt::format("/dev/video{}", dev), status);
}
CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path,
CS_Source CreateUsbCameraPath(std::string_view name, std::string_view path,
CS_Status* status) {
auto& inst = Instance::GetInstance();
return inst.CreateSource(CS_SOURCE_USB, std::make_shared<UsbCameraImpl>(
@@ -1553,7 +1545,7 @@ CS_Source CreateUsbCameraPath(const wpi::Twine& name, const wpi::Twine& path,
inst.telemetry, path));
}
void SetUsbCameraPath(CS_Source source, const wpi::Twine& path,
void SetUsbCameraPath(CS_Source source, std::string_view path,
CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data || data->kind != CS_SOURCE_USB) {
@@ -1629,13 +1621,15 @@ std::vector<UsbCameraInfo> EnumerateUsbCameras(CS_Status* status) {
if (DIR* dp = ::opendir("/dev")) {
while (struct dirent* ep = ::readdir(dp)) {
wpi::StringRef fname{ep->d_name};
if (!fname.startswith("video")) {
std::string_view fname{ep->d_name};
if (!wpi::starts_with(fname, "video")) {
continue;
}
unsigned int dev = 0;
if (fname.substr(5).getAsInteger(10, dev)) {
if (auto v = wpi::parse_integer<unsigned int>(fname.substr(5), 10)) {
dev = v.value();
} else {
continue;
}
@@ -1665,7 +1659,7 @@ std::vector<UsbCameraInfo> EnumerateUsbCameras(CS_Status* status) {
::closedir(dp);
} else {
// *status = ;
WPI_ERROR(Instance::GetInstance().logger, "Could not open /dev");
WPI_ERROR(Instance::GetInstance().logger, "{}", "Could not open /dev");
return retval;
}
@@ -1682,11 +1676,11 @@ std::vector<UsbCameraInfo> EnumerateUsbCameras(CS_Status* status) {
char* target = ::realpath(path.c_str(), nullptr);
if (target) {
std::string fname = fs::path{target}.filename();
unsigned int dev = 0;
if (wpi::StringRef{fname}.startswith("video") &&
!wpi::StringRef{fname}.substr(5).getAsInteger(10, dev) &&
dev < retval.size()) {
retval[dev].otherPaths.emplace_back(path.str());
std::optional<unsigned int> dev;
if (wpi::starts_with(fname, "video") &&
(dev = wpi::parse_integer<unsigned int>(fname.substr(5), 10)) &&
dev.value() < retval.size()) {
retval[dev.value()].otherPaths.emplace_back(path.str());
}
std::free(target);
}

View File

@@ -10,13 +10,13 @@
#include <atomic>
#include <memory>
#include <string>
#include <string_view>
#include <thread>
#include <utility>
#include <vector>
#include <wpi/STLExtras.h>
#include <wpi/SmallVector.h>
#include <wpi/Twine.h>
#include <wpi/condition_variable.h>
#include <wpi/mutex.h>
#include <wpi/raw_istream.h>
@@ -33,15 +33,15 @@ class Telemetry;
class UsbCameraImpl : public SourceImpl {
public:
UsbCameraImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry, const wpi::Twine& path);
UsbCameraImpl(std::string_view name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry, std::string_view path);
~UsbCameraImpl() override;
void Start() override;
// Property functions
void SetProperty(int property, int value, CS_Status* status) override;
void SetStringProperty(int property, const wpi::Twine& value,
void SetStringProperty(int property, std::string_view value,
CS_Status* status) override;
// Standard common camera properties
@@ -63,7 +63,7 @@ class UsbCameraImpl : public SourceImpl {
void NumSinksChanged() override;
void NumSinksEnabledChanged() override;
void SetPath(const wpi::Twine& path, CS_Status* status);
void SetPath(std::string_view path, CS_Status* status);
std::string GetPath() const;
// Messages passed to/from camera thread
@@ -95,7 +95,7 @@ class UsbCameraImpl : public SourceImpl {
protected:
std::unique_ptr<PropertyImpl> CreateEmptyProperty(
const wpi::Twine& name) const override;
std::string_view name) const override;
// Cache properties. Immediately successful if properties are already cached.
// If they are not, tries to connect to the camera to do so; returns false and

View File

@@ -5,6 +5,7 @@
#include "UsbCameraListener.h"
#include <wpi/EventLoopRunner.h>
#include <wpi/StringExtras.h>
#include <wpi/uv/FsEvent.h>
#include <wpi/uv/Timer.h>
@@ -38,7 +39,7 @@ void UsbCameraListener::Start() {
auto devEvents = wpi::uv::FsEvent::Create(loop);
devEvents->fsEvent.connect([refreshTimer](const char* fn, int flags) {
if (wpi::StringRef(fn).startswith("video")) {
if (wpi::starts_with(fn, "video")) {
refreshTimer->Start(wpi::uv::Timer::Time(200));
}
});

View File

@@ -4,8 +4,8 @@
#include "UsbCameraProperty.h"
#include <fmt/format.h>
#include <wpi/SmallString.h>
#include <wpi/raw_ostream.h>
#include "UsbUtil.h"
@@ -92,15 +92,8 @@ static int GetStringCtrlIoctl(int fd, int id, int maximum, std::string* value) {
}
static int SetStringCtrlIoctl(int fd, int id, int maximum,
const wpi::Twine& value) {
wpi::SmallString<64> strBuf, strBuf2;
wpi::StringRef str = value.toNullTerminatedStringRef(strBuf);
if (str.size() > static_cast<size_t>(maximum)) {
// don't know if strBuf was used, just recopy
strBuf2 = str.take_front(maximum);
str = strBuf2;
strBuf2.push_back('\0'); // null terminate
}
std::string_view value) {
wpi::SmallString<64> str{value.substr(0, maximum)};
struct v4l2_ext_control ctrl;
struct v4l2_ext_controls ctrls;
@@ -108,7 +101,7 @@ static int SetStringCtrlIoctl(int fd, int id, int maximum,
std::memset(&ctrls, 0, sizeof(ctrls));
ctrl.id = id;
ctrl.size = str.size();
ctrl.string = const_cast<char*>(str.data());
ctrl.string = const_cast<char*>(str.c_str());
ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(id);
ctrls.count = 1;
ctrls.controls = &ctrl;
@@ -117,8 +110,8 @@ static int SetStringCtrlIoctl(int fd, int id, int maximum,
// Removes non-alphanumeric characters and replaces spaces with underscores.
// e.g. "Zoom, Absolute" -> "zoom_absolute", "Pan (Absolute)" -> "pan_absolute"
static wpi::StringRef NormalizeName(wpi::StringRef name,
wpi::SmallVectorImpl<char>& buf) {
static std::string_view NormalizeName(std::string_view name,
wpi::SmallVectorImpl<char>& buf) {
bool newWord = false;
for (auto ch : name) {
if (std::isalnum(ch)) {
@@ -131,13 +124,12 @@ static wpi::StringRef NormalizeName(wpi::StringRef name,
newWord = true;
}
}
return wpi::StringRef(buf.data(), buf.size());
return {buf.data(), buf.size()};
}
#ifdef VIDIOC_QUERY_EXT_CTRL
UsbCameraProperty::UsbCameraProperty(const struct v4l2_query_ext_ctrl& ctrl)
: PropertyImpl(wpi::StringRef{}, CS_PROP_NONE, ctrl.step,
ctrl.default_value, 0),
: PropertyImpl({}, CS_PROP_NONE, ctrl.step, ctrl.default_value, 0),
id(ctrl.id & V4L2_CTRL_ID_MASK),
type(ctrl.type) {
hasMinimum = true;
@@ -174,13 +166,12 @@ UsbCameraProperty::UsbCameraProperty(const struct v4l2_query_ext_ctrl& ctrl)
++len;
}
wpi::SmallString<64> name_buf;
name = NormalizeName(wpi::StringRef(ctrl.name, len), name_buf);
name = NormalizeName({ctrl.name, len}, name_buf);
}
#endif
UsbCameraProperty::UsbCameraProperty(const struct v4l2_queryctrl& ctrl)
: PropertyImpl(wpi::StringRef{}, CS_PROP_NONE, ctrl.step,
ctrl.default_value, 0),
: PropertyImpl({}, CS_PROP_NONE, ctrl.step, ctrl.default_value, 0),
id(ctrl.id & V4L2_CTRL_ID_MASK),
type(ctrl.type) {
hasMinimum = true;
@@ -214,8 +205,8 @@ UsbCameraProperty::UsbCameraProperty(const struct v4l2_queryctrl& ctrl)
++len;
}
wpi::SmallString<64> name_buf;
name = NormalizeName(
wpi::StringRef(reinterpret_cast<const char*>(ctrl.name), len), name_buf);
name =
NormalizeName({reinterpret_cast<const char*>(ctrl.name), len}, name_buf);
}
std::unique_ptr<UsbCameraProperty> UsbCameraProperty::DeviceQuery(int fd,
@@ -261,8 +252,7 @@ std::unique_ptr<UsbCameraProperty> UsbCameraProperty::DeviceQuery(int fd,
continue;
}
if (prop->intMenu) {
wpi::raw_string_ostream os(prop->enumChoices[i]);
os << qmenu.value;
prop->enumChoices[i] = fmt::to_string(qmenu.value);
} else {
prop->enumChoices[i] = reinterpret_cast<const char*>(qmenu.name);
}
@@ -315,12 +305,12 @@ bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock,
int fd) const {
// Make a copy of the string as we're about to release the lock
wpi::SmallString<128> valueStrCopy{valueStr};
return DeviceSet(lock, fd, value, valueStrCopy);
return DeviceSet(lock, fd, value, valueStrCopy.str());
}
bool UsbCameraProperty::DeviceSet(std::unique_lock<wpi::mutex>& lock, int fd,
int newValue,
const wpi::Twine& newValueStr) const {
std::string_view newValueStr) const {
if (!device || fd < 0) {
return true;
}

View File

@@ -8,6 +8,7 @@
#include <linux/videodev2.h>
#include <memory>
#include <string_view>
#include <wpi/mutex.h>
@@ -19,19 +20,19 @@ namespace cs {
class UsbCameraProperty : public PropertyImpl {
public:
UsbCameraProperty() = default;
explicit UsbCameraProperty(const wpi::Twine& name_) : PropertyImpl{name_} {}
explicit UsbCameraProperty(std::string_view name_) : PropertyImpl{name_} {}
// Software property constructor
UsbCameraProperty(const wpi::Twine& name_, unsigned id_,
CS_PropertyKind kind_, int minimum_, int maximum_,
int step_, int defaultValue_, int value_)
UsbCameraProperty(std::string_view name_, unsigned id_, CS_PropertyKind kind_,
int minimum_, int maximum_, int step_, int defaultValue_,
int value_)
: PropertyImpl(name_, kind_, minimum_, maximum_, step_, defaultValue_,
value_),
device{false},
id{id_} {}
// Normalized property constructor
UsbCameraProperty(const wpi::Twine& name_, int rawIndex_,
UsbCameraProperty(std::string_view name_, int rawIndex_,
const UsbCameraProperty& rawProp, int defaultValue_,
int value_)
: PropertyImpl(name_, rawProp.propKind, 1, defaultValue_, value_),
@@ -55,7 +56,7 @@ class UsbCameraProperty : public PropertyImpl {
bool DeviceGet(std::unique_lock<wpi::mutex>& lock, int fd);
bool DeviceSet(std::unique_lock<wpi::mutex>& lock, int fd) const;
bool DeviceSet(std::unique_lock<wpi::mutex>& lock, int fd, int newValue,
const wpi::Twine& newValueStr) const;
std::string_view newValueStr) const;
// If this is a device (rather than software) property
bool device{true};

View File

@@ -8,8 +8,10 @@
#include <libgen.h>
#include <sys/ioctl.h>
#include <wpi/Format.h>
#include <fmt/format.h>
#include <wpi/SmallString.h>
#include <wpi/StringExtras.h>
#include <wpi/fs.h>
#include <wpi/raw_istream.h>
#include <wpi/raw_ostream.h>
@@ -18,21 +20,18 @@
namespace cs {
static wpi::StringRef GetUsbNameFromFile(int vendor, int product,
wpi::SmallVectorImpl<char>& buf) {
static std::string GetUsbNameFromFile(int vendor, int product) {
int fd = open("/var/lib/usbutils/usb.ids", O_RDONLY);
if (fd < 0) {
return {};
}
wpi::raw_svector_ostream os{buf};
wpi::SmallString<128> buf;
wpi::raw_fd_istream is{fd, true};
// build vendor and product 4-char hex strings
wpi::SmallString<16> vendorStr, productStr;
wpi::raw_svector_ostream vendorOs{vendorStr}, productOs{productStr};
vendorOs << wpi::format_hex_no_prefix(vendor, 4);
productOs << wpi::format_hex_no_prefix(product, 4);
auto vendorStr = fmt::format("{:04x}", vendor);
auto productStr = fmt::format("{:04x}", product);
// scan file
wpi::SmallString<128> lineBuf;
@@ -48,23 +47,24 @@ static wpi::StringRef GetUsbNameFromFile(int vendor, int product,
}
// look for vendor at start of line
if (line.startswith(vendorStr)) {
if (wpi::starts_with(line, vendorStr)) {
foundVendor = true;
os << line.substr(5).trim() << ' ';
buf += wpi::trim(line.substr(5));
buf += ' ';
continue;
}
if (foundVendor) {
// next vendor, but didn't match product?
if (line[0] != '\t') {
os << "Unknown";
return os.str();
buf += "Unknown";
return buf;
}
// look for product
if (line.substr(1).startswith(productStr)) {
os << line.substr(6).trim();
return os.str();
if (wpi::starts_with(line.substr(1), productStr)) {
buf += wpi::trim(line.substr(6));
return buf;
}
}
}
@@ -72,93 +72,90 @@ static wpi::StringRef GetUsbNameFromFile(int vendor, int product,
return {};
}
wpi::StringRef GetUsbNameFromId(int vendor, int product,
wpi::SmallVectorImpl<char>& buf) {
std::string GetUsbNameFromId(int vendor, int product) {
// try reading usb.ids
wpi::StringRef rv = GetUsbNameFromFile(vendor, product, buf);
std::string rv = GetUsbNameFromFile(vendor, product);
if (!rv.empty()) {
return rv;
}
// Fall back to internal database
wpi::raw_svector_ostream os{buf};
switch (vendor) {
case 0x046d:
os << "Logitech, Inc. ";
case 0x046d: {
std::string_view productStr;
switch (product) {
case 0x0802:
os << "Webcam C200";
productStr = "Webcam C200";
break;
case 0x0804:
os << "Webcam C250";
productStr = "Webcam C250";
break;
case 0x0805:
os << "Webcam C300";
productStr = "Webcam C300";
break;
case 0x0807:
os << "Webcam B500";
productStr = "Webcam B500";
break;
case 0x0808:
os << "Webcam C600";
productStr = "Webcam C600";
break;
case 0x0809:
os << "Webcam Pro 9000";
productStr = "Webcam Pro 9000";
break;
case 0x080a:
os << "Portable Webcam C905";
productStr = "Portable Webcam C905";
break;
case 0x080f:
os << "Webcam C120";
productStr = "Webcam C120";
break;
case 0x0819:
os << "Webcam C210";
productStr = "Webcam C210";
break;
case 0x081b:
os << "Webcam C310";
productStr = "Webcam C310";
break;
case 0x081d:
os << "HD Webcam C510";
productStr = "HD Webcam C510";
break;
case 0x0821:
os << "HD Webcam C910";
productStr = "HD Webcam C910";
break;
case 0x0825:
os << "Webcam C270";
productStr = "Webcam C270";
break;
case 0x0826:
os << "HD Webcam C525";
productStr = "HD Webcam C525";
break;
case 0x0828:
os << "HD Webcam B990";
productStr = "HD Webcam B990";
break;
case 0x082b:
os << "Webcam C170";
productStr = "Webcam C170";
break;
case 0x082d:
os << "HD Pro Webcam C920";
productStr = "HD Pro Webcam C920";
break;
case 0x0836:
os << "B525 HD Webcam";
productStr = "B525 HD Webcam";
break;
case 0x0843:
os << "Webcam C930e";
productStr = "Webcam C930e";
break;
}
break;
return fmt::format("Logitech, Inc. {}", productStr);
}
}
return os.str();
return {};
}
int CheckedIoctl(int fd, unsigned long req, void* data, // NOLINT(runtime/int)
const char* name, const char* file, int line, bool quiet) {
int retval = ioctl(fd, req, data);
if (!quiet && retval < 0) {
wpi::SmallString<64> localfile{file};
localfile.push_back('\0');
WPI_ERROR(Instance::GetInstance().logger,
"ioctl " << name << " failed at " << basename(localfile.data())
<< ":" << line << ": " << std::strerror(errno));
WPI_ERROR(Instance::GetInstance().logger, "ioctl {} failed at {}:{}: {}",
name, fs::path{file}.filename().string(), line,
std::strerror(errno));
}
return retval;
}

View File

@@ -5,15 +5,11 @@
#ifndef CSCORE_USBUTIL_H_
#define CSCORE_USBUTIL_H_
#include <stdint.h>
#include <wpi/SmallVector.h>
#include <wpi/StringRef.h>
#include <string>
namespace cs {
wpi::StringRef GetUsbNameFromId(int vendor, int product,
wpi::SmallVectorImpl<char>& buf);
std::string GetUsbNameFromId(int vendor, int product);
int CheckedIoctl(int fd, unsigned long req, void* data, // NOLINT(runtime/int)
const char* name, const char* file, int line, bool quiet);