7#include <duvc-ctl/detail/com_helpers.h>
24using namespace detail;
34 com_ptr<ICreateDevEnum> dev;
37 reinterpret_cast<void **
>(dev.put()));
39 throw_hr(hr,
"CoCreateInstance(SystemDeviceEnum)");
44 com_ptr<IEnumMoniker> e;
50 throw_hr(hr,
"CreateClassEnumerator(VideoInputDeviceCategory)");
66 const wchar_t *ptr =
static_cast<const wchar_t*
>(
bstr);
69 if (
len > 0 &&
len < 2048) {
84 com_ptr<IPropertyBag> bag;
85 HRESULT hr = mon->BindToStorage(
89 reinterpret_cast<void**
>(bag.put())
91 if (FAILED(hr) || !bag) {
103 com_ptr<IPropertyBag> bag;
104 HRESULT hr = mon->BindToStorage(
108 reinterpret_cast<void**
>(bag.put())
110 if (SUCCEEDED(hr) && bag) {
118 LPOLESTR disp =
nullptr;
121 if (SUCCEEDED(mon->GetDisplayName(
nullptr,
nullptr, &disp)) && disp) {
123 const wchar_t *ptr =
static_cast<const wchar_t*
>(bstr);
125 size_t len = bstr.length();
126 if (len > 0 && len < 512) {
127 res.assign(ptr, len);
134 res.erase(res.find_last_not_of(L
"\r\n \t\0") + 1);
142 const std::wstring &path) {
143 if (!d.path.empty() && !path.empty()) {
144 if (_wcsicmp(d.path.c_str(), path.c_str()) == 0)
148 if (!d.name.empty() && !name.empty()) {
149 if (_wcsicmp(d.name.c_str(), name.c_str()) == 0)
158 std::vector<Device> out;
166 com_ptr<IMoniker> mon;
167 while (en->Next(1, mon.put(), &fetched) == S_OK && fetched) {
171 out.emplace_back(std::move(d));
188 com_ptr<IMoniker> mon;
189 while (en->Next(1, mon.put(), &fetched) == S_OK && fetched) {
195 DeviceConnection conn(dev);
196 return conn.is_valid();
213 throw std::runtime_error(
"Device path cannot be empty");
220 throw_hr(
hr,
"CoCreateInstance(SystemDeviceEnum)");
226 throw std::runtime_error(
"No video devices available");
228 throw_hr(
hr,
"CreateClassEnumerator(VideoInputDeviceCategory)");
234 if (!
dpath.empty()) {
235 dpath.erase(
dpath.find_last_not_of(
L"\r\n \t\0") + 1);
245 throw std::runtime_error(
246 "Device with specified path not found. Ensure the device is connected and the path is valid.");
Result type that can contain either a value or an error.
Windows-specific device connection pooling.
EXTERN_C const IID IID_IPropertyBag
EXTERN_C const CLSID CLSID_SystemDeviceEnum
EXTERN_C const CLSID CLSID_VideoInputDeviceCategory
EXTERN_C const IID IID_ICreateDevEnum
Device enumeration and management functions.
std::wstring read_friendly_name(IMoniker *mon)
Read friendly name from device moniker.
static std::wstring read_prop_bstr(IPropertyBag *bag, const wchar_t *key)
bool is_same_device(const Device &d, const std::wstring &name, const std::wstring &path)
Check if two device identifiers refer to same device.
static DeviceChangeCallback g_device_callback
com_ptr< IEnumMoniker > enum_video_devices(ICreateDevEnum *dev)
Enumerate video input devices.
static void throw_hr(HRESULT hr, const char *where)
std::vector< Device > list_devices()
Enumerate all available video input devices.
std::wstring read_device_path(IMoniker *mon)
Read device path from moniker.
void unregister_device_change_callback()
Unregister device change callback.
static HDEVNOTIFY g_device_notify
bool is_device_connected(const Device &dev)
Check if a device is currently connected and accessible.
com_ptr< ICreateDevEnum > create_dev_enum()
Create DirectShow device enumerator.
void register_device_change_callback(DeviceChangeCallback callback)
Register callback for device hotplug events.
std::function< void(bool device_added, const std::wstring &device_path)> DeviceChangeCallback
Device change callback function type.
Device find_device_by_path(const std::wstring &device_path)
Find device by unique Windows device path.
static HWND g_notification_window
String conversion utilities for enums and types.
Represents a camera device.