Allow setting a custom device ID (issue #18).

This commit is contained in:
Gonzalo Exequiel Pedone 2021-06-19 13:45:59 -03:00
parent e3bedce3ce
commit c0d241d0b4
No known key found for this signature in database
GPG key ID: B8B09E63E9B85BAF
9 changed files with 79 additions and 14 deletions

View file

@ -191,6 +191,10 @@ AkVCam::CmdParser::CmdParser()
"DESCRIPTION",
"Add a new device.",
AKVCAM_BIND_FUNC(CmdParserPrivate::addDevice));
this->addFlags("add-device",
{"-i", "--id"},
"DEVICEID",
"Create device as DEVICEID.");
this->addCommand("remove-device",
"DEVICE",
"Remove a device.",
@ -843,6 +847,8 @@ int AkVCam::CmdParserPrivate::showDevices(const StringMap &flags,
if (devices.empty())
return 0;
std::sort(devices.begin(), devices.end());
if (this->m_parseable) {
for (auto &device: devices)
std::cout << device << std::endl;
@ -875,7 +881,8 @@ int AkVCam::CmdParserPrivate::addDevice(const StringMap &flags,
return -1;
}
auto deviceId = this->m_ipcBridge.addDevice(args[1]);
auto deviceId = this->flagValue(flags, "add-device", "-i");
deviceId = this->m_ipcBridge.addDevice(args[1], deviceId);
if (deviceId.empty()) {
std::cerr << "Failed to create device." << std::endl;

View file

@ -145,7 +145,8 @@ namespace AkVCam
/* Server */
std::string addDevice(const std::string &description);
std::string addDevice(const std::string &description,
const std::string &deviceId={});
void removeDevice(const std::string &deviceId);
void addFormat(const std::string &deviceId,
const VideoFormat &format,

View file

@ -285,10 +285,20 @@ void AkVCam::Preferences::sync()
kCFPreferencesAnyHost);
}
std::string AkVCam::Preferences::addDevice(const std::string &description)
std::string AkVCam::Preferences::addDevice(const std::string &description,
const std::string &deviceId)
{
AkLogFunction();
auto path = createDevicePath();
std::string path;
if (deviceId.empty())
path = createDevicePath();
else if (!idDeviceIdTaken(deviceId))
path = deviceId;
if (path.empty())
return {};
int cameraIndex = readInt("cameras");
write("cameras", cameraIndex + 1);
write("cameras."
@ -388,6 +398,21 @@ size_t AkVCam::Preferences::camerasCount()
return size_t(nCameras);
}
bool AkVCam::Preferences::idDeviceIdTaken(const std::string &deviceId)
{
AkLogFunction();
// List device paths in use.
std::vector<std::string> cameraPaths;
for (size_t i = 0; i < camerasCount(); i++)
cameraPaths.push_back(cameraPath(i));
return std::find(cameraPaths.begin(),
cameraPaths.end(),
deviceId) != cameraPaths.end();
}
std::string AkVCam::Preferences::createDevicePath()
{
AkLogFunction();
@ -401,7 +426,7 @@ std::string AkVCam::Preferences::createDevicePath()
const int maxId = 64;
for (int i = 0; i < maxId; i++) {
/* There are no rules for device paths in Windows. Just append an
/* There are no rules for device paths in Mac. Just append an
* incremental index to a common prefix.
*/
auto path = CMIO_PLUGIN_DEVICE_PREFIX + std::to_string(i);

View file

@ -51,7 +51,8 @@ namespace AkVCam
void move(const std::string &keyFrom, const std::string &keyTo);
void moveAll(const std::string &keyFrom, const std::string &keyTo);
void sync();
std::string addDevice(const std::string &description);
std::string addDevice(const std::string &description,
const std::string &deviceId);
std::string addCamera(const std::string &description,
const std::vector<VideoFormat> &formats);
std::string addCamera(const std::string &path,
@ -59,6 +60,7 @@ namespace AkVCam
const std::vector<VideoFormat> &formats);
void removeCamera(const std::string &path);
size_t camerasCount();
bool idDeviceIdTaken(const std::string &deviceId);
std::string createDevicePath();
int cameraFromPath(const std::string &path);
bool cameraExists(const std::string &path);

View file

@ -582,11 +582,12 @@ std::string AkVCam::IpcBridge::clientExe(uint64_t pid) const
return {path};
}
std::string AkVCam::IpcBridge::addDevice(const std::string &description)
std::string AkVCam::IpcBridge::addDevice(const std::string &description,
const std::string &deviceId)
{
AkLogFunction();
return Preferences::addDevice(description);
return Preferences::addDevice(description, deviceId);
}
void AkVCam::IpcBridge::removeDevice(const std::string &deviceId)

View file

@ -223,10 +223,16 @@ bool AkVCam::Preferences::move(const std::string &keyFrom,
return ok;
}
std::string AkVCam::Preferences::addDevice(const std::string &description)
std::string AkVCam::Preferences::addDevice(const std::string &description,
const std::string &deviceId)
{
AkLogFunction();
auto path = createDevicePath();
std::string path;
if (deviceId.empty())
path = createDevicePath();
else if (!idDeviceIdTaken(deviceId))
path = deviceId;
if (path.empty())
return {};
@ -336,6 +342,26 @@ size_t AkVCam::Preferences::camerasCount()
return size_t(nCameras);
}
bool AkVCam::Preferences::idDeviceIdTaken(const std::string &deviceId)
{
AkLogFunction();
// List device paths in use.
std::vector<std::string> cameraPaths;
for (size_t i = 0; i < camerasCount(); i++)
cameraPaths.push_back(cameraPath(i));
// List device CLSIDs in use.
auto cameraClsids = listAllCameras();
auto clsid = createClsidFromStr(deviceId);
auto pit = std::find(cameraPaths.begin(), cameraPaths.end(), deviceId);
auto cit = std::find(cameraClsids.begin(), cameraClsids.end(), clsid);
return pit != cameraPaths.end() || cit != cameraClsids.end();
}
std::string AkVCam::Preferences::createDevicePath()
{
AkLogFunction();

View file

@ -55,7 +55,8 @@ namespace AkVCam
bool move(const std::string &keyFrom,
const std::string &keyTo,
bool global=false);
std::string addDevice(const std::string &description);
std::string addDevice(const std::string &description,
const std::string &deviceId);
std::string addCamera(const std::string &description,
const std::vector<VideoFormat> &formats);
std::string addCamera(const std::string &path,
@ -63,6 +64,7 @@ namespace AkVCam
const std::vector<VideoFormat> &formats);
bool removeCamera(const std::string &path);
size_t camerasCount();
bool idDeviceIdTaken(const std::string &deviceId);
std::string createDevicePath();
int cameraFromCLSID(const CLSID &clsid);
int cameraFromPath(const std::string &path);

View file

@ -568,11 +568,12 @@ std::string AkVCam::IpcBridge::clientExe(uint64_t pid) const
return exe;
}
std::string AkVCam::IpcBridge::addDevice(const std::string &description)
std::string AkVCam::IpcBridge::addDevice(const std::string &description,
const std::string &deviceId)
{
AkLogFunction();
return Preferences::addDevice(description);
return Preferences::addDevice(description, deviceId);
}
void AkVCam::IpcBridge::removeDevice(const std::string &deviceId)

View file

@ -295,7 +295,7 @@ void AkVCam::Pin::frameReady(const VideoFrame &frame)
void AkVCam::Pin::setPicture(const std::string &picture)
{
AkLogFunction();
AkLogDebug() << "Picture: " << picture;
AkLogDebug() << "Picture: " << picture << std::endl;
this->d->m_testFrame = loadPicture(picture);
this->d->updateTestFrame();
this->d->m_mutex.lock();