From 1cf50519bcec10ada242d9d1f895dc259c122570 Mon Sep 17 00:00:00 2001 From: Gonzalo Exequiel Pedone Date: Tue, 6 Oct 2020 20:06:54 -0300 Subject: [PATCH] Use std::string instead of std::wstring. Removed TestFrame.bmp. --- Manager/src/cmdparser.cpp | 28 +-- Manager/src/cmdparser.h | 1 - VCamUtils/src/fraction.cpp | 33 --- VCamUtils/src/fraction.h | 2 - VCamUtils/src/image/videoformat.cpp | 7 - VCamUtils/src/image/videoformat.h | 1 - VCamUtils/src/ipcbridge.h | 10 +- VCamUtils/src/utils.cpp | 83 -------- VCamUtils/src/utils.h | 6 - cmio/PlatformUtils/src/preferences.cpp | 53 +---- cmio/PlatformUtils/src/preferences.h | 17 +- cmio/PlatformUtils/src/utils.cpp | 49 ----- cmio/PlatformUtils/src/utils.h | 2 - cmio/VCamIPC/src/ipcbridge.mm | 13 +- cmio/VirtualCamera/src/objectproperties.cpp | 33 --- cmio/VirtualCamera/src/objectproperties.h | 3 - cmio/VirtualCamera/src/plugininterface.cpp | 2 +- cmio/VirtualCamera/src/plugininterface.h | 2 +- cmio/VirtualCamera/src/stream.cpp | 6 +- dshow/Assistant/src/main.cpp | 2 +- dshow/Assistant/src/service.cpp | 8 +- dshow/PlatformUtils/src/messageserver.cpp | 84 +++----- dshow/PlatformUtils/src/messageserver.h | 11 +- dshow/PlatformUtils/src/mutex.cpp | 29 ++- dshow/PlatformUtils/src/mutex.h | 4 +- dshow/PlatformUtils/src/preferences.cpp | 221 ++++++-------------- dshow/PlatformUtils/src/preferences.h | 17 +- dshow/PlatformUtils/src/sharedmemory.cpp | 29 ++- dshow/PlatformUtils/src/sharedmemory.h | 6 +- dshow/PlatformUtils/src/utils.cpp | 195 ++++++++--------- dshow/PlatformUtils/src/utils.h | 14 +- dshow/VCamIPC/src/ipcbridge.cpp | 66 +++--- dshow/VirtualCamera/VirtualCamera.pro | 13 +- dshow/VirtualCamera/src/basefilter.cpp | 40 ++-- dshow/VirtualCamera/src/basefilter.h | 6 +- dshow/VirtualCamera/src/pin.cpp | 33 +-- dshow/VirtualCamera/src/pin.h | 2 +- dshow/VirtualCamera/src/plugin.cpp | 9 +- dshow/VirtualCamera/src/plugininterface.cpp | 106 ++++------ dshow/VirtualCamera/src/plugininterface.h | 9 +- dshow/dshow.pri | 9 +- ports/deploy/deploy_mac.py | 4 +- ports/deploy/deploy_posix_windows.py | 2 +- ports/deploy/deploy_windows.py | 2 +- share/TestFrame/TestFrame.bmp | Bin 921654 -> 0 bytes share/TestFrame/TestFrame.py | 39 ---- share/TestFrame/TestFrame.qml | 194 ----------------- share/{TestFrame => icons}/webcamoid.png | Bin 48 files changed, 395 insertions(+), 1110 deletions(-) delete mode 100644 share/TestFrame/TestFrame.bmp delete mode 100644 share/TestFrame/TestFrame.py delete mode 100644 share/TestFrame/TestFrame.qml rename share/{TestFrame => icons}/webcamoid.png (100%) diff --git a/Manager/src/cmdparser.cpp b/Manager/src/cmdparser.cpp index 096ef86..5d2afad 100644 --- a/Manager/src/cmdparser.cpp +++ b/Manager/src/cmdparser.cpp @@ -707,13 +707,10 @@ int AkVCam::CmdParserPrivate::showDevices(const StringMap &flags, "Description" }; auto columns = table.size(); - std::wstring_convert> cv; for (auto &device: devices) { table.push_back(device); - auto description = - cv.to_bytes(this->m_ipcBridge.description(device)); - table.push_back(description); + table.push_back(this->m_ipcBridge.description(device)); } this->drawTable(table, columns); @@ -733,8 +730,7 @@ int AkVCam::CmdParserPrivate::addDevice(const StringMap &flags, return -1; } - std::wstring_convert> cv; - auto deviceId = this->m_ipcBridge.addDevice(cv.from_bytes(args[1])); + auto deviceId = this->m_ipcBridge.addDevice(args[1]); if (deviceId.empty()) { std::cerr << "Failed to create device." << std::endl; @@ -810,7 +806,7 @@ int AkVCam::CmdParserPrivate::showDeviceDescription(const StringMap &flags, return -1; } - std::wcout << this->m_ipcBridge.description(args[1]) << std::endl; + std::cout << this->m_ipcBridge.description(args[1]) << std::endl; return 0; } @@ -836,8 +832,7 @@ int AkVCam::CmdParserPrivate::setDeviceDescription(const AkVCam::StringMap &flag return -1; } - std::wstring_convert> cv; - this->m_ipcBridge.setDescription(deviceId, cv.from_bytes(args[2])); + this->m_ipcBridge.setDescription(deviceId, args[2]); return 0; } @@ -1492,7 +1487,7 @@ int AkVCam::CmdParserPrivate::picture(const AkVCam::StringMap &flags, UNUSED(flags); UNUSED(args); - std::wcout << this->m_ipcBridge.picture() << std::endl; + std::cout << this->m_ipcBridge.picture() << std::endl; return 0; } @@ -1508,8 +1503,7 @@ int AkVCam::CmdParserPrivate::setPicture(const AkVCam::StringMap &flags, return -1; } - std::wstring_convert> cv; - this->m_ipcBridge.setPicture(cv.from_bytes(args[1])); + this->m_ipcBridge.setPicture(args[1]); return 0; } @@ -1591,11 +1585,8 @@ void AkVCam::CmdParserPrivate::loadGenerals(Settings &settings) { settings.beginGroup("General"); - if (settings.contains("default_frame")) { - auto defaultFrame = settings.value("default_frame"); - std::wstring_convert> cv; - this->m_ipcBridge.setPicture(cv.from_bytes(defaultFrame)); - } + if (settings.contains("default_frame")) + this->m_ipcBridge.setPicture(settings.value("default_frame")); if (settings.contains("loglevel")) { auto logLevel= settings.value("loglevel"); @@ -1742,8 +1733,7 @@ void AkVCam::CmdParserPrivate::createDevice(Settings &settings, return; } - std::wstring_convert> cv; - auto deviceId = this->m_ipcBridge.addDevice(cv.from_bytes(description)); + auto deviceId = this->m_ipcBridge.addDevice(description); auto supportedFormats = this->m_ipcBridge.supportedPixelFormats(IpcBridge::StreamTypeOutput); for (auto &format: formats) { diff --git a/Manager/src/cmdparser.h b/Manager/src/cmdparser.h index 9ad2ae2..bde97b0 100644 --- a/Manager/src/cmdparser.h +++ b/Manager/src/cmdparser.h @@ -28,7 +28,6 @@ namespace AkVCam { class CmdParserPrivate; using StringVector = std::vector; - using WStringVector = std::vector; using StringMap = std::map; using ProgramOptionsFunc = std::function; diff --git a/VCamUtils/src/fraction.cpp b/VCamUtils/src/fraction.cpp index 3088132..506fb1c 100644 --- a/VCamUtils/src/fraction.cpp +++ b/VCamUtils/src/fraction.cpp @@ -73,31 +73,6 @@ AkVCam::Fraction::Fraction(const std::string &str) } } -AkVCam::Fraction::Fraction(const std::wstring &str) -{ - this->d = new FractionPrivate; - this->d->m_num = 0; - this->d->m_den = 1; - auto pos = str.find(L'/'); - - if (pos == std::wstring::npos) { - auto strCpy = trimmed(str); - - this->d->m_num = uint32_t(wcstol(strCpy.c_str(), nullptr, 10)); - } else { - auto numStr = trimmed(str.substr(0, pos)); - auto denStr = trimmed(str.substr(pos + 1)); - - this->d->m_num = uint32_t(wcstol(numStr.c_str(), nullptr, 10)); - this->d->m_den = uint32_t(wcstol(denStr.c_str(), nullptr, 10)); - - if (this->d->m_den < 1) { - this->d->m_num = 0; - this->d->m_den = 1; - } - } -} - AkVCam::Fraction::Fraction(const Fraction &other) { this->d = new FractionPrivate; @@ -168,11 +143,3 @@ std::string AkVCam::Fraction::toString() const return ss.str(); } - -std::wstring AkVCam::Fraction::toWString() const -{ - std::wstringstream ss; - ss << this->d->m_num << L'/' << this->d->m_den; - - return ss.str(); -} diff --git a/VCamUtils/src/fraction.h b/VCamUtils/src/fraction.h index 01ee4a7..6b4beb9 100644 --- a/VCamUtils/src/fraction.h +++ b/VCamUtils/src/fraction.h @@ -35,7 +35,6 @@ namespace AkVCam Fraction(); Fraction(int64_t num, int64_t den); Fraction(const std::string &str); - Fraction(const std::wstring &str); Fraction(const Fraction &other); virtual ~Fraction(); Fraction &operator =(const Fraction &other); @@ -48,7 +47,6 @@ namespace AkVCam int64_t &den(); double value() const; std::string toString() const; - std::wstring toWString() const; private: FractionPrivate *d; diff --git a/VCamUtils/src/image/videoformat.cpp b/VCamUtils/src/image/videoformat.cpp index a473754..3d1a907 100644 --- a/VCamUtils/src/image/videoformat.cpp +++ b/VCamUtils/src/image/videoformat.cpp @@ -355,13 +355,6 @@ std::string AkVCam::VideoFormat::stringFromFourcc(AkVCam::FourCC fourcc) return vf? vf->str: std::string(); } -std::wstring AkVCam::VideoFormat::wstringFromFourcc(AkVCam::FourCC fourcc) -{ - auto str = stringFromFourcc(fourcc); - - return std::wstring(str.begin(), str.end()); -} - AkVCam::VideoFormatPrivate::VideoFormatPrivate(FourCC fourcc, int width, int height, diff --git a/VCamUtils/src/image/videoformat.h b/VCamUtils/src/image/videoformat.h index ac78ed3..b98347e 100644 --- a/VCamUtils/src/image/videoformat.h +++ b/VCamUtils/src/image/videoformat.h @@ -70,7 +70,6 @@ namespace AkVCam int align=32); static FourCC fourccFromString(const std::string &fourccStr); static std::string stringFromFourcc(FourCC fourcc); - static std::wstring wstringFromFourcc(FourCC fourcc); private: VideoFormatPrivate *d; diff --git a/VCamUtils/src/ipcbridge.h b/VCamUtils/src/ipcbridge.h index 115d1aa..064e548 100644 --- a/VCamUtils/src/ipcbridge.h +++ b/VCamUtils/src/ipcbridge.h @@ -96,8 +96,8 @@ namespace AkVCam /* Server & Client */ - std::wstring picture() const; - void setPicture(const std::wstring &picture); + std::string picture() const; + void setPicture(const std::string &picture); int logLevel() const; void setLogLevel(int logLevel); @@ -111,9 +111,9 @@ namespace AkVCam std::vector devices() const; // Return human readable description of the device. - std::wstring description(const std::string &deviceId) const; + std::string description(const std::string &deviceId) const; void setDescription(const std::string &deviceId, - const std::wstring &description); + const std::string &description); // Output pixel formats supported by the driver. std::vector supportedPixelFormats(StreamType type) const; @@ -144,7 +144,7 @@ namespace AkVCam /* Server */ - std::string addDevice(const std::wstring &description); + std::string addDevice(const std::string &description); void removeDevice(const std::string &deviceId); void addFormat(const std::string &deviceId, const VideoFormat &format, diff --git a/VCamUtils/src/utils.cpp b/VCamUtils/src/utils.cpp index a5e8bae..e13e5d0 100644 --- a/VCamUtils/src/utils.cpp +++ b/VCamUtils/src/utils.cpp @@ -54,50 +54,6 @@ std::string AkVCam::replace(const std::string &str, return newStr; } -std::wstring AkVCam::replace(const std::wstring &str, - const std::wstring &from, - const std::wstring &to) -{ - auto newStr = str; - - for (auto pos = newStr.find(from); - pos != std::wstring::npos; - pos = newStr.find(from)) - newStr.replace(pos, from.size(), to); - - return newStr; -} - -bool AkVCam::isEqualFile(const std::wstring &file1, const std::wstring &file2) -{ - if (file1 == file2) - return true; - - std::fstream f1; - std::fstream f2; - f1.open(std::string(file1.begin(), file1.end()), std::ios_base::in); - f2.open(std::string(file2.begin(), file2.end()), std::ios_base::in); - - if (!f1.is_open() || !f2.is_open()) - return false; - - const size_t bufferSize = 1024; - char buffer1[bufferSize]; - char buffer2[bufferSize]; - memset(buffer1, 0, bufferSize); - memset(buffer2, 0, bufferSize); - - while (!f1.eof() && !f2.eof()) { - f1.read(buffer1, bufferSize); - f2.read(buffer2, bufferSize); - - if (memcmp(buffer1, buffer2, bufferSize) != 0) - return false; - } - - return true; -} - std::string AkVCam::trimmed(const std::string &str) { auto left = uint64_t(str.size()); @@ -128,36 +84,6 @@ std::string AkVCam::trimmed(const std::string &str) return str.substr(size_t(left), strippedLen); } -std::wstring AkVCam::trimmed(const std::wstring &str) -{ - auto left = uint64_t(str.size()); - auto right = uint64_t(str.size()); - - for (size_t i = 0; i < str.size(); i++) - if (!iswspace(str[i])) { - left = uint64_t(i); - - break; - } - - auto strippedLen = str.size(); - - if (left == str.size()) { - strippedLen = 0; - } else { - for (int64_t i = str.size() - 1; i >= 0; i--) - if (!iswspace(str[size_t(i)])) { - right = uint64_t(i); - - break; - } - - strippedLen = size_t(right - left + 1); - } - - return str.substr(size_t(left), strippedLen); -} - std::string AkVCam::fill(const std::string &str, size_t maxSize) { std::stringstream ss; @@ -167,15 +93,6 @@ std::string AkVCam::fill(const std::string &str, size_t maxSize) return ss.str(); } -std::wstring AkVCam::fill(const std::wstring &str, size_t maxSize) -{ - std::wstringstream ss; - std::vector spaces(maxSize, ' '); - ss << str << std::wstring(spaces.data(), maxSize - str.size()); - - return ss.str(); -} - std::string AkVCam::join(const std::vector &strs, const std::string &separator) { diff --git a/VCamUtils/src/utils.h b/VCamUtils/src/utils.h index 1d5fe28..608cab8 100644 --- a/VCamUtils/src/utils.h +++ b/VCamUtils/src/utils.h @@ -147,14 +147,8 @@ namespace AkVCam std::string replace(const std::string &str, const std::string &from, const std::string &to); - std::wstring replace(const std::wstring &str, - const std::wstring &from, - const std::wstring &to); - bool isEqualFile(const std::wstring &file1, const std::wstring &file2); std::string trimmed(const std::string &str); - std::wstring trimmed(const std::wstring &str); std::string fill(const std::string &str, size_t maxSize); - std::wstring fill(const std::wstring &str, size_t maxSize); std::string join(const std::vector &strs, const std::string &separator); std::vector split(const std::string &str, char separator); diff --git a/cmio/PlatformUtils/src/preferences.cpp b/cmio/PlatformUtils/src/preferences.cpp index d399912..cebf58b 100644 --- a/cmio/PlatformUtils/src/preferences.cpp +++ b/cmio/PlatformUtils/src/preferences.cpp @@ -74,19 +74,6 @@ void AkVCam::Preferences::write(const std::string &key, CFPreferencesSetAppValue(CFStringRef(*cfKey), *cfValue, PREFERENCES_ID); } -void AkVCam::Preferences::write(const std::string &key, - const std::wstring &value) -{ - AkLogFunction(); - AkLogInfo() << "Writing: " - << key - << " = " - << std::string(value.begin(), value.end()) << std::endl; - auto cfKey = cfTypeFromStd(key); - auto cfValue = cfTypeFromStd(value); - CFPreferencesSetAppValue(CFStringRef(*cfKey), *cfValue, PREFERENCES_ID); -} - void AkVCam::Preferences::write(const std::string &key, int value) { AkLogFunction(); @@ -147,24 +134,6 @@ std::string AkVCam::Preferences::readString(const std::string &key, return value; } -std::wstring AkVCam::Preferences::readWString(const std::string &key, - const std::wstring &defaultValue) -{ - AkLogFunction(); - auto cfKey = cfTypeFromStd(key); - auto cfValue = - CFStringRef(CFPreferencesCopyAppValue(CFStringRef(*cfKey), - PREFERENCES_ID)); - auto value = defaultValue; - - if (cfValue) { - value = wstringFromCFType(cfValue); - CFRelease(cfValue); - } - - return value; -} - int AkVCam::Preferences::readInt(const std::string &key, int defaultValue) { AkLogFunction(); @@ -284,7 +253,7 @@ void AkVCam::Preferences::sync() CFPreferencesAppSynchronize(PREFERENCES_ID); } -std::string AkVCam::Preferences::addDevice(const std::wstring &description) +std::string AkVCam::Preferences::addDevice(const std::string &description) { AkLogFunction(); auto path = createDevicePath(); @@ -303,14 +272,14 @@ std::string AkVCam::Preferences::addDevice(const std::wstring &description) return path; } -std::string AkVCam::Preferences::addCamera(const std::wstring &description, +std::string AkVCam::Preferences::addCamera(const std::string &description, const std::vector &formats) { return addCamera("", description, formats); } std::string AkVCam::Preferences::addCamera(const std::string &path, - const std::wstring &description, + const std::string &description, const std::vector &formats) { AkLogFunction(); @@ -433,18 +402,18 @@ bool AkVCam::Preferences::cameraExists(const std::string &path) return false; } -std::wstring AkVCam::Preferences::cameraDescription(size_t cameraIndex) +std::string AkVCam::Preferences::cameraDescription(size_t cameraIndex) { if (cameraIndex >= camerasCount()) return {}; - return readWString("cameras." - + std::to_string(cameraIndex) - + ".description"); + return readString("cameras." + + std::to_string(cameraIndex) + + ".description"); } void AkVCam::Preferences::cameraSetDescription(size_t cameraIndex, - const std::wstring &description) + const std::string &description) { if (cameraIndex >= camerasCount()) return; @@ -606,12 +575,12 @@ void AkVCam::Preferences::cameraSetControlValue(size_t cameraIndex, sync(); } -std::wstring AkVCam::Preferences::picture() +std::string AkVCam::Preferences::picture() { - return readWString("picture"); + return readString("picture"); } -void AkVCam::Preferences::setPicture(const std::wstring &picture) +void AkVCam::Preferences::setPicture(const std::string &picture) { write("picture", picture); sync(); diff --git a/cmio/PlatformUtils/src/preferences.h b/cmio/PlatformUtils/src/preferences.h index 1d20852..3488969 100644 --- a/cmio/PlatformUtils/src/preferences.h +++ b/cmio/PlatformUtils/src/preferences.h @@ -35,15 +35,12 @@ namespace AkVCam void write(const std::string &key, const std::shared_ptr &value); 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 &value); std::shared_ptr read(const std::string &key); 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); @@ -54,20 +51,20 @@ namespace AkVCam void move(const std::string &keyFrom, const std::string &keyTo); void moveAll(const std::string &keyFrom, const std::string &keyTo); void sync(); - std::string addDevice(const std::wstring &description); - std::string addCamera(const std::wstring &description, + std::string addDevice(const std::string &description); + std::string addCamera(const std::string &description, const std::vector &formats); std::string addCamera(const std::string &path, - const std::wstring &description, + const std::string &description, const std::vector &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); + std::string cameraDescription(size_t cameraIndex); void cameraSetDescription(size_t cameraIndex, - const std::wstring &description); + const std::string &description); std::string cameraPath(size_t cameraIndex); size_t formatsCount(size_t cameraIndex); VideoFormat cameraFormat(size_t cameraIndex, size_t formatIndex); @@ -83,8 +80,8 @@ namespace AkVCam void cameraSetControlValue(size_t cameraIndex, const std::string &key, int value); - std::wstring picture(); - void setPicture(const std::wstring &picture); + std::string picture(); + void setPicture(const std::string &picture); int logLevel(); void setLogLevel(int logLevel); } diff --git a/cmio/PlatformUtils/src/utils.cpp b/cmio/PlatformUtils/src/utils.cpp index bab83ac..7b9bce9 100644 --- a/cmio/PlatformUtils/src/utils.cpp +++ b/cmio/PlatformUtils/src/utils.cpp @@ -122,21 +122,6 @@ std::shared_ptr AkVCam::cfTypeFromStd(const std::string &str) }); } -std::shared_ptr AkVCam::cfTypeFromStd(const std::wstring &str) -{ - auto ref = - new CFTypeRef(CFStringCreateWithBytes(kCFAllocatorDefault, - reinterpret_cast(str.c_str()), - CFIndex(str.size() * sizeof(wchar_t)), - kCFStringEncodingUTF32LE, - false)); - - return std::shared_ptr(ref, [] (CFTypeRef *ptr) { - CFRelease(*ptr); - delete ptr; - }); -} - std::shared_ptr AkVCam::cfTypeFromStd(int num) { auto ref = @@ -192,40 +177,6 @@ std::string AkVCam::stringFromCFType(CFTypeRef cfType) return str; } -std::wstring AkVCam::wstringFromCFType(CFTypeRef cfType) -{ - auto len = CFStringGetLength(CFStringRef(cfType)); - auto range = CFRangeMake(0, len); - CFIndex bufferLen = 0; - auto converted = CFStringGetBytes(CFStringRef(cfType), - range, - kCFStringEncodingUTF32LE, - 0, - false, - nullptr, - 0, - &bufferLen); - - if (converted < 1 || bufferLen < 1) - return {}; - - wchar_t cstr[bufferLen]; - - converted = CFStringGetBytes(CFStringRef(cfType), - range, - kCFStringEncodingUTF32LE, - 0, - false, - reinterpret_cast(cstr), - bufferLen, - nullptr); - - if (converted < 1) - return {}; - - return std::wstring(cstr, size_t(len)); -} - std::string AkVCam::realPath(const std::string &path) { char resolvedPath[PATH_MAX]; diff --git a/cmio/PlatformUtils/src/utils.h b/cmio/PlatformUtils/src/utils.h index ce6b6fb..2e131d7 100644 --- a/cmio/PlatformUtils/src/utils.h +++ b/cmio/PlatformUtils/src/utils.h @@ -36,11 +36,9 @@ namespace AkVCam FourCharCode formatToCM(PixelFormat format); PixelFormat formatFromCM(FourCharCode format); std::shared_ptr cfTypeFromStd(const std::string &str); - std::shared_ptr cfTypeFromStd(const std::wstring &str); std::shared_ptr cfTypeFromStd(int num); std::shared_ptr cfTypeFromStd(double num); std::string stringFromCFType(CFTypeRef cfType); - std::wstring wstringFromCFType(CFTypeRef cfType); std::string realPath(const std::string &path); VideoFrame loadPicture(const std::string &fileName); } diff --git a/cmio/VCamIPC/src/ipcbridge.mm b/cmio/VCamIPC/src/ipcbridge.mm index 59447ac..843fdc7 100644 --- a/cmio/VCamIPC/src/ipcbridge.mm +++ b/cmio/VCamIPC/src/ipcbridge.mm @@ -110,12 +110,12 @@ AkVCam::IpcBridge::~IpcBridge() delete this->d; } -std::wstring AkVCam::IpcBridge::picture() const +std::string AkVCam::IpcBridge::picture() const { return Preferences::picture(); } -void AkVCam::IpcBridge::setPicture(const std::wstring &picture) +void AkVCam::IpcBridge::setPicture(const std::string &picture) { AkLogFunction(); Preferences::setPicture(picture); @@ -123,10 +123,9 @@ void AkVCam::IpcBridge::setPicture(const std::wstring &picture) if (!this->d->m_serverMessagePort) return; - std::wstring_convert> cv; auto dictionary = xpc_dictionary_create(nullptr, nullptr, 0); xpc_dictionary_set_int64(dictionary, "message", AKVCAM_ASSISTANT_MSG_PICTURE_UPDATED); - xpc_dictionary_set_string(dictionary, "picture", cv.to_bytes(picture).c_str()); + xpc_dictionary_set_string(dictionary, "picture", picture.c_str()); xpc_connection_send_message(this->d->m_serverMessagePort, dictionary); xpc_release(dictionary); } @@ -287,7 +286,7 @@ std::vector AkVCam::IpcBridge::devices() const return devices; } -std::wstring AkVCam::IpcBridge::description(const std::string &deviceId) const +std::string AkVCam::IpcBridge::description(const std::string &deviceId) const { AkLogFunction(); auto cameraIndex = Preferences::cameraFromPath(deviceId); @@ -299,7 +298,7 @@ std::wstring AkVCam::IpcBridge::description(const std::string &deviceId) const } void AkVCam::IpcBridge::setDescription(const std::string &deviceId, - const std::wstring &description) + const std::string &description) { AkLogFunction(); auto cameraIndex = Preferences::cameraFromPath(deviceId); @@ -521,7 +520,7 @@ std::string AkVCam::IpcBridge::clientExe(uint64_t pid) const return {path}; } -std::string AkVCam::IpcBridge::addDevice(const std::wstring &description) +std::string AkVCam::IpcBridge::addDevice(const std::string &description) { return Preferences::addDevice(description); } diff --git a/cmio/VirtualCamera/src/objectproperties.cpp b/cmio/VirtualCamera/src/objectproperties.cpp index 7a32c18..19146c6 100644 --- a/cmio/VirtualCamera/src/objectproperties.cpp +++ b/cmio/VirtualCamera/src/objectproperties.cpp @@ -31,7 +31,6 @@ namespace AkVCam PropertyTypeFloat64, PropertyTypePidT, PropertyTypeString, - PropertyTypeWString, PropertyTypeObjectVector, PropertyTypeObjectPtrVector, PropertyTypeVideoFormat, @@ -55,7 +54,6 @@ namespace AkVCam } num; std::string str; - std::wstring wstr; std::vector objects; std::vector objectsPtr; std::vector videoFormats; @@ -118,17 +116,6 @@ bool AkVCam::ObjectProperties::setProperty(UInt32 property, return true; } -bool AkVCam::ObjectProperties::setProperty(UInt32 property, - const std::wstring &value, - bool isSettable) -{ - this->d->m_properties[property].type = PropertyTypeWString; - this->d->m_properties[property].isSettable = isSettable; - this->d->m_properties[property].wstr = value; - - return true; -} - bool AkVCam::ObjectProperties::setProperty(UInt32 property, UInt32 value, bool isSettable) @@ -460,26 +447,6 @@ bool AkVCam::ObjectProperties::getProperty(UInt32 property, break; - case PropertyTypeWString: - if (dataUsed) { - *dataUsed = sizeof(CFStringRef); - - if (data) - ok = dataSize == *dataUsed; - } - - if (ok && data) { - auto value = this->d->m_properties[property].wstr; - *static_cast(data) = - CFStringCreateWithBytes(kCFAllocatorDefault, - reinterpret_cast(value.c_str()), - CFIndex(value.size() * sizeof(wchar_t)), - kCFStringEncodingUTF32LE, - false); - } - - break; - case PropertyTypeObjectVector: { auto &objects = this->d->m_properties[property].objects; auto objectList = static_cast(data); diff --git a/cmio/VirtualCamera/src/objectproperties.h b/cmio/VirtualCamera/src/objectproperties.h index 97e88a7..752183b 100644 --- a/cmio/VirtualCamera/src/objectproperties.h +++ b/cmio/VirtualCamera/src/objectproperties.h @@ -49,9 +49,6 @@ namespace AkVCam bool setProperty(UInt32 property, const std::string &value, bool isSettable=true); - bool setProperty(UInt32 property, - const std::wstring &value, - bool isSettable=true); bool setProperty(UInt32 property, UInt32 value, bool isSettable=true); diff --git a/cmio/VirtualCamera/src/plugininterface.cpp b/cmio/VirtualCamera/src/plugininterface.cpp index bc2ecfd..6f91444 100644 --- a/cmio/VirtualCamera/src/plugininterface.cpp +++ b/cmio/VirtualCamera/src/plugininterface.cpp @@ -373,7 +373,7 @@ void AkVCam::PluginInterface::removeListener(void *userData, } bool AkVCam::PluginInterface::createDevice(const std::string &deviceId, - const std::wstring &description, + const std::string &description, const std::vector &formats) { AkLogFunction(); diff --git a/cmio/VirtualCamera/src/plugininterface.h b/cmio/VirtualCamera/src/plugininterface.h index 836b542..69ab87a 100644 --- a/cmio/VirtualCamera/src/plugininterface.h +++ b/cmio/VirtualCamera/src/plugininterface.h @@ -68,7 +68,7 @@ namespace AkVCam static void removeListener(void *userData, const std::string &deviceId); bool createDevice(const std::string &deviceId, - const std::wstring &description, + const std::string &description, const std::vector &formats); void destroyDevice(const std::string &deviceId); diff --git a/cmio/VirtualCamera/src/stream.cpp b/cmio/VirtualCamera/src/stream.cpp index 8afbd70..9a348f6 100644 --- a/cmio/VirtualCamera/src/stream.cpp +++ b/cmio/VirtualCamera/src/stream.cpp @@ -79,10 +79,8 @@ AkVCam::Stream::Stream(bool registerObject, this->m_classID = kCMIOStreamClassID; auto picture = Preferences::picture(); - if (!picture.empty()) { - std::wstring_convert> cv; - this->d->m_testFrame = loadPicture(cv.to_bytes(picture)); - } + if (!picture.empty()) + this->d->m_testFrame = loadPicture(picture); this->d->m_clock = std::make_shared("CMIO::VirtualCamera::Stream", diff --git a/dshow/Assistant/src/main.cpp b/dshow/Assistant/src/main.cpp index 10650f0..1d6f267 100644 --- a/dshow/Assistant/src/main.cpp +++ b/dshow/Assistant/src/main.cpp @@ -55,7 +55,7 @@ int main(int argc, char **argv) AkLogInfo() << "Setting service dispatcher" << std::endl; - WCHAR serviceName[] = TEXT(DSHOW_PLUGIN_ASSISTANT_NAME); + TCHAR serviceName[] = TEXT(DSHOW_PLUGIN_ASSISTANT_NAME); SERVICE_TABLE_ENTRY serviceTable[] = { {serviceName, serviceMain}, {nullptr , nullptr } diff --git a/dshow/Assistant/src/service.cpp b/dshow/Assistant/src/service.cpp index bc10e59..8af500c 100644 --- a/dshow/Assistant/src/service.cpp +++ b/dshow/Assistant/src/service.cpp @@ -102,7 +102,7 @@ AkVCam::Service::~Service() BOOL AkVCam::Service::install() { AkLogFunction(); - WCHAR fileName[MAX_PATH]; + TCHAR fileName[MAX_PATH]; if (!GetModuleFileName(nullptr, fileName, MAX_PATH)) { AkLogError() << "Can't read module file name" << std::endl; @@ -142,7 +142,7 @@ BOOL AkVCam::Service::install() // Add detailed description to the service. SERVICE_DESCRIPTION serviceDescription; - WCHAR description[] = TEXT(DSHOW_PLUGIN_DESCRIPTION_EXT); + TCHAR description[] = TEXT(DSHOW_PLUGIN_DESCRIPTION_EXT); serviceDescription.lpDescription = description; auto result = ChangeServiceConfig2(service, @@ -150,7 +150,7 @@ BOOL AkVCam::Service::install() &serviceDescription); // Configure the service so it will restart if fail. - WCHAR rebootMsg[] = L"Service failed restarting..."; + TCHAR rebootMsg[] = TEXT("Service failed restarting..."); std::vector actions { {SC_ACTION_RESTART, 5000} @@ -264,7 +264,7 @@ AkVCam::ServicePrivate::ServicePrivate() 0 }; this->m_statusHandler = nullptr; - this->m_messageServer.setPipeName(L"\\\\.\\pipe\\" DSHOW_PLUGIN_ASSISTANT_NAME_L); + this->m_messageServer.setPipeName("\\\\.\\pipe\\" DSHOW_PLUGIN_ASSISTANT_NAME); this->m_messageServer.setHandlers({ {AKVCAM_ASSISTANT_MSG_FRAME_READY , AKVCAM_BIND_FUNC(ServicePrivate::frameReady) }, {AKVCAM_ASSISTANT_MSG_PICTURE_UPDATED , AKVCAM_BIND_FUNC(ServicePrivate::pictureUpdated) }, diff --git a/dshow/PlatformUtils/src/messageserver.cpp b/dshow/PlatformUtils/src/messageserver.cpp index e589fe9..503bd73 100644 --- a/dshow/PlatformUtils/src/messageserver.cpp +++ b/dshow/PlatformUtils/src/messageserver.cpp @@ -34,7 +34,7 @@ namespace AkVCam { public: MessageServer *self; - std::wstring m_pipeName; + std::string m_pipeName; std::map m_handlers; MessageServer::ServerMode m_mode {MessageServer::ServerModeReceive}; MessageServer::PipeState m_pipeState {MessageServer::PipeStateGone}; @@ -70,17 +70,17 @@ AkVCam::MessageServer::~MessageServer() delete this->d; } -std::wstring AkVCam::MessageServer::pipeName() const +std::string AkVCam::MessageServer::pipeName() const { return this->d->m_pipeName; } -std::wstring &AkVCam::MessageServer::pipeName() +std::string &AkVCam::MessageServer::pipeName() { return this->d->m_pipeName; } -void AkVCam::MessageServer::setPipeName(const std::wstring &pipeName) +void AkVCam::MessageServer::setPipeName(const std::string &pipeName) { this->d->m_pipeName = pipeName; } @@ -169,35 +169,23 @@ BOOL AkVCam::MessageServer::sendMessage(const std::string &pipeName, Message *message, uint32_t timeout) { - return sendMessage(std::wstring(pipeName.begin(), pipeName.end()), - message, - timeout); + return sendMessage(pipeName, *message, message, timeout); } -BOOL AkVCam::MessageServer::sendMessage(const std::wstring &pipeName, - Message *message, - uint32_t timeout) -{ - return sendMessage(pipeName, - *message, - message, - timeout); -} - -BOOL AkVCam::MessageServer::sendMessage(const std::wstring &pipeName, +BOOL AkVCam::MessageServer::sendMessage(const std::string &pipeName, const Message &messageIn, Message *messageOut, uint32_t timeout) { DWORD bytesTransferred = 0; - return CallNamedPipe(pipeName.c_str(), - const_cast(&messageIn), - DWORD(sizeof(Message)), - messageOut, - DWORD(sizeof(Message)), - &bytesTransferred, - timeout); + return CallNamedPipeA(pipeName.c_str(), + const_cast(&messageIn), + DWORD(sizeof(Message)), + messageOut, + DWORD(sizeof(Message)), + &bytesTransferred, + timeout); } AkVCam::MessageServerPrivate::MessageServerPrivate(MessageServer *self): @@ -217,12 +205,12 @@ bool AkVCam::MessageServerPrivate::startReceive(bool wait) * * https://msdn.microsoft.com/en-us/library/windows/desktop/aa379570(v=vs.85).aspx */ - WCHAR descriptor[] = - L"D:" // Discretionary ACL - L"(D;OICI;GA;;;BG)" // Deny access to Built-in Guests - L"(D;OICI;GA;;;AN)" // Deny access to Anonymous Logon - L"(A;OICI;GRGWGX;;;AU)" // Allow read/write/execute to Authenticated Users - L"(A;OICI;GA;;;BA)"; // Allow full control to Administrators + TCHAR descriptor[] = + TEXT("D:") // Discretionary ACL + TEXT("(D;OICI;GA;;;BG)") // Deny access to Built-in Guests + TEXT("(D;OICI;GA;;;AN)") // Deny access to Anonymous Logon + TEXT("(A;OICI;GRGWGX;;;AU)") // Allow read/write/execute to Authenticated Users + TEXT("(A;OICI;GA;;;BA)"); // Allow full control to Administrators SECURITY_ATTRIBUTES securityAttributes; PSECURITY_DESCRIPTOR securityDescriptor = @@ -246,17 +234,17 @@ bool AkVCam::MessageServerPrivate::startReceive(bool wait) securityAttributes.bInheritHandle = TRUE; // Create a read/write message type pipe. - this->m_pipe = CreateNamedPipe(this->m_pipeName.c_str(), - PIPE_ACCESS_DUPLEX - | FILE_FLAG_OVERLAPPED, - PIPE_TYPE_MESSAGE - | PIPE_READMODE_BYTE - | PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, - sizeof(Message), - sizeof(Message), - NMPWAIT_USE_DEFAULT_WAIT, - &securityAttributes); + this->m_pipe = CreateNamedPipeA(this->m_pipeName.c_str(), + PIPE_ACCESS_DUPLEX + | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_MESSAGE + | PIPE_READMODE_BYTE + | PIPE_WAIT, + PIPE_UNLIMITED_INSTANCES, + sizeof(Message), + sizeof(Message), + NMPWAIT_USE_DEFAULT_WAIT, + &securityAttributes); if (this->m_pipe == INVALID_HANDLE_VALUE) goto startReceive_failed; @@ -366,23 +354,17 @@ void AkVCam::MessageServerPrivate::messagesLoop() void AkVCam::MessageServerPrivate::checkLoop() { while (this->m_running) { - auto result = WaitNamedPipe(this->m_pipeName.c_str(), NMPWAIT_NOWAIT); + auto result = WaitNamedPipeA(this->m_pipeName.c_str(), NMPWAIT_NOWAIT); if (result && this->m_pipeState != AkVCam::MessageServer::PipeStateAvailable) { - AkLogInfo() << "Pipe Available: " - << std::string(this->m_pipeName.begin(), - this->m_pipeName.end()) - << std::endl; + AkLogInfo() << "Pipe Available: " << this->m_pipeName << std::endl; this->m_pipeState = AkVCam::MessageServer::PipeStateAvailable; AKVCAM_EMIT(this->self, PipeStateChanged, this->m_pipeState) } else if (!result && this->m_pipeState != AkVCam::MessageServer::PipeStateGone && GetLastError() != ERROR_SEM_TIMEOUT) { - AkLogInfo() << "Pipe Gone: " - << std::string(this->m_pipeName.begin(), - this->m_pipeName.end()) - << std::endl; + AkLogInfo() << "Pipe Gone: " << this->m_pipeName << std::endl; this->m_pipeState = AkVCam::MessageServer::PipeStateGone; AKVCAM_EMIT(this->self, PipeStateChanged, this->m_pipeState) } diff --git a/dshow/PlatformUtils/src/messageserver.h b/dshow/PlatformUtils/src/messageserver.h index c070086..1ab754b 100644 --- a/dshow/PlatformUtils/src/messageserver.h +++ b/dshow/PlatformUtils/src/messageserver.h @@ -66,9 +66,9 @@ namespace AkVCam MessageServer(const MessageServer &other) = delete; ~MessageServer(); - std::wstring pipeName() const; - std::wstring &pipeName(); - void setPipeName(const std::wstring &pipeName); + std::string pipeName() const; + std::string &pipeName(); + void setPipeName(const std::string &pipeName); ServerMode mode() const; ServerMode &mode(); void setMode(ServerMode mode); @@ -87,10 +87,7 @@ namespace AkVCam static BOOL sendMessage(const std::string &pipeName, Message *message, uint32_t timeout=MSERVER_TIMEOUT_MAX); - static BOOL sendMessage(const std::wstring &pipeName, - Message *message, - uint32_t timeout=MSERVER_TIMEOUT_MAX); - static BOOL sendMessage(const std::wstring &pipeName, + static BOOL sendMessage(const std::string &pipeName, const Message &messageIn, Message *messageOut, uint32_t timeout=MSERVER_TIMEOUT_MAX); diff --git a/dshow/PlatformUtils/src/mutex.cpp b/dshow/PlatformUtils/src/mutex.cpp index 4352a58..df1c6a6 100644 --- a/dshow/PlatformUtils/src/mutex.cpp +++ b/dshow/PlatformUtils/src/mutex.cpp @@ -27,27 +27,26 @@ namespace AkVCam { public: HANDLE m_mutex; - std::wstring m_name; + std::string m_name; }; } -AkVCam::Mutex::Mutex(const std::wstring &name) +AkVCam::Mutex::Mutex(const std::string &name) { this->d = new MutexPrivate(); - this->d->m_mutex = CreateMutex(nullptr, - FALSE, - name.empty()? - nullptr: name.c_str()); + this->d->m_mutex = CreateMutexA(nullptr, + FALSE, + name.empty()? nullptr: name.c_str()); this->d->m_name = name; } AkVCam::Mutex::Mutex(const Mutex &other) { this->d = new MutexPrivate(); - this->d->m_mutex = CreateMutex(nullptr, - FALSE, - other.d->m_name.empty()? - nullptr: other.d->m_name.c_str()); + this->d->m_mutex = CreateMutexA(nullptr, + FALSE, + other.d->m_name.empty()? + nullptr: other.d->m_name.c_str()); this->d->m_name = other.d->m_name; } @@ -67,17 +66,17 @@ AkVCam::Mutex &AkVCam::Mutex::operator =(const Mutex &other) if (this->d->m_mutex) CloseHandle(this->d->m_mutex); - this->d->m_mutex = CreateMutex(nullptr, - FALSE, - other.d->m_name.empty()? - nullptr: other.d->m_name.c_str()); + this->d->m_mutex = CreateMutexA(nullptr, + FALSE, + other.d->m_name.empty()? + nullptr: other.d->m_name.c_str()); this->d->m_name = other.d->m_name; } return *this; } -std::wstring AkVCam::Mutex::name() const +std::string AkVCam::Mutex::name() const { return this->d->m_name; } diff --git a/dshow/PlatformUtils/src/mutex.h b/dshow/PlatformUtils/src/mutex.h index 9172148..599fe66 100644 --- a/dshow/PlatformUtils/src/mutex.h +++ b/dshow/PlatformUtils/src/mutex.h @@ -29,12 +29,12 @@ namespace AkVCam class Mutex { public: - Mutex(const std::wstring &name={}); + Mutex(const std::string &name={}); Mutex(const Mutex &other); ~Mutex(); Mutex &operator =(const Mutex &other); - std::wstring name() const; + std::string name() const; void lock(); bool tryLock(int timeout=0); void unlock(); diff --git a/dshow/PlatformUtils/src/preferences.cpp b/dshow/PlatformUtils/src/preferences.cpp index 5078485..695fd64 100644 --- a/dshow/PlatformUtils/src/preferences.cpp +++ b/dshow/PlatformUtils/src/preferences.cpp @@ -39,22 +39,14 @@ namespace AkVCam 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); + bool readValue(const std::string &key, + DWORD dataTypeFlags, + PVOID data, + LPDWORD dataSize); + void setValue(const std::string &key, + DWORD dataType, + LPCSTR data, + DWORD dataSize); } } @@ -63,28 +55,17 @@ void AkVCam::Preferences::write(const std::string &key, { 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())); + setValue(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(&value), - DWORD(sizeof(int))); + setValue(key, + REG_DWORD, + reinterpret_cast(&value), + DWORD(sizeof(int))); } void AkVCam::Preferences::write(const std::string &key, double value) @@ -92,10 +73,10 @@ 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())); + setValue(key, + REG_SZ, + val.c_str(), + DWORD(val.size())); } void AkVCam::Preferences::write(const std::string &key, @@ -113,21 +94,7 @@ std::string AkVCam::Preferences::readString(const std::string &key, 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)) + if (!readValue(key, RRF_RT_REG_SZ, &value, &valueSize)) return defaultValue; return {value}; @@ -139,7 +106,7 @@ int AkVCam::Preferences::readInt(const std::string &key, int defaultValue) DWORD value = 0; DWORD valueSize = sizeof(DWORD); - if (!valueA(key, RRF_RT_REG_DWORD, &value, &valueSize)) + if (!readValue(key, RRF_RT_REG_DWORD, &value, &valueSize)) return defaultValue; return int(value); @@ -174,11 +141,11 @@ std::vector AkVCam::Preferences::listRegisteredCameras(HINSTANCE hinstDLL CoTaskMemFree(strIID); HKEY key = nullptr; - auto result = RegOpenKeyEx(HKEY_CLASSES_ROOT, - ss.str().c_str(), - 0, - MAXIMUM_ALLOWED, - &key); + auto result = RegOpenKeyExW(HKEY_CLASSES_ROOT, + ss.str().c_str(), + 0, + MAXIMUM_ALLOWED, + &key); if (result != ERROR_SUCCESS) return {}; @@ -208,17 +175,17 @@ std::vector AkVCam::Preferences::listRegisteredCameras(HINSTANCE hinstDLL FILETIME lastWrite; for (DWORD i = 0; i < subkeys; i++) { - TCHAR subKey[MAX_PATH]; - memset(subKey, 0, MAX_PATH * sizeof(TCHAR)); + WCHAR subKey[MAX_PATH]; + memset(subKey, 0, MAX_PATH * sizeof(WCHAR)); DWORD subKeyLen = MAX_PATH; - result = RegEnumKeyEx(key, - i, - subKey, - &subKeyLen, - nullptr, - nullptr, - nullptr, - &lastWrite); + result = RegEnumKeyExW(key, + i, + subKey, + &subKeyLen, + nullptr, + nullptr, + nullptr, + &lastWrite); if (result != ERROR_SUCCESS) continue; @@ -229,18 +196,18 @@ std::vector AkVCam::Preferences::listRegisteredCameras(HINSTANCE hinstDLL 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) { + if (RegGetValueW(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); + GetModuleFileNameW(hinstDLL, modulePath, MAX_PATH); - if (!lstrcmpi(path, modulePath)) { + if (!lstrcmpiW(path, modulePath)) { CLSID clsid; memset(&clsid, 0, sizeof(CLSID)); CLSIDFromString(subKey, &clsid); @@ -320,7 +287,7 @@ void AkVCam::Preferences::move(const std::string &keyFrom, } } -std::string AkVCam::Preferences::addDevice(const std::wstring &description) +std::string AkVCam::Preferences::addDevice(const std::string &description) { AkLogFunction(); auto path = createDevicePath(); @@ -333,14 +300,14 @@ std::string AkVCam::Preferences::addDevice(const std::wstring &description) return path; } -std::string AkVCam::Preferences::addCamera(const std::wstring &description, +std::string AkVCam::Preferences::addCamera(const std::string &description, const std::vector &formats) { return addCamera("", description, formats); } std::string AkVCam::Preferences::addCamera(const std::string &path, - const std::wstring &description, + const std::string &description, const std::vector &formats) { AkLogFunction(); @@ -471,18 +438,18 @@ bool AkVCam::Preferences::cameraExists(const std::string &path) return false; } -std::wstring AkVCam::Preferences::cameraDescription(size_t cameraIndex) +std::string AkVCam::Preferences::cameraDescription(size_t cameraIndex) { if (cameraIndex >= camerasCount()) return {}; - return readWString("Cameras\\" - + std::to_string(cameraIndex + 1) - + "\\description"); + return readString("Cameras\\" + + std::to_string(cameraIndex + 1) + + "\\description"); } void AkVCam::Preferences::cameraSetDescription(size_t cameraIndex, - const std::wstring &description) + const std::string &description) { if (cameraIndex >= camerasCount()) return; @@ -642,12 +609,12 @@ void AkVCam::Preferences::cameraSetControlValue(size_t cameraIndex, value); } -std::wstring AkVCam::Preferences::picture() +std::string AkVCam::Preferences::picture() { - return readWString("picture"); + return readString("picture"); } -void AkVCam::Preferences::setPicture(const std::wstring &picture) +void AkVCam::Preferences::setPicture(const std::string &picture) { write("picture", picture); } @@ -679,10 +646,10 @@ void AkVCam::Preferences::splitSubKey(const std::string &key, } } -bool AkVCam::Preferences::valueA(const std::string &key, - DWORD dataTypeFlags, - PVOID data, - LPDWORD dataSize) +bool AkVCam::Preferences::readValue(const std::string &key, + DWORD dataTypeFlags, + PVOID data, + LPDWORD dataSize) { std::string subKey; std::string val; @@ -709,42 +676,10 @@ bool AkVCam::Preferences::valueA(const std::string &key, 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> 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) +void AkVCam::Preferences::setValue(const std::string &key, + DWORD dataType, + LPCSTR data, + DWORD dataSize) { std::string subKey; std::string val; @@ -770,35 +705,3 @@ void AkVCam::Preferences::setValueA(const std::string &key, 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> cv; - auto wval = cv.from_bytes(val); - RegSetValueW(hkey, - wval.c_str(), - dataType, - data, - dataSize); - RegCloseKey(hkey); -} diff --git a/dshow/PlatformUtils/src/preferences.h b/dshow/PlatformUtils/src/preferences.h index 0984094..71ed476 100644 --- a/dshow/PlatformUtils/src/preferences.h +++ b/dshow/PlatformUtils/src/preferences.h @@ -32,25 +32,22 @@ namespace AkVCam 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 &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 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, + std::string addDevice(const std::string &description); + std::string addCamera(const std::string &description, const std::vector &formats); std::string addCamera(const std::string &path, - const std::wstring &description, + const std::string &description, const std::vector &formats); void removeCamera(const std::string &path); size_t camerasCount(); @@ -58,9 +55,9 @@ namespace AkVCam int cameraFromCLSID(const CLSID &clsid); int cameraFromPath(const std::string &path); bool cameraExists(const std::string &path); - std::wstring cameraDescription(size_t cameraIndex); + std::string cameraDescription(size_t cameraIndex); void cameraSetDescription(size_t cameraIndex, - const std::wstring &description); + const std::string &description); std::string cameraPath(size_t cameraIndex); size_t formatsCount(size_t cameraIndex); VideoFormat cameraFormat(size_t cameraIndex, size_t formatIndex); @@ -76,8 +73,8 @@ namespace AkVCam void cameraSetControlValue(size_t cameraIndex, const std::string &key, int value); - std::wstring picture(); - void setPicture(const std::wstring &picture); + std::string picture(); + void setPicture(const std::string &picture); int logLevel(); void setLogLevel(int logLevel); } diff --git a/dshow/PlatformUtils/src/sharedmemory.cpp b/dshow/PlatformUtils/src/sharedmemory.cpp index 64be012..96fb7b9 100644 --- a/dshow/PlatformUtils/src/sharedmemory.cpp +++ b/dshow/PlatformUtils/src/sharedmemory.cpp @@ -30,7 +30,7 @@ namespace AkVCam { public: HANDLE m_sharedHandle; - std::wstring m_name; + std::string m_name; void *m_buffer; size_t m_pageSize; SharedMemory::OpenMode m_mode; @@ -85,17 +85,17 @@ AkVCam::SharedMemory &AkVCam::SharedMemory::operator =(const SharedMemory &other return *this; } -std::wstring AkVCam::SharedMemory::name() const +std::string AkVCam::SharedMemory::name() const { return this->d->m_name; } -std::wstring &AkVCam::SharedMemory::name() +std::string &AkVCam::SharedMemory::name() { return this->d->m_name; } -void AkVCam::SharedMemory::setName(const std::wstring &name) +void AkVCam::SharedMemory::setName(const std::string &name) { this->d->m_name = name; } @@ -110,26 +110,25 @@ bool AkVCam::SharedMemory::open(size_t pageSize, OpenMode mode) if (mode == OpenModeRead) { this->d->m_sharedHandle = - OpenFileMapping(FILE_MAP_ALL_ACCESS, - FALSE, - this->d->m_name.c_str()); + OpenFileMappingA(FILE_MAP_ALL_ACCESS, + FALSE, + this->d->m_name.c_str()); } else { if (pageSize < 1) return false; this->d->m_sharedHandle = - CreateFileMapping(INVALID_HANDLE_VALUE, - nullptr, - PAGE_READWRITE, - 0, - DWORD(pageSize), - this->d->m_name.c_str()); + CreateFileMappingA(INVALID_HANDLE_VALUE, + nullptr, + PAGE_READWRITE, + 0, + DWORD(pageSize), + this->d->m_name.c_str()); } if (!this->d->m_sharedHandle) { AkLogError() << "Error opening shared memory (" - << std::string(this->d->m_name.begin(), - this->d->m_name.end()) + << this->d->m_name << "): " << errorToString(GetLastError()) << " (" << GetLastError() << ")" diff --git a/dshow/PlatformUtils/src/sharedmemory.h b/dshow/PlatformUtils/src/sharedmemory.h index 1ff3b55..ab55578 100644 --- a/dshow/PlatformUtils/src/sharedmemory.h +++ b/dshow/PlatformUtils/src/sharedmemory.h @@ -41,9 +41,9 @@ namespace AkVCam ~SharedMemory(); SharedMemory &operator =(const SharedMemory &other); - std::wstring name() const; - std::wstring &name(); - void setName(const std::wstring &name); + std::string name() const; + std::string &name(); + void setName(const std::string &name); bool open(size_t pageSize=0, OpenMode mode=OpenModeRead); bool isOpen() const; size_t pageSize() const; diff --git a/dshow/PlatformUtils/src/utils.cpp b/dshow/PlatformUtils/src/utils.cpp index 491b35a..7a72c4d 100644 --- a/dshow/PlatformUtils/src/utils.cpp +++ b/dshow/PlatformUtils/src/utils.cpp @@ -29,6 +29,7 @@ #include "utils.h" #include "VCamUtils/src/utils.h" #include "VCamUtils/src/image/videoformat.h" +#include "VCamUtils/src/image/videoframe.h" #define TIME_BASE 1.0e7 @@ -85,16 +86,6 @@ bool operator <(const CLSID &a, const CLSID &b) return AkVCam::stringFromIid(a) < AkVCam::stringFromIid(b); } -BOOL AkVCam::isWow64() -{ - BOOL isWow64 = FALSE; - - if (!IsWow64Process(GetCurrentProcess(), &isWow64)) - return false; - - return isWow64; -} - std::string AkVCam::tempPath() { CHAR tempPath[MAX_PATH]; @@ -104,90 +95,35 @@ std::string AkVCam::tempPath() return std::string(tempPath); } -std::wstring AkVCam::programFilesPath() -{ - 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 (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, - programFiles, - CSIDL_PROGRAM_FILES, - FALSE); - - return std::wstring(programFiles); -} - -std::wstring AkVCam::moduleFileNameW(HINSTANCE hinstDLL) -{ - WCHAR fileName[MAX_PATH]; - memset(fileName, 0, MAX_PATH * sizeof(WCHAR)); - GetModuleFileName(hinstDLL, fileName, MAX_PATH); - - return std::wstring(fileName); -} - std::string AkVCam::moduleFileName(HINSTANCE hinstDLL) { - auto fileName = moduleFileNameW(hinstDLL); + CHAR fileName[MAX_PATH]; + memset(fileName, 0, MAX_PATH * sizeof(CHAR)); + GetModuleFileNameA(hinstDLL, fileName, MAX_PATH); - return std::string(fileName.begin(), fileName.end()); + return std::string(fileName); } -std::wstring AkVCam::errorToStringW(DWORD errorCode) +std::string AkVCam::errorToString(DWORD errorCode) { - WCHAR *errorStr = nullptr; - auto size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER - | FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, - errorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), - reinterpret_cast(&errorStr), - 0, - nullptr); - std::wstring error(errorStr, size); + CHAR *errorStr = nullptr; + auto size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, + errorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), + reinterpret_cast(&errorStr), + 0, + nullptr); + std::string error(errorStr, size); LocalFree(errorStr); return error; } -std::string AkVCam::errorToString(DWORD errorCode) -{ - auto errorStr = errorToStringW(errorCode); - - return std::string(errorStr.begin(), errorStr.end()); -} - // Converts a human redable string to a CLSID using MD5 hash. CLSID AkVCam::createClsidFromStr(const std::string &str) -{ - return createClsidFromStr(std::wstring(str.begin(), str.end())); -} - -CLSID AkVCam::createClsidFromStr(const std::wstring &str) { HCRYPTPROV provider = 0; HCRYPTHASH hash = 0; @@ -227,47 +163,35 @@ clsidFromStr_failed: return clsid; } -std::wstring AkVCam::createClsidWStrFromStr(const std::string &str) -{ - return createClsidWStrFromStr(std::wstring(str.begin(), str.end())); -} - -std::wstring AkVCam::createClsidWStrFromStr(const std::wstring &str) +std::string AkVCam::createClsidStrFromStr(const std::string &str) { auto clsid = createClsidFromStr(str); - OLECHAR *clsidWStr = nullptr; + LPWSTR clsidWStr = nullptr; if (StringFromCLSID(clsid, &clsidWStr) != S_OK) - return std::wstring(); + return {}; - std::wstring wstr(clsidWStr); + auto str_ = stringFromWSTR(clsidWStr); CoTaskMemFree(clsidWStr); - return wstr; + return str_; } std::string AkVCam::stringFromIid(const IID &iid) { - auto wstr = wstringFromIid(iid); - - return std::string(wstr.begin(), wstr.end()); -} - -std::wstring AkVCam::wstringFromIid(const IID &iid) -{ - WCHAR *strIID = nullptr; + LPWSTR strIID = nullptr; StringFromIID(iid, &strIID); - std::wstring wstr(strIID); + auto str = stringFromWSTR(strIID); CoTaskMemFree(strIID); - return wstr; + return str; } std::string AkVCam::stringFromResult(HRESULT result) { - auto msg = std::wstring(_com_error(result).ErrorMessage()); + auto msg = stringFromWSTR(_com_error(result).ErrorMessage()); - return std::string(msg.begin(), msg.end()); + return msg; } std::string AkVCam::stringFromClsid(const CLSID &clsid) @@ -332,17 +256,48 @@ std::string AkVCam::stringFromClsid(const CLSID &clsid) return stringFromIid(clsid); } -wchar_t *AkVCam::wcharStrFromWStr(const std::wstring &wstr) +std::string AkVCam::stringFromWSTR(LPCWSTR wstr) { - if (wstr.size() < 1) - return nullptr; + auto len = WideCharToMultiByte(CP_ACP, + 0, + wstr, + -1, + nullptr, + 0, + nullptr, + nullptr); + CHAR *cstr = new CHAR[len]; + WideCharToMultiByte(CP_ACP, + 0, + wstr, + -1, + cstr, + len, + nullptr, + nullptr); + std::string str(cstr); + delete [] cstr; - auto wcstrSize = wstr.size() * sizeof(wchar_t); - auto wcstr = reinterpret_cast(CoTaskMemAlloc(wcstrSize + 1)); - wcstr[wstr.size()] = 0; - memcpy(wcstr, wstr.data(), wcstrSize); + return str; +} - return wcstr; +LPWSTR AkVCam::stringToWSTR(const std::string &str) +{ + auto len = MultiByteToWideChar(CP_ACP, + 0, + str.c_str(), + str.size(), + nullptr, + 0); + auto wstr = reinterpret_cast(CoTaskMemAlloc(len * sizeof(WCHAR))); + MultiByteToWideChar(CP_ACP, + 0, + str.c_str(), + str.size(), + wstr, + len); + + return wstr; } AkVCam::FourCC AkVCam::formatFromGuid(const GUID &guid) @@ -999,3 +954,21 @@ LSTATUS AkVCam::copyTree(HKEY src, LPCSTR subkey, HKEY dst, REGSAM samFlags) return result; } + +AkVCam::VideoFrame AkVCam::loadPicture(const std::string &fileName) +{ + AkLogFunction(); + VideoFrame frame; + + if (frame.load(fileName)) { + AkLogInfo() << "Picture loaded as BMP" << std::endl; + + return frame; + } + + AkLogDebug() << "Error loading picture: " + << fileName + << std::endl; + + return frame; +} diff --git a/dshow/PlatformUtils/src/utils.h b/dshow/PlatformUtils/src/utils.h index 6c65c36..a5109f3 100644 --- a/dshow/PlatformUtils/src/utils.h +++ b/dshow/PlatformUtils/src/utils.h @@ -32,23 +32,18 @@ namespace AkVCam { class VideoFormat; + class VideoFrame; - BOOL isWow64(); std::string tempPath(); - std::wstring programFilesPath(); - std::wstring moduleFileNameW(HINSTANCE hinstDLL); std::string moduleFileName(HINSTANCE hinstDLL); - std::wstring errorToStringW(DWORD errorCode); std::string errorToString(DWORD errorCode); CLSID createClsidFromStr(const std::string &str); - CLSID createClsidFromStr(const std::wstring &str); - std::wstring createClsidWStrFromStr(const std::string &str); - std::wstring createClsidWStrFromStr(const std::wstring &str); + std::string createClsidStrFromStr(const std::string &str); std::string stringFromIid(const IID &iid); - std::wstring wstringFromIid(const IID &iid); std::string stringFromResult(HRESULT result); std::string stringFromClsid(const CLSID &clsid); - wchar_t *wcharStrFromWStr(const std::wstring &wstr); + std::string stringFromWSTR(LPCWSTR wstr); + LPWSTR stringToWSTR(const std::string &str); FourCC formatFromGuid(const GUID &guid); const GUID &guidFromFormat(FourCC format); DWORD compressionFromFormat(FourCC format); @@ -71,6 +66,7 @@ namespace AkVCam std::string stringFromMediaSample(IMediaSample *mediaSample); LSTATUS deleteTree(HKEY key, LPCSTR subkey, REGSAM samFlags); LSTATUS copyTree(HKEY src, LPCSTR subkey, HKEY dst, REGSAM samFlags); + VideoFrame loadPicture(const std::string &fileName); } #endif // PLATFORM_UTILS_H diff --git a/dshow/VCamIPC/src/ipcbridge.cpp b/dshow/VCamIPC/src/ipcbridge.cpp index e8b618d..1920182 100644 --- a/dshow/VCamIPC/src/ipcbridge.cpp +++ b/dshow/VCamIPC/src/ipcbridge.cpp @@ -109,23 +109,21 @@ AkVCam::IpcBridge::~IpcBridge() delete this->d; } -std::wstring AkVCam::IpcBridge::picture() const +std::string AkVCam::IpcBridge::picture() const { return Preferences::picture(); } -void AkVCam::IpcBridge::setPicture(const std::wstring &picture) +void AkVCam::IpcBridge::setPicture(const std::string &picture) { Preferences::setPicture(picture); - std::wstring_convert> cv; - auto picture_ = cv.to_bytes(picture); Message message; message.messageId = AKVCAM_ASSISTANT_MSG_PICTURE_UPDATED; message.dataSize = sizeof(MsgPictureUpdated); auto data = messageData(&message); memcpy(data->picture, - picture_.c_str(), - (std::min)(picture_.size(), MAX_STRING)); + picture.c_str(), + (std::min)(picture.size(), MAX_STRING)); this->d->m_mainServer.sendMessage(&message); } @@ -149,14 +147,13 @@ bool AkVCam::IpcBridge::registerPeer() message.dataSize = sizeof(MsgRequestPort); auto requestData = messageData(&message); - if (!MessageServer::sendMessage(L"\\\\.\\pipe\\" DSHOW_PLUGIN_ASSISTANT_NAME_L, + if (!MessageServer::sendMessage("\\\\.\\pipe\\" DSHOW_PLUGIN_ASSISTANT_NAME, &message)) return false; std::string portName(requestData->port); auto pipeName = "\\\\.\\pipe\\" + portName; - this->d->m_messageServer.setPipeName(std::wstring(pipeName.begin(), - pipeName.end())); + this->d->m_messageServer.setPipeName(pipeName); this->d->m_messageServer.setHandlers(this->d->m_messageHandlers); AkLogInfo() << "Recommended port name: " << portName << std::endl; @@ -179,7 +176,7 @@ bool AkVCam::IpcBridge::registerPeer() AkLogInfo() << "Registering port name: " << portName << std::endl; - if (!MessageServer::sendMessage(L"\\\\.\\pipe\\" DSHOW_PLUGIN_ASSISTANT_NAME_L, + if (!MessageServer::sendMessage("\\\\.\\pipe\\" DSHOW_PLUGIN_ASSISTANT_NAME, &message)) { this->d->m_messageServer.stop(true); @@ -192,13 +189,8 @@ bool AkVCam::IpcBridge::registerPeer() return false; } - this->d->m_sharedMemory.setName(L"Local\\" - + std::wstring(portName.begin(), - portName.end()) - + L".data"); - this->d->m_globalMutex = Mutex(std::wstring(portName.begin(), - portName.end()) - + L".mutex"); + this->d->m_sharedMemory.setName("Local\\" + portName + ".data"); + this->d->m_globalMutex = Mutex(portName + ".mutex"); this->d->m_portName = portName; AkLogInfo() << "Peer registered as " << portName << std::endl; @@ -220,7 +212,7 @@ void AkVCam::IpcBridge::unregisterPeer() memcpy(data->port, this->d->m_portName.c_str(), (std::min)(this->d->m_portName.size(), MAX_STRING)); - MessageServer::sendMessage(L"\\\\.\\pipe\\" DSHOW_PLUGIN_ASSISTANT_NAME_L, + MessageServer::sendMessage("\\\\.\\pipe\\" DSHOW_PLUGIN_ASSISTANT_NAME, &message); this->d->m_messageServer.stop(true); this->d->m_portName.clear(); @@ -242,7 +234,7 @@ std::vector AkVCam::IpcBridge::devices() const return devices; } -std::wstring AkVCam::IpcBridge::description(const std::string &deviceId) const +std::string AkVCam::IpcBridge::description(const std::string &deviceId) const { AkLogFunction(); auto cameraIndex = Preferences::cameraFromPath(deviceId); @@ -254,7 +246,7 @@ std::wstring AkVCam::IpcBridge::description(const std::string &deviceId) const } void AkVCam::IpcBridge::setDescription(const std::string &deviceId, - const std::wstring &description) + const std::string &description) { AkLogFunction(); auto cameraIndex = Preferences::cameraFromPath(deviceId); @@ -456,8 +448,8 @@ std::vector AkVCam::IpcBridge::clientsPids() const auto currentPid = GetCurrentProcessId(); for (size_t i = 0; i < nProcess; i++) { - auto processHnd = OpenProcess(PROCESS_QUERY_INFORMATION | - PROCESS_VM_READ, + auto processHnd = OpenProcess(PROCESS_QUERY_INFORMATION + | PROCESS_VM_READ, FALSE, process[i]); if (!processHnd) @@ -522,7 +514,7 @@ std::string AkVCam::IpcBridge::clientExe(uint64_t pid) const return exe; } -std::string AkVCam::IpcBridge::addDevice(const std::wstring &description) +std::string AkVCam::IpcBridge::addDevice(const std::string &description) { return Preferences::addDevice(description); } @@ -602,10 +594,8 @@ bool AkVCam::IpcBridge::deviceStart(const std::string &deviceId, return false; } - std::wstring portName(this->d->m_portName.begin(), - this->d->m_portName.end()); - this->d->m_sharedMemory.setName(L"Local\\" + portName + L".data"); - this->d->m_globalMutex = Mutex(portName + L".mutex"); + this->d->m_sharedMemory.setName("Local\\" + this->d->m_portName + ".data"); + this->d->m_globalMutex = Mutex(this->d->m_portName + ".mutex"); if (!this->d->m_sharedMemory.open(maxBufferSize, SharedMemory::OpenModeWrite)) { @@ -755,7 +745,7 @@ bool AkVCam::IpcBridge::removeListener(const std::string &deviceId) AkVCam::IpcBridgePrivate::IpcBridgePrivate(IpcBridge *self): self(self) { - this->m_mainServer.setPipeName(L"\\\\.\\pipe\\" DSHOW_PLUGIN_ASSISTANT_NAME_L); + this->m_mainServer.setPipeName("\\\\.\\pipe\\" DSHOW_PLUGIN_ASSISTANT_NAME); this->m_mainServer.setMode(MessageServer::ServerModeSend); this->m_mainServer.connectPipeStateChanged(this, &IpcBridgePrivate::pipeStateChanged); @@ -811,18 +801,16 @@ std::string AkVCam::IpcBridgePrivate::dirname(const std::string &path) void AkVCam::IpcBridgePrivate::updateDeviceSharedProperties() { for (size_t i = 0; i < Preferences::camerasCount(); i++) { - auto cameraPath = Preferences::cameraPath(i); - std::string deviceId(cameraPath.begin(), cameraPath.end()); - + auto path = Preferences::cameraPath(i); Message message; message.messageId = AKVCAM_ASSISTANT_MSG_DEVICE_BROADCASTING; message.dataSize = sizeof(MsgBroadcasting); auto data = messageData(&message); memcpy(data->device, - deviceId.c_str(), - (std::min)(deviceId.size(), MAX_STRING)); + path.c_str(), + (std::min)(path.size(), MAX_STRING)); this->m_mainServer.sendMessage(&message); - this->updateDeviceSharedProperties(deviceId, + this->updateDeviceSharedProperties(path, std::string(data->broadcaster)); } } @@ -833,11 +821,9 @@ void AkVCam::IpcBridgePrivate::updateDeviceSharedProperties(const std::string &d if (owner.empty()) { this->m_devices[deviceId] = {SharedMemory(), Mutex()}; } else { - Mutex mutex(std::wstring(owner.begin(), owner.end()) + L".mutex"); + Mutex mutex(owner + ".mutex"); SharedMemory sharedMemory; - sharedMemory.setName(L"Local\\" - + std::wstring(owner.begin(), owner.end()) - + L".data"); + sharedMemory.setName("Local\\" + owner + ".data"); if (sharedMemory.open()) this->m_devices[deviceId] = {sharedMemory, mutex}; @@ -936,9 +922,7 @@ void AkVCam::IpcBridgePrivate::pictureUpdated(Message *message) { AkLogFunction(); auto data = messageData(message); - AKVCAM_EMIT(this->self, - PictureChanged, - std::string(data->picture)) + AKVCAM_EMIT(this->self, PictureChanged, std::string(data->picture)) } void AkVCam::IpcBridgePrivate::deviceUpdate(Message *message) diff --git a/dshow/VirtualCamera/VirtualCamera.pro b/dshow/VirtualCamera/VirtualCamera.pro index a720f51..231e97c 100644 --- a/dshow/VirtualCamera/VirtualCamera.pro +++ b/dshow/VirtualCamera/VirtualCamera.pro @@ -121,17 +121,6 @@ RESOURCESPATH = $${DSHOW_PLUGIN_NAME}.plugin/share DESTDIR = $${OUT_PWD}/../../$${INSTALLPATH} INSTALLS += \ - target \ - resources + target target.path = $${PREFIX}/$${INSTALLPATH} - -resources.files = ../../share/TestFrame/TestFrame.bmp -resources.path = $${PREFIX}/$${RESOURCESPATH} - -QMAKE_POST_LINK = \ - $$sprintf($$QMAKE_MKDIR_CMD, \ - $$shell_quote($$shell_path($${OUT_PWD}/../../$${RESOURCESPATH}))) \ - $${CMD_SEP} \ - $(COPY) $$shell_quote($$shell_path($${PWD}/../../share/TestFrame/TestFrame.bmp)) \ - $$shell_quote($$shell_path($${OUT_PWD}/../../$${RESOURCESPATH}/TestFrame.bmp)) diff --git a/dshow/VirtualCamera/src/basefilter.cpp b/dshow/VirtualCamera/src/basefilter.cpp index 18f8070..97fe146 100644 --- a/dshow/VirtualCamera/src/basefilter.cpp +++ b/dshow/VirtualCamera/src/basefilter.cpp @@ -58,14 +58,14 @@ namespace AkVCam EnumPins *m_pins; VideoProcAmp *m_videoProcAmp; ReferenceClock *m_referenceClock; - std::wstring m_vendor; - std::wstring m_filterName; + std::string m_vendor; + std::string m_filterName; IFilterGraph *m_filterGraph; IpcBridge m_ipcBridge; BaseFilterPrivate(BaseFilter *self, - const std::wstring &filterName, - const std::wstring &vendor); + const std::string &filterName, + const std::string &vendor); BaseFilterPrivate(const BaseFilterPrivate &other) = delete; ~BaseFilterPrivate(); IEnumPins *pinsForDevice(const std::string &deviceId); @@ -85,8 +85,8 @@ namespace AkVCam } AkVCam::BaseFilter::BaseFilter(const GUID &clsid, - const std::wstring &filterName, - const std::wstring &vendor): + const std::string &filterName, + const std::string &vendor): MediaFilter(clsid, this) { this->setParent(this, &IID_IBaseFilter); @@ -99,7 +99,7 @@ AkVCam::BaseFilter::~BaseFilter() } void AkVCam::BaseFilter::addPin(const std::vector &formats, - const std::wstring &pinName, + const std::string &pinName, bool changed) { AkLogFunction(); @@ -123,15 +123,12 @@ AkVCam::BaseFilter *AkVCam::BaseFilter::create(const GUID &clsid) return nullptr; auto description = Preferences::cameraDescription(size_t(camera)); - AkLogInfo() << "Description: " - << std::string(description.begin(), - description.end()) - << std::endl; + AkLogInfo() << "Description: " << description << std::endl; auto baseFilter = new BaseFilter(clsid, description, - DSHOW_PLUGIN_VENDOR_L); + DSHOW_PLUGIN_VENDOR); auto formats = Preferences::cameraFormats(size_t(camera)); - baseFilter->addPin(formats, L"Video", false); + baseFilter->addPin(formats, "Video", false); return baseFilter; } @@ -282,10 +279,12 @@ HRESULT AkVCam::BaseFilter::QueryFilterInfo(FILTER_INFO *pInfo) memset(pInfo->achName, 0, MAX_FILTER_NAME * sizeof(WCHAR)); if (this->d->m_filterName.size() > 0) { + auto filterName = stringToWSTR(this->d->m_filterName); memcpy(pInfo->achName, - this->d->m_filterName.c_str(), + filterName, std::max(this->d->m_filterName.size() * sizeof(WCHAR), MAX_FILTER_NAME)); + CoTaskMemFree(filterName); } pInfo->pGraph = this->d->m_filterGraph; @@ -301,13 +300,10 @@ HRESULT AkVCam::BaseFilter::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName) AkLogFunction(); this->d->m_filterGraph = pGraph; - this->d->m_filterName = std::wstring(pName? pName: L""); + this->d->m_filterName = pName? stringFromWSTR(pName): ""; AkLogInfo() << "Filter graph: " << this->d->m_filterGraph << std::endl; - AkLogInfo() << "Name: " - << std::string(this->d->m_filterName.begin(), - this->d->m_filterName.end()) - << std::endl; + AkLogInfo() << "Name: " << this->d->m_filterName << std::endl; return S_OK; } @@ -322,7 +318,7 @@ HRESULT AkVCam::BaseFilter::QueryVendorInfo(LPWSTR *pVendorInfo) if (!pVendorInfo) return E_POINTER; - *pVendorInfo = wcharStrFromWStr(this->d->m_vendor); + *pVendorInfo = stringToWSTR(this->d->m_vendor); return S_OK; } @@ -345,8 +341,8 @@ void AkVCam::BaseFilter::stateChanged(FILTER_STATE state) } AkVCam::BaseFilterPrivate::BaseFilterPrivate(AkVCam::BaseFilter *self, - const std::wstring &filterName, - const std::wstring &vendor): + const std::string &filterName, + const std::string &vendor): self(self), m_pins(new AkVCam::EnumPins), m_videoProcAmp(new VideoProcAmp), diff --git a/dshow/VirtualCamera/src/basefilter.h b/dshow/VirtualCamera/src/basefilter.h index 5b66f55..1ac8f69 100644 --- a/dshow/VirtualCamera/src/basefilter.h +++ b/dshow/VirtualCamera/src/basefilter.h @@ -36,12 +36,12 @@ namespace AkVCam { public: BaseFilter(const GUID &clsid, - const std::wstring &filterName={}, - const std::wstring &vendor={}); + const std::string &filterName={}, + const std::string &vendor={}); virtual ~BaseFilter(); void addPin(const std::vector &formats={}, - const std::wstring &pinName={}, + const std::string &pinName={}, bool changed=true); void removePin(IPin *pin, bool changed=true); static BaseFilter *create(const GUID &clsid); diff --git a/dshow/VirtualCamera/src/pin.cpp b/dshow/VirtualCamera/src/pin.cpp index c52e3de..b9e246a 100644 --- a/dshow/VirtualCamera/src/pin.cpp +++ b/dshow/VirtualCamera/src/pin.cpp @@ -36,6 +36,7 @@ #include "qualitycontrol.h" #include "referenceclock.h" #include "videoprocamp.h" +#include "PlatformUtils/src/preferences.h" #include "PlatformUtils/src/utils.h" #include "VCamUtils/src/image/videoformat.h" #include "VCamUtils/src/image/videoframe.h" @@ -49,8 +50,8 @@ namespace AkVCam Pin *self; BaseFilter *m_baseFilter; VideoProcAmp *m_videoProcAmp; - std::wstring m_pinName; - std::wstring m_pinId; + std::string m_pinName; + std::string m_pinId; EnumMediaTypes *m_mediaTypes; IPin *m_connectedTo; IMemInputPin *m_memInputPin; @@ -96,7 +97,7 @@ namespace AkVCam AkVCam::Pin::Pin(BaseFilter *baseFilter, const std::vector &formats, - const std::wstring &pinName): + const std::string &pinName): StreamConfig(this) { this->setParent(this, &IID_IPin); @@ -105,9 +106,9 @@ AkVCam::Pin::Pin(BaseFilter *baseFilter, this->d->self = this; this->d->m_baseFilter = baseFilter; this->d->m_pinName = pinName; - std::wstringstream wss; - wss << L"pin(" << this << L")"; - this->d->m_pinId = wss.str(); + std::stringstream ss; + ss << "pin(" << this << ")"; + this->d->m_pinId = ss.str(); this->d->m_mediaTypes = new AkVCam::EnumMediaTypes(formats); this->d->m_mediaTypes->AddRef(); this->d->m_connectedTo = nullptr; @@ -124,9 +125,10 @@ AkVCam::Pin::Pin(BaseFilter *baseFilter, this->d->m_adviseCookie = 0; this->d->m_sendFrameEvent = nullptr; this->d->m_running = false; - auto bmp = programFilesPath() - + L"\\" DSHOW_PLUGIN_NAME_L L".plugin\\share\\TestFrame.bmp"; - this->d->m_testFrame.load(std::string(bmp.begin(), bmp.end())); + auto picture = Preferences::picture(); + + if (!picture.empty()) + this->d->m_testFrame = loadPicture(picture); baseFilter->QueryInterface(IID_IAMVideoProcAmp, reinterpret_cast(&this->d->m_videoProcAmp)); @@ -671,11 +673,14 @@ HRESULT AkVCam::Pin::QueryPinInfo(PIN_INFO *pInfo) pInfo->dir = PINDIR_OUTPUT; memset(pInfo->achName, 0, MAX_PIN_NAME * sizeof(WCHAR)); - if (!this->d->m_pinName.empty()) + if (!this->d->m_pinName.empty()) { + auto pinName = stringToWSTR(this->d->m_pinName); memcpy(pInfo->achName, - this->d->m_pinName.c_str(), + pinName, (std::min)(this->d->m_pinName.size() * sizeof(WCHAR), MAX_PIN_NAME)); + CoTaskMemFree(pinName); + } return S_OK; } @@ -706,9 +711,9 @@ HRESULT AkVCam::Pin::QueryId(LPWSTR *Id) return E_OUTOFMEMORY; memset(*Id, 0, wstrSize); - memcpy(*Id, - this->d->m_pinId.c_str(), - this->d->m_pinId.size() * sizeof(WCHAR)); + auto pinId = stringToWSTR(this->d->m_pinId); + memcpy(*Id, pinId, this->d->m_pinId.size() * sizeof(WCHAR)); + CoTaskMemFree(pinId); return S_OK; } diff --git a/dshow/VirtualCamera/src/pin.h b/dshow/VirtualCamera/src/pin.h index 5c0e446..4295ac9 100644 --- a/dshow/VirtualCamera/src/pin.h +++ b/dshow/VirtualCamera/src/pin.h @@ -41,7 +41,7 @@ namespace AkVCam public: Pin(BaseFilter *baseFilter=nullptr, const std::vector &formats={}, - const std::wstring &pinName={}); + const std::string &pinName={}); virtual ~Pin(); BaseFilter *baseFilter() const; diff --git a/dshow/VirtualCamera/src/plugin.cpp b/dshow/VirtualCamera/src/plugin.cpp index b26c5e1..32a045f 100644 --- a/dshow/VirtualCamera/src/plugin.cpp +++ b/dshow/VirtualCamera/src/plugin.cpp @@ -118,13 +118,8 @@ STDAPI DllRegisterServer() auto clsid = AkVCam::createClsidFromStr(path); AkLogInfo() << "Creating Camera" << std::endl; - AkLogInfo() << "\tDescription: " - << std::string(description.begin(), - description.end()) - << std::endl; - AkLogInfo() << "\tPath: " - << std::string(path.begin(), path.end()) - << std::endl; + AkLogInfo() << "\tDescription: " << description << std::endl; + AkLogInfo() << "\tPath: " << path << std::endl; AkLogInfo() << "\tCLSID: " << AkVCam::stringFromIid(clsid) << std::endl; ok &= pluginInterface()->createDevice(path, description); diff --git a/dshow/VirtualCamera/src/plugininterface.cpp b/dshow/VirtualCamera/src/plugininterface.cpp index b5ba08f..58b2f0d 100644 --- a/dshow/VirtualCamera/src/plugininterface.cpp +++ b/dshow/VirtualCamera/src/plugininterface.cpp @@ -56,62 +56,62 @@ HINSTANCE &AkVCam::PluginInterface::pluginHinstance() } bool AkVCam::PluginInterface::registerServer(const std::string &deviceId, - const std::wstring &description) const + const std::string &description) const { AkLogFunction(); // Define the layout in registry of the filter. - auto clsid = createClsidWStrFromStr(deviceId); - auto fileName = AkVCam::moduleFileNameW(this->d->m_pluginHinstance); - std::wstring threadingModel = L"Both"; + auto clsid = createClsidStrFromStr(deviceId); + auto fileName = moduleFileName(this->d->m_pluginHinstance); + std::string threadingModel = "Both"; - AkLogInfo() << "CLSID: " << std::string(clsid.begin(), clsid.end()) << std::endl; - AkLogInfo() << "Description: " << std::string(description.begin(), description.end()) << std::endl; - AkLogInfo() << "Filename: " << std::string(fileName.begin(), fileName.end()) << std::endl; + AkLogInfo() << "CLSID: " << clsid << std::endl; + AkLogInfo() << "Description: " << description << std::endl; + AkLogInfo() << "Filename: " << fileName << std::endl; - auto subkey = L"CLSID\\" + clsid; + auto subkey = "CLSID\\" + clsid; HKEY keyCLSID = nullptr; HKEY keyServerType = nullptr; - LONG result = RegCreateKey(HKEY_CLASSES_ROOT, subkey.c_str(), &keyCLSID); + LONG result = RegCreateKeyA(HKEY_CLASSES_ROOT, subkey.c_str(), &keyCLSID); bool ok = false; if (result != ERROR_SUCCESS) goto registerServer_failed; result = - RegSetValue(keyCLSID, - nullptr, - REG_SZ, - description.c_str(), - DWORD(description.size())); + RegSetValueA(keyCLSID, + nullptr, + REG_SZ, + description.c_str(), + DWORD(description.size())); if (result != ERROR_SUCCESS) goto registerServer_failed; - result = RegCreateKey(keyCLSID, L"InprocServer32", &keyServerType); + result = RegCreateKey(keyCLSID, TEXT("InprocServer32"), &keyServerType); if (result != ERROR_SUCCESS) goto registerServer_failed; result = - RegSetValue(keyServerType, - nullptr, - REG_SZ, - fileName.c_str(), - DWORD(fileName.size())); + RegSetValueA(keyServerType, + nullptr, + REG_SZ, + fileName.c_str(), + DWORD(fileName.size())); if (result != ERROR_SUCCESS) goto registerServer_failed; result = - RegSetValueEx(keyServerType, - L"ThreadingModel", - 0L, - REG_SZ, - reinterpret_cast(threadingModel.c_str()), - DWORD((threadingModel.size() + 1) * sizeof(wchar_t))); + RegSetValueExA(keyServerType, + "ThreadingModel", + 0L, + REG_SZ, + reinterpret_cast(threadingModel.c_str()), + DWORD((threadingModel.size() + 1) * sizeof(wchar_t))); ok = true; @@ -134,13 +134,6 @@ void AkVCam::PluginInterface::unregisterServer(const std::string &deviceId) cons this->unregisterServer(createClsidFromStr(deviceId)); } -void AkVCam::PluginInterface::unregisterServer(const std::wstring &deviceId) const -{ - AkLogFunction(); - - this->unregisterServer(createClsidFromStr(deviceId)); -} - void AkVCam::PluginInterface::unregisterServer(const CLSID &clsid) const { AkLogFunction(); @@ -152,7 +145,7 @@ void AkVCam::PluginInterface::unregisterServer(const CLSID &clsid) const } bool AkVCam::PluginInterface::registerFilter(const std::string &deviceId, - const std::wstring &description) const + const std::string &description) const { AkLogFunction(); @@ -182,6 +175,7 @@ bool AkVCam::PluginInterface::registerFilter(const std::string &deviceId, auto result = CoInitialize(nullptr); bool ok = false; + LPWSTR wdescription = nullptr; if (FAILED(result)) goto registerFilter_failed; @@ -195,13 +189,14 @@ bool AkVCam::PluginInterface::registerFilter(const std::string &deviceId, if (FAILED(result)) goto registerFilter_failed; + wdescription = stringToWSTR(description); result = filterMapper->RegisterFilter(clsid, - description.c_str(), + wdescription, &pMoniker, &CLSID_VideoInputDeviceCategory, nullptr, ®Filter); - + CoTaskMemFree(wdescription); ok = true; registerFilter_failed: @@ -223,13 +218,6 @@ void AkVCam::PluginInterface::unregisterFilter(const std::string &deviceId) cons this->unregisterFilter(AkVCam::createClsidFromStr(deviceId)); } -void AkVCam::PluginInterface::unregisterFilter(const std::wstring &deviceId) const -{ - AkLogFunction(); - - this->unregisterFilter(AkVCam::createClsidFromStr(deviceId)); -} - void AkVCam::PluginInterface::unregisterFilter(const CLSID &clsid) const { AkLogFunction(); @@ -265,20 +253,20 @@ bool AkVCam::PluginInterface::setDevicePath(const std::string &deviceId) const { AkLogFunction(); - std::wstring subKey = - L"CLSID\\" - + wstringFromIid(CLSID_VideoInputDeviceCategory) - + L"\\Instance\\" - + createClsidWStrFromStr(deviceId); + std::string subKey = + "CLSID\\" + + stringFromIid(CLSID_VideoInputDeviceCategory) + + "\\Instance\\" + + createClsidStrFromStr(deviceId); AkLogInfo() << "Key: HKEY_CLASSES_ROOT" << std::endl; - AkLogInfo() << "SubKey: " << std::string(subKey.begin(), subKey.end()) << std::endl; + AkLogInfo() << "SubKey: " << subKey << std::endl; HKEY hKey = nullptr; - auto result = RegOpenKeyEx(HKEY_CLASSES_ROOT, - subKey.c_str(), - 0, - KEY_ALL_ACCESS, - &hKey); + auto result = RegOpenKeyExA(HKEY_CLASSES_ROOT, + subKey.c_str(), + 0, + KEY_ALL_ACCESS, + &hKey); bool ok = false; if (result != ERROR_SUCCESS) @@ -306,7 +294,7 @@ setDevicePath_failed: } bool AkVCam::PluginInterface::createDevice(const std::string &deviceId, - const std::wstring &description) + const std::string &description) { AkLogFunction(); @@ -335,14 +323,6 @@ void AkVCam::PluginInterface::destroyDevice(const std::string &deviceId) this->unregisterServer(deviceId); } -void AkVCam::PluginInterface::destroyDevice(const std::wstring &deviceId) -{ - AkLogFunction(); - - this->unregisterFilter(deviceId); - this->unregisterServer(deviceId); -} - void AkVCam::PluginInterface::destroyDevice(const CLSID &clsid) { AkLogFunction(); diff --git a/dshow/VirtualCamera/src/plugininterface.h b/dshow/VirtualCamera/src/plugininterface.h index 2298b16..4a6cb86 100644 --- a/dshow/VirtualCamera/src/plugininterface.h +++ b/dshow/VirtualCamera/src/plugininterface.h @@ -37,20 +37,17 @@ namespace AkVCam HINSTANCE pluginHinstance() const; HINSTANCE &pluginHinstance(); bool registerServer(const std::string &deviceId, - const std::wstring &description) const; + const std::string &description) const; void unregisterServer(const std::string &deviceId) const; - void unregisterServer(const std::wstring &deviceId) const; void unregisterServer(const CLSID &clsid) const; bool registerFilter(const std::string &deviceId, - const std::wstring &description) const; + const std::string &description) const; void unregisterFilter(const std::string &deviceId) const; - void unregisterFilter(const std::wstring &deviceId) const; void unregisterFilter(const CLSID &clsid) const; bool setDevicePath(const std::string &deviceId) const; bool createDevice(const std::string &deviceId, - const std::wstring &description); + const std::string &description); void destroyDevice(const std::string &deviceId); - void destroyDevice(const std::wstring &deviceId); void destroyDevice(const CLSID &clsid); private: diff --git a/dshow/dshow.pri b/dshow/dshow.pri index b1ded3b..47480dd 100644 --- a/dshow/dshow.pri +++ b/dshow/dshow.pri @@ -33,19 +33,12 @@ isEmpty(DSHOW_PLUGIN_VENDOR): DEFINES += \ DSHOW_PLUGIN_NAME=\"\\\"$$DSHOW_PLUGIN_NAME\\\"\" \ - DSHOW_PLUGIN_NAME_L=\"L\\\"$$DSHOW_PLUGIN_NAME\\\"\" \ DSHOW_PLUGIN_ASSISTANT_NAME=\"\\\"$$DSHOW_PLUGIN_ASSISTANT_NAME\\\"\" \ - DSHOW_PLUGIN_ASSISTANT_NAME_L=\"L\\\"$$DSHOW_PLUGIN_ASSISTANT_NAME\\\"\" \ DSHOW_PLUGIN_ASSISTANT_DESCRIPTION=\"\\\"$$DSHOW_PLUGIN_ASSISTANT_DESCRIPTION\\\"\" \ - DSHOW_PLUGIN_ASSISTANT_DESCRIPTION_L=\"L\\\"$$DSHOW_PLUGIN_ASSISTANT_DESCRIPTION\\\"\" \ DSHOW_PLUGIN_DESCRIPTION=\"\\\"$$DSHOW_PLUGIN_DESCRIPTION\\\"\" \ - DSHOW_PLUGIN_DESCRIPTION_L=\"L\\\"$$DSHOW_PLUGIN_DESCRIPTION\\\"\" \ DSHOW_PLUGIN_DESCRIPTION_EXT=\"\\\"$$DSHOW_PLUGIN_DESCRIPTION_EXT\\\"\" \ - DSHOW_PLUGIN_DESCRIPTION_EXT_L=\"L\\\"$$DSHOW_PLUGIN_DESCRIPTION_EXT\\\"\" \ DSHOW_PLUGIN_DEVICE_PREFIX=\"\\\"$$DSHOW_PLUGIN_DEVICE_PREFIX\\\"\" \ - DSHOW_PLUGIN_DEVICE_PREFIX_L=\"L\\\"$$DSHOW_PLUGIN_DEVICE_PREFIX\\\"\" \ - DSHOW_PLUGIN_VENDOR=\"\\\"$$DSHOW_PLUGIN_VENDOR\\\"\" \ - DSHOW_PLUGIN_VENDOR_L=\"L\\\"$$DSHOW_PLUGIN_VENDOR\\\"\" + DSHOW_PLUGIN_VENDOR=\"\\\"$$DSHOW_PLUGIN_VENDOR\\\"\" defineReplace(normalizedArch) { arch = $$replace($$1, i386, x86) diff --git a/ports/deploy/deploy_mac.py b/ports/deploy/deploy_mac.py index 3e57f0a..a154a49 100644 --- a/ports/deploy/deploy_mac.py +++ b/ports/deploy/deploy_mac.py @@ -53,7 +53,7 @@ class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt): self.dependencies = [] self.installerConfig = os.path.join(self.installDir, 'installer/config') self.installerPackages = os.path.join(self.installDir, 'installer/packages') - self.appIcon = os.path.join(self.rootDir, 'share/TestFrame/webcamoid.png') + self.appIcon = os.path.join(self.rootDir, 'share/icons/webcamoid.png') self.licenseFile = os.path.join(self.rootDir, 'COPYING') self.installerTargetDir = '@ApplicationsDir@/' + self.programName self.installerScript = os.path.join(self.rootDir, 'ports/deploy/installscript.mac.qs') @@ -190,7 +190,7 @@ class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt): size += os.path.getsize(fpath) return size - + def signPackage(self, package): process = subprocess.Popen(['codesign', # nosec '--force', diff --git a/ports/deploy/deploy_posix_windows.py b/ports/deploy/deploy_posix_windows.py index 5106e89..f120d3c 100644 --- a/ports/deploy/deploy_posix_windows.py +++ b/ports/deploy/deploy_posix_windows.py @@ -51,7 +51,7 @@ class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt): self.dependencies = [] self.installerConfig = os.path.join(self.installDir, 'installer/config') self.installerPackages = os.path.join(self.installDir, 'installer/packages') - self.appIcon = os.path.join(self.rootDir, 'share/TestFrame/webcamoid.png') + self.appIcon = os.path.join(self.rootDir, 'share/icons/webcamoid.png') self.licenseFile = os.path.join(self.rootDir, 'COPYING') self.installerScript = os.path.join(self.rootDir, 'ports/deploy/installscript.windows.qs') self.changeLog = os.path.join(self.rootDir, 'ChangeLog') diff --git a/ports/deploy/deploy_windows.py b/ports/deploy/deploy_windows.py index 1daa041..1e7f571 100644 --- a/ports/deploy/deploy_windows.py +++ b/ports/deploy/deploy_windows.py @@ -51,7 +51,7 @@ class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt): self.dependencies = [] self.installerConfig = os.path.join(self.installDir, 'installer/config') self.installerPackages = os.path.join(self.installDir, 'installer/packages') - self.appIcon = os.path.join(self.rootDir, 'share/TestFrame/webcamoid.png') + self.appIcon = os.path.join(self.rootDir, 'share/icons/webcamoid.png') self.licenseFile = os.path.join(self.rootDir, 'COPYING') self.installerScript = os.path.join(self.rootDir, 'ports/deploy/installscript.windows.qs') self.changeLog = os.path.join(self.rootDir, 'ChangeLog') diff --git a/share/TestFrame/TestFrame.bmp b/share/TestFrame/TestFrame.bmp deleted file mode 100644 index 17a52f28ef57518c861250a23bc989cdf834c487..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 921654 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. -# -# Web-Site: http://webcamoid.github.io/ - -import sys -from PyQt5 import QtWidgets, QtQml, QtQuick - - -if __name__ =='__main__': - app = QtWidgets.QApplication(sys.argv); - engine = QtQml.QQmlApplicationEngine() - engine.load("TestFrame.qml") - - def capture(): - for obj in engine.rootObjects(): - image = obj.grabWindow() - image.save("TestFrame.bmp") - obj.close() - - for obj in engine.rootObjects(): - obj.sceneGraphInitialized.connect(capture) - - app.exec_() diff --git a/share/TestFrame/TestFrame.qml b/share/TestFrame/TestFrame.qml deleted file mode 100644 index f223f30..0000000 --- a/share/TestFrame/TestFrame.qml +++ /dev/null @@ -1,194 +0,0 @@ -/* 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 . - * - * Web-Site: http://webcamoid.github.io/ - */ - -import QtQuick 2.12 -import QtQuick.Window 2.12 -import QtQuick.Controls 2.5 -import QtQuick.Layouts 1.3 - -ApplicationWindow { - width: 640 - height: 480 - color: "#3f2a7e" - visible: true - - property int patternSize: 24 - - ColumnLayout { - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - - GridLayout { - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - columns: 2 - - // Info - Image { - id: icon - width: 128 - height: width - sourceSize.width: width - sourceSize.height: height - source: "webcamoid.png" - } - - ColumnLayout { - Text { - id: programName - color: "#ffffff" - text: "Webcamoid" - font.weight: Font.Bold - font.pixelSize: 40 - } - - Text { - color: "#ffffff" - text: "The ultimate webcam suite!" - leftPadding: 24 - font.weight: Font.Bold - font.pixelSize: 0.5 * programName.font.pixelSize - } - } - - // Color pattern - GridLayout { - columns: 8 - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - Layout.columnSpan: 2 - - Text { - text: "R" - color: "#ffffff" - font.pixelSize: 0.3 * programName.font.pixelSize - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - } - Text { - text: "G" - color: "#ffffff" - font.pixelSize: 0.3 * programName.font.pixelSize - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - } - Text { - text: "B" - color: "#ffffff" - font.pixelSize: 0.3 * programName.font.pixelSize - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - } - - Text { - text: "C" - color: "#ffffff" - font.pixelSize: 0.3 * programName.font.pixelSize - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - } - Text { - text: "M" - color: "#ffffff" - font.pixelSize: 0.3 * programName.font.pixelSize - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - } - Text { - text: "Y" - color: "#ffffff" - font.pixelSize: 0.3 * programName.font.pixelSize - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - } - - Text { - text: "K" - color: "#ffffff" - font.pixelSize: 0.3 * programName.font.pixelSize - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - } - Text { - text: "W" - color: "#ffffff" - font.pixelSize: 0.3 * programName.font.pixelSize - Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter - } - - // RGB - Rectangle { - color: "#ff0000" - width: patternSize - height: patternSize - } - Rectangle { - color: "#00ff00" - width: patternSize - height: patternSize - } - Rectangle { - color: "#0000ff" - width: patternSize - height: patternSize - } - - // CMY - Rectangle { - color: "#00ffff" - width: patternSize - height: patternSize - } - Rectangle { - color: "#ff00ff" - width: patternSize - height: patternSize - } - Rectangle { - color: "#ffff00" - width: patternSize - height: patternSize - } - - // BW - Rectangle { - color: "#000000" - width: patternSize - height: patternSize - } - Rectangle { - color: "#ffffff" - width: patternSize - height: patternSize - } - } - } - - // Usage - Rectangle { - width: 500 - height: 125 - color: "#00000000" - - Text { - id: usage - color: "#ffffff" - text: "This is a Webcamoid's virtual webcam device.\n" - + "Go to Webcamoid, enable virtual webcam output, select " - + "this device and play some webcam, desktop or video." - wrapMode: Text.WordWrap - anchors.fill: parent - topPadding: 8 - Layout.columnSpan: 2 - font.pixelSize: 0.45 * programName.font.pixelSize - } - } - } -} diff --git a/share/TestFrame/webcamoid.png b/share/icons/webcamoid.png similarity index 100% rename from share/TestFrame/webcamoid.png rename to share/icons/webcamoid.png