Skip to content

Commit 83bb26b

Browse files
committed
Add UsbCameraList
1 parent a0978d0 commit 83bb26b

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright (c) FIRST and other WPILib contributors.
2+
// Open Source Software; you can modify and/or share it under the terms of
3+
// the WPILib BSD license file in the root directory of this project.
4+
5+
#include "glass/camera/UsbCameraList.h"
6+
7+
#include <cscore_cpp.h>
8+
#include <fmt/format.h>
9+
#include <imgui.h>
10+
11+
using namespace glass;
12+
13+
struct UsbCameraList::UsbInfoThread : public wpi::SafeThread {
14+
void Main() override;
15+
16+
std::vector<cs::UsbCameraInfo> m_usbInfo;
17+
};
18+
19+
void UsbCameraList::UsbInfoThread::Main() {
20+
std::unique_lock lock{m_mutex};
21+
while (m_active) {
22+
// enumerate without lock held
23+
lock.unlock();
24+
CS_Status status = 0;
25+
auto usbInfo = cs::EnumerateUsbCameras(&status);
26+
27+
lock.lock();
28+
m_usbInfo = std::move(usbInfo);
29+
30+
// wait for change
31+
m_cond.wait(lock);
32+
}
33+
}
34+
35+
UsbCameraList::UsbCameraList() : m_poller{cs::CreateListenerPoller()} {
36+
CS_Status status = 0;
37+
cs::AddPolledListener(m_poller, CS_USB_CAMERAS_CHANGED, false, &status);
38+
39+
m_usbInfoThread.Start();
40+
}
41+
42+
UsbCameraList::~UsbCameraList() {
43+
cs::DestroyListenerPoller(m_poller);
44+
}
45+
46+
std::string UsbCameraList::DisplayMenu() {
47+
std::string rv;
48+
bool any = false;
49+
if (auto thr = m_usbInfoThread.GetThread()) {
50+
// TODO: hide cameras that already exist as sources
51+
for (auto&& info : thr->m_usbInfo) {
52+
ImGui::SeparatorText(fmt::format("{} ({:04x}:{:04x})", info.name,
53+
info.vendorId, info.productId)
54+
.c_str());
55+
if (ImGui::MenuItem(info.path.c_str())) {
56+
rv = info.path;
57+
}
58+
for (auto&& path : info.otherPaths) {
59+
if (ImGui::MenuItem(path.c_str())) {
60+
rv = info.path;
61+
}
62+
}
63+
}
64+
any = !thr->m_usbInfo.empty();
65+
}
66+
if (!any) {
67+
ImGui::MenuItem("(None)", nullptr, false, false);
68+
}
69+
return rv;
70+
}
71+
72+
void UsbCameraList::Update() {
73+
bool timedOut = false;
74+
for (auto&& event : cs::PollListener(m_poller, 0, &timedOut)) {
75+
if (event.kind == cs::RawEvent::kUsbCamerasChanged) {
76+
// enumerate on separate thread
77+
if (auto thr = m_usbInfoThread.GetThread()) {
78+
thr->m_cond.notify_all();
79+
}
80+
}
81+
}
82+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) FIRST and other WPILib contributors.
2+
// Open Source Software; you can modify and/or share it under the terms of
3+
// the WPILib BSD license file in the root directory of this project.
4+
5+
#pragma once
6+
7+
#include <string>
8+
9+
#include <cscore_cpp.h>
10+
#include <wpi/SafeThread.h>
11+
12+
namespace glass {
13+
14+
class Storage;
15+
16+
/**
17+
* Provider for CameraServer models and views for USB cameras.
18+
*/
19+
class UsbCameraList {
20+
public:
21+
explicit UsbCameraList();
22+
~UsbCameraList();
23+
24+
UsbCameraList(const UsbCameraList&) = delete;
25+
UsbCameraList& operator=(const UsbCameraList&) = delete;
26+
27+
void Update();
28+
29+
/**
30+
* Displays menu contents.
31+
*
32+
* @return camera path to add, if not empty
33+
*/
34+
std::string DisplayMenu();
35+
36+
private:
37+
struct UsbInfoThread;
38+
wpi::SafeThreadOwner<UsbInfoThread> m_usbInfoThread;
39+
40+
CS_ListenerPoller m_poller;
41+
};
42+
43+
} // namespace glass

0 commit comments

Comments
 (0)