Working in the DirectShow plugin.
This commit is contained in:
parent
1ce2384623
commit
bd5e1d4e94
20 changed files with 1382 additions and 2295 deletions
|
@ -262,12 +262,10 @@ AkVCam::CmdParser::CmdParser()
|
||||||
"",
|
"",
|
||||||
"Show clients using the camera.",
|
"Show clients using the camera.",
|
||||||
AKVCAM_BIND_FUNC(CmdParserPrivate::showClients));
|
AKVCAM_BIND_FUNC(CmdParserPrivate::showClients));
|
||||||
this->d->m_ipcBridge.connectService();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AkVCam::CmdParser::~CmdParser()
|
AkVCam::CmdParser::~CmdParser()
|
||||||
{
|
{
|
||||||
this->d->m_ipcBridge.disconnectService();
|
|
||||||
delete this->d;
|
delete this->d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,10 +104,6 @@ namespace AkVCam
|
||||||
int logLevel() const;
|
int logLevel() const;
|
||||||
void setLogLevel(int logLevel);
|
void setLogLevel(int logLevel);
|
||||||
|
|
||||||
// Manage main service connection.
|
|
||||||
void connectService();
|
|
||||||
void disconnectService();
|
|
||||||
|
|
||||||
// Register the peer to the global server.
|
// Register the peer to the global server.
|
||||||
bool registerPeer();
|
bool registerPeer();
|
||||||
|
|
||||||
|
|
|
@ -54,10 +54,6 @@
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_SETBROADCASTING 0x401
|
#define AKVCAM_ASSISTANT_MSG_DEVICE_SETBROADCASTING 0x401
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_CONTROLS_UPDATED 0x402
|
#define AKVCAM_ASSISTANT_MSG_DEVICE_CONTROLS_UPDATED 0x402
|
||||||
|
|
||||||
// Connections
|
|
||||||
#define AKVCAM_ASSISTANT_MSG_CONNECTIONS 0x500
|
|
||||||
#define AKVCAM_ASSISTANT_MSG_SETCONNECTIONS 0x501
|
|
||||||
|
|
||||||
namespace AkVCam
|
namespace AkVCam
|
||||||
{
|
{
|
||||||
using XpcMessage = std::function<void (xpc_connection_t, xpc_object_t)>;
|
using XpcMessage = std::function<void (xpc_connection_t, xpc_object_t)>;
|
||||||
|
|
|
@ -361,7 +361,7 @@ void AkVCam::Preferences::removeCamera(const std::string &path)
|
||||||
if (cameraIndex < 0)
|
if (cameraIndex < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cameraSetFormats(cameraIndex, {});
|
cameraSetFormats(size_t(cameraIndex), {});
|
||||||
|
|
||||||
auto nCameras = camerasCount();
|
auto nCameras = camerasCount();
|
||||||
deleteAllKeys("cameras." + std::to_string(cameraIndex));
|
deleteAllKeys("cameras." + std::to_string(cameraIndex));
|
||||||
|
@ -451,6 +451,7 @@ void AkVCam::Preferences::cameraSetDescription(size_t cameraIndex,
|
||||||
|
|
||||||
write("cameras." + std::to_string(cameraIndex) + ".description",
|
write("cameras." + std::to_string(cameraIndex) + ".description",
|
||||||
description);
|
description);
|
||||||
|
sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AkVCam::Preferences::cameraPath(size_t cameraIndex)
|
std::string AkVCam::Preferences::cameraPath(size_t cameraIndex)
|
||||||
|
@ -536,7 +537,7 @@ void AkVCam::Preferences::cameraAddFormat(size_t cameraIndex,
|
||||||
auto formats = cameraFormats(cameraIndex);
|
auto formats = cameraFormats(cameraIndex);
|
||||||
|
|
||||||
if (index < 0 || index > int(formats.size()))
|
if (index < 0 || index > int(formats.size()))
|
||||||
index = formats.size();
|
index = int(formats.size());
|
||||||
|
|
||||||
formats.insert(formats.begin() + index, format);
|
formats.insert(formats.begin() + index, format);
|
||||||
write("cameras."
|
write("cameras."
|
||||||
|
@ -563,7 +564,6 @@ void AkVCam::Preferences::cameraAddFormat(size_t cameraIndex,
|
||||||
void AkVCam::Preferences::cameraRemoveFormat(size_t cameraIndex, int index)
|
void AkVCam::Preferences::cameraRemoveFormat(size_t cameraIndex, int index)
|
||||||
{
|
{
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
|
|
||||||
auto formats = cameraFormats(cameraIndex);
|
auto formats = cameraFormats(cameraIndex);
|
||||||
|
|
||||||
if (index < 0 || index >= int(formats.size()))
|
if (index < 0 || index >= int(formats.size()))
|
||||||
|
@ -592,26 +592,6 @@ void AkVCam::Preferences::cameraRemoveFormat(size_t cameraIndex, int index)
|
||||||
sync();
|
sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring AkVCam::Preferences::picture()
|
|
||||||
{
|
|
||||||
return readWString("picture");
|
|
||||||
}
|
|
||||||
|
|
||||||
void AkVCam::Preferences::setPicture(const std::wstring &picture)
|
|
||||||
{
|
|
||||||
write("picture", picture);
|
|
||||||
}
|
|
||||||
|
|
||||||
int AkVCam::Preferences::logLevel()
|
|
||||||
{
|
|
||||||
return readInt("loglevel", AKVCAM_LOGLEVEL_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AkVCam::Preferences::setLogLevel(int logLevel)
|
|
||||||
{
|
|
||||||
write("loglevel", logLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
int AkVCam::Preferences::cameraControlValue(size_t cameraIndex,
|
int AkVCam::Preferences::cameraControlValue(size_t cameraIndex,
|
||||||
const std::string &key)
|
const std::string &key)
|
||||||
{
|
{
|
||||||
|
@ -623,4 +603,27 @@ void AkVCam::Preferences::cameraSetControlValue(size_t cameraIndex,
|
||||||
int value)
|
int value)
|
||||||
{
|
{
|
||||||
write("cameras." + std::to_string(cameraIndex) + ".controls." + key, value);
|
write("cameras." + std::to_string(cameraIndex) + ".controls." + key, value);
|
||||||
|
sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring AkVCam::Preferences::picture()
|
||||||
|
{
|
||||||
|
return readWString("picture");
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::setPicture(const std::wstring &picture)
|
||||||
|
{
|
||||||
|
write("picture", picture);
|
||||||
|
sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
int AkVCam::Preferences::logLevel()
|
||||||
|
{
|
||||||
|
return readInt("loglevel", AKVCAM_LOGLEVEL_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::setLogLevel(int logLevel)
|
||||||
|
{
|
||||||
|
write("loglevel", logLevel);
|
||||||
|
sync();
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,8 +74,6 @@ namespace AkVCam
|
||||||
std::vector<VideoFormat> cameraFormats(size_t cameraIndex);
|
std::vector<VideoFormat> cameraFormats(size_t cameraIndex);
|
||||||
void cameraSetFormats(size_t cameraIndex,
|
void cameraSetFormats(size_t cameraIndex,
|
||||||
const std::vector<VideoFormat> &formats);
|
const std::vector<VideoFormat> &formats);
|
||||||
void cameraFormats(size_t cameraIndex,
|
|
||||||
const std::vector<VideoFormat> &formats);
|
|
||||||
void cameraAddFormat(size_t cameraIndex,
|
void cameraAddFormat(size_t cameraIndex,
|
||||||
const VideoFormat &format,
|
const VideoFormat &format,
|
||||||
int index);
|
int index);
|
||||||
|
|
|
@ -80,11 +80,7 @@ namespace AkVCam
|
||||||
void connectionInterrupted();
|
void connectionInterrupted();
|
||||||
|
|
||||||
// Utility methods
|
// Utility methods
|
||||||
std::string homePath() const;
|
|
||||||
bool fileExists(const std::wstring &path) const;
|
|
||||||
bool fileExists(const std::string &path) const;
|
bool fileExists(const std::string &path) const;
|
||||||
bool mkpath(const std::string &path) const;
|
|
||||||
bool rm(const std::string &path) const;
|
|
||||||
static std::string locatePluginPath();
|
static std::string locatePluginPath();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -148,30 +144,10 @@ void AkVCam::IpcBridge::setLogLevel(int logLevel)
|
||||||
Logger::setLogLevel(logLevel);
|
Logger::setLogLevel(logLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AkVCam::IpcBridge::connectService()
|
|
||||||
{
|
|
||||||
AkLogFunction();
|
|
||||||
this->registerPeer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AkVCam::IpcBridge::disconnectService()
|
|
||||||
{
|
|
||||||
AkLogFunction();
|
|
||||||
this->unregisterPeer();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AkVCam::IpcBridge::registerPeer()
|
bool AkVCam::IpcBridge::registerPeer()
|
||||||
{
|
{
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
|
|
||||||
std::string plistFile =
|
|
||||||
CMIO_DAEMONS_PATH "/" CMIO_ASSISTANT_NAME ".plist";
|
|
||||||
|
|
||||||
auto daemon = replace(plistFile, "~", this->d->homePath());
|
|
||||||
|
|
||||||
if (!this->d->fileExists(daemon))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (this->d->m_serverMessagePort)
|
if (this->d->m_serverMessagePort)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -318,7 +294,10 @@ std::wstring AkVCam::IpcBridge::description(const std::string &deviceId) const
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||||
|
|
||||||
return Preferences::cameraDescription(cameraIndex);
|
if (cameraIndex < 0)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return Preferences::cameraDescription(size_t(cameraIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AkVCam::IpcBridge::setDescription(const std::string &deviceId,
|
void AkVCam::IpcBridge::setDescription(const std::string &deviceId,
|
||||||
|
@ -327,7 +306,8 @@ void AkVCam::IpcBridge::setDescription(const std::string &deviceId,
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||||
|
|
||||||
return Preferences::cameraSetDescription(cameraIndex, description);
|
if (cameraIndex >= 0)
|
||||||
|
Preferences::cameraSetDescription(size_t(cameraIndex), description);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AkVCam::PixelFormat> AkVCam::IpcBridge::supportedPixelFormats(StreamType type) const
|
std::vector<AkVCam::PixelFormat> AkVCam::IpcBridge::supportedPixelFormats(StreamType type) const
|
||||||
|
@ -355,7 +335,10 @@ std::vector<AkVCam::VideoFormat> AkVCam::IpcBridge::formats(const std::string &d
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||||
|
|
||||||
return Preferences::cameraFormats(cameraIndex);
|
if (cameraIndex < 0)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return Preferences::cameraFormats(size_t(cameraIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AkVCam::IpcBridge::setFormats(const std::string &deviceId,
|
void AkVCam::IpcBridge::setFormats(const std::string &deviceId,
|
||||||
|
@ -363,7 +346,8 @@ void AkVCam::IpcBridge::setFormats(const std::string &deviceId,
|
||||||
{
|
{
|
||||||
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||||
|
|
||||||
return Preferences::cameraSetFormats(cameraIndex, formats);
|
if (cameraIndex >= 0)
|
||||||
|
Preferences::cameraSetFormats(size_t(cameraIndex), formats);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AkVCam::IpcBridge::broadcaster(const std::string &deviceId) const
|
std::string AkVCam::IpcBridge::broadcaster(const std::string &deviceId) const
|
||||||
|
@ -409,7 +393,7 @@ std::vector<AkVCam::DeviceControl> AkVCam::IpcBridge::controls(const std::string
|
||||||
for (auto &control: this->d->controls()) {
|
for (auto &control: this->d->controls()) {
|
||||||
controls.push_back(control);
|
controls.push_back(control);
|
||||||
controls.back().value =
|
controls.back().value =
|
||||||
Preferences::cameraControlValue(cameraIndex, control.id);
|
Preferences::cameraControlValue(size_t(cameraIndex), control.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return controls;
|
return controls;
|
||||||
|
@ -428,13 +412,14 @@ void AkVCam::IpcBridge::setControls(const std::string &deviceId,
|
||||||
|
|
||||||
for (auto &control: this->d->controls()) {
|
for (auto &control: this->d->controls()) {
|
||||||
auto oldValue =
|
auto oldValue =
|
||||||
Preferences::cameraControlValue(cameraIndex, control.id);
|
Preferences::cameraControlValue(size_t(cameraIndex),
|
||||||
|
control.id);
|
||||||
|
|
||||||
if (controls.count(control.id)) {
|
if (controls.count(control.id)) {
|
||||||
auto newValue = controls.at(control.id);
|
auto newValue = controls.at(control.id);
|
||||||
|
|
||||||
if (newValue != oldValue) {
|
if (newValue != oldValue) {
|
||||||
Preferences::cameraSetControlValue(cameraIndex,
|
Preferences::cameraSetControlValue(size_t(cameraIndex),
|
||||||
control.id,
|
control.id,
|
||||||
newValue);
|
newValue);
|
||||||
updated = true;
|
updated = true;
|
||||||
|
@ -490,13 +475,13 @@ std::vector<std::string> AkVCam::IpcBridge::listeners(const std::string &deviceI
|
||||||
std::vector<uint64_t> AkVCam::IpcBridge::clientsPids() const
|
std::vector<uint64_t> AkVCam::IpcBridge::clientsPids() const
|
||||||
{
|
{
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
auto driverPath = this->d->locatePluginPath();
|
auto pluginPath = this->d->locatePluginPath();
|
||||||
AkLogDebug() << "Plugin path: " << driverPath << std::endl;
|
AkLogDebug() << "Plugin path: " << pluginPath << std::endl;
|
||||||
|
|
||||||
if (driverPath.empty())
|
if (pluginPath.empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
auto path = driverPath + "/Contents/MacOS/" CMIO_PLUGIN_NAME;
|
auto path = pluginPath + "/Contents/MacOS/" CMIO_PLUGIN_NAME;
|
||||||
AkLogDebug() << "Plugin binary: " << path << std::endl;
|
AkLogDebug() << "Plugin binary: " << path << std::endl;
|
||||||
|
|
||||||
if (!this->d->fileExists(path))
|
if (!this->d->fileExists(path))
|
||||||
|
@ -553,16 +538,22 @@ void AkVCam::IpcBridge::addFormat(const std::string &deviceId,
|
||||||
int index)
|
int index)
|
||||||
{
|
{
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
Preferences::cameraAddFormat(Preferences::cameraFromPath(deviceId),
|
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||||
format,
|
|
||||||
index);
|
if (cameraIndex >= 0)
|
||||||
|
Preferences::cameraAddFormat(size_t(cameraIndex),
|
||||||
|
format,
|
||||||
|
index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AkVCam::IpcBridge::removeFormat(const std::string &deviceId, int index)
|
void AkVCam::IpcBridge::removeFormat(const std::string &deviceId, int index)
|
||||||
{
|
{
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
Preferences::cameraRemoveFormat(Preferences::cameraFromPath(deviceId),
|
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||||
index);
|
|
||||||
|
if (cameraIndex >= 0)
|
||||||
|
Preferences::cameraRemoveFormat(size_t(cameraIndex),
|
||||||
|
index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AkVCam::IpcBridge::updateDevices()
|
void AkVCam::IpcBridge::updateDevices()
|
||||||
|
@ -578,7 +569,6 @@ void AkVCam::IpcBridge::updateDevices()
|
||||||
AKVCAM_ASSISTANT_MSG_DEVICE_UPDATE);
|
AKVCAM_ASSISTANT_MSG_DEVICE_UPDATE);
|
||||||
xpc_connection_send_message(this->d->m_serverMessagePort, dictionary);
|
xpc_connection_send_message(this->d->m_serverMessagePort, dictionary);
|
||||||
xpc_release(dictionary);
|
xpc_release(dictionary);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AkVCam::IpcBridge::deviceStart(const std::string &deviceId,
|
bool AkVCam::IpcBridge::deviceStart(const std::string &deviceId,
|
||||||
|
@ -957,11 +947,15 @@ void AkVCam::IpcBridgePrivate::controlsUpdated(xpc_connection_t client,
|
||||||
std::string deviceId =
|
std::string deviceId =
|
||||||
xpc_dictionary_get_string(event, "device");
|
xpc_dictionary_get_string(event, "device");
|
||||||
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||||
|
|
||||||
|
if (cameraIndex < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
std::map<std::string, int> controls;
|
std::map<std::string, int> controls;
|
||||||
|
|
||||||
for (auto &control: this->controls())
|
for (auto &control: this->controls())
|
||||||
controls[control.id] =
|
controls[control.id] =
|
||||||
Preferences::cameraControlValue(cameraIndex, control.id);
|
Preferences::cameraControlValue(size_t(cameraIndex), control.id);
|
||||||
|
|
||||||
for (auto bridge: this->m_bridges)
|
for (auto bridge: this->m_bridges)
|
||||||
AKVCAM_EMIT(bridge,
|
AKVCAM_EMIT(bridge,
|
||||||
|
@ -1029,21 +1023,6 @@ void AkVCam::IpcBridgePrivate::connectionInterrupted()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AkVCam::IpcBridgePrivate::homePath() const
|
|
||||||
{
|
|
||||||
auto homePath = NSHomeDirectory();
|
|
||||||
|
|
||||||
if (!homePath)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
return std::string(homePath.UTF8String);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AkVCam::IpcBridgePrivate::fileExists(const std::wstring &path) const
|
|
||||||
{
|
|
||||||
return this->fileExists(std::string(path.begin(), path.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AkVCam::IpcBridgePrivate::fileExists(const std::string &path) const
|
bool AkVCam::IpcBridgePrivate::fileExists(const std::string &path) const
|
||||||
{
|
{
|
||||||
struct stat stats;
|
struct stat stats;
|
||||||
|
@ -1052,62 +1031,6 @@ bool AkVCam::IpcBridgePrivate::fileExists(const std::string &path) const
|
||||||
return stat(path.c_str(), &stats) == 0;
|
return stat(path.c_str(), &stats) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AkVCam::IpcBridgePrivate::mkpath(const std::string &path) const
|
|
||||||
{
|
|
||||||
if (path.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (this->fileExists(path))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Create parent folders
|
|
||||||
for (auto pos = path.find('/');
|
|
||||||
pos != std::string::npos;
|
|
||||||
pos = path.find('/', pos + 1)) {
|
|
||||||
auto path_ = path.substr(0, pos);
|
|
||||||
|
|
||||||
if (path_.empty() || this->fileExists(path_))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mkdir(path_.c_str(),
|
|
||||||
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !mkdir(path.c_str(),
|
|
||||||
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AkVCam::IpcBridgePrivate::rm(const std::string &path) const
|
|
||||||
{
|
|
||||||
if (path.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
struct stat stats;
|
|
||||||
memset(&stats, 0, sizeof(struct stat));
|
|
||||||
|
|
||||||
if (stat(path.c_str(), &stats))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
if (S_ISDIR(stats.st_mode)) {
|
|
||||||
auto dir = opendir(path.c_str());
|
|
||||||
|
|
||||||
while (auto entry = readdir(dir))
|
|
||||||
if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
|
|
||||||
this->rm(entry->d_name);
|
|
||||||
|
|
||||||
closedir(dir);
|
|
||||||
|
|
||||||
ok &= !rmdir(path.c_str());
|
|
||||||
} else {
|
|
||||||
ok &= !::remove(path.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AkVCam::IpcBridgePrivate::locatePluginPath()
|
std::string AkVCam::IpcBridgePrivate::locatePluginPath()
|
||||||
{
|
{
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
|
|
|
@ -157,7 +157,6 @@ AkVCam::PluginInterface::PluginInterface():
|
||||||
this->d->m_ref = 0;
|
this->d->m_ref = 0;
|
||||||
this->d->m_reserved = 0;
|
this->d->m_reserved = 0;
|
||||||
|
|
||||||
this->d->m_ipcBridge.connectService();
|
|
||||||
this->d->m_ipcBridge.connectServerStateChanged(this, &PluginInterface::serverStateChanged);
|
this->d->m_ipcBridge.connectServerStateChanged(this, &PluginInterface::serverStateChanged);
|
||||||
this->d->m_ipcBridge.connectDeviceAdded(this, &PluginInterface::deviceAdded);
|
this->d->m_ipcBridge.connectDeviceAdded(this, &PluginInterface::deviceAdded);
|
||||||
this->d->m_ipcBridge.connectDeviceRemoved(this, &PluginInterface::deviceRemoved);
|
this->d->m_ipcBridge.connectDeviceRemoved(this, &PluginInterface::deviceRemoved);
|
||||||
|
@ -170,7 +169,6 @@ AkVCam::PluginInterface::PluginInterface():
|
||||||
|
|
||||||
AkVCam::PluginInterface::~PluginInterface()
|
AkVCam::PluginInterface::~PluginInterface()
|
||||||
{
|
{
|
||||||
this->d->m_ipcBridge.disconnectService();
|
|
||||||
delete this->d->pluginInterface;
|
delete this->d->pluginInterface;
|
||||||
delete this->d;
|
delete this->d;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,18 +21,17 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
#include "PlatformUtils/src/preferences.h"
|
||||||
#include "PlatformUtils/src/utils.h"
|
#include "PlatformUtils/src/utils.h"
|
||||||
#include "VCamUtils/src/logger/logger.h"
|
#include "VCamUtils/src/logger/logger.h"
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
auto loglevel = AkVCam::regReadInt("loglevel", AKVCAM_LOGLEVEL_DEFAULT);
|
auto loglevel = AkVCam::Preferences::logLevel();
|
||||||
AkVCam::Logger::setLogLevel(loglevel);
|
AkVCam::Logger::setLogLevel(loglevel);
|
||||||
auto temp = AkVCam::tempPath();
|
auto defaultLogFile = AkVCam::tempPath()
|
||||||
auto logFile =
|
+ "\\" DSHOW_PLUGIN_ASSISTANT_NAME ".log";
|
||||||
AkVCam::regReadString("logfile",
|
auto logFile = AkVCam::Preferences::readString("logfile", defaultLogFile);
|
||||||
std::string(temp.begin(), temp.end())
|
|
||||||
+ "\\" DSHOW_PLUGIN_ASSISTANT_NAME ".log");
|
|
||||||
AkVCam::Logger::setLogFile(logFile);
|
AkVCam::Logger::setLogFile(logFile);
|
||||||
AkVCam::Service service;
|
AkVCam::Service service;
|
||||||
|
|
||||||
|
|
|
@ -42,20 +42,6 @@ namespace AkVCam
|
||||||
{
|
{
|
||||||
std::string broadcaster;
|
std::string broadcaster;
|
||||||
std::vector<std::string> listeners;
|
std::vector<std::string> listeners;
|
||||||
bool horizontalMirror;
|
|
||||||
bool verticalMirror;
|
|
||||||
Scaling scaling;
|
|
||||||
AspectRatio aspectRatio;
|
|
||||||
bool swapRgb;
|
|
||||||
|
|
||||||
AssistantDevice():
|
|
||||||
horizontalMirror(false),
|
|
||||||
verticalMirror(false),
|
|
||||||
scaling(ScalingFast),
|
|
||||||
aspectRatio(AspectRatioIgnore),
|
|
||||||
swapRgb(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map<std::string, std::string> AssistantPeers;
|
typedef std::map<std::string, std::string> AssistantPeers;
|
||||||
|
@ -85,20 +71,15 @@ namespace AkVCam
|
||||||
void addPort(Message *message);
|
void addPort(Message *message);
|
||||||
void removePort(Message *message);
|
void removePort(Message *message);
|
||||||
void setBroadCasting(Message *message);
|
void setBroadCasting(Message *message);
|
||||||
void setMirroring(Message *message);
|
|
||||||
void setScaling(Message *message);
|
|
||||||
void setAspectRatio(Message *message);
|
|
||||||
void setSwapRgb(Message *message);
|
|
||||||
void frameReady(Message *message);
|
void frameReady(Message *message);
|
||||||
|
void pictureUpdated(Message *message);
|
||||||
|
void deviceUpdate(Message *message);
|
||||||
void listeners(Message *message);
|
void listeners(Message *message);
|
||||||
void listener(Message *message);
|
void listener(Message *message);
|
||||||
void broadcasting(Message *message);
|
void broadcasting(Message *message);
|
||||||
void mirroring(Message *message);
|
|
||||||
void scaling(Message *message);
|
|
||||||
void aspectRatio(Message *message);
|
|
||||||
void swapRgb(Message *message);
|
|
||||||
void listenerAdd(Message *message);
|
void listenerAdd(Message *message);
|
||||||
void listenerRemove(Message *message);
|
void listenerRemove(Message *message);
|
||||||
|
void controlsUpdated(Message *message);
|
||||||
};
|
};
|
||||||
|
|
||||||
GLOBAL_STATIC(ServicePrivate, servicePrivate)
|
GLOBAL_STATIC(ServicePrivate, servicePrivate)
|
||||||
|
@ -245,7 +226,7 @@ void AkVCam::Service::debug()
|
||||||
void AkVCam::Service::showHelp(int argc, char **argv)
|
void AkVCam::Service::showHelp(int argc, char **argv)
|
||||||
{
|
{
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
UNUSED(argc)
|
UNUSED(argc);
|
||||||
|
|
||||||
auto programName = strrchr(argv[0], '\\');
|
auto programName = strrchr(argv[0], '\\');
|
||||||
|
|
||||||
|
@ -285,24 +266,19 @@ AkVCam::ServicePrivate::ServicePrivate()
|
||||||
this->m_statusHandler = nullptr;
|
this->m_statusHandler = nullptr;
|
||||||
this->m_messageServer.setPipeName(L"\\\\.\\pipe\\" DSHOW_PLUGIN_ASSISTANT_NAME_L);
|
this->m_messageServer.setPipeName(L"\\\\.\\pipe\\" DSHOW_PLUGIN_ASSISTANT_NAME_L);
|
||||||
this->m_messageServer.setHandlers({
|
this->m_messageServer.setHandlers({
|
||||||
{AKVCAM_ASSISTANT_MSG_FRAME_READY , AKVCAM_BIND_FUNC(ServicePrivate::frameReady) },
|
{AKVCAM_ASSISTANT_MSG_FRAME_READY , AKVCAM_BIND_FUNC(ServicePrivate::frameReady) },
|
||||||
{AKVCAM_ASSISTANT_MSG_REQUEST_PORT , AKVCAM_BIND_FUNC(ServicePrivate::requestPort) },
|
{AKVCAM_ASSISTANT_MSG_PICTURE_UPDATED , AKVCAM_BIND_FUNC(ServicePrivate::pictureUpdated) },
|
||||||
{AKVCAM_ASSISTANT_MSG_ADD_PORT , AKVCAM_BIND_FUNC(ServicePrivate::addPort) },
|
{AKVCAM_ASSISTANT_MSG_REQUEST_PORT , AKVCAM_BIND_FUNC(ServicePrivate::requestPort) },
|
||||||
{AKVCAM_ASSISTANT_MSG_REMOVE_PORT , AKVCAM_BIND_FUNC(ServicePrivate::removePort) },
|
{AKVCAM_ASSISTANT_MSG_ADD_PORT , AKVCAM_BIND_FUNC(ServicePrivate::addPort) },
|
||||||
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_ADD , AKVCAM_BIND_FUNC(ServicePrivate::listenerAdd) },
|
{AKVCAM_ASSISTANT_MSG_REMOVE_PORT , AKVCAM_BIND_FUNC(ServicePrivate::removePort) },
|
||||||
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_REMOVE, AKVCAM_BIND_FUNC(ServicePrivate::listenerRemove) },
|
{AKVCAM_ASSISTANT_MSG_DEVICE_UPDATE , AKVCAM_BIND_FUNC(ServicePrivate::deviceUpdate) },
|
||||||
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENERS , AKVCAM_BIND_FUNC(ServicePrivate::listeners) },
|
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_ADD , AKVCAM_BIND_FUNC(ServicePrivate::listenerAdd) },
|
||||||
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER , AKVCAM_BIND_FUNC(ServicePrivate::listener) },
|
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_REMOVE , AKVCAM_BIND_FUNC(ServicePrivate::listenerRemove) },
|
||||||
{AKVCAM_ASSISTANT_MSG_DEVICE_BROADCASTING , AKVCAM_BIND_FUNC(ServicePrivate::broadcasting) },
|
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENERS , AKVCAM_BIND_FUNC(ServicePrivate::listeners) },
|
||||||
{AKVCAM_ASSISTANT_MSG_DEVICE_SETBROADCASTING, AKVCAM_BIND_FUNC(ServicePrivate::setBroadCasting)},
|
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER , AKVCAM_BIND_FUNC(ServicePrivate::listener) },
|
||||||
{AKVCAM_ASSISTANT_MSG_DEVICE_MIRRORING , AKVCAM_BIND_FUNC(ServicePrivate::mirroring) },
|
{AKVCAM_ASSISTANT_MSG_DEVICE_BROADCASTING , AKVCAM_BIND_FUNC(ServicePrivate::broadcasting) },
|
||||||
{AKVCAM_ASSISTANT_MSG_DEVICE_SETMIRRORING , AKVCAM_BIND_FUNC(ServicePrivate::setMirroring) },
|
{AKVCAM_ASSISTANT_MSG_DEVICE_SETBROADCASTING , AKVCAM_BIND_FUNC(ServicePrivate::setBroadCasting)},
|
||||||
{AKVCAM_ASSISTANT_MSG_DEVICE_SCALING , AKVCAM_BIND_FUNC(ServicePrivate::scaling) },
|
{AKVCAM_ASSISTANT_MSG_DEVICE_CONTROLS_UPDATED, AKVCAM_BIND_FUNC(ServicePrivate::controlsUpdated)},
|
||||||
{AKVCAM_ASSISTANT_MSG_DEVICE_SETSCALING , AKVCAM_BIND_FUNC(ServicePrivate::setScaling) },
|
|
||||||
{AKVCAM_ASSISTANT_MSG_DEVICE_ASPECTRATIO , AKVCAM_BIND_FUNC(ServicePrivate::aspectRatio) },
|
|
||||||
{AKVCAM_ASSISTANT_MSG_DEVICE_SETASPECTRATIO , AKVCAM_BIND_FUNC(ServicePrivate::setAspectRatio) },
|
|
||||||
{AKVCAM_ASSISTANT_MSG_DEVICE_SWAPRGB , AKVCAM_BIND_FUNC(ServicePrivate::swapRgb) },
|
|
||||||
{AKVCAM_ASSISTANT_MSG_DEVICE_SETSWAPRGB , AKVCAM_BIND_FUNC(ServicePrivate::setSwapRgb) },
|
|
||||||
});
|
});
|
||||||
this->m_timer.setInterval(60000);
|
this->m_timer.setInterval(60000);
|
||||||
this->m_timer.connectTimeout(this, &ServicePrivate::checkPeers);
|
this->m_timer.connectTimeout(this, &ServicePrivate::checkPeers);
|
||||||
|
@ -311,7 +287,7 @@ AkVCam::ServicePrivate::ServicePrivate()
|
||||||
void AkVCam::ServicePrivate::stateChanged(void *userData,
|
void AkVCam::ServicePrivate::stateChanged(void *userData,
|
||||||
MessageServer::State state)
|
MessageServer::State state)
|
||||||
{
|
{
|
||||||
UNUSED(userData)
|
UNUSED(userData);
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case MessageServer::StateAboutToStart:
|
case MessageServer::StateAboutToStart:
|
||||||
|
@ -368,7 +344,6 @@ void AkVCam::ServicePrivate::sendStatus(DWORD currentState,
|
||||||
DWORD wait)
|
DWORD wait)
|
||||||
{
|
{
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
|
|
||||||
this->m_status.dwControlsAccepted =
|
this->m_status.dwControlsAccepted =
|
||||||
currentState == SERVICE_START_PENDING? 0: SERVICE_ACCEPT_STOP;
|
currentState == SERVICE_START_PENDING? 0: SERVICE_ACCEPT_STOP;
|
||||||
this->m_status.dwCurrentState = currentState;
|
this->m_status.dwCurrentState = currentState;
|
||||||
|
@ -460,11 +435,8 @@ void AkVCam::ServicePrivate::requestPort(AkVCam::Message *message)
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
|
|
||||||
auto data = messageData<MsgRequestPort>(message);
|
auto data = messageData<MsgRequestPort>(message);
|
||||||
std::string portName = data->client?
|
std::string portName = AKVCAM_ASSISTANT_CLIENT_NAME;
|
||||||
AKVCAM_ASSISTANT_CLIENT_NAME:
|
|
||||||
AKVCAM_ASSISTANT_SERVER_NAME;
|
|
||||||
portName += std::to_string(this->id());
|
portName += std::to_string(this->id());
|
||||||
|
|
||||||
AkLogInfo() << "Returning Port: " << portName << std::endl;
|
AkLogInfo() << "Returning Port: " << portName << std::endl;
|
||||||
memcpy(data->port,
|
memcpy(data->port,
|
||||||
portName.c_str(),
|
portName.c_str(),
|
||||||
|
@ -547,112 +519,6 @@ void AkVCam::ServicePrivate::setBroadCasting(AkVCam::Message *message)
|
||||||
this->m_peerMutex.unlock();
|
this->m_peerMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AkVCam::ServicePrivate::setMirroring(AkVCam::Message *message)
|
|
||||||
{
|
|
||||||
AkLogFunction();
|
|
||||||
auto data = messageData<MsgMirroring>(message);
|
|
||||||
std::string deviceId(data->device);
|
|
||||||
data->status = false;
|
|
||||||
|
|
||||||
if (this->m_deviceConfigs.count(deviceId) < 1)
|
|
||||||
this->m_deviceConfigs[deviceId] = {};
|
|
||||||
|
|
||||||
if (this->m_deviceConfigs[deviceId].horizontalMirror == data->hmirror
|
|
||||||
&& this->m_deviceConfigs[deviceId].verticalMirror == data->vmirror)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this->m_deviceConfigs[deviceId].horizontalMirror = data->hmirror;
|
|
||||||
this->m_deviceConfigs[deviceId].verticalMirror = data->vmirror;
|
|
||||||
data->status = true;
|
|
||||||
|
|
||||||
this->m_peerMutex.lock();
|
|
||||||
|
|
||||||
for (auto &client: this->m_clients) {
|
|
||||||
Message msg(message);
|
|
||||||
MessageServer::sendMessage(client.second, &msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->m_peerMutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AkVCam::ServicePrivate::setScaling(AkVCam::Message *message)
|
|
||||||
{
|
|
||||||
AkLogFunction();
|
|
||||||
auto data = messageData<MsgScaling>(message);
|
|
||||||
std::string deviceId(data->device);
|
|
||||||
data->status = false;
|
|
||||||
|
|
||||||
if (this->m_deviceConfigs.count(deviceId) < 1)
|
|
||||||
this->m_deviceConfigs[deviceId] = {};
|
|
||||||
|
|
||||||
if (this->m_deviceConfigs[deviceId].scaling == data->scaling)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this->m_deviceConfigs[deviceId].scaling = data->scaling;
|
|
||||||
data->status = true;
|
|
||||||
|
|
||||||
this->m_peerMutex.lock();
|
|
||||||
|
|
||||||
for (auto &client: this->m_clients) {
|
|
||||||
Message msg(message);
|
|
||||||
MessageServer::sendMessage(client.second, &msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->m_peerMutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AkVCam::ServicePrivate::setAspectRatio(AkVCam::Message *message)
|
|
||||||
{
|
|
||||||
AkLogFunction();
|
|
||||||
auto data = messageData<MsgAspectRatio>(message);
|
|
||||||
std::string deviceId(data->device);
|
|
||||||
data->status = false;
|
|
||||||
|
|
||||||
if (this->m_deviceConfigs.count(deviceId) < 1)
|
|
||||||
this->m_deviceConfigs[deviceId] = {};
|
|
||||||
|
|
||||||
if (this->m_deviceConfigs[deviceId].aspectRatio == data->aspect)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this->m_deviceConfigs[deviceId].aspectRatio = data->aspect;
|
|
||||||
data->status = true;
|
|
||||||
|
|
||||||
this->m_peerMutex.lock();
|
|
||||||
|
|
||||||
for (auto &client: this->m_clients) {
|
|
||||||
Message msg(message);
|
|
||||||
MessageServer::sendMessage(client.second, &msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->m_peerMutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AkVCam::ServicePrivate::setSwapRgb(AkVCam::Message *message)
|
|
||||||
{
|
|
||||||
AkLogFunction();
|
|
||||||
auto data = messageData<MsgSwapRgb>(message);
|
|
||||||
std::string deviceId(data->device);
|
|
||||||
data->status = false;
|
|
||||||
|
|
||||||
if (this->m_deviceConfigs.count(deviceId) < 1)
|
|
||||||
this->m_deviceConfigs[deviceId] = {};
|
|
||||||
|
|
||||||
if (this->m_deviceConfigs[deviceId].swapRgb == data->swap)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this->m_deviceConfigs[deviceId].swapRgb = data->swap;
|
|
||||||
data->status = true;
|
|
||||||
|
|
||||||
this->m_peerMutex.lock();
|
|
||||||
|
|
||||||
for (auto &client: this->m_clients) {
|
|
||||||
Message msg(message);
|
|
||||||
MessageServer::sendMessage(client.second, &msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->m_peerMutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AkVCam::ServicePrivate::frameReady(AkVCam::Message *message)
|
void AkVCam::ServicePrivate::frameReady(AkVCam::Message *message)
|
||||||
{
|
{
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
|
@ -664,6 +530,28 @@ void AkVCam::ServicePrivate::frameReady(AkVCam::Message *message)
|
||||||
this->m_peerMutex.unlock();
|
this->m_peerMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AkVCam::ServicePrivate::pictureUpdated(AkVCam::Message *message)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
this->m_peerMutex.lock();
|
||||||
|
|
||||||
|
for (auto &client: this->m_clients)
|
||||||
|
MessageServer::sendMessage(client.second, message);
|
||||||
|
|
||||||
|
this->m_peerMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::ServicePrivate::deviceUpdate(AkVCam::Message *message)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
this->m_peerMutex.lock();
|
||||||
|
|
||||||
|
for (auto &client: this->m_clients)
|
||||||
|
MessageServer::sendMessage(client.second, message);
|
||||||
|
|
||||||
|
this->m_peerMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
void AkVCam::ServicePrivate::listeners(AkVCam::Message *message)
|
void AkVCam::ServicePrivate::listeners(AkVCam::Message *message)
|
||||||
{
|
{
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
|
@ -726,59 +614,6 @@ void AkVCam::ServicePrivate::broadcasting(AkVCam::Message *message)
|
||||||
data->status = true;
|
data->status = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AkVCam::ServicePrivate::mirroring(AkVCam::Message *message)
|
|
||||||
{
|
|
||||||
AkLogFunction();
|
|
||||||
auto data = messageData<MsgMirroring>(message);
|
|
||||||
std::string deviceId(data->device);
|
|
||||||
|
|
||||||
if (this->m_deviceConfigs.count(deviceId) < 1)
|
|
||||||
this->m_deviceConfigs[deviceId] = {};
|
|
||||||
|
|
||||||
data->hmirror = this->m_deviceConfigs[deviceId].horizontalMirror;
|
|
||||||
data->vmirror = this->m_deviceConfigs[deviceId].verticalMirror;
|
|
||||||
data->status = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AkVCam::ServicePrivate::scaling(AkVCam::Message *message)
|
|
||||||
{
|
|
||||||
AkLogFunction();
|
|
||||||
auto data = messageData<MsgScaling>(message);
|
|
||||||
std::string deviceId(data->device);
|
|
||||||
|
|
||||||
if (this->m_deviceConfigs.count(deviceId) < 1)
|
|
||||||
this->m_deviceConfigs[deviceId] = {};
|
|
||||||
|
|
||||||
data->scaling = this->m_deviceConfigs[deviceId].scaling;
|
|
||||||
data->status = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AkVCam::ServicePrivate::aspectRatio(AkVCam::Message *message)
|
|
||||||
{
|
|
||||||
AkLogFunction();
|
|
||||||
auto data = messageData<MsgAspectRatio>(message);
|
|
||||||
std::string deviceId(data->device);
|
|
||||||
|
|
||||||
if (this->m_deviceConfigs.count(deviceId) < 1)
|
|
||||||
this->m_deviceConfigs[deviceId] = {};
|
|
||||||
|
|
||||||
data->aspect = this->m_deviceConfigs[deviceId].aspectRatio;
|
|
||||||
data->status = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AkVCam::ServicePrivate::swapRgb(AkVCam::Message *message)
|
|
||||||
{
|
|
||||||
AkLogFunction();
|
|
||||||
auto data = messageData<MsgSwapRgb>(message);
|
|
||||||
std::string deviceId(data->device);
|
|
||||||
|
|
||||||
if (this->m_deviceConfigs.count(deviceId) < 1)
|
|
||||||
this->m_deviceConfigs[deviceId] = {};
|
|
||||||
|
|
||||||
data->swap = this->m_deviceConfigs[deviceId].swapRgb;
|
|
||||||
data->status = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AkVCam::ServicePrivate::listenerAdd(AkVCam::Message *message)
|
void AkVCam::ServicePrivate::listenerAdd(AkVCam::Message *message)
|
||||||
{
|
{
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
|
@ -843,14 +678,25 @@ void AkVCam::ServicePrivate::listenerRemove(AkVCam::Message *message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AkVCam::ServicePrivate::controlsUpdated(AkVCam::Message *message)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
this->m_peerMutex.lock();
|
||||||
|
|
||||||
|
for (auto &client: this->m_clients)
|
||||||
|
MessageServer::sendMessage(client.second, message);
|
||||||
|
|
||||||
|
this->m_peerMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
DWORD WINAPI controlHandler(DWORD control,
|
DWORD WINAPI controlHandler(DWORD control,
|
||||||
DWORD eventType,
|
DWORD eventType,
|
||||||
LPVOID eventData,
|
LPVOID eventData,
|
||||||
LPVOID context)
|
LPVOID context)
|
||||||
{
|
{
|
||||||
UNUSED(eventType)
|
UNUSED(eventType);
|
||||||
UNUSED(eventData)
|
UNUSED(eventData);
|
||||||
UNUSED(context)
|
UNUSED(context);
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
|
|
||||||
DWORD result = ERROR_CALL_NOT_IMPLEMENTED;
|
DWORD result = ERROR_CALL_NOT_IMPLEMENTED;
|
||||||
|
@ -896,8 +742,8 @@ BOOL WINAPI controlDebugHandler(DWORD control)
|
||||||
|
|
||||||
void WINAPI serviceMain(DWORD dwArgc, LPTSTR *lpszArgv)
|
void WINAPI serviceMain(DWORD dwArgc, LPTSTR *lpszArgv)
|
||||||
{
|
{
|
||||||
UNUSED(dwArgc)
|
UNUSED(dwArgc);
|
||||||
UNUSED(lpszArgv)
|
UNUSED(lpszArgv);
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
AkLogInfo() << "Setting service control handler" << std::endl;
|
AkLogInfo() << "Setting service control handler" << std::endl;
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ LIBS = \
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
src/messageserver.cpp \
|
src/messageserver.cpp \
|
||||||
src/mutex.cpp \
|
src/mutex.cpp \
|
||||||
|
src/preferences.cpp \
|
||||||
src/utils.cpp \
|
src/utils.cpp \
|
||||||
src/sharedmemory.cpp
|
src/sharedmemory.cpp
|
||||||
|
|
||||||
|
@ -57,6 +58,7 @@ HEADERS = \
|
||||||
src/messagecommons.h \
|
src/messagecommons.h \
|
||||||
src/messageserver.h \
|
src/messageserver.h \
|
||||||
src/mutex.h \
|
src/mutex.h \
|
||||||
|
src/preferences.h \
|
||||||
src/utils.h \
|
src/utils.h \
|
||||||
src/sharedmemory.h
|
src/sharedmemory.h
|
||||||
|
|
||||||
|
|
|
@ -30,38 +30,33 @@
|
||||||
#define AKVCAM_ASSISTANT_SERVER_NAME "AkVCam_Server"
|
#define AKVCAM_ASSISTANT_SERVER_NAME "AkVCam_Server"
|
||||||
|
|
||||||
// General messages
|
// General messages
|
||||||
#define AKVCAM_ASSISTANT_MSG_ISALIVE 0x000
|
#define AKVCAM_ASSISTANT_MSG_ISALIVE 0x000
|
||||||
#define AKVCAM_ASSISTANT_MSG_FRAME_READY 0x001
|
#define AKVCAM_ASSISTANT_MSG_FRAME_READY 0x001
|
||||||
|
#define AKVCAM_ASSISTANT_MSG_PICTURE_UPDATED 0x002
|
||||||
|
|
||||||
// Assistant messages
|
// Assistant messages
|
||||||
#define AKVCAM_ASSISTANT_MSG_REQUEST_PORT 0x100
|
#define AKVCAM_ASSISTANT_MSG_REQUEST_PORT 0x100
|
||||||
#define AKVCAM_ASSISTANT_MSG_ADD_PORT 0x101
|
#define AKVCAM_ASSISTANT_MSG_ADD_PORT 0x101
|
||||||
#define AKVCAM_ASSISTANT_MSG_REMOVE_PORT 0x102
|
#define AKVCAM_ASSISTANT_MSG_REMOVE_PORT 0x102
|
||||||
|
|
||||||
// Device control and information
|
// Device control and information
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICES 0x200
|
#define AKVCAM_ASSISTANT_MSG_DEVICES 0x200
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_CREATE 0x201
|
#define AKVCAM_ASSISTANT_MSG_DEVICE_CREATE 0x201
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_DESTROY 0x202
|
#define AKVCAM_ASSISTANT_MSG_DEVICE_DESTROY 0x202
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_DESCRIPTION 0x203
|
#define AKVCAM_ASSISTANT_MSG_DEVICE_DESCRIPTION 0x203
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_FORMATS 0x204
|
#define AKVCAM_ASSISTANT_MSG_DEVICE_FORMATS 0x204
|
||||||
|
#define AKVCAM_ASSISTANT_MSG_DEVICE_UPDATE 0x205
|
||||||
|
|
||||||
// Device listeners controls
|
// Device listeners controls
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENERS 0x300
|
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENERS 0x300
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER 0x301
|
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER 0x301
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_ADD 0x302
|
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_ADD 0x302
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_REMOVE 0x303
|
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_REMOVE 0x303
|
||||||
|
|
||||||
// Device dynamic properties
|
// Device dynamic properties
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_BROADCASTING 0x400
|
#define AKVCAM_ASSISTANT_MSG_DEVICE_BROADCASTING 0x400
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_SETBROADCASTING 0x401
|
#define AKVCAM_ASSISTANT_MSG_DEVICE_SETBROADCASTING 0x401
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_MIRRORING 0x402
|
#define AKVCAM_ASSISTANT_MSG_DEVICE_CONTROLS_UPDATED 0x402
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_SETMIRRORING 0x403
|
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_SCALING 0x404
|
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_SETSCALING 0x405
|
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_ASPECTRATIO 0x406
|
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_SETASPECTRATIO 0x407
|
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_SWAPRGB 0x408
|
|
||||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_SETSWAPRGB 0x409
|
|
||||||
|
|
||||||
#define MSG_BUFFER_SIZE 4096
|
#define MSG_BUFFER_SIZE 4096
|
||||||
#define MAX_STRING 1024
|
#define MAX_STRING 1024
|
||||||
|
@ -136,7 +131,6 @@ namespace AkVCam
|
||||||
|
|
||||||
struct MsgRequestPort
|
struct MsgRequestPort
|
||||||
{
|
{
|
||||||
bool client;
|
|
||||||
char port[MAX_STRING];
|
char port[MAX_STRING];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -152,6 +146,16 @@ namespace AkVCam
|
||||||
char port[MAX_STRING];
|
char port[MAX_STRING];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MsgDeviceAdded
|
||||||
|
{
|
||||||
|
char device[MAX_STRING];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MsgDeviceRemoved
|
||||||
|
{
|
||||||
|
char device[MAX_STRING];
|
||||||
|
};
|
||||||
|
|
||||||
struct MsgBroadcasting
|
struct MsgBroadcasting
|
||||||
{
|
{
|
||||||
char device[MAX_STRING];
|
char device[MAX_STRING];
|
||||||
|
@ -159,35 +163,6 @@ namespace AkVCam
|
||||||
bool status;
|
bool status;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MsgMirroring
|
|
||||||
{
|
|
||||||
char device[MAX_STRING];
|
|
||||||
bool hmirror;
|
|
||||||
bool vmirror;
|
|
||||||
bool status;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MsgScaling
|
|
||||||
{
|
|
||||||
char device[MAX_STRING];
|
|
||||||
Scaling scaling;
|
|
||||||
bool status;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MsgAspectRatio
|
|
||||||
{
|
|
||||||
char device[MAX_STRING];
|
|
||||||
AspectRatio aspect;
|
|
||||||
bool status;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MsgSwapRgb
|
|
||||||
{
|
|
||||||
char device[MAX_STRING];
|
|
||||||
bool swap;
|
|
||||||
bool status;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MsgListeners
|
struct MsgListeners
|
||||||
{
|
{
|
||||||
char device[MAX_STRING];
|
char device[MAX_STRING];
|
||||||
|
@ -206,6 +181,16 @@ namespace AkVCam
|
||||||
char device[MAX_STRING];
|
char device[MAX_STRING];
|
||||||
char port[MAX_STRING];
|
char port[MAX_STRING];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MsgPictureUpdated
|
||||||
|
{
|
||||||
|
char picture[MAX_STRING];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MsgControlsUpdated
|
||||||
|
{
|
||||||
|
char device[MAX_STRING];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MESSAGECOMMONS_H
|
#endif // MESSAGECOMMONS_H
|
||||||
|
|
|
@ -375,7 +375,7 @@ void AkVCam::MessageServerPrivate::checkLoop()
|
||||||
this->m_pipeName.end())
|
this->m_pipeName.end())
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
this->m_pipeState = AkVCam::MessageServer::PipeStateAvailable;
|
this->m_pipeState = AkVCam::MessageServer::PipeStateAvailable;
|
||||||
AKVCAM_EMIT(this->self, PipeStateChanged, this->m_pipeState);
|
AKVCAM_EMIT(this->self, PipeStateChanged, this->m_pipeState)
|
||||||
} else if (!result
|
} else if (!result
|
||||||
&& this->m_pipeState != AkVCam::MessageServer::PipeStateGone
|
&& this->m_pipeState != AkVCam::MessageServer::PipeStateGone
|
||||||
&& GetLastError() != ERROR_SEM_TIMEOUT) {
|
&& GetLastError() != ERROR_SEM_TIMEOUT) {
|
||||||
|
@ -384,7 +384,7 @@ void AkVCam::MessageServerPrivate::checkLoop()
|
||||||
this->m_pipeName.end())
|
this->m_pipeName.end())
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
this->m_pipeState = AkVCam::MessageServer::PipeStateGone;
|
this->m_pipeState = AkVCam::MessageServer::PipeStateGone;
|
||||||
AKVCAM_EMIT(this->self, PipeStateChanged, this->m_pipeState);
|
AKVCAM_EMIT(this->self, PipeStateChanged, this->m_pipeState)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->m_running)
|
if (!this->m_running)
|
||||||
|
|
792
dshow/PlatformUtils/src/preferences.cpp
Normal file
792
dshow/PlatformUtils/src/preferences.cpp
Normal file
|
@ -0,0 +1,792 @@
|
||||||
|
/* akvirtualcamera, virtual camera for Mac and Windows.
|
||||||
|
* Copyright (C) 2020 Gonzalo Exequiel Pedone
|
||||||
|
*
|
||||||
|
* akvirtualcamera is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* akvirtualcamera is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with akvirtualcamera. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Web-Site: http://webcamoid.github.io/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <codecvt>
|
||||||
|
#include <locale>
|
||||||
|
#include <sstream>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winreg.h>
|
||||||
|
#include <uuids.h>
|
||||||
|
|
||||||
|
#include "preferences.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "VCamUtils/src/image/videoformat.h"
|
||||||
|
#include "VCamUtils/src/logger/logger.h"
|
||||||
|
|
||||||
|
#define REG_PREFIX "SOFTWARE\\Webcamoid\\VirtualCamera\\"
|
||||||
|
|
||||||
|
namespace AkVCam
|
||||||
|
{
|
||||||
|
namespace Preferences
|
||||||
|
{
|
||||||
|
void splitSubKey(const std::string &key,
|
||||||
|
std::string &subKey,
|
||||||
|
std::string &value);
|
||||||
|
bool valueA(const std::string &key,
|
||||||
|
DWORD dataTypeFlags,
|
||||||
|
PVOID data,
|
||||||
|
LPDWORD dataSize);
|
||||||
|
bool valueW(const std::string &key,
|
||||||
|
DWORD dataTypeFlags,
|
||||||
|
PVOID data,
|
||||||
|
LPDWORD dataSize);
|
||||||
|
void setValueA(const std::string &key,
|
||||||
|
DWORD dataType,
|
||||||
|
LPCSTR data,
|
||||||
|
DWORD dataSize);
|
||||||
|
void setValueW(const std::string &key,
|
||||||
|
DWORD dataType,
|
||||||
|
LPCWSTR data,
|
||||||
|
DWORD dataSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::write(const std::string &key,
|
||||||
|
const std::string &value)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
AkLogInfo() << "Writing: " << key << " = " << value << std::endl;
|
||||||
|
setValueA(key, REG_SZ, value.c_str(), DWORD(value.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::write(const std::string &key,
|
||||||
|
const std::wstring &value)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
AkLogInfo() << "Writing: "
|
||||||
|
<< key
|
||||||
|
<< " = "
|
||||||
|
<< std::string(value.begin(), value.end()) << std::endl;
|
||||||
|
setValueW(key, REG_SZ, value.c_str(), DWORD(value.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::write(const std::string &key, int value)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
AkLogInfo() << "Writing: " << key << " = " << value << std::endl;
|
||||||
|
setValueA(key,
|
||||||
|
REG_DWORD,
|
||||||
|
reinterpret_cast<const char *>(&value),
|
||||||
|
DWORD(sizeof(int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::write(const std::string &key, double value)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
AkLogInfo() << "Writing: " << key << " = " << value << std::endl;
|
||||||
|
auto val = std::to_string(value);
|
||||||
|
setValueA(key,
|
||||||
|
REG_SZ,
|
||||||
|
val.c_str(),
|
||||||
|
DWORD(val.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::write(const std::string &key,
|
||||||
|
std::vector<std::string> &value)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
write(key, join(value, ","));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AkVCam::Preferences::readString(const std::string &key,
|
||||||
|
const std::string &defaultValue)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
char value[MAX_PATH];
|
||||||
|
memset(value, 0, MAX_PATH * sizeof(char));
|
||||||
|
DWORD valueSize = MAX_PATH;
|
||||||
|
|
||||||
|
if (!valueA(key, RRF_RT_REG_SZ, &value, &valueSize))
|
||||||
|
return defaultValue;
|
||||||
|
|
||||||
|
return {value};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring AkVCam::Preferences::readWString(const std::string &key,
|
||||||
|
const std::wstring &defaultValue)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
TCHAR value[MAX_PATH];
|
||||||
|
memset(value, 0, MAX_PATH * sizeof(TCHAR));
|
||||||
|
DWORD valueSize = MAX_PATH;
|
||||||
|
|
||||||
|
if (!valueW(key, RRF_RT_REG_SZ, &value, &valueSize))
|
||||||
|
return defaultValue;
|
||||||
|
|
||||||
|
return {value};
|
||||||
|
}
|
||||||
|
|
||||||
|
int AkVCam::Preferences::readInt(const std::string &key, int defaultValue)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
DWORD value = 0;
|
||||||
|
DWORD valueSize = sizeof(DWORD);
|
||||||
|
|
||||||
|
if (!valueA(key, RRF_RT_REG_DWORD, &value, &valueSize))
|
||||||
|
return defaultValue;
|
||||||
|
|
||||||
|
return int(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
double AkVCam::Preferences::readDouble(const std::string &key,
|
||||||
|
double defaultValue)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
auto value = readString(key, std::to_string(defaultValue));
|
||||||
|
std::string::size_type sz;
|
||||||
|
|
||||||
|
return std::stod(value, &sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AkVCam::Preferences::readBool(const std::string &key, bool defaultValue)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
|
||||||
|
return readInt(key, defaultValue) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CLSID> AkVCam::Preferences::listRegisteredCameras(HINSTANCE hinstDLL)
|
||||||
|
{
|
||||||
|
WCHAR *strIID = nullptr;
|
||||||
|
StringFromIID(CLSID_VideoInputDeviceCategory, &strIID);
|
||||||
|
|
||||||
|
std::wstringstream ss;
|
||||||
|
ss << L"CLSID\\"
|
||||||
|
<< strIID
|
||||||
|
<< L"\\Instance";
|
||||||
|
CoTaskMemFree(strIID);
|
||||||
|
|
||||||
|
HKEY key = nullptr;
|
||||||
|
auto result = RegOpenKeyEx(HKEY_CLASSES_ROOT,
|
||||||
|
ss.str().c_str(),
|
||||||
|
0,
|
||||||
|
MAXIMUM_ALLOWED,
|
||||||
|
&key);
|
||||||
|
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
DWORD subkeys = 0;
|
||||||
|
|
||||||
|
result = RegQueryInfoKey(key,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
&subkeys,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
if (result != ERROR_SUCCESS) {
|
||||||
|
RegCloseKey(key);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CLSID> cameras;
|
||||||
|
FILETIME lastWrite;
|
||||||
|
|
||||||
|
for (DWORD i = 0; i < subkeys; i++) {
|
||||||
|
TCHAR subKey[MAX_PATH];
|
||||||
|
memset(subKey, 0, MAX_PATH * sizeof(TCHAR));
|
||||||
|
DWORD subKeyLen = MAX_PATH;
|
||||||
|
result = RegEnumKeyEx(key,
|
||||||
|
i,
|
||||||
|
subKey,
|
||||||
|
&subKeyLen,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
&lastWrite);
|
||||||
|
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::wstringstream ss;
|
||||||
|
ss << L"CLSID\\" << subKey << L"\\InprocServer32";
|
||||||
|
WCHAR path[MAX_PATH];
|
||||||
|
memset(path, 0, MAX_PATH * sizeof(WCHAR));
|
||||||
|
DWORD pathSize = MAX_PATH;
|
||||||
|
|
||||||
|
if (RegGetValue(HKEY_CLASSES_ROOT,
|
||||||
|
ss.str().c_str(),
|
||||||
|
nullptr,
|
||||||
|
RRF_RT_REG_SZ,
|
||||||
|
nullptr,
|
||||||
|
path,
|
||||||
|
&pathSize) == ERROR_SUCCESS) {
|
||||||
|
WCHAR modulePath[MAX_PATH];
|
||||||
|
memset(modulePath, 0, MAX_PATH * sizeof(WCHAR));
|
||||||
|
GetModuleFileName(hinstDLL, modulePath, MAX_PATH);
|
||||||
|
|
||||||
|
if (!lstrcmpi(path, modulePath)) {
|
||||||
|
CLSID clsid;
|
||||||
|
memset(&clsid, 0, sizeof(CLSID));
|
||||||
|
CLSIDFromString(subKey, &clsid);
|
||||||
|
cameras.push_back(clsid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RegCloseKey(key);
|
||||||
|
|
||||||
|
return cameras;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::deleteKey(const std::string &key)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
AkLogInfo() << "Deleting " << key << std::endl;
|
||||||
|
std::string subKey;
|
||||||
|
std::string val;
|
||||||
|
splitSubKey(key, subKey, val);
|
||||||
|
HKEY hkey = nullptr;
|
||||||
|
auto result = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||||
|
subKey.c_str(),
|
||||||
|
0,
|
||||||
|
KEY_ALL_ACCESS | KEY_WOW64_64KEY,
|
||||||
|
&hkey);
|
||||||
|
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (val.empty())
|
||||||
|
RegDeleteTreeA(hkey, nullptr);
|
||||||
|
else
|
||||||
|
RegDeleteValueA(hkey, val.c_str());
|
||||||
|
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::move(const std::string &keyFrom,
|
||||||
|
const std::string &keyTo)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
AkLogInfo() << "From: " << keyFrom << std::endl;
|
||||||
|
AkLogInfo() << "To: " << keyTo << std::endl;
|
||||||
|
|
||||||
|
std::string subKeyFrom = REG_PREFIX "\\" + keyFrom;
|
||||||
|
HKEY hkeyFrom = nullptr;
|
||||||
|
auto result = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||||
|
subKeyFrom.c_str(),
|
||||||
|
0,
|
||||||
|
KEY_READ | KEY_WOW64_64KEY,
|
||||||
|
&hkeyFrom);
|
||||||
|
|
||||||
|
if (result == ERROR_SUCCESS) {
|
||||||
|
std::string subKeyTo = REG_PREFIX "\\" + keyTo;
|
||||||
|
HKEY hkeyTo = nullptr;
|
||||||
|
result = RegCreateKeyExA(HKEY_LOCAL_MACHINE,
|
||||||
|
subKeyTo.c_str(),
|
||||||
|
0,
|
||||||
|
nullptr,
|
||||||
|
REG_OPTION_NON_VOLATILE,
|
||||||
|
KEY_WRITE | KEY_WOW64_64KEY,
|
||||||
|
nullptr,
|
||||||
|
&hkeyTo,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
if (result == ERROR_SUCCESS) {
|
||||||
|
result = RegCopyTree(hkeyFrom, nullptr, hkeyTo);
|
||||||
|
|
||||||
|
if (result == ERROR_SUCCESS)
|
||||||
|
deleteKey(keyFrom);
|
||||||
|
|
||||||
|
RegCloseKey(hkeyTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
RegCloseKey(hkeyFrom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AkVCam::Preferences::addDevice(const std::wstring &description)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
auto path = createDevicePath();
|
||||||
|
int cameraIndex = readInt("Cameras\\size") + 1;
|
||||||
|
write("Cameras\\size", cameraIndex);
|
||||||
|
write("Cameras\\" + std::to_string(cameraIndex) + "\\description",
|
||||||
|
description);
|
||||||
|
write("Cameras\\" + std::to_string(cameraIndex) + "\\path", path);
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AkVCam::Preferences::addCamera(const std::wstring &description,
|
||||||
|
const std::vector<VideoFormat> &formats)
|
||||||
|
{
|
||||||
|
return addCamera("", description, formats);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AkVCam::Preferences::addCamera(const std::string &path,
|
||||||
|
const std::wstring &description,
|
||||||
|
const std::vector<VideoFormat> &formats)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
|
||||||
|
if (!path.empty() && cameraExists(path))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto path_ = path.empty()? createDevicePath(): path;
|
||||||
|
int cameraIndex = readInt("Cameras\\") + 1;
|
||||||
|
write("Cameras\\size", cameraIndex);
|
||||||
|
write("Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex)
|
||||||
|
+ "\\description",
|
||||||
|
description);
|
||||||
|
write("Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex)
|
||||||
|
+ "\\path",
|
||||||
|
path_);
|
||||||
|
write("Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex)
|
||||||
|
+ "\\Formats\\size",
|
||||||
|
int(formats.size()));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < formats.size(); i++) {
|
||||||
|
auto &format = formats[i];
|
||||||
|
auto prefix = "Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex)
|
||||||
|
+ "\\Formats\\"
|
||||||
|
+ std::to_string(i + 1);
|
||||||
|
auto formatStr = VideoFormat::stringFromFourcc(format.fourcc());
|
||||||
|
write(prefix + "\\format", formatStr);
|
||||||
|
write(prefix + "\\width", format.width());
|
||||||
|
write(prefix + "\\height", format.height());
|
||||||
|
write(prefix + "\\fps", format.minimumFrameRate().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return path_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::removeCamera(const std::string &path)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
AkLogInfo() << "Device: " << path << std::endl;
|
||||||
|
int cameraIndex = cameraFromPath(path);
|
||||||
|
|
||||||
|
if (cameraIndex < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cameraSetFormats(size_t(cameraIndex), {});
|
||||||
|
|
||||||
|
auto nCameras = camerasCount();
|
||||||
|
deleteKey("Cameras\\" + std::to_string(cameraIndex + 1) + '\\');
|
||||||
|
|
||||||
|
for (auto i = size_t(cameraIndex + 1); i < nCameras; i++)
|
||||||
|
move("Cameras\\" + std::to_string(i + 1),
|
||||||
|
"Cameras\\" + std::to_string(i));
|
||||||
|
|
||||||
|
if (nCameras > 1)
|
||||||
|
write("Cameras\\size", int(nCameras - 1));
|
||||||
|
else
|
||||||
|
deleteKey("Cameras\\");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AkVCam::Preferences::camerasCount()
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
int nCameras = readInt("Cameras\\size");
|
||||||
|
AkLogInfo() << "Cameras: " << nCameras << std::endl;
|
||||||
|
|
||||||
|
return size_t(nCameras);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AkVCam::Preferences::createDevicePath()
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
|
||||||
|
// List device paths in use.
|
||||||
|
std::vector<std::string> cameraPaths;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < camerasCount(); i++)
|
||||||
|
cameraPaths.push_back(cameraPath(i));
|
||||||
|
|
||||||
|
const int maxId = 64;
|
||||||
|
|
||||||
|
for (int i = 0; i < maxId; i++) {
|
||||||
|
/* There are no rules for device paths in Windows. Just append an
|
||||||
|
* incremental index to a common prefix.
|
||||||
|
*/
|
||||||
|
auto path = DSHOW_PLUGIN_DEVICE_PREFIX + std::to_string(i);
|
||||||
|
|
||||||
|
// Check if the path is being used, if not return it.
|
||||||
|
if (std::find(cameraPaths.begin(),
|
||||||
|
cameraPaths.end(),
|
||||||
|
path) == cameraPaths.end())
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
int AkVCam::Preferences::cameraFromPath(const std::string &path)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < camerasCount(); i++)
|
||||||
|
if (cameraPath(i) == path)
|
||||||
|
return int(i);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AkVCam::Preferences::cameraExists(const std::string &path)
|
||||||
|
{
|
||||||
|
for (DWORD i = 0; i < camerasCount(); i++)
|
||||||
|
if (cameraPath(i) == path)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring AkVCam::Preferences::cameraDescription(size_t cameraIndex)
|
||||||
|
{
|
||||||
|
if (cameraIndex >= camerasCount())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return readWString("Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex + 1)
|
||||||
|
+ "\\description");
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::cameraSetDescription(size_t cameraIndex,
|
||||||
|
const std::wstring &description)
|
||||||
|
{
|
||||||
|
if (cameraIndex >= camerasCount())
|
||||||
|
return;
|
||||||
|
|
||||||
|
write("Cameras\\" + std::to_string(cameraIndex + 1) + "\\description",
|
||||||
|
description);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AkVCam::Preferences::cameraPath(size_t cameraIndex)
|
||||||
|
{
|
||||||
|
return readString("Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex + 1)
|
||||||
|
+ "\\path");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AkVCam::Preferences::formatsCount(size_t cameraIndex)
|
||||||
|
{
|
||||||
|
return size_t(readInt("Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex + 1)
|
||||||
|
+ "\\Formats\\size"));
|
||||||
|
}
|
||||||
|
|
||||||
|
AkVCam::VideoFormat AkVCam::Preferences::cameraFormat(size_t cameraIndex,
|
||||||
|
size_t formatIndex)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
auto prefix = "Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex + 1)
|
||||||
|
+ "\\Formats\\"
|
||||||
|
+ std::to_string(formatIndex + 1);
|
||||||
|
auto format = readString(prefix + "\\format");
|
||||||
|
auto fourcc = VideoFormat::fourccFromString(format);
|
||||||
|
int width = readInt(prefix + "\\width");
|
||||||
|
int height = readInt(prefix + "\\height");
|
||||||
|
auto fps = Fraction(readString(prefix + "\\fps"));
|
||||||
|
|
||||||
|
return VideoFormat(fourcc, width, height, {fps});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<AkVCam::VideoFormat> AkVCam::Preferences::cameraFormats(size_t cameraIndex)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
std::vector<AkVCam::VideoFormat> formats;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < formatsCount(cameraIndex); i++) {
|
||||||
|
auto videoFormat = cameraFormat(cameraIndex, i);
|
||||||
|
|
||||||
|
if (videoFormat)
|
||||||
|
formats.push_back(videoFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
return formats;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::cameraSetFormats(size_t cameraIndex,
|
||||||
|
const std::vector<AkVCam::VideoFormat> &formats)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
|
||||||
|
if (cameraIndex >= camerasCount())
|
||||||
|
return;
|
||||||
|
|
||||||
|
write("Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex + 1)
|
||||||
|
+ "\\Formats\\size",
|
||||||
|
int(formats.size()));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < formats.size(); i++) {
|
||||||
|
auto &format = formats[i];
|
||||||
|
auto prefix = "Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex + 1)
|
||||||
|
+ "\\Formats\\"
|
||||||
|
+ std::to_string(i + 1);
|
||||||
|
auto formatStr = VideoFormat::stringFromFourcc(format.fourcc());
|
||||||
|
write(prefix + "\\format", formatStr);
|
||||||
|
write(prefix + "\\width", format.width());
|
||||||
|
write(prefix + "\\height", format.height());
|
||||||
|
write(prefix + "\\fps", format.minimumFrameRate().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::cameraAddFormat(size_t cameraIndex,
|
||||||
|
const AkVCam::VideoFormat &format,
|
||||||
|
int index)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
auto formats = cameraFormats(cameraIndex);
|
||||||
|
|
||||||
|
if (index < 0 || index > int(formats.size()))
|
||||||
|
index = int(formats.size());
|
||||||
|
|
||||||
|
formats.insert(formats.begin() + index, format);
|
||||||
|
write("Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex + 1)
|
||||||
|
+ "\\Formats\\size",
|
||||||
|
int(formats.size()));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < formats.size(); i++) {
|
||||||
|
auto &format = formats[i];
|
||||||
|
auto prefix = "Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex + 1)
|
||||||
|
+ "\\Formats\\"
|
||||||
|
+ std::to_string(i + 1);
|
||||||
|
auto formatStr = VideoFormat::stringFromFourcc(format.fourcc());
|
||||||
|
write(prefix + "\\format", formatStr);
|
||||||
|
write(prefix + "\\width", format.width());
|
||||||
|
write(prefix + "\\height", format.height());
|
||||||
|
write(prefix + "\\fps", format.minimumFrameRate().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::cameraRemoveFormat(size_t cameraIndex, int index)
|
||||||
|
{
|
||||||
|
AkLogFunction();
|
||||||
|
auto formats = cameraFormats(cameraIndex);
|
||||||
|
|
||||||
|
if (index < 0 || index >= int(formats.size()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
formats.erase(formats.begin() + index);
|
||||||
|
write("Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex + 1)
|
||||||
|
+ "\\Formats\\size",
|
||||||
|
int(formats.size()));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < formats.size(); i++) {
|
||||||
|
auto &format = formats[i];
|
||||||
|
auto prefix = "Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex)
|
||||||
|
+ "\\Formats\\"
|
||||||
|
+ std::to_string(i + 1);
|
||||||
|
auto formatStr = VideoFormat::stringFromFourcc(format.fourcc());
|
||||||
|
write(prefix + "\\format", formatStr);
|
||||||
|
write(prefix + "\\width", format.width());
|
||||||
|
write(prefix + "\\height", format.height());
|
||||||
|
write(prefix + "\\fps", format.minimumFrameRate().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int AkVCam::Preferences::cameraControlValue(size_t cameraIndex,
|
||||||
|
const std::string &key)
|
||||||
|
{
|
||||||
|
return readInt("Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex + 1)
|
||||||
|
+ "\\Controls\\"
|
||||||
|
+ key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::cameraSetControlValue(size_t cameraIndex,
|
||||||
|
const std::string &key,
|
||||||
|
int value)
|
||||||
|
{
|
||||||
|
write("Cameras\\"
|
||||||
|
+ std::to_string(cameraIndex + 1)
|
||||||
|
+ "\\Controls\\"
|
||||||
|
+ key,
|
||||||
|
value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring AkVCam::Preferences::picture()
|
||||||
|
{
|
||||||
|
return readWString("picture");
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::setPicture(const std::wstring &picture)
|
||||||
|
{
|
||||||
|
write("picture", picture);
|
||||||
|
}
|
||||||
|
|
||||||
|
int AkVCam::Preferences::logLevel()
|
||||||
|
{
|
||||||
|
return readInt("loglevel", AKVCAM_LOGLEVEL_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::setLogLevel(int logLevel)
|
||||||
|
{
|
||||||
|
write("loglevel", logLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::splitSubKey(const std::string &key,
|
||||||
|
std::string &subKey,
|
||||||
|
std::string &value)
|
||||||
|
{
|
||||||
|
subKey = REG_PREFIX;
|
||||||
|
auto separator = key.rfind('\\');
|
||||||
|
|
||||||
|
if (separator == std::string::npos) {
|
||||||
|
value = key;
|
||||||
|
} else {
|
||||||
|
subKey += '\\' + key.substr(0, separator);
|
||||||
|
|
||||||
|
if (separator + 1 < key.size())
|
||||||
|
value = key.substr(separator + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AkVCam::Preferences::valueA(const std::string &key,
|
||||||
|
DWORD dataTypeFlags,
|
||||||
|
PVOID data,
|
||||||
|
LPDWORD dataSize)
|
||||||
|
{
|
||||||
|
std::string subKey;
|
||||||
|
std::string val;
|
||||||
|
splitSubKey(key, subKey, val);
|
||||||
|
HKEY hkey = nullptr;
|
||||||
|
auto result = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||||
|
subKey.c_str(),
|
||||||
|
0,
|
||||||
|
KEY_READ | KEY_WOW64_64KEY,
|
||||||
|
&hkey);
|
||||||
|
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
result = RegGetValueA(hkey,
|
||||||
|
nullptr,
|
||||||
|
val.c_str(),
|
||||||
|
dataTypeFlags,
|
||||||
|
nullptr,
|
||||||
|
data,
|
||||||
|
dataSize);
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
|
||||||
|
return result == ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AkVCam::Preferences::valueW(const std::string &key,
|
||||||
|
DWORD dataTypeFlags,
|
||||||
|
PVOID data,
|
||||||
|
LPDWORD dataSize)
|
||||||
|
{
|
||||||
|
std::string subKey;
|
||||||
|
std::string val;
|
||||||
|
splitSubKey(key, subKey, val);
|
||||||
|
HKEY hkey = nullptr;
|
||||||
|
auto result = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
||||||
|
subKey.c_str(),
|
||||||
|
0,
|
||||||
|
KEY_READ | KEY_WOW64_64KEY,
|
||||||
|
&hkey);
|
||||||
|
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> cv;
|
||||||
|
auto wval = cv.from_bytes(val);
|
||||||
|
result = RegGetValueW(hkey,
|
||||||
|
nullptr,
|
||||||
|
wval.c_str(),
|
||||||
|
dataTypeFlags,
|
||||||
|
nullptr,
|
||||||
|
data,
|
||||||
|
dataSize);
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
|
||||||
|
return result == ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::setValueA(const std::string &key,
|
||||||
|
DWORD dataType,
|
||||||
|
LPCSTR data,
|
||||||
|
DWORD dataSize)
|
||||||
|
{
|
||||||
|
std::string subKey;
|
||||||
|
std::string val;
|
||||||
|
splitSubKey(key, subKey, val);
|
||||||
|
HKEY hkey = nullptr;
|
||||||
|
LONG result = RegCreateKeyExA(HKEY_LOCAL_MACHINE,
|
||||||
|
subKey.c_str(),
|
||||||
|
0,
|
||||||
|
nullptr,
|
||||||
|
REG_OPTION_NON_VOLATILE,
|
||||||
|
KEY_WRITE | KEY_WOW64_64KEY,
|
||||||
|
nullptr,
|
||||||
|
&hkey,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RegSetValueA(hkey,
|
||||||
|
val.c_str(),
|
||||||
|
dataType,
|
||||||
|
data,
|
||||||
|
dataSize);
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AkVCam::Preferences::setValueW(const std::string &key,
|
||||||
|
DWORD dataType,
|
||||||
|
LPCWSTR data,
|
||||||
|
DWORD dataSize)
|
||||||
|
{
|
||||||
|
std::string subKey;
|
||||||
|
std::string val;
|
||||||
|
splitSubKey(key, subKey, val);
|
||||||
|
HKEY hkey = nullptr;
|
||||||
|
LONG result = RegCreateKeyExA(HKEY_LOCAL_MACHINE,
|
||||||
|
subKey.c_str(),
|
||||||
|
0,
|
||||||
|
nullptr,
|
||||||
|
REG_OPTION_NON_VOLATILE,
|
||||||
|
KEY_WRITE | KEY_WOW64_64KEY,
|
||||||
|
nullptr,
|
||||||
|
&hkey,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> cv;
|
||||||
|
auto wval = cv.from_bytes(val);
|
||||||
|
RegSetValueW(hkey,
|
||||||
|
wval.c_str(),
|
||||||
|
dataType,
|
||||||
|
data,
|
||||||
|
dataSize);
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
}
|
85
dshow/PlatformUtils/src/preferences.h
Normal file
85
dshow/PlatformUtils/src/preferences.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/* akvirtualcamera, virtual camera for Mac and Windows.
|
||||||
|
* Copyright (C) 2020 Gonzalo Exequiel Pedone
|
||||||
|
*
|
||||||
|
* akvirtualcamera is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* akvirtualcamera is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with akvirtualcamera. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Web-Site: http://webcamoid.github.io/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PREFERENCES_H
|
||||||
|
#define PREFERENCES_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <strmif.h>
|
||||||
|
|
||||||
|
namespace AkVCam
|
||||||
|
{
|
||||||
|
class VideoFormat;
|
||||||
|
|
||||||
|
namespace Preferences
|
||||||
|
{
|
||||||
|
void write(const std::string &key, const std::string &value);
|
||||||
|
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::string readString(const std::string &key,
|
||||||
|
const std::string &defaultValue={});
|
||||||
|
std::wstring readWString(const std::string &key,
|
||||||
|
const std::wstring &defaultValue={});
|
||||||
|
int readInt(const std::string &key, int defaultValue=0);
|
||||||
|
double readDouble(const std::string &key, double defaultValue=0.0);
|
||||||
|
bool readBool(const std::string &key, bool defaultValue=false);
|
||||||
|
std::vector<CLSID> listRegisteredCameras(HINSTANCE hinstDLL);
|
||||||
|
void deleteKey(const std::string &key);
|
||||||
|
void move(const std::string &keyFrom, const std::string &keyTo);
|
||||||
|
std::string addDevice(const std::wstring &description);
|
||||||
|
std::string addCamera(const std::wstring &description,
|
||||||
|
const std::vector<VideoFormat> &formats);
|
||||||
|
std::string addCamera(const std::string &path,
|
||||||
|
const std::wstring &description,
|
||||||
|
const std::vector<VideoFormat> &formats);
|
||||||
|
void removeCamera(const std::string &path);
|
||||||
|
size_t camerasCount();
|
||||||
|
std::string createDevicePath();
|
||||||
|
int cameraFromPath(const std::string &path);
|
||||||
|
bool cameraExists(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);
|
||||||
|
std::vector<VideoFormat> cameraFormats(size_t cameraIndex);
|
||||||
|
void cameraSetFormats(size_t cameraIndex,
|
||||||
|
const std::vector<VideoFormat> &formats);
|
||||||
|
void cameraAddFormat(size_t cameraIndex,
|
||||||
|
const VideoFormat &format,
|
||||||
|
int index);
|
||||||
|
void cameraRemoveFormat(size_t cameraIndex, int index);
|
||||||
|
int cameraControlValue(size_t cameraIndex,
|
||||||
|
const std::string &key);
|
||||||
|
void cameraSetControlValue(size_t cameraIndex,
|
||||||
|
const std::string &key,
|
||||||
|
int value);
|
||||||
|
std::wstring picture();
|
||||||
|
void setPicture(const std::wstring &picture);
|
||||||
|
int logLevel();
|
||||||
|
void setLogLevel(int logLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PREFERENCES_H
|
|
@ -95,31 +95,41 @@ BOOL AkVCam::isWow64()
|
||||||
return isWow64;
|
return isWow64;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring AkVCam::tempPath()
|
std::string AkVCam::tempPath()
|
||||||
{
|
{
|
||||||
WCHAR tempPath[MAX_PATH];
|
CHAR tempPath[MAX_PATH];
|
||||||
memset(tempPath, 0, MAX_PATH * sizeof(WCHAR));
|
memset(tempPath, 0, MAX_PATH * sizeof(CHAR));
|
||||||
GetTempPath(MAX_PATH, tempPath);
|
GetTempPathA(MAX_PATH, tempPath);
|
||||||
|
|
||||||
return std::wstring(tempPath);
|
return std::string(tempPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring AkVCam::programFilesPath()
|
std::wstring AkVCam::programFilesPath()
|
||||||
{
|
{
|
||||||
WCHAR programFiles[MAX_PATH];
|
|
||||||
DWORD programFilesSize = MAX_PATH * sizeof(WCHAR);
|
|
||||||
memset(programFiles, 0, programFilesSize);
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
TCHAR programFiles[MAX_PATH];
|
||||||
|
DWORD programFilesSize = MAX_PATH * sizeof(TCHAR);
|
||||||
|
memset(programFiles, 0, programFilesSize);
|
||||||
|
HKEY hkey = nullptr;
|
||||||
|
auto result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||||
|
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
|
||||||
|
0,
|
||||||
|
KEY_READ | KEY_WOW64_64KEY,
|
||||||
|
&hkey);
|
||||||
|
|
||||||
if (isWow64()
|
if (result == ERROR_SUCCESS) {
|
||||||
&& regGetValue(HKEY_LOCAL_MACHINE,
|
result = RegGetValue(hkey,
|
||||||
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
|
nullptr,
|
||||||
L"ProgramFilesDir",
|
L"ProgramFilesDir",
|
||||||
RRF_RT_REG_SZ,
|
RRF_RT_REG_SZ,
|
||||||
nullptr,
|
nullptr,
|
||||||
&programFiles,
|
&programFiles,
|
||||||
&programFilesSize) == ERROR_SUCCESS)
|
&programFilesSize);
|
||||||
ok = true;
|
if (isWow64())
|
||||||
|
ok = true;
|
||||||
|
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
}
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
SHGetSpecialFolderPath(nullptr,
|
SHGetSpecialFolderPath(nullptr,
|
||||||
|
@ -391,16 +401,15 @@ AM_MEDIA_TYPE *AkVCam::mediaTypeFromFormat(const AkVCam::VideoFormat &format)
|
||||||
memset(videoInfo, 0, sizeof(VIDEOINFO));
|
memset(videoInfo, 0, sizeof(VIDEOINFO));
|
||||||
auto fps = format.minimumFrameRate();
|
auto fps = format.minimumFrameRate();
|
||||||
|
|
||||||
|
|
||||||
// Initialize info header.
|
// Initialize info header.
|
||||||
videoInfo->rcSource = {0, 0, 0, 0};
|
videoInfo->rcSource = {0, 0, 0, 0};
|
||||||
videoInfo->rcTarget = videoInfo->rcSource;
|
videoInfo->rcTarget = videoInfo->rcSource;
|
||||||
videoInfo->dwBitRate = DWORD(8
|
videoInfo->dwBitRate = DWORD(8
|
||||||
* frameSize
|
* frameSize
|
||||||
* fps.num()
|
* size_t(fps.num())
|
||||||
/ fps.den());
|
/ size_t(fps.den()));
|
||||||
videoInfo->AvgTimePerFrame = REFERENCE_TIME(TIME_BASE
|
videoInfo->AvgTimePerFrame = REFERENCE_TIME(TIME_BASE / fps.value());
|
||||||
* fps.den()
|
|
||||||
/ fps.num());
|
|
||||||
|
|
||||||
// Initialize bitmap header.
|
// Initialize bitmap header.
|
||||||
videoInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
videoInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||||
|
@ -783,405 +792,3 @@ std::string AkVCam::stringFromMediaSample(IMediaSample *mediaSample)
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
LONG AkVCam::regGetValue(HKEY hkey,
|
|
||||||
LPCWSTR lpSubKey,
|
|
||||||
LPCWSTR lpValue,
|
|
||||||
DWORD dwFlags,
|
|
||||||
LPDWORD pdwType,
|
|
||||||
PVOID pvData,
|
|
||||||
LPDWORD pcbData)
|
|
||||||
{
|
|
||||||
HKEY key = nullptr;
|
|
||||||
auto result = RegOpenKeyEx(hkey,
|
|
||||||
lpSubKey,
|
|
||||||
0,
|
|
||||||
KEY_READ | KEY_WOW64_64KEY,
|
|
||||||
&key);
|
|
||||||
|
|
||||||
if (result != ERROR_SUCCESS)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
result = RegGetValue(key,
|
|
||||||
nullptr,
|
|
||||||
lpValue,
|
|
||||||
dwFlags,
|
|
||||||
pdwType,
|
|
||||||
pvData,
|
|
||||||
pcbData);
|
|
||||||
RegCloseKey(key);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AkVCam::regReadString(const std::string &key, const std::string &defaultValue)
|
|
||||||
{
|
|
||||||
auto wkey = std::wstring(key.begin(), key.end());
|
|
||||||
WCHAR value[MAX_PATH];
|
|
||||||
memset(value, 0, MAX_PATH * sizeof(WCHAR));
|
|
||||||
DWORD valueSize = MAX_PATH;
|
|
||||||
if (FAILED(regGetValue(HKEY_LOCAL_MACHINE,
|
|
||||||
L"SOFTWARE\\Webcamoid\\VirtualCamera",
|
|
||||||
wkey.c_str(),
|
|
||||||
RRF_RT_REG_SZ,
|
|
||||||
nullptr,
|
|
||||||
&value,
|
|
||||||
&valueSize)))
|
|
||||||
return defaultValue;
|
|
||||||
|
|
||||||
char str[MAX_PATH];
|
|
||||||
char defaultChar = '?';
|
|
||||||
WideCharToMultiByte(CP_ACP,
|
|
||||||
0,
|
|
||||||
value,
|
|
||||||
-1,
|
|
||||||
str,
|
|
||||||
MAX_PATH,
|
|
||||||
&defaultChar,
|
|
||||||
nullptr);
|
|
||||||
|
|
||||||
return std::string(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
int AkVCam::regReadInt(const std::string &key, int defaultValue)
|
|
||||||
{
|
|
||||||
auto wkey = std::wstring(key.begin(), key.end());
|
|
||||||
DWORD value = 0;
|
|
||||||
DWORD valueSize = sizeof(DWORD);
|
|
||||||
|
|
||||||
if (FAILED(regGetValue(HKEY_LOCAL_MACHINE,
|
|
||||||
L"SOFTWARE\\Webcamoid\\VirtualCamera",
|
|
||||||
wkey.c_str(),
|
|
||||||
RRF_RT_REG_DWORD,
|
|
||||||
nullptr,
|
|
||||||
&value,
|
|
||||||
&valueSize)))
|
|
||||||
return defaultValue;
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<CLSID> AkVCam::listRegisteredCameras(HINSTANCE hinstDLL)
|
|
||||||
{
|
|
||||||
WCHAR *strIID = nullptr;
|
|
||||||
StringFromIID(CLSID_VideoInputDeviceCategory, &strIID);
|
|
||||||
|
|
||||||
std::wstringstream ss;
|
|
||||||
ss << L"CLSID\\"
|
|
||||||
<< strIID
|
|
||||||
<< L"\\Instance";
|
|
||||||
CoTaskMemFree(strIID);
|
|
||||||
|
|
||||||
HKEY key = nullptr;
|
|
||||||
auto result = RegOpenKeyEx(HKEY_CLASSES_ROOT,
|
|
||||||
ss.str().c_str(),
|
|
||||||
0,
|
|
||||||
MAXIMUM_ALLOWED,
|
|
||||||
&key);
|
|
||||||
|
|
||||||
if (result != ERROR_SUCCESS)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
DWORD subkeys = 0;
|
|
||||||
|
|
||||||
result = RegQueryInfoKey(key,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
&subkeys,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
nullptr);
|
|
||||||
|
|
||||||
if (result != ERROR_SUCCESS) {
|
|
||||||
RegCloseKey(key);
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<CLSID> cameras;
|
|
||||||
FILETIME lastWrite;
|
|
||||||
|
|
||||||
for (DWORD i = 0; i < subkeys; i++) {
|
|
||||||
TCHAR subKey[MAX_PATH];
|
|
||||||
memset(subKey, 0, MAX_PATH * sizeof(TCHAR));
|
|
||||||
DWORD subKeyLen = MAX_PATH;
|
|
||||||
result = RegEnumKeyEx(key,
|
|
||||||
i,
|
|
||||||
subKey,
|
|
||||||
&subKeyLen,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
&lastWrite);
|
|
||||||
|
|
||||||
if (result != ERROR_SUCCESS)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::wstringstream ss;
|
|
||||||
ss << L"CLSID\\" << subKey << L"\\InprocServer32";
|
|
||||||
WCHAR path[MAX_PATH];
|
|
||||||
memset(path, 0, MAX_PATH * sizeof(WCHAR));
|
|
||||||
DWORD pathSize = MAX_PATH;
|
|
||||||
|
|
||||||
if (RegGetValue(HKEY_CLASSES_ROOT,
|
|
||||||
ss.str().c_str(),
|
|
||||||
nullptr,
|
|
||||||
RRF_RT_REG_SZ,
|
|
||||||
nullptr,
|
|
||||||
path,
|
|
||||||
&pathSize) == ERROR_SUCCESS) {
|
|
||||||
WCHAR modulePath[MAX_PATH];
|
|
||||||
memset(modulePath, 0, MAX_PATH * sizeof(WCHAR));
|
|
||||||
GetModuleFileName(hinstDLL, modulePath, MAX_PATH);
|
|
||||||
|
|
||||||
if (!lstrcmpi(path, modulePath)) {
|
|
||||||
CLSID clsid;
|
|
||||||
memset(&clsid, 0, sizeof(CLSID));
|
|
||||||
CLSIDFromString(subKey, &clsid);
|
|
||||||
cameras.push_back(clsid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RegCloseKey(key);
|
|
||||||
|
|
||||||
return cameras;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD AkVCam::camerasCount()
|
|
||||||
{
|
|
||||||
DWORD nCameras = 0;
|
|
||||||
DWORD nCamerasSize = sizeof(DWORD);
|
|
||||||
|
|
||||||
regGetValue(HKEY_LOCAL_MACHINE,
|
|
||||||
L"SOFTWARE\\Webcamoid\\VirtualCamera\\Cameras",
|
|
||||||
L"size",
|
|
||||||
RRF_RT_REG_DWORD,
|
|
||||||
nullptr,
|
|
||||||
&nCameras,
|
|
||||||
&nCamerasSize);
|
|
||||||
|
|
||||||
return nCameras;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring AkVCam::createDevicePath()
|
|
||||||
{
|
|
||||||
// List device paths in use.
|
|
||||||
std::vector<std::wstring> cameraPaths;
|
|
||||||
|
|
||||||
for (DWORD i = 0; i < camerasCount(); i++)
|
|
||||||
cameraPaths.push_back(cameraPath(i));
|
|
||||||
|
|
||||||
const int maxId = 64;
|
|
||||||
|
|
||||||
for (int i = 0; i < maxId; i++) {
|
|
||||||
/* There are no rules for device paths in Windows. Just append an
|
|
||||||
* incremental index to a common prefix.
|
|
||||||
*/
|
|
||||||
auto path = DSHOW_PLUGIN_DEVICE_PREFIX_L + std::to_wstring(i);
|
|
||||||
|
|
||||||
// Check if the path is being used, if not return it.
|
|
||||||
if (std::find(cameraPaths.begin(),
|
|
||||||
cameraPaths.end(),
|
|
||||||
path) == cameraPaths.end())
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
int AkVCam::cameraFromId(const std::wstring &path)
|
|
||||||
{
|
|
||||||
auto clsid = createClsidFromStr(path);
|
|
||||||
|
|
||||||
return cameraFromId(clsid);
|
|
||||||
}
|
|
||||||
|
|
||||||
int AkVCam::cameraFromId(const CLSID &clsid)
|
|
||||||
{
|
|
||||||
for (DWORD i = 0; i < camerasCount(); i++) {
|
|
||||||
auto cameraClsid = createClsidFromStr(cameraPath(i));
|
|
||||||
|
|
||||||
if (IsEqualCLSID(cameraClsid, clsid) && !cameraFormats(i).empty())
|
|
||||||
return int(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AkVCam::cameraExists(const std::string &path)
|
|
||||||
{
|
|
||||||
return cameraExists(std::wstring(path.begin(), path.end()));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AkVCam::cameraExists(const std::wstring &path)
|
|
||||||
{
|
|
||||||
for (DWORD i = 0; i < camerasCount(); i++)
|
|
||||||
if (cameraPath(i) == path)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring AkVCam::cameraDescription(DWORD cameraIndex)
|
|
||||||
{
|
|
||||||
std::wstringstream ss;
|
|
||||||
ss << L"SOFTWARE\\Webcamoid\\VirtualCamera\\Cameras\\"
|
|
||||||
<< cameraIndex + 1;
|
|
||||||
|
|
||||||
WCHAR description[1024];
|
|
||||||
DWORD descriptionSize = 1024 * sizeof(WCHAR);
|
|
||||||
memset(description, 0, descriptionSize);
|
|
||||||
|
|
||||||
if (regGetValue(HKEY_LOCAL_MACHINE,
|
|
||||||
ss.str().c_str(),
|
|
||||||
L"description",
|
|
||||||
RRF_RT_REG_SZ,
|
|
||||||
nullptr,
|
|
||||||
&description,
|
|
||||||
&descriptionSize) != ERROR_SUCCESS)
|
|
||||||
return std::wstring();
|
|
||||||
|
|
||||||
return std::wstring(description);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring AkVCam::cameraPath(DWORD cameraIndex)
|
|
||||||
{
|
|
||||||
std::wstringstream ss;
|
|
||||||
ss << L"SOFTWARE\\Webcamoid\\VirtualCamera\\Cameras\\"
|
|
||||||
<< cameraIndex + 1;
|
|
||||||
|
|
||||||
WCHAR path[1024];
|
|
||||||
DWORD pathSize = 1024 * sizeof(WCHAR);
|
|
||||||
memset(path, 0, pathSize);
|
|
||||||
|
|
||||||
if (regGetValue(HKEY_LOCAL_MACHINE,
|
|
||||||
ss.str().c_str(),
|
|
||||||
L"path",
|
|
||||||
RRF_RT_REG_SZ,
|
|
||||||
nullptr,
|
|
||||||
&path,
|
|
||||||
&pathSize) != ERROR_SUCCESS)
|
|
||||||
return std::wstring();
|
|
||||||
|
|
||||||
return std::wstring(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring AkVCam::cameraPath(const CLSID &clsid)
|
|
||||||
{
|
|
||||||
auto camera = cameraFromId(clsid);
|
|
||||||
|
|
||||||
if (camera < 0)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
return cameraPath(DWORD(camera));
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD AkVCam::formatsCount(DWORD cameraIndex)
|
|
||||||
{
|
|
||||||
std::wstringstream ss;
|
|
||||||
ss << L"SOFTWARE\\Webcamoid\\VirtualCamera\\Cameras\\"
|
|
||||||
<< cameraIndex + 1
|
|
||||||
<< L"\\Formats";
|
|
||||||
|
|
||||||
DWORD nFormats;
|
|
||||||
DWORD nFormatsSize = sizeof(DWORD);
|
|
||||||
memset(&nFormats, 0, nFormatsSize);
|
|
||||||
|
|
||||||
regGetValue(HKEY_LOCAL_MACHINE,
|
|
||||||
ss.str().c_str(),
|
|
||||||
L"size",
|
|
||||||
RRF_RT_REG_DWORD,
|
|
||||||
nullptr,
|
|
||||||
&nFormats,
|
|
||||||
&nFormatsSize);
|
|
||||||
|
|
||||||
return nFormats;
|
|
||||||
}
|
|
||||||
|
|
||||||
AkVCam::VideoFormat AkVCam::cameraFormat(DWORD cameraIndex, DWORD formatIndex)
|
|
||||||
{
|
|
||||||
std::wstringstream ss;
|
|
||||||
ss << L"SOFTWARE\\Webcamoid\\VirtualCamera\\Cameras\\"
|
|
||||||
<< cameraIndex + 1
|
|
||||||
<< L"\\Formats\\"
|
|
||||||
<< formatIndex + 1;
|
|
||||||
|
|
||||||
WCHAR formatStr[1024];
|
|
||||||
DWORD variableSize = 1024 * sizeof(WCHAR);
|
|
||||||
memset(formatStr, 0, variableSize);
|
|
||||||
|
|
||||||
if (regGetValue(HKEY_LOCAL_MACHINE,
|
|
||||||
ss.str().c_str(),
|
|
||||||
L"format",
|
|
||||||
RRF_RT_REG_SZ,
|
|
||||||
nullptr,
|
|
||||||
&formatStr,
|
|
||||||
&variableSize) != ERROR_SUCCESS)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
DWORD width = 0;
|
|
||||||
variableSize = sizeof(DWORD);
|
|
||||||
|
|
||||||
if (regGetValue(HKEY_LOCAL_MACHINE,
|
|
||||||
ss.str().c_str(),
|
|
||||||
L"width",
|
|
||||||
RRF_RT_REG_DWORD,
|
|
||||||
nullptr,
|
|
||||||
&width,
|
|
||||||
&variableSize) != ERROR_SUCCESS)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
DWORD height = 0;
|
|
||||||
variableSize = sizeof(DWORD);
|
|
||||||
|
|
||||||
if (regGetValue(HKEY_LOCAL_MACHINE,
|
|
||||||
ss.str().c_str(),
|
|
||||||
L"height",
|
|
||||||
RRF_RT_REG_DWORD,
|
|
||||||
nullptr,
|
|
||||||
&height,
|
|
||||||
&variableSize) != ERROR_SUCCESS)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
WCHAR fpsStr[1024];
|
|
||||||
variableSize = 1024 * sizeof(WCHAR);
|
|
||||||
memset(fpsStr, 0, variableSize);
|
|
||||||
|
|
||||||
if (regGetValue(HKEY_LOCAL_MACHINE,
|
|
||||||
ss.str().c_str(),
|
|
||||||
L"fps",
|
|
||||||
RRF_RT_REG_SZ,
|
|
||||||
nullptr,
|
|
||||||
&fpsStr,
|
|
||||||
&variableSize) != ERROR_SUCCESS)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
std::wstring format(formatStr);
|
|
||||||
auto fourcc = VideoFormat::fourccFromString(std::string(format.begin(),
|
|
||||||
format.end()));
|
|
||||||
|
|
||||||
return VideoFormat(fourcc,
|
|
||||||
int(width),
|
|
||||||
int(height),
|
|
||||||
{Fraction(fpsStr)});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<AkVCam::VideoFormat> AkVCam::cameraFormats(DWORD cameraIndex)
|
|
||||||
{
|
|
||||||
std::vector<AkVCam::VideoFormat> formats;
|
|
||||||
|
|
||||||
for (DWORD i = 0; i < formatsCount(cameraIndex); i++) {
|
|
||||||
auto videoFormat = cameraFormat(cameraIndex, i);
|
|
||||||
|
|
||||||
if (videoFormat)
|
|
||||||
formats.push_back(videoFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
return formats;
|
|
||||||
}
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace AkVCam
|
||||||
class VideoFormat;
|
class VideoFormat;
|
||||||
|
|
||||||
BOOL isWow64();
|
BOOL isWow64();
|
||||||
std::wstring tempPath();
|
std::string tempPath();
|
||||||
std::wstring programFilesPath();
|
std::wstring programFilesPath();
|
||||||
std::wstring moduleFileNameW(HINSTANCE hinstDLL);
|
std::wstring moduleFileNameW(HINSTANCE hinstDLL);
|
||||||
std::string moduleFileName(HINSTANCE hinstDLL);
|
std::string moduleFileName(HINSTANCE hinstDLL);
|
||||||
|
@ -69,29 +69,6 @@ namespace AkVCam
|
||||||
std::string stringFromFormatType(const GUID &formatType);
|
std::string stringFromFormatType(const GUID &formatType);
|
||||||
std::string stringFromMediaType(const AM_MEDIA_TYPE *mediaType);
|
std::string stringFromMediaType(const AM_MEDIA_TYPE *mediaType);
|
||||||
std::string stringFromMediaSample(IMediaSample *mediaSample);
|
std::string stringFromMediaSample(IMediaSample *mediaSample);
|
||||||
LONG regGetValue(HKEY hkey,
|
|
||||||
LPCWSTR lpSubKey,
|
|
||||||
LPCWSTR lpValue,
|
|
||||||
DWORD dwFlags,
|
|
||||||
LPDWORD pdwType,
|
|
||||||
PVOID pvData,
|
|
||||||
LPDWORD pcbData);
|
|
||||||
std::string regReadString(const std::string &key,
|
|
||||||
const std::string &defaultValue={});
|
|
||||||
int regReadInt(const std::string &key, int defaultValue=0);
|
|
||||||
std::vector<CLSID> listRegisteredCameras(HINSTANCE hinstDLL);
|
|
||||||
DWORD camerasCount();
|
|
||||||
std::wstring createDevicePath();
|
|
||||||
int cameraFromId(const std::wstring &path);
|
|
||||||
int cameraFromId(const CLSID &clsid);
|
|
||||||
bool cameraExists(const std::string &path);
|
|
||||||
bool cameraExists(const std::wstring &path);
|
|
||||||
std::wstring cameraDescription(DWORD cameraIndex);
|
|
||||||
std::wstring cameraPath(DWORD cameraIndex);
|
|
||||||
std::wstring cameraPath(const CLSID &clsid);
|
|
||||||
DWORD formatsCount(DWORD cameraIndex);
|
|
||||||
VideoFormat cameraFormat(DWORD cameraIndex, DWORD formatIndex);
|
|
||||||
std::vector<VideoFormat> cameraFormats(DWORD cameraIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // PLATFORM_UTILS_H
|
#endif // PLATFORM_UTILS_H
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -52,7 +52,6 @@ LIBS += \
|
||||||
-lwinmm
|
-lwinmm
|
||||||
|
|
||||||
TARGET = $${DSHOW_PLUGIN_NAME}
|
TARGET = $${DSHOW_PLUGIN_NAME}
|
||||||
|
|
||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
|
|
@ -113,15 +113,11 @@ void AkVCam::BaseFilter::addPin(const std::vector<AkVCam::VideoFormat> &formats,
|
||||||
{
|
{
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
this->d->m_pins->addPin(new Pin(this, formats, pinName), changed);
|
this->d->m_pins->addPin(new Pin(this, formats, pinName), changed);
|
||||||
|
|
||||||
if (this->d->m_pins->count() == 1)
|
|
||||||
this->d->m_ipcBridge.connectService(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AkVCam::BaseFilter::removePin(IPin *pin, bool changed)
|
void AkVCam::BaseFilter::removePin(IPin *pin, bool changed)
|
||||||
{
|
{
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
this->d->m_ipcBridge.disconnectService();
|
|
||||||
this->d->m_pins->removePin(pin, changed);
|
this->d->m_pins->removePin(pin, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "plugininterface.h"
|
#include "plugininterface.h"
|
||||||
#include "classfactory.h"
|
#include "classfactory.h"
|
||||||
|
#include "PlatformUtils/src/preferences.h"
|
||||||
#include "PlatformUtils/src/utils.h"
|
#include "PlatformUtils/src/utils.h"
|
||||||
#include "VCamUtils/src/utils.h"
|
#include "VCamUtils/src/utils.h"
|
||||||
|
|
||||||
|
@ -33,24 +34,20 @@ inline AkVCam::PluginInterface *pluginInterface()
|
||||||
// Filter entry point
|
// Filter entry point
|
||||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
{
|
{
|
||||||
UNUSED(lpvReserved)
|
UNUSED(lpvReserved);
|
||||||
AkLogFunction();
|
AkLogFunction();
|
||||||
auto logLevel =
|
auto loglevel = AkVCam::Preferences::logLevel();
|
||||||
AkVCam::regReadInt("loglevel", AKVCAM_LOGLEVEL_DEFAULT);
|
AkVCam::Logger::setLogLevel(loglevel);
|
||||||
AkVCam::Logger::setLogLevel(logLevel);
|
|
||||||
|
|
||||||
if (AkVCam::Logger::logLevel() > AKVCAM_LOGLEVEL_DEFAULT) {
|
if (loglevel > AKVCAM_LOGLEVEL_DEFAULT) {
|
||||||
// Turn on lights
|
// Turn on lights
|
||||||
freopen("CONOUT$", "a", stdout);
|
freopen("CONOUT$", "a", stdout);
|
||||||
freopen("CONOUT$", "a", stderr);
|
freopen("CONOUT$", "a", stderr);
|
||||||
setbuf(stdout, nullptr);
|
setbuf(stdout, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto temp = AkVCam::tempPath();
|
auto defaultLogFile = AkVCam::tempPath() + "\\" DSHOW_PLUGIN_NAME ".log";
|
||||||
auto logFile =
|
auto logFile = AkVCam::Preferences::readString("logfile", defaultLogFile);
|
||||||
AkVCam::regReadString("logfile",
|
|
||||||
std::string(temp.begin(), temp.end())
|
|
||||||
+ "\\" DSHOW_PLUGIN_NAME ".log");
|
|
||||||
AkVCam::Logger::setLogFile(logFile);
|
AkVCam::Logger::setLogFile(logFile);
|
||||||
|
|
||||||
switch (fdwReason) {
|
switch (fdwReason) {
|
||||||
|
|
Loading…
Reference in a new issue