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.",
|
||||
AKVCAM_BIND_FUNC(CmdParserPrivate::showClients));
|
||||
this->d->m_ipcBridge.connectService();
|
||||
}
|
||||
|
||||
AkVCam::CmdParser::~CmdParser()
|
||||
{
|
||||
this->d->m_ipcBridge.disconnectService();
|
||||
delete this->d;
|
||||
}
|
||||
|
||||
|
|
|
@ -104,10 +104,6 @@ namespace AkVCam
|
|||
int logLevel() const;
|
||||
void setLogLevel(int logLevel);
|
||||
|
||||
// Manage main service connection.
|
||||
void connectService();
|
||||
void disconnectService();
|
||||
|
||||
// Register the peer to the global server.
|
||||
bool registerPeer();
|
||||
|
||||
|
|
|
@ -54,10 +54,6 @@
|
|||
#define AKVCAM_ASSISTANT_MSG_DEVICE_SETBROADCASTING 0x401
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_CONTROLS_UPDATED 0x402
|
||||
|
||||
// Connections
|
||||
#define AKVCAM_ASSISTANT_MSG_CONNECTIONS 0x500
|
||||
#define AKVCAM_ASSISTANT_MSG_SETCONNECTIONS 0x501
|
||||
|
||||
namespace AkVCam
|
||||
{
|
||||
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)
|
||||
return;
|
||||
|
||||
cameraSetFormats(cameraIndex, {});
|
||||
cameraSetFormats(size_t(cameraIndex), {});
|
||||
|
||||
auto nCameras = camerasCount();
|
||||
deleteAllKeys("cameras." + std::to_string(cameraIndex));
|
||||
|
@ -451,6 +451,7 @@ void AkVCam::Preferences::cameraSetDescription(size_t cameraIndex,
|
|||
|
||||
write("cameras." + std::to_string(cameraIndex) + ".description",
|
||||
description);
|
||||
sync();
|
||||
}
|
||||
|
||||
std::string AkVCam::Preferences::cameraPath(size_t cameraIndex)
|
||||
|
@ -536,7 +537,7 @@ void AkVCam::Preferences::cameraAddFormat(size_t cameraIndex,
|
|||
auto formats = cameraFormats(cameraIndex);
|
||||
|
||||
if (index < 0 || index > int(formats.size()))
|
||||
index = formats.size();
|
||||
index = int(formats.size());
|
||||
|
||||
formats.insert(formats.begin() + index, format);
|
||||
write("cameras."
|
||||
|
@ -563,7 +564,6 @@ void AkVCam::Preferences::cameraAddFormat(size_t cameraIndex,
|
|||
void AkVCam::Preferences::cameraRemoveFormat(size_t cameraIndex, int index)
|
||||
{
|
||||
AkLogFunction();
|
||||
|
||||
auto formats = cameraFormats(cameraIndex);
|
||||
|
||||
if (index < 0 || index >= int(formats.size()))
|
||||
|
@ -592,26 +592,6 @@ void AkVCam::Preferences::cameraRemoveFormat(size_t cameraIndex, int index)
|
|||
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,
|
||||
const std::string &key)
|
||||
{
|
||||
|
@ -623,4 +603,27 @@ void AkVCam::Preferences::cameraSetControlValue(size_t cameraIndex,
|
|||
int 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);
|
||||
void cameraSetFormats(size_t cameraIndex,
|
||||
const std::vector<VideoFormat> &formats);
|
||||
void cameraFormats(size_t cameraIndex,
|
||||
const std::vector<VideoFormat> &formats);
|
||||
void cameraAddFormat(size_t cameraIndex,
|
||||
const VideoFormat &format,
|
||||
int index);
|
||||
|
|
|
@ -80,11 +80,7 @@ namespace AkVCam
|
|||
void connectionInterrupted();
|
||||
|
||||
// Utility methods
|
||||
std::string homePath() const;
|
||||
bool fileExists(const std::wstring &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();
|
||||
|
||||
private:
|
||||
|
@ -148,30 +144,10 @@ void AkVCam::IpcBridge::setLogLevel(int logLevel)
|
|||
Logger::setLogLevel(logLevel);
|
||||
}
|
||||
|
||||
void AkVCam::IpcBridge::connectService()
|
||||
{
|
||||
AkLogFunction();
|
||||
this->registerPeer();
|
||||
}
|
||||
|
||||
void AkVCam::IpcBridge::disconnectService()
|
||||
{
|
||||
AkLogFunction();
|
||||
this->unregisterPeer();
|
||||
}
|
||||
|
||||
bool AkVCam::IpcBridge::registerPeer()
|
||||
{
|
||||
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)
|
||||
return true;
|
||||
|
||||
|
@ -318,7 +294,10 @@ std::wstring AkVCam::IpcBridge::description(const std::string &deviceId) const
|
|||
AkLogFunction();
|
||||
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,
|
||||
|
@ -327,7 +306,8 @@ void AkVCam::IpcBridge::setDescription(const std::string &deviceId,
|
|||
AkLogFunction();
|
||||
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
|
||||
|
@ -355,7 +335,10 @@ std::vector<AkVCam::VideoFormat> AkVCam::IpcBridge::formats(const std::string &d
|
|||
AkLogFunction();
|
||||
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,
|
||||
|
@ -363,7 +346,8 @@ void AkVCam::IpcBridge::setFormats(const std::string &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
|
||||
|
@ -409,7 +393,7 @@ std::vector<AkVCam::DeviceControl> AkVCam::IpcBridge::controls(const std::string
|
|||
for (auto &control: this->d->controls()) {
|
||||
controls.push_back(control);
|
||||
controls.back().value =
|
||||
Preferences::cameraControlValue(cameraIndex, control.id);
|
||||
Preferences::cameraControlValue(size_t(cameraIndex), control.id);
|
||||
}
|
||||
|
||||
return controls;
|
||||
|
@ -428,13 +412,14 @@ void AkVCam::IpcBridge::setControls(const std::string &deviceId,
|
|||
|
||||
for (auto &control: this->d->controls()) {
|
||||
auto oldValue =
|
||||
Preferences::cameraControlValue(cameraIndex, control.id);
|
||||
Preferences::cameraControlValue(size_t(cameraIndex),
|
||||
control.id);
|
||||
|
||||
if (controls.count(control.id)) {
|
||||
auto newValue = controls.at(control.id);
|
||||
|
||||
if (newValue != oldValue) {
|
||||
Preferences::cameraSetControlValue(cameraIndex,
|
||||
Preferences::cameraSetControlValue(size_t(cameraIndex),
|
||||
control.id,
|
||||
newValue);
|
||||
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
|
||||
{
|
||||
AkLogFunction();
|
||||
auto driverPath = this->d->locatePluginPath();
|
||||
AkLogDebug() << "Plugin path: " << driverPath << std::endl;
|
||||
auto pluginPath = this->d->locatePluginPath();
|
||||
AkLogDebug() << "Plugin path: " << pluginPath << std::endl;
|
||||
|
||||
if (driverPath.empty())
|
||||
if (pluginPath.empty())
|
||||
return {};
|
||||
|
||||
auto path = driverPath + "/Contents/MacOS/" CMIO_PLUGIN_NAME;
|
||||
auto path = pluginPath + "/Contents/MacOS/" CMIO_PLUGIN_NAME;
|
||||
AkLogDebug() << "Plugin binary: " << path << std::endl;
|
||||
|
||||
if (!this->d->fileExists(path))
|
||||
|
@ -553,16 +538,22 @@ void AkVCam::IpcBridge::addFormat(const std::string &deviceId,
|
|||
int index)
|
||||
{
|
||||
AkLogFunction();
|
||||
Preferences::cameraAddFormat(Preferences::cameraFromPath(deviceId),
|
||||
format,
|
||||
index);
|
||||
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||
|
||||
if (cameraIndex >= 0)
|
||||
Preferences::cameraAddFormat(size_t(cameraIndex),
|
||||
format,
|
||||
index);
|
||||
}
|
||||
|
||||
void AkVCam::IpcBridge::removeFormat(const std::string &deviceId, int index)
|
||||
{
|
||||
AkLogFunction();
|
||||
Preferences::cameraRemoveFormat(Preferences::cameraFromPath(deviceId),
|
||||
index);
|
||||
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||
|
||||
if (cameraIndex >= 0)
|
||||
Preferences::cameraRemoveFormat(size_t(cameraIndex),
|
||||
index);
|
||||
}
|
||||
|
||||
void AkVCam::IpcBridge::updateDevices()
|
||||
|
@ -578,7 +569,6 @@ void AkVCam::IpcBridge::updateDevices()
|
|||
AKVCAM_ASSISTANT_MSG_DEVICE_UPDATE);
|
||||
xpc_connection_send_message(this->d->m_serverMessagePort, dictionary);
|
||||
xpc_release(dictionary);
|
||||
|
||||
}
|
||||
|
||||
bool AkVCam::IpcBridge::deviceStart(const std::string &deviceId,
|
||||
|
@ -957,11 +947,15 @@ void AkVCam::IpcBridgePrivate::controlsUpdated(xpc_connection_t client,
|
|||
std::string deviceId =
|
||||
xpc_dictionary_get_string(event, "device");
|
||||
auto cameraIndex = Preferences::cameraFromPath(deviceId);
|
||||
|
||||
if (cameraIndex < 0)
|
||||
return;
|
||||
|
||||
std::map<std::string, int> controls;
|
||||
|
||||
for (auto &control: this->controls())
|
||||
controls[control.id] =
|
||||
Preferences::cameraControlValue(cameraIndex, control.id);
|
||||
Preferences::cameraControlValue(size_t(cameraIndex), control.id);
|
||||
|
||||
for (auto bridge: this->m_bridges)
|
||||
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
|
||||
{
|
||||
struct stat stats;
|
||||
|
@ -1052,62 +1031,6 @@ bool AkVCam::IpcBridgePrivate::fileExists(const std::string &path) const
|
|||
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()
|
||||
{
|
||||
AkLogFunction();
|
||||
|
|
|
@ -157,7 +157,6 @@ AkVCam::PluginInterface::PluginInterface():
|
|||
this->d->m_ref = 0;
|
||||
this->d->m_reserved = 0;
|
||||
|
||||
this->d->m_ipcBridge.connectService();
|
||||
this->d->m_ipcBridge.connectServerStateChanged(this, &PluginInterface::serverStateChanged);
|
||||
this->d->m_ipcBridge.connectDeviceAdded(this, &PluginInterface::deviceAdded);
|
||||
this->d->m_ipcBridge.connectDeviceRemoved(this, &PluginInterface::deviceRemoved);
|
||||
|
@ -170,7 +169,6 @@ AkVCam::PluginInterface::PluginInterface():
|
|||
|
||||
AkVCam::PluginInterface::~PluginInterface()
|
||||
{
|
||||
this->d->m_ipcBridge.disconnectService();
|
||||
delete this->d->pluginInterface;
|
||||
delete this->d;
|
||||
}
|
||||
|
|
|
@ -21,18 +21,17 @@
|
|||
#include <windows.h>
|
||||
|
||||
#include "service.h"
|
||||
#include "PlatformUtils/src/preferences.h"
|
||||
#include "PlatformUtils/src/utils.h"
|
||||
#include "VCamUtils/src/logger/logger.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
auto loglevel = AkVCam::regReadInt("loglevel", AKVCAM_LOGLEVEL_DEFAULT);
|
||||
auto loglevel = AkVCam::Preferences::logLevel();
|
||||
AkVCam::Logger::setLogLevel(loglevel);
|
||||
auto temp = AkVCam::tempPath();
|
||||
auto logFile =
|
||||
AkVCam::regReadString("logfile",
|
||||
std::string(temp.begin(), temp.end())
|
||||
+ "\\" DSHOW_PLUGIN_ASSISTANT_NAME ".log");
|
||||
auto defaultLogFile = AkVCam::tempPath()
|
||||
+ "\\" DSHOW_PLUGIN_ASSISTANT_NAME ".log";
|
||||
auto logFile = AkVCam::Preferences::readString("logfile", defaultLogFile);
|
||||
AkVCam::Logger::setLogFile(logFile);
|
||||
AkVCam::Service service;
|
||||
|
||||
|
|
|
@ -42,20 +42,6 @@ namespace AkVCam
|
|||
{
|
||||
std::string broadcaster;
|
||||
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;
|
||||
|
@ -85,20 +71,15 @@ namespace AkVCam
|
|||
void addPort(Message *message);
|
||||
void removePort(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 pictureUpdated(Message *message);
|
||||
void deviceUpdate(Message *message);
|
||||
void listeners(Message *message);
|
||||
void listener(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 listenerRemove(Message *message);
|
||||
void controlsUpdated(Message *message);
|
||||
};
|
||||
|
||||
GLOBAL_STATIC(ServicePrivate, servicePrivate)
|
||||
|
@ -245,7 +226,7 @@ void AkVCam::Service::debug()
|
|||
void AkVCam::Service::showHelp(int argc, char **argv)
|
||||
{
|
||||
AkLogFunction();
|
||||
UNUSED(argc)
|
||||
UNUSED(argc);
|
||||
|
||||
auto programName = strrchr(argv[0], '\\');
|
||||
|
||||
|
@ -285,24 +266,19 @@ AkVCam::ServicePrivate::ServicePrivate()
|
|||
this->m_statusHandler = nullptr;
|
||||
this->m_messageServer.setPipeName(L"\\\\.\\pipe\\" DSHOW_PLUGIN_ASSISTANT_NAME_L);
|
||||
this->m_messageServer.setHandlers({
|
||||
{AKVCAM_ASSISTANT_MSG_FRAME_READY , AKVCAM_BIND_FUNC(ServicePrivate::frameReady) },
|
||||
{AKVCAM_ASSISTANT_MSG_REQUEST_PORT , AKVCAM_BIND_FUNC(ServicePrivate::requestPort) },
|
||||
{AKVCAM_ASSISTANT_MSG_ADD_PORT , AKVCAM_BIND_FUNC(ServicePrivate::addPort) },
|
||||
{AKVCAM_ASSISTANT_MSG_REMOVE_PORT , AKVCAM_BIND_FUNC(ServicePrivate::removePort) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_ADD , AKVCAM_BIND_FUNC(ServicePrivate::listenerAdd) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_REMOVE, AKVCAM_BIND_FUNC(ServicePrivate::listenerRemove) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENERS , AKVCAM_BIND_FUNC(ServicePrivate::listeners) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER , AKVCAM_BIND_FUNC(ServicePrivate::listener) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_BROADCASTING , AKVCAM_BIND_FUNC(ServicePrivate::broadcasting) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_SETBROADCASTING, AKVCAM_BIND_FUNC(ServicePrivate::setBroadCasting)},
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_MIRRORING , AKVCAM_BIND_FUNC(ServicePrivate::mirroring) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_SETMIRRORING , AKVCAM_BIND_FUNC(ServicePrivate::setMirroring) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_SCALING , AKVCAM_BIND_FUNC(ServicePrivate::scaling) },
|
||||
{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) },
|
||||
{AKVCAM_ASSISTANT_MSG_FRAME_READY , AKVCAM_BIND_FUNC(ServicePrivate::frameReady) },
|
||||
{AKVCAM_ASSISTANT_MSG_PICTURE_UPDATED , AKVCAM_BIND_FUNC(ServicePrivate::pictureUpdated) },
|
||||
{AKVCAM_ASSISTANT_MSG_REQUEST_PORT , AKVCAM_BIND_FUNC(ServicePrivate::requestPort) },
|
||||
{AKVCAM_ASSISTANT_MSG_ADD_PORT , AKVCAM_BIND_FUNC(ServicePrivate::addPort) },
|
||||
{AKVCAM_ASSISTANT_MSG_REMOVE_PORT , AKVCAM_BIND_FUNC(ServicePrivate::removePort) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_UPDATE , AKVCAM_BIND_FUNC(ServicePrivate::deviceUpdate) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_ADD , AKVCAM_BIND_FUNC(ServicePrivate::listenerAdd) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_REMOVE , AKVCAM_BIND_FUNC(ServicePrivate::listenerRemove) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENERS , AKVCAM_BIND_FUNC(ServicePrivate::listeners) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER , AKVCAM_BIND_FUNC(ServicePrivate::listener) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_BROADCASTING , AKVCAM_BIND_FUNC(ServicePrivate::broadcasting) },
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_SETBROADCASTING , AKVCAM_BIND_FUNC(ServicePrivate::setBroadCasting)},
|
||||
{AKVCAM_ASSISTANT_MSG_DEVICE_CONTROLS_UPDATED, AKVCAM_BIND_FUNC(ServicePrivate::controlsUpdated)},
|
||||
});
|
||||
this->m_timer.setInterval(60000);
|
||||
this->m_timer.connectTimeout(this, &ServicePrivate::checkPeers);
|
||||
|
@ -311,7 +287,7 @@ AkVCam::ServicePrivate::ServicePrivate()
|
|||
void AkVCam::ServicePrivate::stateChanged(void *userData,
|
||||
MessageServer::State state)
|
||||
{
|
||||
UNUSED(userData)
|
||||
UNUSED(userData);
|
||||
|
||||
switch (state) {
|
||||
case MessageServer::StateAboutToStart:
|
||||
|
@ -368,7 +344,6 @@ void AkVCam::ServicePrivate::sendStatus(DWORD currentState,
|
|||
DWORD wait)
|
||||
{
|
||||
AkLogFunction();
|
||||
|
||||
this->m_status.dwControlsAccepted =
|
||||
currentState == SERVICE_START_PENDING? 0: SERVICE_ACCEPT_STOP;
|
||||
this->m_status.dwCurrentState = currentState;
|
||||
|
@ -460,11 +435,8 @@ void AkVCam::ServicePrivate::requestPort(AkVCam::Message *message)
|
|||
AkLogFunction();
|
||||
|
||||
auto data = messageData<MsgRequestPort>(message);
|
||||
std::string portName = data->client?
|
||||
AKVCAM_ASSISTANT_CLIENT_NAME:
|
||||
AKVCAM_ASSISTANT_SERVER_NAME;
|
||||
std::string portName = AKVCAM_ASSISTANT_CLIENT_NAME;
|
||||
portName += std::to_string(this->id());
|
||||
|
||||
AkLogInfo() << "Returning Port: " << portName << std::endl;
|
||||
memcpy(data->port,
|
||||
portName.c_str(),
|
||||
|
@ -547,112 +519,6 @@ void AkVCam::ServicePrivate::setBroadCasting(AkVCam::Message *message)
|
|||
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)
|
||||
{
|
||||
AkLogFunction();
|
||||
|
@ -664,6 +530,28 @@ void AkVCam::ServicePrivate::frameReady(AkVCam::Message *message)
|
|||
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)
|
||||
{
|
||||
AkLogFunction();
|
||||
|
@ -726,59 +614,6 @@ void AkVCam::ServicePrivate::broadcasting(AkVCam::Message *message)
|
|||
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)
|
||||
{
|
||||
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 eventType,
|
||||
LPVOID eventData,
|
||||
LPVOID context)
|
||||
{
|
||||
UNUSED(eventType)
|
||||
UNUSED(eventData)
|
||||
UNUSED(context)
|
||||
UNUSED(eventType);
|
||||
UNUSED(eventData);
|
||||
UNUSED(context);
|
||||
AkLogFunction();
|
||||
|
||||
DWORD result = ERROR_CALL_NOT_IMPLEMENTED;
|
||||
|
@ -896,8 +742,8 @@ BOOL WINAPI controlDebugHandler(DWORD control)
|
|||
|
||||
void WINAPI serviceMain(DWORD dwArgc, LPTSTR *lpszArgv)
|
||||
{
|
||||
UNUSED(dwArgc)
|
||||
UNUSED(lpszArgv)
|
||||
UNUSED(dwArgc);
|
||||
UNUSED(lpszArgv);
|
||||
AkLogFunction();
|
||||
AkLogInfo() << "Setting service control handler" << std::endl;
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ LIBS = \
|
|||
SOURCES = \
|
||||
src/messageserver.cpp \
|
||||
src/mutex.cpp \
|
||||
src/preferences.cpp \
|
||||
src/utils.cpp \
|
||||
src/sharedmemory.cpp
|
||||
|
||||
|
@ -57,6 +58,7 @@ HEADERS = \
|
|||
src/messagecommons.h \
|
||||
src/messageserver.h \
|
||||
src/mutex.h \
|
||||
src/preferences.h \
|
||||
src/utils.h \
|
||||
src/sharedmemory.h
|
||||
|
||||
|
|
|
@ -30,38 +30,33 @@
|
|||
#define AKVCAM_ASSISTANT_SERVER_NAME "AkVCam_Server"
|
||||
|
||||
// General messages
|
||||
#define AKVCAM_ASSISTANT_MSG_ISALIVE 0x000
|
||||
#define AKVCAM_ASSISTANT_MSG_FRAME_READY 0x001
|
||||
#define AKVCAM_ASSISTANT_MSG_ISALIVE 0x000
|
||||
#define AKVCAM_ASSISTANT_MSG_FRAME_READY 0x001
|
||||
#define AKVCAM_ASSISTANT_MSG_PICTURE_UPDATED 0x002
|
||||
|
||||
// Assistant messages
|
||||
#define AKVCAM_ASSISTANT_MSG_REQUEST_PORT 0x100
|
||||
#define AKVCAM_ASSISTANT_MSG_ADD_PORT 0x101
|
||||
#define AKVCAM_ASSISTANT_MSG_REMOVE_PORT 0x102
|
||||
#define AKVCAM_ASSISTANT_MSG_REQUEST_PORT 0x100
|
||||
#define AKVCAM_ASSISTANT_MSG_ADD_PORT 0x101
|
||||
#define AKVCAM_ASSISTANT_MSG_REMOVE_PORT 0x102
|
||||
|
||||
// Device control and information
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICES 0x200
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_CREATE 0x201
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_DESTROY 0x202
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_DESCRIPTION 0x203
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_FORMATS 0x204
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICES 0x200
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_CREATE 0x201
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_DESTROY 0x202
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_DESCRIPTION 0x203
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_FORMATS 0x204
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_UPDATE 0x205
|
||||
|
||||
// Device listeners controls
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENERS 0x300
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER 0x301
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_ADD 0x302
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_REMOVE 0x303
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENERS 0x300
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER 0x301
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_ADD 0x302
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_LISTENER_REMOVE 0x303
|
||||
|
||||
// Device dynamic properties
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_BROADCASTING 0x400
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_SETBROADCASTING 0x401
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_MIRRORING 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 AKVCAM_ASSISTANT_MSG_DEVICE_BROADCASTING 0x400
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_SETBROADCASTING 0x401
|
||||
#define AKVCAM_ASSISTANT_MSG_DEVICE_CONTROLS_UPDATED 0x402
|
||||
|
||||
#define MSG_BUFFER_SIZE 4096
|
||||
#define MAX_STRING 1024
|
||||
|
@ -136,7 +131,6 @@ namespace AkVCam
|
|||
|
||||
struct MsgRequestPort
|
||||
{
|
||||
bool client;
|
||||
char port[MAX_STRING];
|
||||
};
|
||||
|
||||
|
@ -152,6 +146,16 @@ namespace AkVCam
|
|||
char port[MAX_STRING];
|
||||
};
|
||||
|
||||
struct MsgDeviceAdded
|
||||
{
|
||||
char device[MAX_STRING];
|
||||
};
|
||||
|
||||
struct MsgDeviceRemoved
|
||||
{
|
||||
char device[MAX_STRING];
|
||||
};
|
||||
|
||||
struct MsgBroadcasting
|
||||
{
|
||||
char device[MAX_STRING];
|
||||
|
@ -159,35 +163,6 @@ namespace AkVCam
|
|||
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
|
||||
{
|
||||
char device[MAX_STRING];
|
||||
|
@ -206,6 +181,16 @@ namespace AkVCam
|
|||
char device[MAX_STRING];
|
||||
char port[MAX_STRING];
|
||||
};
|
||||
|
||||
struct MsgPictureUpdated
|
||||
{
|
||||
char picture[MAX_STRING];
|
||||
};
|
||||
|
||||
struct MsgControlsUpdated
|
||||
{
|
||||
char device[MAX_STRING];
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MESSAGECOMMONS_H
|
||||
|
|
|
@ -375,7 +375,7 @@ void AkVCam::MessageServerPrivate::checkLoop()
|
|||
this->m_pipeName.end())
|
||||
<< std::endl;
|
||||
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
|
||||
&& this->m_pipeState != AkVCam::MessageServer::PipeStateGone
|
||||
&& GetLastError() != ERROR_SEM_TIMEOUT) {
|
||||
|
@ -384,7 +384,7 @@ void AkVCam::MessageServerPrivate::checkLoop()
|
|||
this->m_pipeName.end())
|
||||
<< std::endl;
|
||||
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)
|
||||
|
|
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;
|
||||
}
|
||||
|
||||
std::wstring AkVCam::tempPath()
|
||||
std::string AkVCam::tempPath()
|
||||
{
|
||||
WCHAR tempPath[MAX_PATH];
|
||||
memset(tempPath, 0, MAX_PATH * sizeof(WCHAR));
|
||||
GetTempPath(MAX_PATH, tempPath);
|
||||
CHAR tempPath[MAX_PATH];
|
||||
memset(tempPath, 0, MAX_PATH * sizeof(CHAR));
|
||||
GetTempPathA(MAX_PATH, tempPath);
|
||||
|
||||
return std::wstring(tempPath);
|
||||
return std::string(tempPath);
|
||||
}
|
||||
|
||||
std::wstring AkVCam::programFilesPath()
|
||||
{
|
||||
WCHAR programFiles[MAX_PATH];
|
||||
DWORD programFilesSize = MAX_PATH * sizeof(WCHAR);
|
||||
memset(programFiles, 0, programFilesSize);
|
||||
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()
|
||||
&& regGetValue(HKEY_LOCAL_MACHINE,
|
||||
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
|
||||
L"ProgramFilesDir",
|
||||
RRF_RT_REG_SZ,
|
||||
nullptr,
|
||||
&programFiles,
|
||||
&programFilesSize) == ERROR_SUCCESS)
|
||||
ok = true;
|
||||
if (result == ERROR_SUCCESS) {
|
||||
result = RegGetValue(hkey,
|
||||
nullptr,
|
||||
L"ProgramFilesDir",
|
||||
RRF_RT_REG_SZ,
|
||||
nullptr,
|
||||
&programFiles,
|
||||
&programFilesSize);
|
||||
if (isWow64())
|
||||
ok = true;
|
||||
|
||||
RegCloseKey(hkey);
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
SHGetSpecialFolderPath(nullptr,
|
||||
|
@ -391,16 +401,15 @@ AM_MEDIA_TYPE *AkVCam::mediaTypeFromFormat(const AkVCam::VideoFormat &format)
|
|||
memset(videoInfo, 0, sizeof(VIDEOINFO));
|
||||
auto fps = format.minimumFrameRate();
|
||||
|
||||
|
||||
// Initialize info header.
|
||||
videoInfo->rcSource = {0, 0, 0, 0};
|
||||
videoInfo->rcTarget = videoInfo->rcSource;
|
||||
videoInfo->dwBitRate = DWORD(8
|
||||
* frameSize
|
||||
* fps.num()
|
||||
/ fps.den());
|
||||
videoInfo->AvgTimePerFrame = REFERENCE_TIME(TIME_BASE
|
||||
* fps.den()
|
||||
/ fps.num());
|
||||
* size_t(fps.num())
|
||||
/ size_t(fps.den()));
|
||||
videoInfo->AvgTimePerFrame = REFERENCE_TIME(TIME_BASE / fps.value());
|
||||
|
||||
// Initialize bitmap header.
|
||||
videoInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
|
@ -783,405 +792,3 @@ std::string AkVCam::stringFromMediaSample(IMediaSample *mediaSample)
|
|||
|
||||
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;
|
||||
|
||||
BOOL isWow64();
|
||||
std::wstring tempPath();
|
||||
std::string tempPath();
|
||||
std::wstring programFilesPath();
|
||||
std::wstring moduleFileNameW(HINSTANCE hinstDLL);
|
||||
std::string moduleFileName(HINSTANCE hinstDLL);
|
||||
|
@ -69,29 +69,6 @@ namespace AkVCam
|
|||
std::string stringFromFormatType(const GUID &formatType);
|
||||
std::string stringFromMediaType(const AM_MEDIA_TYPE *mediaType);
|
||||
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
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -52,7 +52,6 @@ LIBS += \
|
|||
-lwinmm
|
||||
|
||||
TARGET = $${DSHOW_PLUGIN_NAME}
|
||||
|
||||
TEMPLATE = lib
|
||||
|
||||
HEADERS += \
|
||||
|
|
|
@ -113,15 +113,11 @@ void AkVCam::BaseFilter::addPin(const std::vector<AkVCam::VideoFormat> &formats,
|
|||
{
|
||||
AkLogFunction();
|
||||
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)
|
||||
{
|
||||
AkLogFunction();
|
||||
this->d->m_ipcBridge.disconnectService();
|
||||
this->d->m_pins->removePin(pin, changed);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "plugin.h"
|
||||
#include "plugininterface.h"
|
||||
#include "classfactory.h"
|
||||
#include "PlatformUtils/src/preferences.h"
|
||||
#include "PlatformUtils/src/utils.h"
|
||||
#include "VCamUtils/src/utils.h"
|
||||
|
||||
|
@ -33,24 +34,20 @@ inline AkVCam::PluginInterface *pluginInterface()
|
|||
// Filter entry point
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
UNUSED(lpvReserved)
|
||||
AkLogFunction();
|
||||
auto logLevel =
|
||||
AkVCam::regReadInt("loglevel", AKVCAM_LOGLEVEL_DEFAULT);
|
||||
AkVCam::Logger::setLogLevel(logLevel);
|
||||
UNUSED(lpvReserved);
|
||||
AkLogFunction();
|
||||
auto loglevel = AkVCam::Preferences::logLevel();
|
||||
AkVCam::Logger::setLogLevel(loglevel);
|
||||
|
||||
if (AkVCam::Logger::logLevel() > AKVCAM_LOGLEVEL_DEFAULT) {
|
||||
if (loglevel > AKVCAM_LOGLEVEL_DEFAULT) {
|
||||
// Turn on lights
|
||||
freopen("CONOUT$", "a", stdout);
|
||||
freopen("CONOUT$", "a", stderr);
|
||||
setbuf(stdout, nullptr);
|
||||
}
|
||||
|
||||
auto temp = AkVCam::tempPath();
|
||||
auto logFile =
|
||||
AkVCam::regReadString("logfile",
|
||||
std::string(temp.begin(), temp.end())
|
||||
+ "\\" DSHOW_PLUGIN_NAME ".log");
|
||||
auto defaultLogFile = AkVCam::tempPath() + "\\" DSHOW_PLUGIN_NAME ".log";
|
||||
auto logFile = AkVCam::Preferences::readString("logfile", defaultLogFile);
|
||||
AkVCam::Logger::setLogFile(logFile);
|
||||
|
||||
switch (fdwReason) {
|
||||
|
|
Loading…
Reference in a new issue