[cscore] Add USB camera change event (#3123)

This commit is contained in:
Peter Johnson
2021-01-31 18:52:48 -08:00
committed by GitHub
parent 5337258888
commit ba6fe8ff2e
12 changed files with 202 additions and 4 deletions

View File

@@ -26,7 +26,8 @@ public class VideoEvent {
kTelemetryUpdated(0x8000),
kSinkPropertyCreated(0x10000),
kSinkPropertyValueUpdated(0x20000),
kSinkPropertyChoicesUpdated(0x40000);
kSinkPropertyChoicesUpdated(0x40000),
kUsbCamerasChanged(0x80000);
private final int value;
@@ -84,6 +85,8 @@ public class VideoEvent {
return Kind.kSinkPropertyValueUpdated;
case 0x40000:
return Kind.kSinkPropertyChoicesUpdated;
case 0x80000:
return Kind.kUsbCamerasChanged;
default:
return Kind.kUnknown;
}

View File

@@ -36,7 +36,10 @@ static void def_log_func(unsigned int level, const char* file,
wpi::errs() << oss.str();
}
Instance::Instance() : telemetry(notifier), networkListener(logger, notifier) {
Instance::Instance()
: telemetry(notifier),
networkListener(logger, notifier),
usbCameraListener(logger, notifier) {
SetDefaultLogger();
}
@@ -52,6 +55,7 @@ void Instance::Shutdown() {
m_sinks.FreeAll();
m_sources.FreeAll();
networkListener.Stop();
usbCameraListener.Stop();
telemetry.Stop();
notifier.Stop();
}

View File

@@ -18,6 +18,7 @@
#include "SourceImpl.h"
#include "Telemetry.h"
#include "UnlimitedHandleResource.h"
#include "UsbCameraListener.h"
namespace cs {
@@ -54,6 +55,7 @@ class Instance {
Notifier notifier;
Telemetry telemetry;
NetworkListener networkListener;
UsbCameraListener usbCameraListener;
private:
UnlimitedHandleResource<Handle, SourceData, Handle::kSource> m_sources;

View File

@@ -94,3 +94,7 @@ void Notifier::NotifyNetworkInterfacesChanged() {
void Notifier::NotifyTelemetryUpdated() {
Send(UINT_MAX, RawEvent::kTelemetryUpdated);
}
void Notifier::NotifyUsbCamerasChanged() {
Send(UINT_MAX, RawEvent::kUsbCamerasChanged);
}

View File

@@ -83,6 +83,7 @@ class Notifier : public wpi::CallbackManager<Notifier, impl::NotifierThread> {
const wpi::Twine& valueStr);
void NotifyNetworkInterfacesChanged();
void NotifyTelemetryUpdated();
void NotifyUsbCamerasChanged();
};
} // namespace cs

View File

@@ -0,0 +1,31 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#ifndef CSCORE_USBCAMERALISTENER_H_
#define CSCORE_USBCAMERALISTENER_H_
#include <memory>
#include <wpi/Logger.h>
namespace cs {
class Notifier;
class UsbCameraListener {
public:
UsbCameraListener(wpi::Logger& logger, Notifier& notifier);
~UsbCameraListener();
void Start();
void Stop();
private:
class Impl;
std::unique_ptr<Impl> m_impl;
};
} // namespace cs
#endif // CSCORE_USBCAMERALISTENER_H_

View File

@@ -718,6 +718,13 @@ static void StartBackground(int eventMask, bool immediateNotify) {
inst.notifier.NotifyNetworkInterfacesChanged();
}
}
if ((eventMask & CS_USB_CAMERAS_CHANGED) != 0) {
// start network interface event listener
inst.usbCameraListener.Start();
if (immediateNotify) {
inst.notifier.NotifyUsbCamerasChanged();
}
}
}
CS_Listener AddListener(std::function<void(const RawEvent& event)> callback,

View File

@@ -170,7 +170,8 @@ enum CS_EventKind {
CS_TELEMETRY_UPDATED = 0x8000,
CS_SINK_PROPERTY_CREATED = 0x10000,
CS_SINK_PROPERTY_VALUE_UPDATED = 0x20000,
CS_SINK_PROPERTY_CHOICES_UPDATED = 0x40000
CS_SINK_PROPERTY_CHOICES_UPDATED = 0x40000,
CS_USB_CAMERAS_CHANGED = 0x80000
};
/**

View File

@@ -116,7 +116,8 @@ struct RawEvent {
kTelemetryUpdated = CS_TELEMETRY_UPDATED,
kSinkPropertyCreated = CS_SINK_PROPERTY_CREATED,
kSinkPropertyValueUpdated = CS_SINK_PROPERTY_VALUE_UPDATED,
kSinkPropertyChoicesUpdated = CS_SINK_PROPERTY_CHOICES_UPDATED
kSinkPropertyChoicesUpdated = CS_SINK_PROPERTY_CHOICES_UPDATED,
kUsbCamerasChanged = CS_USB_CAMERAS_CHANGED
};
RawEvent() = default;

View File

@@ -0,0 +1,55 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "UsbCameraListener.h"
#include <wpi/EventLoopRunner.h>
#include <wpi/uv/FsEvent.h>
#include <wpi/uv/Timer.h>
#include "Notifier.h"
using namespace cs;
class UsbCameraListener::Impl {
public:
explicit Impl(Notifier& notifier) : m_notifier(notifier) {}
Notifier& m_notifier;
std::unique_ptr<wpi::EventLoopRunner> m_runner;
};
UsbCameraListener::UsbCameraListener(wpi::Logger& logger, Notifier& notifier)
: m_impl(std::make_unique<Impl>(notifier)) {}
UsbCameraListener::~UsbCameraListener() = default;
void UsbCameraListener::Start() {
if (!m_impl->m_runner) {
m_impl->m_runner = std::make_unique<wpi::EventLoopRunner>();
m_impl->m_runner->ExecAsync([impl = m_impl.get()](wpi::uv::Loop& loop) {
auto refreshTimer = wpi::uv::Timer::Create(loop);
refreshTimer->timeout.connect([notifier = &impl->m_notifier] {
notifier->NotifyUsbCamerasChanged();
});
refreshTimer->Unreference();
auto devEvents = wpi::uv::FsEvent::Create(loop);
devEvents->fsEvent.connect([refreshTimer](const char* fn, int flags) {
if (wpi::StringRef(fn).startswith("video")) {
refreshTimer->Start(wpi::uv::Timer::Time(200));
}
});
devEvents->Start("/dev");
devEvents->Unreference();
});
}
}
void UsbCameraListener::Stop() {
if (m_impl->m_runner) {
m_impl->m_runner.reset();
}
}

View File

@@ -0,0 +1,17 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "UsbCameraListener.h"
using namespace cs;
class UsbCameraListener::Impl {};
UsbCameraListener::UsbCameraListener(wpi::Logger& logger, Notifier& notifier) {}
UsbCameraListener::~UsbCameraListener() = default;
void UsbCameraListener::Start() {}
void UsbCameraListener::Stop() {}

View File

@@ -0,0 +1,72 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "UsbCameraListener.h"
#include "Notifier.h"
#include "WindowsMessagePump.h"
#include <dbt.h> // NOLINT(build/include_order)
#define IDT_TIMER1 1001
using namespace cs;
class UsbCameraListener::Impl {
public:
explicit Impl(Notifier& notifier) : m_notifier{notifier} {}
void Start() {
m_messagePump = std::make_unique<WindowsMessagePump>(
[this](HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) {
return this->PumpMain(hwnd, uiMsg, wParam, lParam);
});
}
void Stop() { m_messagePump = nullptr; }
LRESULT PumpMain(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) {
switch (uiMsg) {
case WM_CLOSE:
KillTimer(hwnd, IDT_TIMER1);
break;
case WM_TIMER:
if (wParam == IDT_TIMER1) {
KillTimer(hwnd, IDT_TIMER1);
m_notifier.NotifyUsbCamerasChanged();
}
break;
case WM_DEVICECHANGE:
PDEV_BROADCAST_HDR parameter =
reinterpret_cast<PDEV_BROADCAST_HDR>(lParam);
if (wParam == DBT_DEVICEARRIVAL &&
parameter->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
SetTimer(hwnd, IDT_TIMER1, 200, nullptr);
} else if (wParam == DBT_DEVICEREMOVECOMPLETE &&
parameter->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
SetTimer(hwnd, IDT_TIMER1, 200, nullptr);
}
break;
}
return 0;
}
Notifier& m_notifier;
std::unique_ptr<cs::WindowsMessagePump> m_messagePump;
};
UsbCameraListener::UsbCameraListener(wpi::Logger& logger, Notifier& notifier)
: m_impl{std::make_unique<Impl>(notifier)} {}
UsbCameraListener::~UsbCameraListener() {
Stop();
}
void UsbCameraListener::Start() {
m_impl->Start();
}
void UsbCameraListener::Stop() {
m_impl->Stop();
}