Very basic camera management commands working.
This commit is contained in:
parent
40482cb484
commit
277e479269
27 changed files with 445 additions and 331 deletions
|
@ -63,10 +63,6 @@ namespace AkVCam {
|
|||
size_t maxFlagsValueLength(const std::vector<CmdParserFlags> &flags);
|
||||
size_t maxStringLength(const StringVector &strings);
|
||||
size_t maxStringLength(const WStringVector &strings);
|
||||
std::string fill(const std::string &str, size_t maxSize);
|
||||
std::wstring fill(const std::wstring &str, size_t maxSize);
|
||||
std::string join(const StringVector &strings,
|
||||
const std::string &separator);
|
||||
CmdParserCommand *parserCommand(const std::string &command);
|
||||
const CmdParserFlags *parserFlag(const std::vector<CmdParserFlags> &cmdFlags,
|
||||
const std::string &flag);
|
||||
|
@ -86,6 +82,8 @@ namespace AkVCam {
|
|||
const StringVector &args);
|
||||
int showDeviceDescription(const StringMap &flags,
|
||||
const StringVector &args);
|
||||
int setDeviceDescription(const StringMap &flags,
|
||||
const StringVector &args);
|
||||
int showSupportedFormats(const StringMap &flags,
|
||||
const StringVector &args);
|
||||
int showFormats(const StringMap &flags, const StringVector &args);
|
||||
|
@ -137,14 +135,18 @@ AkVCam::CmdParser::CmdParser()
|
|||
"DEVICE",
|
||||
"Remove a device.",
|
||||
AKVCAM_BIND_FUNC(CmdParserPrivate::removeDevice));
|
||||
this->addCommand("device-type",
|
||||
this->addCommand("type",
|
||||
"DEVICE",
|
||||
"Show device type.",
|
||||
AKVCAM_BIND_FUNC(CmdParserPrivate::showDeviceType));
|
||||
this->addCommand("device-description",
|
||||
this->addCommand("description",
|
||||
"DEVICE",
|
||||
"Show device description.",
|
||||
AKVCAM_BIND_FUNC(CmdParserPrivate::showDeviceDescription));
|
||||
this->addCommand("set-description",
|
||||
"DEVICE DESCRIPTION",
|
||||
"Set device description.",
|
||||
AKVCAM_BIND_FUNC(CmdParserPrivate::setDeviceDescription));
|
||||
this->addCommand("supported-formats",
|
||||
"",
|
||||
"Show supported formats.",
|
||||
|
@ -180,15 +182,15 @@ AkVCam::CmdParser::CmdParser()
|
|||
"Create devices from a setting file.",
|
||||
AKVCAM_BIND_FUNC(CmdParserPrivate::loadSettings));
|
||||
this->addCommand("connections",
|
||||
"[DEVICE]",
|
||||
"DEVICE",
|
||||
"Show device connections.",
|
||||
AKVCAM_BIND_FUNC(CmdParserPrivate::showConnections));
|
||||
this->addCommand("connect",
|
||||
"OUTPUT_DEVICE INPUTDEVICE [INPUT_DEVICE ...]",
|
||||
"INPUT_DEVICE OUTPUTDEVICE [OUTPUT_DEVICE ...]",
|
||||
"Connect devices.",
|
||||
AKVCAM_BIND_FUNC(CmdParserPrivate::connectDevices));
|
||||
this->addCommand("disconnect",
|
||||
"OUTPUT_DEVICE INPUTDEVICE",
|
||||
"INPUT_DEVICE OUTPUTDEVICE",
|
||||
"Disconnect devices.",
|
||||
AKVCAM_BIND_FUNC(CmdParserPrivate::disconnectDevices));
|
||||
this->addCommand("options",
|
||||
|
@ -380,13 +382,13 @@ void AkVCam::CmdParserPrivate::printFlags(const std::vector<CmdParserFlags> &cmd
|
|||
auto maxFlagsValueLen = this->maxFlagsValueLength(cmdFlags);
|
||||
|
||||
for (auto &flag: cmdFlags) {
|
||||
auto allFlags = this->join(flag.flags, ", ");
|
||||
auto allFlags = join(flag.flags, ", ");
|
||||
std::cout << std::string(spaces.data(), indent)
|
||||
<< this->fill(allFlags, maxFlagsLen);
|
||||
<< fill(allFlags, maxFlagsLen);
|
||||
|
||||
if (maxFlagsValueLen > 0) {
|
||||
std::cout << " "
|
||||
<< this->fill(flag.value, maxFlagsValueLen);
|
||||
<< fill(flag.value, maxFlagsValueLen);
|
||||
}
|
||||
|
||||
std::cout << " "
|
||||
|
@ -420,7 +422,7 @@ size_t AkVCam::CmdParserPrivate::maxFlagsLength(const std::vector<CmdParserFlags
|
|||
size_t length = 0;
|
||||
|
||||
for (auto &flag: flags)
|
||||
length = std::max(this->join(flag.flags, ", ").size(), length);
|
||||
length = std::max(join(flag.flags, ", ").size(), length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
@ -455,43 +457,6 @@ size_t AkVCam::CmdParserPrivate::maxStringLength(const WStringVector &strings)
|
|||
return length;
|
||||
}
|
||||
|
||||
std::string AkVCam::CmdParserPrivate::fill(const std::string &str,
|
||||
size_t maxSize)
|
||||
{
|
||||
std::stringstream ss;
|
||||
std::vector<char> spaces(maxSize, ' ');
|
||||
ss << str << std::string(spaces.data(), maxSize - str.size());
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::wstring AkVCam::CmdParserPrivate::fill(const std::wstring &str, size_t maxSize)
|
||||
{
|
||||
std::wstringstream ss;
|
||||
std::vector<wchar_t> spaces(maxSize, ' ');
|
||||
ss << str << std::wstring(spaces.data(), maxSize - str.size());
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string AkVCam::CmdParserPrivate::join(const StringVector &strings,
|
||||
const std::string &separator)
|
||||
{
|
||||
std::stringstream ss;
|
||||
bool append = false;
|
||||
|
||||
for (auto &str: strings) {
|
||||
if (append)
|
||||
ss << separator;
|
||||
else
|
||||
append = true;
|
||||
|
||||
ss << str;
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
AkVCam::CmdParserCommand *AkVCam::CmdParserPrivate::parserCommand(const std::string &command)
|
||||
{
|
||||
for (auto &cmd: this->m_commands)
|
||||
|
@ -604,9 +569,9 @@ int AkVCam::CmdParserPrivate::showHelp(const StringMap &flags,
|
|||
continue;
|
||||
|
||||
std::cout << " "
|
||||
<< this->fill(cmd.command, maxCmdLen)
|
||||
<< fill(cmd.command, maxCmdLen)
|
||||
<< " "
|
||||
<< this->fill(cmd.arguments, maxArgsLen)
|
||||
<< fill(cmd.arguments, maxArgsLen)
|
||||
<< " "
|
||||
<< cmd.helpString << std::endl;
|
||||
|
||||
|
@ -628,8 +593,13 @@ int AkVCam::CmdParserPrivate::showDevices(const StringMap &flags,
|
|||
UNUSED(flags);
|
||||
UNUSED(args);
|
||||
|
||||
auto devices = this->m_ipcBridge.devices();
|
||||
|
||||
if (devices.empty())
|
||||
return 0;
|
||||
|
||||
if (this->m_parseable) {
|
||||
for (auto &device: this->m_ipcBridge.listDevices())
|
||||
for (auto &device: devices)
|
||||
std::cout << device << std::endl;
|
||||
} else {
|
||||
StringVector devicesColumn;
|
||||
|
@ -640,7 +610,7 @@ int AkVCam::CmdParserPrivate::showDevices(const StringMap &flags,
|
|||
typesColumn.push_back("Type");
|
||||
descriptionsColumn.push_back(L"Description");
|
||||
|
||||
for (auto &device: this->m_ipcBridge.listDevices()) {
|
||||
for (auto &device: devices) {
|
||||
devicesColumn.push_back(device);
|
||||
typesColumn.push_back(this->m_ipcBridge.deviceType(device) == IpcBridge::DeviceTypeInput?
|
||||
"Input":
|
||||
|
@ -652,11 +622,11 @@ int AkVCam::CmdParserPrivate::showDevices(const StringMap &flags,
|
|||
auto typesColumnSize = this->maxStringLength(typesColumn);
|
||||
auto descriptionsColumnSize = this->maxStringLength(descriptionsColumn);
|
||||
|
||||
std::cout << this->fill("Device", devicesColumnSize)
|
||||
std::cout << fill("Device", devicesColumnSize)
|
||||
<< " | "
|
||||
<< this->fill("Type", typesColumnSize)
|
||||
<< fill("Type", typesColumnSize)
|
||||
<< " | "
|
||||
<< this->fill("Description", descriptionsColumnSize)
|
||||
<< fill("Description", descriptionsColumnSize)
|
||||
<< std::endl;
|
||||
std::cout << std::string("-")
|
||||
* (devicesColumnSize
|
||||
|
@ -664,17 +634,17 @@ int AkVCam::CmdParserPrivate::showDevices(const StringMap &flags,
|
|||
+ descriptionsColumnSize
|
||||
+ 6) << std::endl;
|
||||
|
||||
for (auto &device: this->m_ipcBridge.listDevices()) {
|
||||
for (auto &device: devices) {
|
||||
std::string type =
|
||||
this->m_ipcBridge.deviceType(device) == IpcBridge::DeviceTypeInput?
|
||||
"Input":
|
||||
"Output";
|
||||
std::cout << this->fill(device, devicesColumnSize)
|
||||
std::cout << fill(device, devicesColumnSize)
|
||||
<< " | "
|
||||
<< this->fill(type, typesColumnSize)
|
||||
<< fill(type, typesColumnSize)
|
||||
<< " | ";
|
||||
std::wcout << this->fill(this->m_ipcBridge.description(device),
|
||||
descriptionsColumnSize)
|
||||
std::wcout << fill(this->m_ipcBridge.description(device),
|
||||
descriptionsColumnSize)
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -724,11 +694,11 @@ int AkVCam::CmdParserPrivate::removeDevice(const StringMap &flags,
|
|||
return -1;
|
||||
}
|
||||
|
||||
auto devices = this->m_ipcBridge.listDevices();
|
||||
auto devices = this->m_ipcBridge.devices();
|
||||
auto it = std::find(devices.begin(), devices.end(), args[1]);
|
||||
|
||||
if (it == devices.end()) {
|
||||
std::cerr << "Device not doesn't exists." << std::endl;
|
||||
std::cerr << "Device doesn't exists." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -749,11 +719,11 @@ int AkVCam::CmdParserPrivate::showDeviceType(const StringMap &flags,
|
|||
return -1;
|
||||
}
|
||||
|
||||
auto devices = this->m_ipcBridge.listDevices();
|
||||
auto devices = this->m_ipcBridge.devices();
|
||||
auto it = std::find(devices.begin(), devices.end(), args[1]);
|
||||
|
||||
if (it == devices.end()) {
|
||||
std::cerr << "Device not doesn't exists." << std::endl;
|
||||
std::cerr << "device doesn't exists." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -777,11 +747,11 @@ int AkVCam::CmdParserPrivate::showDeviceDescription(const StringMap &flags,
|
|||
return -1;
|
||||
}
|
||||
|
||||
auto devices = this->m_ipcBridge.listDevices();
|
||||
auto devices = this->m_ipcBridge.devices();
|
||||
auto it = std::find(devices.begin(), devices.end(), args[1]);
|
||||
|
||||
if (it == devices.end()) {
|
||||
std::cerr << "Device not doesn't exists." << std::endl;
|
||||
std::cerr << "Device doesn't exists." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -791,6 +761,33 @@ int AkVCam::CmdParserPrivate::showDeviceDescription(const StringMap &flags,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int AkVCam::CmdParserPrivate::setDeviceDescription(const AkVCam::StringMap &flags,
|
||||
const AkVCam::StringVector &args)
|
||||
{
|
||||
UNUSED(flags);
|
||||
|
||||
if (args.size() < 3) {
|
||||
std::cerr << "Not enough arguments." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto deviceId = args[1];
|
||||
auto devices = this->m_ipcBridge.devices();
|
||||
auto dit = std::find(devices.begin(), devices.end(), args[1]);
|
||||
|
||||
if (dit == devices.end()) {
|
||||
std::cerr << "device doesn't exists." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> cv;
|
||||
this->m_ipcBridge.setDescription(deviceId, cv.from_bytes(args[2]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AkVCam::CmdParserPrivate::showSupportedFormats(const StringMap &flags,
|
||||
const StringVector &args)
|
||||
{
|
||||
|
@ -828,11 +825,11 @@ int AkVCam::CmdParserPrivate::showFormats(const StringMap &flags,
|
|||
return -1;
|
||||
}
|
||||
|
||||
auto devices = this->m_ipcBridge.listDevices();
|
||||
auto devices = this->m_ipcBridge.devices();
|
||||
auto it = std::find(devices.begin(), devices.end(), args[1]);
|
||||
|
||||
if (it == devices.end()) {
|
||||
std::cerr << "Device not doesn't exists." << std::endl;
|
||||
std::cerr << "device doesn't exists." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -883,11 +880,11 @@ int AkVCam::CmdParserPrivate::addFormat(const StringMap &flags,
|
|||
}
|
||||
|
||||
auto deviceId = args[1];
|
||||
auto devices = this->m_ipcBridge.listDevices();
|
||||
auto devices = this->m_ipcBridge.devices();
|
||||
auto dit = std::find(devices.begin(), devices.end(), args[1]);
|
||||
|
||||
if (dit == devices.end()) {
|
||||
std::cerr << "Device not doesn't exists." << std::endl;
|
||||
std::cerr << "device doesn't exists." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -962,6 +959,8 @@ int AkVCam::CmdParserPrivate::addFormat(const StringMap &flags,
|
|||
int AkVCam::CmdParserPrivate::removeFormat(const StringMap &flags,
|
||||
const StringVector &args)
|
||||
{
|
||||
UNUSED(flags);
|
||||
|
||||
if (args.size() < 3) {
|
||||
std::cerr << "Not enough arguments." << std::endl;
|
||||
|
||||
|
@ -969,11 +968,11 @@ int AkVCam::CmdParserPrivate::removeFormat(const StringMap &flags,
|
|||
}
|
||||
|
||||
auto deviceId = args[1];
|
||||
auto devices = this->m_ipcBridge.listDevices();
|
||||
auto devices = this->m_ipcBridge.devices();
|
||||
auto dit = std::find(devices.begin(), devices.end(), args[1]);
|
||||
|
||||
if (dit == devices.end()) {
|
||||
std::cerr << "Device not doesn't exists." << std::endl;
|
||||
std::cerr << "device doesn't exists." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -1003,6 +1002,10 @@ int AkVCam::CmdParserPrivate::removeFormat(const StringMap &flags,
|
|||
int AkVCam::CmdParserPrivate::update(const StringMap &flags,
|
||||
const StringVector &args)
|
||||
{
|
||||
UNUSED(flags);
|
||||
UNUSED(args);
|
||||
this->m_ipcBridge.update();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1015,18 +1018,140 @@ int AkVCam::CmdParserPrivate::loadSettings(const AkVCam::StringMap &flags,
|
|||
int AkVCam::CmdParserPrivate::showConnections(const StringMap &flags,
|
||||
const StringVector &args)
|
||||
{
|
||||
UNUSED(flags);
|
||||
|
||||
if (args.size() < 2) {
|
||||
std::cerr << "Not enough arguments." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto deviceId = args[1];
|
||||
auto devices = this->m_ipcBridge.devices();
|
||||
auto dit = std::find(devices.begin(), devices.end(), args[1]);
|
||||
|
||||
if (dit == devices.end()) {
|
||||
std::cerr << "device doesn't exists." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (auto &connectedDevice: this->m_ipcBridge.connections(deviceId))
|
||||
std::cout << connectedDevice << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AkVCam::CmdParserPrivate::connectDevices(const StringMap &flags,
|
||||
const StringVector &args)
|
||||
{
|
||||
UNUSED(flags);
|
||||
|
||||
if (args.size() < 3) {
|
||||
std::cerr << "Not enough arguments." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto inputDevice = args[1];
|
||||
auto devices = this->m_ipcBridge.devices();
|
||||
auto it = std::find(devices.begin(), devices.end(), inputDevice);
|
||||
|
||||
if (it == devices.end()) {
|
||||
std::cerr << inputDevice << " doesn't exists." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (this->m_ipcBridge.deviceType(inputDevice) != IpcBridge::DeviceTypeInput) {
|
||||
std::cerr << inputDevice << " is not an input." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto outputDevices = this->m_ipcBridge.connections(inputDevice);
|
||||
|
||||
for (size_t i = 2; i < args.size(); i++) {
|
||||
auto &outputDevice = args[i];
|
||||
auto it = std::find(devices.begin(), devices.end(), outputDevice);
|
||||
|
||||
if (it == devices.end()) {
|
||||
std::cerr << outputDevice << " doesn't exists." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (this->m_ipcBridge.deviceType(outputDevice) != IpcBridge::DeviceTypeOutput) {
|
||||
std::cerr << outputDevice << " is not an output." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto cit = std::find(outputDevices.begin(),
|
||||
outputDevices.end(),
|
||||
outputDevice);
|
||||
|
||||
if (cit == outputDevices.end())
|
||||
outputDevices.push_back(outputDevice);
|
||||
}
|
||||
|
||||
this->m_ipcBridge.setConnections(inputDevice, outputDevices);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AkVCam::CmdParserPrivate::disconnectDevices(const StringMap &flags,
|
||||
const StringVector &args)
|
||||
{
|
||||
UNUSED(flags);
|
||||
|
||||
if (args.size() < 3) {
|
||||
std::cerr << "Not enough arguments." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto inputDevice = args[1];
|
||||
auto devices = this->m_ipcBridge.devices();
|
||||
auto it = std::find(devices.begin(), devices.end(), inputDevice);
|
||||
|
||||
if (it == devices.end()) {
|
||||
std::cerr << inputDevice << " doesn't exists." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (this->m_ipcBridge.deviceType(inputDevice) != IpcBridge::DeviceTypeInput) {
|
||||
std::cerr << inputDevice << " is not an input." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto outputDevices = this->m_ipcBridge.connections(inputDevice);
|
||||
auto &outputDevice = args[2];
|
||||
auto dit = std::find(devices.begin(), devices.end(), outputDevice);
|
||||
|
||||
if (dit == devices.end()) {
|
||||
std::cerr << outputDevice << " doesn't exists." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (this->m_ipcBridge.deviceType(outputDevice) != IpcBridge::DeviceTypeOutput) {
|
||||
std::cerr << outputDevice << " is not an output." << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto cit = std::find(outputDevices.begin(),
|
||||
outputDevices.end(),
|
||||
outputDevice);
|
||||
|
||||
if (cit == outputDevices.end())
|
||||
outputDevices.push_back(outputDevice);
|
||||
|
||||
this->m_ipcBridge.setConnections(inputDevice, outputDevices);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1051,6 +1176,50 @@ int AkVCam::CmdParserPrivate::writeOption(const StringMap &flags,
|
|||
int AkVCam::CmdParserPrivate::showClients(const StringMap &flags,
|
||||
const StringVector &args)
|
||||
{
|
||||
UNUSED(flags);
|
||||
UNUSED(args);
|
||||
|
||||
auto clients = this->m_ipcBridge.clientsPids();
|
||||
|
||||
if (clients.empty())
|
||||
return 0;
|
||||
|
||||
if (this->m_parseable) {
|
||||
for (auto &pid: clients)
|
||||
std::cout << pid
|
||||
<< " "
|
||||
<< this->m_ipcBridge.clientExe(pid)
|
||||
<< std::endl;
|
||||
} else {
|
||||
StringVector pidsColumn;
|
||||
StringVector exesColumn;
|
||||
|
||||
pidsColumn.push_back("Pid");
|
||||
exesColumn.push_back("Executable");
|
||||
|
||||
for (auto &pid: clients) {
|
||||
pidsColumn.push_back(std::to_string(pid));
|
||||
exesColumn.push_back(this->m_ipcBridge.clientExe(pid));
|
||||
}
|
||||
|
||||
auto pidsColumnSize = this->maxStringLength(pidsColumn);
|
||||
auto exesColumnSize = this->maxStringLength(exesColumn);
|
||||
|
||||
std::cout << fill("Pid", pidsColumnSize)
|
||||
<< " | "
|
||||
<< fill("Executable", exesColumnSize)
|
||||
<< std::endl;
|
||||
std::cout << std::string("-")
|
||||
* (pidsColumnSize + exesColumnSize + 4)
|
||||
<< std::endl;
|
||||
|
||||
for (auto &pid: clients)
|
||||
std::cout << fill(std::to_string(pid), pidsColumnSize)
|
||||
<< " | "
|
||||
<< fill(this->m_ipcBridge.clientExe(pid), exesColumnSize)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -121,10 +121,12 @@ namespace AkVCam
|
|||
void unregisterPeer();
|
||||
|
||||
// List available devices.
|
||||
std::vector<std::string> listDevices() const;
|
||||
std::vector<std::string> devices() const;
|
||||
|
||||
// Return human readable description of the device.
|
||||
std::wstring description(const std::string &deviceId) const;
|
||||
void setDescription(const std::string &deviceId,
|
||||
const std::wstring &description);
|
||||
|
||||
// Output pixel formats supported by the driver.
|
||||
std::vector<PixelFormat> supportedPixelFormats(DeviceType type) const;
|
||||
|
@ -172,26 +174,10 @@ namespace AkVCam
|
|||
const VideoFormat &format,
|
||||
int index=-1);
|
||||
void removeFormat(const std::string &deviceId, int index);
|
||||
|
||||
// Create a device definition.
|
||||
std::string deviceCreate(const std::wstring &description,
|
||||
const std::vector<VideoFormat> &formats,
|
||||
DeviceType type);
|
||||
|
||||
// Edit a device definition.
|
||||
bool deviceEdit(const std::string &deviceId,
|
||||
const std::wstring &description,
|
||||
const std::vector<VideoFormat> &formats);
|
||||
|
||||
// Change device description.
|
||||
bool changeDescription(const std::string &deviceId,
|
||||
const std::wstring &description);
|
||||
|
||||
// Remove a device definition.
|
||||
bool deviceDestroy(const std::string &deviceId);
|
||||
|
||||
// Remove all device definitions.
|
||||
bool destroyAllDevices();
|
||||
void update();
|
||||
std::vector<std::string> connections(const std::string &deviceId);
|
||||
void setConnections(const std::string &deviceId,
|
||||
const std::vector<std::string> &connectedDevices);
|
||||
|
||||
void updateDevices();
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
|
@ -157,6 +158,39 @@ std::wstring AkVCam::trimmed(const std::wstring &str)
|
|||
return str.substr(size_t(left), strippedLen);
|
||||
}
|
||||
|
||||
std::string AkVCam::fill(const std::string &str, size_t maxSize)
|
||||
{
|
||||
std::stringstream ss;
|
||||
std::vector<char> spaces(maxSize, ' ');
|
||||
ss << str << std::string(spaces.data(), maxSize - str.size());
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::wstring AkVCam::fill(const std::wstring &str, size_t maxSize)
|
||||
{
|
||||
std::wstringstream ss;
|
||||
std::vector<wchar_t> spaces(maxSize, ' ');
|
||||
ss << str << std::wstring(spaces.data(), maxSize - str.size());
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string AkVCam::join(const std::vector<std::string> &strs,
|
||||
const std::string &separator)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
for (size_t i = 0; i < strs.size(); i++) {
|
||||
if (i > 0)
|
||||
ss << separator;
|
||||
|
||||
ss << strs[i];
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::vector<std::string> AkVCam::split(const std::string &str, char separator)
|
||||
{
|
||||
if (str.empty())
|
||||
|
|
|
@ -153,6 +153,10 @@ namespace AkVCam
|
|||
bool isEqualFile(const std::wstring &file1, const std::wstring &file2);
|
||||
std::string trimmed(const std::string &str);
|
||||
std::wstring trimmed(const std::wstring &str);
|
||||
std::string fill(const std::string &str, size_t maxSize);
|
||||
std::wstring fill(const std::wstring &str, size_t maxSize);
|
||||
std::string join(const std::vector<std::string> &strs,
|
||||
const std::string &separator);
|
||||
std::vector<std::string> split(const std::string &str, char separator);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ int main(int argc, char **argv)
|
|||
auto loglevel =
|
||||
AkVCam::Preferences::readInt("loglevel", AKVCAM_LOGLEVEL_DEFAULT);
|
||||
AkVCam::Logger::setLogLevel(loglevel);
|
||||
AkLogDebug() << "Creating Service: " << CMIO_ASSISTANT_NAME << std::endl;
|
||||
auto server =
|
||||
xpc_connection_create_mach_service(CMIO_ASSISTANT_NAME,
|
||||
NULL,
|
||||
|
@ -50,6 +51,8 @@ int main(int argc, char **argv)
|
|||
break;
|
||||
}
|
||||
|
||||
AkLogDebug() << "Setting up handler" << std::endl;
|
||||
|
||||
xpc_connection_set_event_handler(server, ^(xpc_object_t event) {
|
||||
auto type = xpc_get_type(event);
|
||||
|
||||
|
@ -70,7 +73,9 @@ int main(int argc, char **argv)
|
|||
xpc_connection_resume(client);
|
||||
});
|
||||
|
||||
AkLogDebug() << "Resuming connection" << std::endl;
|
||||
xpc_connection_resume(server);
|
||||
AkLogDebug() << "Running loop" << std::endl;
|
||||
CFRunLoopRun();
|
||||
xpc_release(server);
|
||||
|
||||
|
|
|
@ -103,6 +103,13 @@ void AkVCam::Preferences::write(const std::string &key, double value)
|
|||
CFPreferencesSetAppValue(CFStringRef(*cfKey), *cfValue, PREFERENCES_ID);
|
||||
}
|
||||
|
||||
void AkVCam::Preferences::write(const std::string &key,
|
||||
std::vector<std::string> &value)
|
||||
{
|
||||
AkLogFunction();
|
||||
write(key, join(value, ","));
|
||||
}
|
||||
|
||||
std::shared_ptr<CFTypeRef> AkVCam::Preferences::read(const std::string &key)
|
||||
{
|
||||
AkLogFunction();
|
||||
|
@ -418,7 +425,7 @@ std::string AkVCam::Preferences::createDevicePath()
|
|||
int AkVCam::Preferences::cameraFromPath(const std::string &path)
|
||||
{
|
||||
for (size_t i = 0; i < camerasCount(); i++)
|
||||
if (cameraPath(i) == path && !cameraFormats(i).empty())
|
||||
if (cameraPath(i) == path)
|
||||
return int(i);
|
||||
|
||||
return -1;
|
||||
|
@ -438,23 +445,26 @@ bool AkVCam::Preferences::cameraIsInput(size_t cameraIndex)
|
|||
return readBool("cameras." + std::to_string(cameraIndex) + ".isinput");
|
||||
}
|
||||
|
||||
bool AkVCam::Preferences::cameraIsInput(const std::string &path)
|
||||
{
|
||||
auto cameraIndex = cameraFromPath(path);
|
||||
|
||||
if (cameraIndex < 0)
|
||||
return {};
|
||||
|
||||
return cameraIsInput(cameraIndex);
|
||||
}
|
||||
|
||||
std::wstring AkVCam::Preferences::cameraDescription(size_t cameraIndex)
|
||||
{
|
||||
if (cameraIndex >= camerasCount())
|
||||
return {};
|
||||
|
||||
return readWString("cameras."
|
||||
+ std::to_string(cameraIndex)
|
||||
+ ".description");
|
||||
}
|
||||
|
||||
void AkVCam::Preferences::cameraSetDescription(size_t cameraIndex,
|
||||
const std::wstring &description)
|
||||
{
|
||||
if (cameraIndex >= camerasCount())
|
||||
return;
|
||||
|
||||
write("cameras." + std::to_string(cameraIndex) + ".description",
|
||||
description);
|
||||
}
|
||||
|
||||
std::string AkVCam::Preferences::cameraPath(size_t cameraIndex)
|
||||
{
|
||||
return readString("cameras."
|
||||
|
@ -537,7 +547,7 @@ void AkVCam::Preferences::cameraRemoveFormat(size_t cameraIndex, int index)
|
|||
{
|
||||
AkLogFunction();
|
||||
|
||||
if (cameraIndex < 0 || !cameraIsInput(cameraIndex))
|
||||
if (!cameraIsInput(cameraIndex))
|
||||
return;
|
||||
|
||||
auto formats = cameraFormats(cameraIndex);
|
||||
|
@ -571,32 +581,71 @@ void AkVCam::Preferences::cameraRemoveFormat(size_t cameraIndex, int index)
|
|||
std::vector<std::string> AkVCam::Preferences::cameraConnections(size_t cameraIndex)
|
||||
{
|
||||
AkLogFunction();
|
||||
|
||||
if (cameraIndex < 0 || !cameraIsInput(cameraIndex))
|
||||
return {};
|
||||
|
||||
std::vector<std::string> cameraConnections;
|
||||
auto connections = readStringList("cameras."
|
||||
+ std::to_string(cameraIndex)
|
||||
+ ".connections");
|
||||
|
||||
for (auto &connection: connections) {
|
||||
if (connection.empty())
|
||||
continue;
|
||||
if (cameraIsInput(cameraIndex)) {
|
||||
auto connections = readStringList("cameras."
|
||||
+ std::to_string(cameraIndex)
|
||||
+ ".connections");
|
||||
|
||||
size_t pos = 0;
|
||||
auto outputIndex = std::stoi(connection, &pos);
|
||||
for (auto &connection: connections) {
|
||||
if (connection.empty())
|
||||
continue;
|
||||
|
||||
if (pos == connection.size())
|
||||
cameraConnections.push_back(cameraPath(outputIndex));
|
||||
size_t pos = 0;
|
||||
auto outputIndex = std::stoi(connection, &pos);
|
||||
|
||||
if (pos == connection.size())
|
||||
cameraConnections.push_back(cameraPath(outputIndex));
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < camerasCount(); i++)
|
||||
if (cameraIsInput(i)) {
|
||||
auto connections = readStringList("cameras."
|
||||
+ std::to_string(i)
|
||||
+ ".connections");
|
||||
|
||||
for (auto &connection: connections) {
|
||||
if (connection.empty())
|
||||
continue;
|
||||
|
||||
size_t pos = 0;
|
||||
auto outputIndex = std::stoi(connection, &pos);
|
||||
|
||||
if (pos == connection.size() && size_t(outputIndex) == cameraIndex)
|
||||
cameraConnections.push_back(cameraPath(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cameraConnections;
|
||||
}
|
||||
|
||||
std::vector<std::string> AkVCam::Preferences::cameraConnections(const std::string &path)
|
||||
void AkVCam::Preferences::cameraSetConnections(size_t cameraIndex,
|
||||
const std::vector<std::string> &connectedDevices)
|
||||
{
|
||||
AkLogFunction();
|
||||
|
||||
return cameraConnections(cameraFromPath(path));
|
||||
if (!cameraIsInput(cameraIndex))
|
||||
return;
|
||||
|
||||
std::vector<std::string> connections;
|
||||
|
||||
for (auto &connection: connectedDevices) {
|
||||
if (connection.empty())
|
||||
continue;
|
||||
|
||||
auto outputIndex = cameraFromPath(connection);
|
||||
|
||||
if (outputIndex < 0)
|
||||
continue;
|
||||
|
||||
if (cameraIsInput(outputIndex))
|
||||
continue;
|
||||
|
||||
connections.push_back(std::to_string(outputIndex));
|
||||
}
|
||||
|
||||
write("cameras." + std::to_string(cameraIndex) + ".connections",
|
||||
connections);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ namespace AkVCam
|
|||
void write(const std::string &key, const std::wstring &value);
|
||||
void write(const std::string &key, int value);
|
||||
void write(const std::string &key, double value);
|
||||
void write(const std::string &key, std::vector<std::string> &value);
|
||||
std::shared_ptr<CFTypeRef> read(const std::string &key);
|
||||
std::string readString(const std::string &key,
|
||||
const std::string &defaultValue={});
|
||||
|
@ -69,8 +70,9 @@ namespace AkVCam
|
|||
int cameraFromPath(const std::string &path);
|
||||
bool cameraExists(const std::string &path);
|
||||
bool cameraIsInput(size_t cameraIndex);
|
||||
bool cameraIsInput(const std::string &path);
|
||||
std::wstring cameraDescription(size_t cameraIndex);
|
||||
void cameraSetDescription(size_t cameraIndex,
|
||||
const std::wstring &description);
|
||||
std::string cameraPath(size_t cameraIndex);
|
||||
size_t formatsCount(size_t cameraIndex);
|
||||
VideoFormat cameraFormat(size_t cameraIndex, size_t formatIndex);
|
||||
|
@ -80,7 +82,8 @@ namespace AkVCam
|
|||
int index);
|
||||
void cameraRemoveFormat(size_t cameraIndex, int index);
|
||||
std::vector<std::string> cameraConnections(size_t cameraIndex);
|
||||
std::vector<std::string> cameraConnections(const std::string &path);
|
||||
void cameraSetConnections(size_t cameraIndex,
|
||||
const std::vector<std::string> &connectedDevices);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -82,11 +82,20 @@ std::string AkVCam::stringFromCFType(CFTypeRef cfType)
|
|||
if (data)
|
||||
return std::string(data, len);
|
||||
|
||||
auto cstr = new char[len];
|
||||
CFStringGetCString(CFStringRef(cfType),
|
||||
cstr,
|
||||
CFIndex(len),
|
||||
kCFStringEncodingUTF8);
|
||||
auto maxLen =
|
||||
CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8) + 1;
|
||||
auto cstr = new char[maxLen];
|
||||
memset(cstr, 0, maxLen);
|
||||
|
||||
if (!CFStringGetCString(CFStringRef(cfType),
|
||||
cstr,
|
||||
maxLen,
|
||||
kCFStringEncodingUTF8)) {
|
||||
delete [] cstr;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string str(cstr, len);
|
||||
delete [] cstr;
|
||||
|
||||
|
|
|
@ -323,38 +323,18 @@ void AkVCam::IpcBridge::unregisterPeer()
|
|||
this->d->m_portName.clear();
|
||||
}
|
||||
|
||||
std::vector<std::string> AkVCam::IpcBridge::listDevices() const
|
||||
std::vector<std::string> AkVCam::IpcBridge::devices() const
|
||||
{
|
||||
AkLogFunction();
|
||||
|
||||
if (!this->d->m_serverMessagePort)
|
||||
return {};
|
||||
|
||||
auto dictionary = xpc_dictionary_create(nullptr, nullptr, 0);
|
||||
xpc_dictionary_set_int64(dictionary, "message", AKVCAM_ASSISTANT_MSG_DEVICES);
|
||||
auto reply = xpc_connection_send_message_with_reply_sync(this->d->m_serverMessagePort,
|
||||
dictionary);
|
||||
xpc_release(dictionary);
|
||||
auto replyType = xpc_get_type(reply);
|
||||
|
||||
if (replyType != XPC_TYPE_DICTIONARY) {
|
||||
xpc_release(reply);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
auto devicesList = xpc_dictionary_get_array(reply, "devices");
|
||||
auto nCameras = Preferences::camerasCount();
|
||||
std::vector<std::string> devices;
|
||||
|
||||
for (size_t i = 0; i < xpc_array_get_count(devicesList); i++)
|
||||
devices.push_back(xpc_array_get_string(devicesList, i));
|
||||
|
||||
xpc_release(reply);
|
||||
|
||||
AkLogInfo() << "Devices:" << std::endl;
|
||||
|
||||
for (auto &device: devices)
|
||||
AkLogInfo() << " " << device << std::endl;
|
||||
for (size_t i = 0; i < nCameras; i++) {
|
||||
auto deviceId = Preferences::cameraPath(i);
|
||||
devices.push_back(deviceId);
|
||||
AkLogInfo() << " " << deviceId << std::endl;
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
@ -362,37 +342,24 @@ std::vector<std::string> AkVCam::IpcBridge::listDevices() const
|
|||
std::wstring AkVCam::IpcBridge::description(const std::string &deviceId) const
|
||||
{
|
||||
AkLogFunction();
|
||||
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||
|
||||
if (!this->d->m_serverMessagePort)
|
||||
return {};
|
||||
return Preferences::cameraDescription(cameraIndex);
|
||||
}
|
||||
|
||||
auto dictionary = xpc_dictionary_create(nullptr, nullptr, 0);
|
||||
xpc_dictionary_set_int64(dictionary, "message", AKVCAM_ASSISTANT_MSG_DEVICE_DESCRIPTION);
|
||||
xpc_dictionary_set_string(dictionary, "device", deviceId.c_str());
|
||||
auto reply = xpc_connection_send_message_with_reply_sync(this->d->m_serverMessagePort,
|
||||
dictionary);
|
||||
xpc_release(dictionary);
|
||||
auto replyType = xpc_get_type(reply);
|
||||
void AkVCam::IpcBridge::setDescription(const std::string &deviceId,
|
||||
const std::wstring &description)
|
||||
{
|
||||
AkLogFunction();
|
||||
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||
|
||||
if (replyType != XPC_TYPE_DICTIONARY) {
|
||||
xpc_release(reply);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
auto data = reinterpret_cast<const wchar_t *>(xpc_dictionary_get_data(reply,
|
||||
"description",
|
||||
&len));
|
||||
std::wstring description(data, len / sizeof(wchar_t));
|
||||
xpc_release(reply);
|
||||
|
||||
return description;
|
||||
return Preferences::cameraSetDescription(cameraIndex, description);
|
||||
}
|
||||
|
||||
std::vector<AkVCam::PixelFormat> AkVCam::IpcBridge::supportedPixelFormats(DeviceType type) const
|
||||
{
|
||||
UNUSED(type);
|
||||
if (type == DeviceTypeInput)
|
||||
return {PixelFormatRGB24};
|
||||
|
||||
return {
|
||||
PixelFormatRGB32,
|
||||
|
@ -404,48 +371,17 @@ std::vector<AkVCam::PixelFormat> AkVCam::IpcBridge::supportedPixelFormats(Device
|
|||
|
||||
AkVCam::PixelFormat AkVCam::IpcBridge::defaultPixelFormat(DeviceType type) const
|
||||
{
|
||||
UNUSED(type);
|
||||
|
||||
return PixelFormatYUY2;
|
||||
return type == DeviceTypeInput?
|
||||
PixelFormatRGB24:
|
||||
PixelFormatYUY2;
|
||||
}
|
||||
|
||||
std::vector<AkVCam::VideoFormat> AkVCam::IpcBridge::formats(const std::string &deviceId) const
|
||||
{
|
||||
AkLogFunction();
|
||||
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||
|
||||
if (!this->d->m_serverMessagePort)
|
||||
return {};
|
||||
|
||||
auto dictionary = xpc_dictionary_create(nullptr, nullptr, 0);
|
||||
xpc_dictionary_set_int64(dictionary, "message", AKVCAM_ASSISTANT_MSG_DEVICE_FORMATS);
|
||||
xpc_dictionary_set_string(dictionary, "device", deviceId.c_str());
|
||||
auto reply = xpc_connection_send_message_with_reply_sync(this->d->m_serverMessagePort,
|
||||
dictionary);
|
||||
xpc_release(dictionary);
|
||||
auto replyType = xpc_get_type(reply);
|
||||
|
||||
if (replyType != XPC_TYPE_DICTIONARY) {
|
||||
xpc_release(reply);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
auto formatsList = xpc_dictionary_get_array(reply, "formats");
|
||||
std::vector<VideoFormat> formats;
|
||||
|
||||
for (size_t i = 0; i < xpc_array_get_count(formatsList); i++) {
|
||||
auto format = xpc_array_get_dictionary(formatsList, i);
|
||||
auto fourcc = FourCC(xpc_dictionary_get_uint64(format, "fourcc"));
|
||||
auto width = int(xpc_dictionary_get_int64(format, "width"));
|
||||
auto height = int(xpc_dictionary_get_int64(format, "height"));
|
||||
auto fps = Fraction(xpc_dictionary_get_string(format, "fps"));
|
||||
|
||||
formats.push_back(VideoFormat(fourcc, width, height, {fps}));
|
||||
}
|
||||
|
||||
xpc_release(reply);
|
||||
|
||||
return formats;
|
||||
return Preferences::cameraFormats(cameraIndex);
|
||||
}
|
||||
|
||||
std::string AkVCam::IpcBridge::broadcaster(const std::string &deviceId) const
|
||||
|
@ -699,7 +635,9 @@ std::string AkVCam::IpcBridge::clientExe(uint64_t pid) const
|
|||
|
||||
AkVCam::IpcBridge::DeviceType AkVCam::IpcBridge::deviceType(const std::string &deviceId)
|
||||
{
|
||||
return Preferences::cameraIsInput(deviceId)?
|
||||
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||
|
||||
return Preferences::cameraIsInput(cameraIndex)?
|
||||
DeviceTypeInput:
|
||||
DeviceTypeOutput;
|
||||
}
|
||||
|
@ -732,124 +670,31 @@ void AkVCam::IpcBridge::removeFormat(const std::string &deviceId, int index)
|
|||
index);
|
||||
}
|
||||
|
||||
std::string AkVCam::IpcBridge::deviceCreate(const std::wstring &description,
|
||||
const std::vector<VideoFormat> &formats,
|
||||
DeviceType type)
|
||||
{
|
||||
AkLogFunction();
|
||||
|
||||
if (!this->d->m_serverMessagePort || !this->d->m_messagePort) {
|
||||
this->d->m_error = L"Can't register peer";
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
auto dictionary = xpc_dictionary_create(nullptr, nullptr, 0);
|
||||
xpc_dictionary_set_int64(dictionary, "message", AKVCAM_ASSISTANT_MSG_DEVICE_CREATE);
|
||||
xpc_dictionary_set_string(dictionary, "port", this->d->m_portName.c_str());
|
||||
xpc_dictionary_set_data(dictionary,
|
||||
"description",
|
||||
description.c_str(),
|
||||
description.size() * sizeof(wchar_t));
|
||||
xpc_dictionary_set_bool(dictionary, "isinput", type == DeviceTypeInput);
|
||||
auto formatsList = xpc_array_create(nullptr, 0);
|
||||
|
||||
for (auto &format: formats) {
|
||||
auto dictFormat = xpc_dictionary_create(nullptr, nullptr, 0);
|
||||
xpc_dictionary_set_uint64(dictFormat, "fourcc", format.fourcc());
|
||||
xpc_dictionary_set_int64(dictFormat, "width", format.width());
|
||||
xpc_dictionary_set_int64(dictFormat, "height", format.height());
|
||||
xpc_dictionary_set_string(dictFormat, "fps", format.minimumFrameRate().toString().c_str());
|
||||
xpc_array_append_value(formatsList, dictFormat);
|
||||
}
|
||||
|
||||
xpc_dictionary_set_value(dictionary, "formats", formatsList);
|
||||
|
||||
auto reply = xpc_connection_send_message_with_reply_sync(this->d->m_serverMessagePort,
|
||||
dictionary);
|
||||
xpc_release(dictionary);
|
||||
auto replyType = xpc_get_type(reply);
|
||||
|
||||
if (replyType != XPC_TYPE_DICTIONARY) {
|
||||
this->d->m_error = L"Can't set virtual camera formats";
|
||||
xpc_release(reply);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string deviceId(xpc_dictionary_get_string(reply, "device"));
|
||||
xpc_release(reply);
|
||||
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
bool AkVCam::IpcBridge::deviceEdit(const std::string &deviceId,
|
||||
const std::wstring &description,
|
||||
const std::vector<VideoFormat> &formats)
|
||||
{
|
||||
AkLogFunction();
|
||||
|
||||
auto type = this->deviceType(deviceId);
|
||||
this->deviceDestroy(deviceId);
|
||||
|
||||
if (this->deviceCreate(description.empty()?
|
||||
L"AvKys Virtual Camera":
|
||||
description,
|
||||
formats,
|
||||
type).empty())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AkVCam::IpcBridge::changeDescription(const std::string &deviceId,
|
||||
const std::wstring &description)
|
||||
{
|
||||
AkLogFunction();
|
||||
|
||||
auto formats = this->formats(deviceId);
|
||||
|
||||
if (formats.empty())
|
||||
return false;
|
||||
|
||||
auto type = this->deviceType(deviceId);
|
||||
this->deviceDestroy(deviceId);
|
||||
|
||||
if (this->deviceCreate(description.empty()?
|
||||
L"AvKys Virtual Camera":
|
||||
description,
|
||||
formats,
|
||||
type).empty())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AkVCam::IpcBridge::deviceDestroy(const std::string &deviceId)
|
||||
void AkVCam::IpcBridge::update()
|
||||
{
|
||||
AkLogFunction();
|
||||
|
||||
if (!this->d->m_serverMessagePort)
|
||||
return false;
|
||||
return;
|
||||
|
||||
auto dictionary = xpc_dictionary_create(nullptr, nullptr, 0);
|
||||
xpc_dictionary_set_int64(dictionary, "message", AKVCAM_ASSISTANT_MSG_DEVICE_DESTROY);
|
||||
xpc_dictionary_set_string(dictionary, "device", deviceId.c_str());
|
||||
xpc_connection_send_message(this->d->m_serverMessagePort,
|
||||
dictionary);
|
||||
xpc_dictionary_set_int64(dictionary,
|
||||
"message",
|
||||
AKVCAM_ASSISTANT_MSG_DEVICE_UPDATE);
|
||||
xpc_connection_send_message(this->d->m_serverMessagePort, dictionary);
|
||||
xpc_release(dictionary);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AkVCam::IpcBridge::destroyAllDevices()
|
||||
std::vector<std::string> AkVCam::IpcBridge::connections(const std::string &deviceId)
|
||||
{
|
||||
AkLogFunction();
|
||||
return Preferences::cameraConnections(Preferences::cameraFromPath(deviceId));
|
||||
}
|
||||
|
||||
for (auto &device: this->listDevices())
|
||||
this->deviceDestroy(device);
|
||||
|
||||
return true;
|
||||
void AkVCam::IpcBridge::setConnections(const std::string &deviceId,
|
||||
const std::vector<std::string> &connectedDevices)
|
||||
{
|
||||
Preferences::cameraSetConnections(Preferences::cameraFromPath(deviceId),
|
||||
connectedDevices);
|
||||
}
|
||||
|
||||
void AkVCam::IpcBridge::updateDevices()
|
||||
|
|
|
@ -234,7 +234,7 @@ OSStatus AkVCam::PluginInterface::InitializeWithObjectID(CMIOObjectID objectID)
|
|||
|
||||
this->m_objectID = objectID;
|
||||
|
||||
for (auto deviceId: this->d->m_ipcBridge.listDevices())
|
||||
for (auto &deviceId: this->d->m_ipcBridge.devices())
|
||||
this->deviceAdded(this, deviceId);
|
||||
|
||||
return kCMIOHardwareNoError;
|
||||
|
@ -301,7 +301,7 @@ void AkVCam::PluginInterface::devicesUpdated(void *userData, void *unused)
|
|||
for (auto &deviceId: devices)
|
||||
self->destroyDevice(deviceId);
|
||||
|
||||
for (auto &deviceId: self->d->m_ipcBridge.listDevices()) {
|
||||
for (auto &deviceId: self->d->m_ipcBridge.devices()) {
|
||||
auto description = self->d->m_ipcBridge.description(deviceId);
|
||||
auto formats = self->d->m_ipcBridge.formats(deviceId);
|
||||
auto type = self->d->m_ipcBridge.deviceType(deviceId);
|
||||
|
@ -315,7 +315,8 @@ void AkVCam::PluginInterface::frameReady(void *userData,
|
|||
{
|
||||
AkLogFunction();
|
||||
auto self = reinterpret_cast<PluginInterface *>(userData);
|
||||
auto connections = Preferences::cameraConnections(deviceId);
|
||||
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||
auto connections = Preferences::cameraConnections(cameraIndex);
|
||||
|
||||
for (auto device: self->m_devices)
|
||||
if (std::find(connections.begin(),
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
isEmpty(CMIO_PLUGINS_DAL_PATH):
|
||||
CMIO_PLUGINS_DAL_PATH = /Library/CoreMediaIO/Plug-Ins/DAL
|
||||
isEmpty(CMIO_DAEMONS_PATH):
|
||||
CMIO_DAEMONS_PATH = ~/Library/LaunchAgents
|
||||
CMIO_DAEMONS_PATH = /Library/LaunchAgents
|
||||
isEmpty(CMIO_PLUGIN_NAME):
|
||||
CMIO_PLUGIN_NAME = AkVirtualCamera
|
||||
isEmpty(CMIO_PLUGIN_ASSISTANT_NAME):
|
||||
|
|
|
@ -303,7 +303,7 @@ void AkVCam::IpcBridge::unregisterPeer()
|
|||
this->d->m_portName.clear();
|
||||
}
|
||||
|
||||
std::vector<std::string> AkVCam::IpcBridge::listDevices() const
|
||||
std::vector<std::string> AkVCam::IpcBridge::devices() const
|
||||
{
|
||||
AkLogFunction();
|
||||
std::vector<std::string> devices;
|
||||
|
@ -649,7 +649,7 @@ bool AkVCam::IpcBridge::needsRestart(Operation operation) const
|
|||
{
|
||||
return operation == OperationDestroyAll
|
||||
|| (operation == OperationDestroy
|
||||
&& this->listDevices().size() == 1);
|
||||
&& this->devices().size() == 1);
|
||||
}
|
||||
|
||||
bool AkVCam::IpcBridge::canApply(AkVCam::IpcBridge::Operation operation) const
|
||||
|
|
0
ports/ci/appveyor/build.bat
Normal file → Executable file
0
ports/ci/appveyor/build.bat
Normal file → Executable file
0
ports/ci/appveyor/build.sh
Executable file → Normal file
0
ports/ci/appveyor/build.sh
Executable file → Normal file
0
ports/ci/appveyor/deploy.bat
Normal file → Executable file
0
ports/ci/appveyor/deploy.bat
Normal file → Executable file
0
ports/ci/appveyor/deploy.sh
Executable file → Normal file
0
ports/ci/appveyor/deploy.sh
Executable file → Normal file
0
ports/ci/appveyor/install_deps.bat
Normal file → Executable file
0
ports/ci/appveyor/install_deps.bat
Normal file → Executable file
0
ports/ci/appveyor/install_deps.sh
Executable file → Normal file
0
ports/ci/appveyor/install_deps.sh
Executable file → Normal file
0
ports/ci/appveyor/push_artifacts.bat
Normal file → Executable file
0
ports/ci/appveyor/push_artifacts.bat
Normal file → Executable file
0
ports/ci/appveyor/upload.bat
Normal file → Executable file
0
ports/ci/appveyor/upload.bat
Normal file → Executable file
0
ports/ci/travis/build.sh
Executable file → Normal file
0
ports/ci/travis/build.sh
Executable file → Normal file
0
ports/ci/travis/deploy.sh
Executable file → Normal file
0
ports/ci/travis/deploy.sh
Executable file → Normal file
0
ports/ci/travis/install_deps.sh
Executable file → Normal file
0
ports/ci/travis/install_deps.sh
Executable file → Normal file
0
ports/ci/travis/upload.sh
Executable file → Normal file
0
ports/ci/travis/upload.sh
Executable file → Normal file
0
ports/deploy/deploy.py
Executable file → Normal file
0
ports/deploy/deploy.py
Executable file → Normal file
|
@ -23,6 +23,15 @@ Component.prototype.createOperations = function()
|
|||
"rm",
|
||||
"-rf",
|
||||
"/Library/CoreMediaIO/Plug-Ins/DAL/@Name@.plugin");
|
||||
|
||||
component.addElevatedOperation("Execute",
|
||||
"chmod",
|
||||
"+x",
|
||||
"@TargetDir@/@Name@.plugin/Contents/Resources/AkVCamAssistant");
|
||||
component.addElevatedOperation("Execute",
|
||||
"chmod",
|
||||
"+x",
|
||||
"@TargetDir@/@Name@.plugin/Contents/Resources/AkVCamManager");
|
||||
}
|
||||
|
||||
// Create a symlink to the plugin.
|
||||
|
|
0
share/TestFrame/TestFrame.py
Executable file → Normal file
0
share/TestFrame/TestFrame.py
Executable file → Normal file
Loading…
Reference in a new issue