diff --git a/.github/workflows/wxOSX_arm64.yml b/.github/workflows/wxOSX_arm64.yml index c148811..a6e6435 100644 --- a/.github/workflows/wxOSX_arm64.yml +++ b/.github/workflows/wxOSX_arm64.yml @@ -1,73 +1,73 @@ -name: wxOSX_arm64 - -on: -# push: -# branches: '*' -# pull_request: -# branches: '*' -# workflow_dispatch: -# branches: '*' +name: wxOSX_arm64 + +on: +# push: +# branches: '*' +# pull_request: +# branches: '*' +# workflow_dispatch: +# branches: '*' workflow_dispatch: - -jobs: - build: - - runs-on: macos-14 - - steps: - - name: Install boost - uses: MarkusJx/install-boost@v2.4.5 - id: install-boost - with: - # REQUIRED: Specify the required boost version - # A list of supported versions can be found here: - # https://github.com/MarkusJx/prebuilt-boost/blob/main/versions-manifest.json - boost_version: 1.86.0 - boost_install_dir: /tmp/wxModularAppOCX/boost/ - - - uses: actions/checkout@v4 - - name: Install wxWidgets - run: | - curl -L https://download.osgeo.org/libtiff/tiff-4.6.0.tar.gz --output tiff-4.6.0.tar.gz - tar xzf tiff-4.6.0.tar.gz - cd tiff-4.6.0 - ./configure - make -j$(getconf _NPROCESSORS_ONLN) - sudo make install - cd .. - curl -L https://github.com/wxWidgets/wxWidgets/releases/download/v3.2.5/wxWidgets-3.2.5.tar.bz2 --output wxWidgets-3.2.5.tar.bz2 - tar xjf wxWidgets-3.2.5.tar.bz2 - cd wxwidgets-3.2.5 - mkdir buildOSX - cd buildOSX - ../configure --enable-debug - make -j$(getconf _NPROCESSORS_ONLN) - sudo make install - cd ../.. - wx-config --list - wx-config --cxxflags - wx-config --libs - - - name: Run CMake - run: | - cd build - chmod +x ./cmAppleMac.sh - ./cmAppleMac.sh - cd .. - env: - BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} - - - name: Run GNU Make with GNU compiler - run: | - cd build - mkdir -p bin - mkdir -p bin/Debug - cd Mac - make VERBOSE=1 -j$(getconf _NPROCESSORS_ONLN) - cd ../.. - cp wxWidgets-3.2.5/buildOSX/lib/*.dylib build/bin/wxModularHost.app/Contents - - - uses: actions/upload-artifact@v4 - with: - name: artifacts_wxOSX_arm64 - path: build/bin/wxModularHost.app/Contents + +jobs: + build: + + runs-on: macos-14 + + steps: + - name: Install boost + uses: MarkusJx/install-boost@v2.4.5 + id: install-boost + with: + # REQUIRED: Specify the required boost version + # A list of supported versions can be found here: + # https://github.com/MarkusJx/prebuilt-boost/blob/main/versions-manifest.json + boost_version: 1.86.0 + boost_install_dir: /tmp/wxModularAppOCX/boost/ + + - uses: actions/checkout@v4 + - name: Install wxWidgets + run: | + curl -L https://download.osgeo.org/libtiff/tiff-4.6.0.tar.gz --output tiff-4.6.0.tar.gz + tar xzf tiff-4.6.0.tar.gz + cd tiff-4.6.0 + ./configure + make -j$(getconf _NPROCESSORS_ONLN) + sudo make install + cd .. + curl -L https://github.com/wxWidgets/wxWidgets/releases/download/v3.2.5/wxWidgets-3.2.5.tar.bz2 --output wxWidgets-3.2.5.tar.bz2 + tar xjf wxWidgets-3.2.5.tar.bz2 + cd wxwidgets-3.2.5 + mkdir buildOSX + cd buildOSX + ../configure --enable-debug + make -j$(getconf _NPROCESSORS_ONLN) + sudo make install + cd ../.. + wx-config --list + wx-config --cxxflags + wx-config --libs + + - name: Run CMake + run: | + cd build + chmod +x ./cmAppleMac.sh + ./cmAppleMac.sh + cd .. + env: + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} + + - name: Run GNU Make with GNU compiler + run: | + cd build + mkdir -p bin + mkdir -p bin/Debug + cd Mac + make VERBOSE=1 -j$(getconf _NPROCESSORS_ONLN) + cd ../.. + cp wxWidgets-3.2.5/buildOSX/lib/*.dylib build/bin/wxModularHost.app/Contents + + - uses: actions/upload-artifact@v4 + with: + name: artifacts_wxOSX_arm64 + path: build/bin/wxModularHost.app/Contents diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1a4e60f --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +build/ +.cmake/ +out/ +CMakeCache.txt +CMakeFiles/ +cmake_install.cmake +CMakeSettings.json + +Debug/ +Release/ +x64/ +x86/ + +*.pch +*.obj +*.o +*.tlog +*.pdb +*.ilk +*.exp + +.vs/ +*.VC.db +*.VC.opendb +*.suo +*.user +*.userosscache +*.sln.docstates + +.DS_Store +Thumbs.db +*.log +*.tmp \ No newline at end of file diff --git a/CommonPluginBase/CMakeLists.txt b/CommonPluginBase/CMakeLists.txt new file mode 100644 index 0000000..e5e9d82 --- /dev/null +++ b/CommonPluginBase/CMakeLists.txt @@ -0,0 +1,40 @@ +# +# Stuff the average programmer needs to change +# +set(SRCS + CommonConfigWindowBase.cpp + SerializableBase.cpp +) +set(HFILES + CommonConfigWindowBase.h + SerializableBase.h + CommonPlugin.h +) + +set(INCLUDE_DIRECTORIES + ${BASE_INCLUDE_DIRECTORIES} + ${THIRD_PARTY_DIR}/wxXS/include +) + +set(LIBRARY_NAME CommonPluginBase) + +if(WIN32) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D_USRDLL;/DIFLOOR_EXPORTS_COMMONPLUGINBASE) +endif(WIN32) + +set(SRCS ${SRCS} ${HFILES} ${PROJECT_ROOT_DIR}/include/stdwx.h ${PROJECT_ROOT_DIR}/include/stdwx.cpp) + +add_definitions(${PREPROCESSOR_DEFINITIONS}) +include_directories(${INCLUDE_DIRECTORIES}) + +add_library(${LIBRARY_NAME} SHARED ${SRCS}) + +target_link_libraries(${LIBRARY_NAME} + ${wxWidgets_LIBRARIES} + wxXS +) + +target_precompile_headers(${LIBRARY_NAME} + PRIVATE + "${PROJECT_ROOT_DIR}/include/stdwx.h" +) \ No newline at end of file diff --git a/CommonPluginBase/CommonConfigWindowBase.cpp b/CommonPluginBase/CommonConfigWindowBase.cpp new file mode 100644 index 0000000..a44757e --- /dev/null +++ b/CommonPluginBase/CommonConfigWindowBase.cpp @@ -0,0 +1,44 @@ +#include "stdwx.h" +#include "CommonConfigWindowBase.h" + +IMPLEMENT_DYNAMIC_CLASS(CommonConfigWindowBase, wxPanel) + +CommonConfigWindowBase::CommonConfigWindowBase() +{ + +} + +CommonConfigWindowBase::CommonConfigWindowBase(wxWindow *parent, + wxWindowID winid /*= wxID_ANY*/, + const wxPoint& pos /*= wxDefaultPosition*/, + const wxSize& size /*= wxDefaultSize*/, + long style /*= wxTAB_TRAVERSAL | wxNO_BORDER*/, + const wxString& name /*= wxPanelNameStr*/) +{ + Create(parent, winid, pos, size, style, name); +} + +bool CommonConfigWindowBase::Create(wxWindow *parent, + wxWindowID winid /*= wxID_ANY*/, + const wxPoint& pos /*= wxDefaultPosition*/, + const wxSize& size /*= wxDefaultSize*/, + long style /*= wxTAB_TRAVERSAL | wxNO_BORDER*/, + const wxString& name /*= wxPanelNameStr*/) +{ + return wxPanel::Create(parent, winid, pos, size, style, name); +} + +CommonConfigWindowBase::~CommonConfigWindowBase(void) +{ + +} + +bool CommonConfigWindowBase::ReadConfig() +{ + return true; +} + +bool CommonConfigWindowBase::SaveConfig() +{ + return true; +} \ No newline at end of file diff --git a/CommonPluginBase/CommonConfigWindowBase.h b/CommonPluginBase/CommonConfigWindowBase.h new file mode 100644 index 0000000..84c0a64 --- /dev/null +++ b/CommonPluginBase/CommonConfigWindowBase.h @@ -0,0 +1,37 @@ +#ifndef _COMMONCONFIGWINDOWBASE_H +#define _COMMONCONFIGWINDOWBASE_H +#include "CommonPlugin.h" +#include + +class IFLOOR_API_COMMONPLUGINBASE CommonConfigWindowBase : public wxPanel +{ + DECLARE_DYNAMIC_CLASS(CommonConfigWindowBase) +public: + /// Constructors + CommonConfigWindowBase(); + CommonConfigWindowBase(wxWindow *parent, + wxWindowID winid = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxTAB_TRAVERSAL | wxNO_BORDER, + const wxString& name = wxPanelNameStr); + + /// Pseudo ctor + bool Create(wxWindow *parent, + wxWindowID winid = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxTAB_TRAVERSAL | wxNO_BORDER, + const wxString& name = wxPanelNameStr); + + virtual ~CommonConfigWindowBase(); + + /// Reads config from the effect + virtual bool ReadConfig(); + + /// Saves config to the effect + virtual bool SaveConfig(); +}; + + +#endif // _COMMONCONFIGWINDOWBASE_H diff --git a/CommonPluginBase/CommonPlugin.h b/CommonPluginBase/CommonPlugin.h new file mode 100644 index 0000000..c36d560 --- /dev/null +++ b/CommonPluginBase/CommonPlugin.h @@ -0,0 +1,14 @@ +#ifndef _COMMONPLUGIN_H +#define _COMMONPLUGIN_H + +#if defined(__WXMSW__) +#ifdef IFLOOR_EXPORTS_COMMONPLUGINBASE +#define IFLOOR_API_COMMONPLUGINBASE __declspec(dllexport) +#else +#define IFLOOR_API_COMMONPLUGINBASE __declspec(dllimport) +#endif +#else +#define IFLOOR_API_COMMONPLUGINBASE +#endif + +#endif // _COMMONPLUGIN_H diff --git a/CommonPluginBase/SerializableBase.cpp b/CommonPluginBase/SerializableBase.cpp new file mode 100644 index 0000000..a738d8c --- /dev/null +++ b/CommonPluginBase/SerializableBase.cpp @@ -0,0 +1,63 @@ +#include "stdwx.h" +#include "SerializableBase.h" +#include + +IMPLEMENT_ABSTRACT_CLASS(SerializableBase, xsSerializable); + +WX_DEFINE_USER_EXPORTED_LIST(SerializableBaseList); + +SerializableBase::SerializableBase() +{ +} + +SerializableBase::~SerializableBase() +{ +} + +bool SerializableBase::Deserialize(wxInputStream & instream) +{ + return Deserialize(instream, *this); +} + +bool SerializableBase::Deserialize(wxInputStream & instream, xsSerializable & obj) +{ + wxXmlSerializer Serializer; + Serializer.EnableCloning(false); + Serializer.SetRootItem(&obj); + bool res = Serializer.DeserializeFromXml(instream); + Serializer.SetRootItem(nullptr, false); + obj.Reparent(nullptr); + obj.SetParentManager(nullptr); + return res; +} + +bool SerializableBase::Deserialize(const wxString & config, xsSerializable & obj) +{ + wxStringInputStream stream(config); + return Deserialize(stream, obj); +} + +bool SerializableBase::Serialize(wxOutputStream & outstream) +{ + return Serialize(outstream, *this); +} + +bool SerializableBase::Serialize(wxOutputStream & outstream, xsSerializable & obj) +{ + wxXmlSerializer Serializer; + Serializer.EnableCloning(false); + Serializer.SetRootItem(&obj); + bool res = Serializer.SerializeToXml(outstream, true); + Serializer.SetRootItem(nullptr, false); + obj.Reparent(nullptr); + obj.SetParentManager(nullptr); + return res; +} + +wxString SerializableBase::Serialize(xsSerializable & obj) +{ + wxString config; + wxStringOutputStream stream(&config); + Serialize(stream, obj); + return config; +} \ No newline at end of file diff --git a/CommonPluginBase/SerializableBase.h b/CommonPluginBase/SerializableBase.h new file mode 100644 index 0000000..8194db2 --- /dev/null +++ b/CommonPluginBase/SerializableBase.h @@ -0,0 +1,42 @@ +#ifndef _SERIALIZABLEBASE_H +#define _SERIALIZABLEBASE_H + +#include "CommonPlugin.h" +#include "CommonConfigWindowBase.h" +#include + +/// Base class for all iFloor effects +class IFLOOR_API_COMMONPLUGINBASE SerializableBase : public xsSerializable +{ + DECLARE_ABSTRACT_CLASS(SerializableBase) +public: + /// Default constructor + SerializableBase(); + /// Default destructor + virtual ~SerializableBase(); + /// Returns GUID (unique identifier) of effect + /// \return string which contains unique identifier of effect + virtual wxString GetID() const = 0; + /// Returns name of effect + /// \return string which contains human-readable name of effect + virtual wxString GetName() const = 0; + /// Creates settings panel where user can setup effect properties + /// \param parent parent window of settings panel + /// \return pointer to created settings panel. If function fails, return value is NULL + virtual CommonConfigWindowBase * CreateSettingsEditor(wxWindow * parent = NULL) = 0; + + virtual bool Deserialize(wxInputStream & instream); + virtual bool Serialize(wxOutputStream & outstream); + + static bool Deserialize(wxInputStream & instream, xsSerializable & obj); + static bool Serialize(wxOutputStream & outstream, xsSerializable & obj); + + static bool Deserialize(const wxString & config, xsSerializable & obj); + static wxString Serialize(xsSerializable & obj); +}; + +/// List of iFloor effects +WX_DECLARE_USER_EXPORTED_LIST(SerializableBase, SerializableBaseList, IFLOOR_API_COMMONPLUGINBASE); +WX_DECLARE_STRING_HASH_MAP(SerializableBase *, SerializableBaseDictionary); + +#endif // _SERIALIZABLEBASE_H \ No newline at end of file diff --git a/CommonPluginBase/Win/CommonPluginBase.vcxproj b/CommonPluginBase/Win/CommonPluginBase.vcxproj new file mode 100644 index 0000000..5465b0d --- /dev/null +++ b/CommonPluginBase/Win/CommonPluginBase.vcxproj @@ -0,0 +1,260 @@ + + + + x64 + + + + Debug + x64 + + + Release + x64 + + + + {751A15C0-76C2-3506-AB9D-0CD3545003FA} + Win32Proj + 10.0.26100.0 + x64 + CommonPluginBase + NoUpgrade + + + + DynamicLibrary + Unicode + v143 + + + DynamicLibrary + Unicode + v143 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + CommonPluginBase.dir\Debug\ + CommonPluginBase + .dll + true + true + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + CommonPluginBase.dir\Release\ + CommonPluginBase + .dll + false + true + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + $(IntDir) + EnableFastChecks + + + ProgramDatabase + 4996 + Sync + + + Disabled + stdcpp17 + + true + Disabled + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CMakeFiles/CommonPluginBase.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CommonPluginBase.dir/Debug//cmake_pch.pch + + MultiThreadedDebugDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;IFLOOR_EXPORTS_COMMONPLUGINBASE;CMAKE_INTDIR="Debug";CommonPluginBase_EXPORTS + $(IntDir) + false + + + %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;IFLOOR_EXPORTS_COMMONPLUGINBASE;CMAKE_INTDIR=\"Debug\";CommonPluginBase_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxXS.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxJSON.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + true + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Debug/CommonPluginBase.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/CommonPluginBase.pdb + + Console + + + false + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + $(IntDir) + Default + + + 4996 + Sync + + + AnySuitable + stdcpp17 + + true + MaxSpeed + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CMakeFiles/CommonPluginBase.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CommonPluginBase.dir/Release//cmake_pch.pch + + MultiThreadedDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;IFLOOR_EXPORTS_COMMONPLUGINBASE;CMAKE_INTDIR="Release";CommonPluginBase_EXPORTS + $(IntDir) + + + false + + + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;IFLOOR_EXPORTS_COMMONPLUGINBASE;CMAKE_INTDIR=\"Release\";CommonPluginBase_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxXS.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxJSON.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + false + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Release/CommonPluginBase.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/CommonPluginBase.pdb + + Console + + + false + + + + + Always + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\CommonPluginBase\Win\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\CommonPluginBase\Win\CMakeFiles\generate.stamp + false + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CMakeFiles/CommonPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CMakeFiles/CommonPluginBase.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CommonPluginBase.dir/Debug//cmake_pch.pch + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CMakeFiles/CommonPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CMakeFiles/CommonPluginBase.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CommonPluginBase.dir/Release//cmake_pch.pch + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CMakeFiles/CommonPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CMakeFiles/CommonPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CMakeFiles/CommonPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CMakeFiles/CommonPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CMakeFiles/CommonPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/CommonPluginBase/Win/CMakeFiles/CommonPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + ZERO_CHECK + false + Never + + + {7887B55C-77B9-3262-AFAD-ABA738C61029} + wxJSON + + + {78CFCEBE-5466-3128-9717-547416DBFFE5} + wxXS + + + + + + \ No newline at end of file diff --git a/CommonPluginBase/Win/CommonPluginBase.vcxproj.filters b/CommonPluginBase/Win/CommonPluginBase.vcxproj.filters new file mode 100644 index 0000000..3b81716 --- /dev/null +++ b/CommonPluginBase/Win/CommonPluginBase.vcxproj.filters @@ -0,0 +1,51 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Precompile Header File + + + Precompile Header File + + + + + + + + {4951AEE1-75F2-3C38-B593-C6BC8C809FB0} + + + {112D4227-BB51-3360-BB5B-5EA5DBA5A65F} + + + {05450AB2-CB7B-34EA-83DF-1EE86424EDF0} + + + diff --git a/MotionDetectorCore/AmplifyFilter.cpp b/MotionDetectorCore/AmplifyFilter.cpp new file mode 100644 index 0000000..bcefbb3 --- /dev/null +++ b/MotionDetectorCore/AmplifyFilter.cpp @@ -0,0 +1,55 @@ +//#include "stdwx.h" +#include "AmplifyFilter.h" + +IMPLEMENT_DYNAMIC_CLASS(AmplifyFilter, Filter); + +AmplifyFilter::AmplifyFilter() +{ + level = 0; + XS_SERIALIZE(level, wxT("AmplifyLevel")); +} + +AmplifyFilter::~AmplifyFilter() +{ +} + +wxString AmplifyFilter::GetName() const +{ + return _("Amplify"); +} + +#if defined(HAVE_CUDA) +bool AmplifyFilter::KernelGPU() +{ + if (m_src->empty()) + return false; + + double scalef = static_cast(level) / 128.0; + cv::cuda::multiply(*m_src, *m_src, m_dst, scalef); + return true; +} +#endif + +bool AmplifyFilter::Kernel() +{ + // derived class responsible for allocating storage for filtered image + if (source.empty()) + return false; + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), source.type()); + } + + float scalef = level / 128.0f; + + cv::multiply(source, source, destination, scalef); + return true; +} + +void AmplifyFilter::CreateParamInputs() +{ + AddParameterSpinInput(_("Amplify level:"), &level, 300); +} + +wxFORCE_LINK_THIS_MODULE(AmplifyFilter); \ No newline at end of file diff --git a/MotionDetectorCore/AmplifyFilter.h b/MotionDetectorCore/AmplifyFilter.h new file mode 100644 index 0000000..7876420 --- /dev/null +++ b/MotionDetectorCore/AmplifyFilter.h @@ -0,0 +1,28 @@ +#ifndef __TOUCHLIB_FILTER_AMPLIFY__ +#define __TOUCHLIB_FILTER_AMPLIFY__ + +#include "FilterTemplate.h" +#include + +class MOTION_DETECTOR_CORE_API AmplifyFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(AmplifyFilter) +public: + AmplifyFilter(); + virtual ~AmplifyFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(); + cv::cuda::GpuMat m_floatGpuMat; +#endif + virtual wxString GetName() const; + + int level; + +protected: + virtual void CreateParamInputs(); + +}; + +#endif // __TOUCHLIB_FILTER_AMPLIFY__ diff --git a/MotionDetectorCore/BackgroundFilter.cpp b/MotionDetectorCore/BackgroundFilter.cpp new file mode 100644 index 0000000..eb79f42 --- /dev/null +++ b/MotionDetectorCore/BackgroundFilter.cpp @@ -0,0 +1,202 @@ +#include "stdwx.h" +#include "BackgroundFilter.h" +#include "vector2d.h" +//#include "Image.h" + +IMPLEMENT_DYNAMIC_CLASS(BackgroundFilter, Filter); + +#define ROWSTOSCAN 40 + +#define UPDATERATE_UP 2 +#define UPDATERATE_DOWN 1 + +#define DEFAULT_UPDATE_THRESH 50 + +BackgroundFilter::BackgroundFilter() +{ + nPolyMask = 1; + recapture = false; + count = -1; + //recapture = true; + //count = 10; + updateThreshold = DEFAULT_UPDATE_THRESH; + currentRow = 0; + XS_SERIALIZE(updateThreshold, wxT("Threshold")) +// pMap["threshold"] = iFloorImageRecognitionParam(INT_PARAM, &updateThreshold, 0, 255); +} + +BackgroundFilter::~BackgroundFilter() +{ + +} + +wxString BackgroundFilter::GetName() const +{ + return _("Background"); +} + +//void BackgroundFilter::setParameter(const char *name, const char *value) +//{ +// if(strcmp(name, "capture") == 0) +// { +// printf("Recap\n"); +// recapture = true; +// } else if(strcmp(name, "threshold") == 0) +// { +// updateThreshold = (int) atof(value); +// } else if(strcmp(name, "mask") == 0) +// { +// if(value) +// setMask((touchlib::vector2df*)value,GRID_X+1,GRID_Y+1); +// else +// clearMask(); +// } +//} + +//void BackgroundFilter::getParameters(iFloorParamMap& pMap) +//{ +// pMap[std::string("threshold")] = toString(updateThreshold); +//} + + +//#define ADAPTIVE_BACKGROUND + +bool BackgroundFilter::Kernel() +{ + // derived class responsible for allocating storage for filtered image + + if (source.empty()) + return false; + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), CV_8UC1); + } + + if (count > -1) + count--; + + if (reference.empty() || recapture || count == 0) + { + source.copyTo(reference); + + if (mask.empty()) { + mask = cv::Mat::zeros(reference.size(), reference.type()); + } + + // ßêùî ìàñêà çàäàíà, ìàëþºìî ¿¿ ñó÷àñíèì ìåòîäîì cv::fillConvexPoly + if (!polyMask.empty() && updateThreshold == 0) { + mask.setTo(cv::Scalar(255, 255, 255)); + cv::fillConvexPoly(mask, polyMask, cv::Scalar(0, 0, 0)); + } + + // Ñó÷àñíå â³äí³ìàííÿ ñêàëÿðà (çàì³ñòü cvSubS) + if (updateThreshold != 0) + { + reference -= cv::Scalar(updateThreshold, updateThreshold, updateThreshold); + } + + recapture = false; + + //count = updateThreshold; + recapture = false; + } + +#ifdef ADAPTIVE_BACKGROUND + BwImage imgSrc(source), imgRef(reference); + + int x, y; + int h, w; + h = source->height; + w = source->width; + + int stoprow = currentRow + ROWSTOSCAN; + + if (stoprow > h) + stoprow = h; + + // only do N number of rows per frame to speed up processing.. + for(y=currentRow; y ref) + { + ref += UPDATERATE_UP; + if (ref > pix) + ref = pix; + + imgRef[y][x] = ref; // update background + } + + // In most cases we won't really need to go 'down'.. + // as the screen gets dirtier, it gets brighter.. + // + //if (pix < ref) + //ref -= UPDATERATE_DOWN; + + } + + } + } + currentRow += ROWSTOSCAN; + + if (currentRow >= h) + currentRow = 0; +#endif + // destination = source-reference + cv::subtract(source, reference, destination); + return true; +} + +void BackgroundFilter::setMask(void* vaPoints, int xGrid, int yGrid) +{ + touchlib::vector2df* aPoints = (touchlib::vector2df*)vaPoints; + + // Ïåðåâèä³ëÿºìî ðîçì³ð íàøîãî âåêòîðà òî÷îê C++ + int totalPoints = 2 * (xGrid + yGrid - 2); + polyMask.resize(totalPoints); + + int countPoints = 0; + // top side + for (int i = 0; i < xGrid; i++) { + polyMask[countPoints++] = cv::Point(static_cast(aPoints[i].X), static_cast(aPoints[i].Y)); + } + // right side + for (int i = 2; i < yGrid; i++) { + polyMask[countPoints++] = cv::Point(static_cast(aPoints[i * xGrid - 1].X), static_cast(aPoints[i * xGrid - 1].Y)); + } + // bottom side + for (int i = xGrid - 1; i >= 0; i--) { + polyMask[countPoints++] = cv::Point(static_cast(aPoints[i + (yGrid - 1) * xGrid].X), static_cast(aPoints[i + (yGrid - 1) * xGrid].Y)); + } + // left side + for (int i = yGrid - 2; i > 0; i--) { + polyMask[countPoints++] = cv::Point(static_cast(aPoints[i * xGrid].X), static_cast(aPoints[i * xGrid].Y)); + } + + recapture = true; +}// deletes an old mask and tells Kernel func to recapture +void BackgroundFilter::clearMask() +{ + polyMask.clear(); + if (!mask.empty()) + { + mask.setTo(cv::Scalar(0, 0, 0)); + } + recapture = true; + +} + +void BackgroundFilter::CreateParamInputs() +{ + AddParameterSpinInput(_("Update threshold"), &updateThreshold); + AddParameterBoolInput(_("Recapture"), &recapture); +} + +wxFORCE_LINK_THIS_MODULE(BackgroundFilter); \ No newline at end of file diff --git a/MotionDetectorCore/BackgroundFilter.h b/MotionDetectorCore/BackgroundFilter.h new file mode 100644 index 0000000..837c23a --- /dev/null +++ b/MotionDetectorCore/BackgroundFilter.h @@ -0,0 +1,37 @@ +#ifndef __TOUCHLIB_FILTER_BACKGROUND__ +#define __TOUCHLIB_FILTER_BACKGROUND__ + +#include "FilterTemplate.h" +#include +#include + +class MOTION_DETECTOR_CORE_API BackgroundFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(BackgroundFilter) +public: + BackgroundFilter(); + virtual ~BackgroundFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(){return false;} +#endif + virtual wxString GetName() const; + + void setMask(void *aPoints,int xRes, int yRes); + void clearMask(); +protected: + virtual void CreateParamInputs(); +private: + bool recapture; + cv::Mat reference; + bool ownsImage; + int updateThreshold; // anything above this threshold is considered a 'press' and not part of the background + int count; + int currentRow; + cv::Mat mask; + std::vector polyMask; + int nPolyMask; +}; + +#endif // __TOUCHLIB_FILTER_BACKGROUND__ diff --git a/MotionDetectorCore/BarrelDistortionCorrectionFilter.cpp b/MotionDetectorCore/BarrelDistortionCorrectionFilter.cpp new file mode 100644 index 0000000..9396978 --- /dev/null +++ b/MotionDetectorCore/BarrelDistortionCorrectionFilter.cpp @@ -0,0 +1,163 @@ +// Filter description +// Name: Barrel Distortion Correction Filter +// Purpose: Correcting the barrel distortion of the lens +// Original author: Laurence Muller (aka Falcon4ever) + +/* +Tool url: +http://www.multigesture.net/wp-content/uploads/2007/12/touchlib_barreldistortion_tool.zip + +example of usage: + + + + +Place the camera.yml (created by the calibration tool) in the same directory as the config.xml +*/ +#include "stdwx.h" +#include "BarrelDistortionCorrectionFilter.h" + +IMPLEMENT_DYNAMIC_CLASS(BarrelDistortionCorrectionFilter, Filter); + +BarrelDistortionCorrectionFilter::BarrelDistortionCorrectionFilter() +{ + const char* configfile = "camera.yml"; + + cv::FileStorage fs(configfile, cv::FileStorage::READ); + if (fs.isOpened()) + { + fs["camera_matrix"] >> camera; + fs["distortion_coefficients"] >> dist_coeffs; + fs.release(); + } + else + { + camera = cv::Mat::eye(3, 3, CV_64FC1); + dist_coeffs = cv::Mat::zeros(5, 1, CV_64FC1); + } + + border_size = 0; + init = false; + init2 = false; + + MapX = NULL; + MapY = NULL; +} + +BarrelDistortionCorrectionFilter::~BarrelDistortionCorrectionFilter() +{ + +} + +wxString BarrelDistortionCorrectionFilter::GetName() const +{ + return _("Barrel Distortion Correction"); +} + +//void BarrelDistortionCorrectionFilter::getParameters(iFloorParamMap& pMap) +//{ +// pMap[std::string("border_size")] = toString(border_size); +//} +// +//void BarrelDistortionCorrectionFilter::setParameter(const char *name, const char *value) +//{ +// if(strcmp(name, "border_size") == 0) +// { +// border_size = (int) atof(value); +// } +//} + +bool BarrelDistortionCorrectionFilter::Kernel() +{ + if (border_size > 0) + { + cv::Mat tempResult = undistorted_with_border2(source, camera, dist_coeffs, border_size); + + if (!tempResult.empty()) + { + cv::Rect roi(border_size, border_size, source.cols, source.rows); + tempResult(roi).copyTo(destination); + } + } + else + { + cv::Mat tempResult = undistorted_with_border2(source, camera, dist_coeffs, 0); + if (!tempResult.empty()) + { + tempResult.copyTo(destination); + } + } + + return true; +} + +cv::Mat BarrelDistortionCorrectionFilter::undistorted_with_border( const cv::Mat& image, const cv::Mat& intrinsic, const cv::Mat& distortion, short int border) +{ + if (!init) + { + if (intrinsic.empty() || distortion.empty()) + return cv::Mat(); + + intrinsic.copyTo(b_intrinsic); + + if (b_intrinsic.type() == CV_64FC1) { + b_intrinsic.at(0, 2) += border; + b_intrinsic.at(1, 2) += border; + } + else { + b_intrinsic.at(0, 2) += static_cast(border); + b_intrinsic.at(1, 2) += static_cast(border); + } + + init = true; + } + + if (b_intrinsic.empty()) + return cv::Mat(); + + cv::copyMakeBorder(image, bordered, border, border, border, border, cv::BORDER_CONSTANT, cv::Scalar::all(0)); + + cv::undistort(bordered, bordered_corr, b_intrinsic, distortion); + + return bordered_corr; +} + +cv::Mat BarrelDistortionCorrectionFilter::undistorted_with_border2(const cv::Mat& image, const cv::Mat& intrinsic, const cv::Mat& distortion, short int border) +{ + if (!init2) + { + if (intrinsic.empty() || distortion.empty()) + return cv::Mat(); + + intrinsic.copyTo(b_intrinsic); + + if (b_intrinsic.type() == CV_64FC1) { + b_intrinsic.at(0, 2) += border; + b_intrinsic.at(1, 2) += border; + } + else { + b_intrinsic.at(0, 2) += static_cast(border); + b_intrinsic.at(1, 2) += static_cast(border); + } + + cv::Size borderedSize(image.cols + 2 * border, image.rows + 2 * border); + + cv::initUndistortRectifyMap( + b_intrinsic, distortion, cv::Mat(), b_intrinsic, + borderedSize, CV_32FC1, MapX, MapY + ); + + init2 = true; + } + + if (MapX.empty() || MapY.empty()) + return cv::Mat(); + + cv::copyMakeBorder(image, bordered, border, border, border, border, cv::BORDER_CONSTANT, cv::Scalar::all(0)); + + cv::remap(bordered, bordered_corr, MapX, MapY, cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar::all(0)); + + return bordered_corr; +} + +wxFORCE_LINK_THIS_MODULE(BarrelDistortionCorrectionFilter); \ No newline at end of file diff --git a/MotionDetectorCore/BarrelDistortionCorrectionFilter.h b/MotionDetectorCore/BarrelDistortionCorrectionFilter.h new file mode 100644 index 0000000..e0f0c5c --- /dev/null +++ b/MotionDetectorCore/BarrelDistortionCorrectionFilter.h @@ -0,0 +1,44 @@ +// Filter description +// Name: Barrel Distortion Correction Filter +// Purpose: Correcting the barrel distortion of the lens +// Original author: Laurence Muller (aka Falcon4ever) + +#ifndef __TOUCHSCREEN_FILTER_BARRELDISTORTIONCORRECTION__ +#define __TOUCHSCREEN_FILTER_BARRELDISTORTIONCORRECTION__ + +#include "FilterTemplate.h" +#include + +class MOTION_DETECTOR_CORE_API BarrelDistortionCorrectionFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(BarrelDistortionCorrectionFilter) +public: + BarrelDistortionCorrectionFilter(); + virtual ~BarrelDistortionCorrectionFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(){return false;} +#endif + virtual wxString GetName() const; + +private: + cv::Mat undistorted_with_border( const cv::Mat& image, const cv::Mat& intrinsic, const cv::Mat& distortion, short int border ); + cv::Mat undistorted_with_border2( const cv::Mat& image, const cv::Mat& intrinsic, const cv::Mat& distortion, short int border ); + cv::Mat camera; + cv::Mat dist_coeffs; + short int border_size; + + cv::Mat b_intrinsic; + cv::Mat bordered; + cv::Mat bordered_corr; + + bool init; + + // Method 2 + bool init2; + cv::Mat MapX; + cv::Mat MapY; +}; + +#endif // __TOUCHSCREEN_FILTER_BARRELDISTORTIONCORRECTION__ diff --git a/MotionDetectorCore/BrightnessContrastFilter.cpp b/MotionDetectorCore/BrightnessContrastFilter.cpp new file mode 100644 index 0000000..c06a4d0 --- /dev/null +++ b/MotionDetectorCore/BrightnessContrastFilter.cpp @@ -0,0 +1,141 @@ +#include "stdwx.h" +#include "BrightnessContrastFilter.h" + +IMPLEMENT_DYNAMIC_CLASS(BrightnessContrastFilter, Filter); + +BrightnessContrastFilter::BrightnessContrastFilter() +{ + brightness = (float) DEFAULT_BRIGHTNESS; + contrast = (float) DEFAULT_CONTRAST; + + // mapping from input to output values via lookup table, recalculated when brightness or contrast changed + lutMat = cv::Mat(1, 256, CV_8UC1); + + brightness_slider = 128; + contrast_slider = 128; + + updateLUT(); + + XS_SERIALIZE(brightness_slider, wxT("Brightness")); + XS_SERIALIZE(contrast_slider, wxT("Contrast")); +} + + +BrightnessContrastFilter::~BrightnessContrastFilter() +{ + +} + +wxString BrightnessContrastFilter::GetName() const +{ + return _("Brightness/Contrast"); +} + +void BrightnessContrastFilter::setBrightness(float value) +{ + brightness = value; + brightness_slider = static_cast((value * 128.0f) + 128.0f); + updateLUT(); +} + + +void BrightnessContrastFilter::setContrast(float value) +{ + contrast = value; + contrast_slider = static_cast((value * 128.0f) + 128.0f); + updateLUT(); +} + + +//void BrightnessContrastFilter::getParameters(iFloorParamMap& pMap) +//{ +// pMap[std::string("brightness")] = toString(brightness); +// pMap[std::string("contrast")] = toString(contrast); +//} +// +// +//void BrightnessContrastFilter::setParameter(const char *name, const char *value) +//{ +// if(strcmp(name, "brightness") == 0) +// { +// setBrightness(atof(value)); +// } else if(strcmp(name, "contrast") == 0) +// { +// setContrast(atof(value)); +// } +// +//} + + +void BrightnessContrastFilter::updateLUT( void ) +{ + + float tmp_brightness = 2.0f * ((static_cast(brightness_slider) / 255.0f)); + float tmp_contrast = 2.0f * ((static_cast(contrast_slider) / 255.0f)); + + if (brightness != tmp_brightness || contrast != tmp_contrast) + { + brightness = tmp_brightness; + contrast = tmp_contrast; + + if (contrast > 0) + { + float delta = 127.0f * contrast; + float a = 255.0f / (255.0f - delta * 2.0f); + float b = a * (brightness * 100.0f - delta); + for (int i = 0; i < 256; i++) + { + int v = cvRound(a * i + b); + if (v < 0) v = 0; + if (v > 255) v = 255; + lutMat.at(i) = static_cast(v); + } + } + else + { + float delta = -128.0f * contrast; + float a = (256.0f - delta * 2.0f) / 255.0f; + float b = a * brightness * 100.0f + delta; + for (int i = 0; i < 256; i++) + { + int v = cvRound(a * i + b); + if (v < 0) v = 0; + if (v > 255) v = 255; + lutMat.at(i) = static_cast(v); + } + } + } + +} +#if defined(HAVE_CUDA) +bool BrightnessContrastFilter::KernelGPU() +{ + updateLUT(); + cv::cuda::lookUpTable(*m_src, lutMat, m_dst); + return true; +} +#endif + +bool BrightnessContrastFilter::Kernel() +{ + + if (source.empty()) + return false; + + updateLUT(); + // derived class responsible for allocating storage for filtered image + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), source.type()); + } + cv::LUT(source, lutMat, destination); + return true; +} + +void BrightnessContrastFilter::CreateParamInputs() +{ + AddParameterSpinInput(_("Brightness:"), &brightness_slider, 127, -127); + AddParameterSpinInput(_("Contrast:"), &contrast_slider, 127, -127); +} + +wxFORCE_LINK_THIS_MODULE(BrightnessContrastFilter); \ No newline at end of file diff --git a/MotionDetectorCore/BrightnessContrastFilter.h b/MotionDetectorCore/BrightnessContrastFilter.h new file mode 100644 index 0000000..321fa21 --- /dev/null +++ b/MotionDetectorCore/BrightnessContrastFilter.h @@ -0,0 +1,43 @@ +#ifndef __TOUCHLIB_FILTER_BRIGHTNESSCONTRAST__ +#define __TOUCHLIB_FILTER_BRIGHTNESSCONTRAST__ + +#include "FilterTemplate.h" +#include + +#define DEFAULT_BRIGHTNESS 0.0 +#define DEFAULT_CONTRAST 0.2 + +class MOTION_DETECTOR_CORE_API BrightnessContrastFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(BrightnessContrastFilter) +public: + BrightnessContrastFilter(); + virtual ~BrightnessContrastFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(); +#endif + virtual wxString GetName() const; + + void setBrightness(float value); + void setContrast(float value); + float getContrast(void) {return contrast;} + float getBrightness(void) {return brightness;} + +protected: + void CreateParamInputs(); +private: + void updateLUT( void ); + + uchar lut[256*4]; + + int brightness_slider; + int contrast_slider; + + float brightness; + float contrast; + cv::Mat lutMat; +}; + +#endif // __TOUCHLIB_FILTER_BRIGHTNESSCONTRAST__ diff --git a/MotionDetectorCore/CMakeLists.txt b/MotionDetectorCore/CMakeLists.txt new file mode 100644 index 0000000..040d6e2 --- /dev/null +++ b/MotionDetectorCore/CMakeLists.txt @@ -0,0 +1,149 @@ +# +# Stuff the average programmer needs to change +# +set(SRCS + FilterPreviewWindow.cpp + AmplifyFilter.cpp + BackgroundFilter.cpp + BarrelDistortionCorrectionFilter.cpp + BrightnessContrastFilter.cpp + ContourFinder.cpp + CropFilter.cpp + DummyFilter.cpp + DynamicBGFilter.cpp + EqualizeHistFilter.cpp + FilterFactory.cpp + FilterTemplate.cpp + FlipFilter.cpp + HighpassFilter.cpp + IFloorImagePreprocessor.cpp + IFloorImagePreprocessorSettings.cpp + InvertFilter.cpp + MonoFilter.cpp + PerspectiveFilter.cpp + RectifyFilter.cpp + ResizeFilter.cpp + ScalerFilter.cpp + ShapeFilter.cpp + SimpleBGFilter.cpp + SubOrBGFilter.cpp + XorBGFilter.cpp + SimpleHighpassFilter.cpp + SmoothingFilter.cpp + ThresholdFilter.cpp + KinectMonoFilter.cpp + KinectDepthBGFilter.cpp + KinectBGFilter.cpp + KinectThresholdFilter.cpp + Tracking.cpp + DisplayGeometryWindow.cpp + LinuxUtils.cpp +) + +set(HFILES + MotionDetectorCorePlugin.h + FilterPreviewWindow.h + wxBitmapEvent.h + AmplifyFilter.h + BackgroundFilter.h + BarrelDistortionCorrectionFilter.h + BrightnessContrastFilter.h + ContourFinder.h + CropFilter.h + DummyFilter.h + DynamicBGFilter.h + EqualizeHistFilter.h + FilterFactory.h + FilterTemplate.h + FlipFilter.h + HighpassFilter.h + IFloorImagePreprocessor.h + IFloorImagePreprocessorSettings.h + Image.h + InvertFilter.h + MonoFilter.h + PerspectiveFilter.h + RectifyFilter.h + ResizeFilter.h + ScalerFilter.h + ShapeFilter.h + SimpleBGFilter.h + SubOrBGFilter.h + XorBGFilter.h + SimpleHighpassFilter.h + SmoothingFilter.h + ThresholdFilter.h + KinectMonoFilter.h + KinectDepthBGFilter.h + KinectBGFilter.h + KinectThresholdFilter.h + Tracking.h + vector2d.h + DisplayGeometryWindow.h + LinuxUtils.h +) + +source_group("Filters\\Headers" ".*Filter\\.h") +source_group("Filters\\Sources" ".*Filter\\.cpp") + +set(INCLUDE_DIRECTORIES ${BASE_INCLUDE_DIRECTORIES} + ${PROJECT_ROOT_DIR}/MotionDetectorPluginBase + ${PROJECT_ROOT_DIR}/CommonPluginBase + ${THIRD_PARTY_DIR}/wxXS/include + ${OpenCV_INCLUDE_DIRS} + ${THIRD_PARTY_DIR}/MotionPrimitives +) + +set(LIBRARY_NAME MotionDetectorCore) + +if(CUDA_FOUND) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/DHAVE_CUDA) +endif(CUDA_FOUND) + +if(WIN32) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D_USRDLL;/DMOTION_DETECTOR_CORE_EXPORTS) +endif(WIN32) + + +set(SRCS ${SRCS} ${HFILES} ${PROJECT_ROOT_DIR}/include/stdwx.h ${PROJECT_ROOT_DIR}/include/stdwx.cpp) + +add_definitions(${PREPROCESSOR_DEFINITIONS}) +include_directories(${INCLUDE_DIRECTORIES}) + + +add_library(${LIBRARY_NAME} SHARED ${SRCS}) + + +target_link_libraries(${LIBRARY_NAME} + ${wxWidgets_LIBRARIES} + CommonPluginBase + Utils + MotionDetectorPluginBase + MotionPrimitives + ${OpenCV_LIBS} +) + +add_dependencies(${LIBRARY_NAME} + MotionDetectorPluginBase + CommonPluginBase +) + +target_precompile_headers(${LIBRARY_NAME} + PRIVATE + "${PROJECT_ROOT_DIR}/include/stdwx.h" +) + +if(LINUX) + add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/${OS_BASE_NAME}${LIB_SUFFIX}/lib${LIBRARY_NAME}.so" "${PROJECT_SOURCE_DIR}/${DLL_DIR}${LIB_SUFFIX}/lib${LIBRARY_NAME}.so" + ) +endif(LINUX) + +set(PLUGIN_TARGET_DIR "${OUTPUT_BIN_DIR}/plugins/motion_detector") + +add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "${PLUGIN_TARGET_DIR}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "$" + "${PLUGIN_TARGET_DIR}/$" +) \ No newline at end of file diff --git a/MotionDetectorCore/ContourFinder.cpp b/MotionDetectorCore/ContourFinder.cpp new file mode 100644 index 0000000..6b7f876 --- /dev/null +++ b/MotionDetectorCore/ContourFinder.cpp @@ -0,0 +1,180 @@ +#include "stdwx.h" +#include "ContourFinder.h" +#include + +static int qsort_carea_compare(void const * _a, void const * _b) +{ + // pointers, ugh.... sorry about this + auto a = reinterpret_cast(_a); + auto b = reinterpret_cast(_b); + // use opencv to calc size, then sort based on size + float areaa = a->Area; + float areab = b->Area; + // note, based on the -1 / 1 flip + // we sort biggest to smallest, not smallest to biggest + auto out = areaa > areab ? -1 : 1; + return out; +} + +ContourFinder::ContourFinder() +{ + reset(); +} + +ContourFinder::~ContourFinder() +{ +} + +void ContourFinder::reset() +{ + blobs.clear(); +} + +void ContourFinder::FillBlob(SeqArea& seqBlob, iFloorBlob& blob) +{ + if (seqBlob.Seq.empty()) return; + + cv::Point oldPt(0, 0); + size_t totalPoints = seqBlob.Seq.size(); + + for (size_t j = 0; j < totalPoints; ++j) + { + cv::Point pt = seqBlob.Seq[j]; + + switch (j) + { + case 0: + blob.pts.push_back(iFloorPoint(pt.x, pt.y)); + break; + default: + + if ((abs(oldPt.x - pt.x) + abs(oldPt.y - pt.y)) > 5 || (j == totalPoints - 1)) + { + blob.pts.push_back(iFloorPoint(pt.x, pt.y)); + } + break; + } + oldPt = pt; + } +} + +int ContourFinder::findContours(/*ofxCvGrayscaleImage& input,*/ + cv::Mat img, + int minArea, + int maxArea, + size_t nConsidered, + bool bFindHoles, + bool bUseApproximation) +{ + reset(); + + // opencv will clober the image it detects contours on, so we want to + // copy it into a copy before we detect contours. That copy is allocated + // if necessary (necessary = (a) not allocated or (b) wrong size) + // so be careful if you pass in different sized images to "findContours" + // there is a performance penalty, but we think there is not a memory leak + // to worry about better to create mutiple contour finders for different + // sizes, ie, if you are finding contours in a 640x480 image but also a + // 320x240 image better to make two ContourFinder objects then to use + // one, because you will get penalized less. + + //if( inputCopy.width == 0 ) { + // inputCopy.allocate( input.width, input.height ); + // inputCopy = input; + //} else { + // if( inputCopy.width == input.width && inputCopy.height == input.height ) { + // inputCopy = input; + // } else { + // // we are allocated, but to the wrong size -- + // // been checked for memory leaks, but a warning: + // // be careful if you call this function with alot of different + // // sized "input" images!, it does allocation every time + // // a new size is passed in.... + // //inputCopy.clear(); + // inputCopy.allocate( input.width, input.height ); + // inputCopy = input; + // } + //} + + if (img.empty()) return 0; + + cv::Mat grayImg; + if (img.channels() == 3) { + cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY); + } + else { + grayImg = img.clone(); + } + + + std::vector> all_contours; + + int retrieve_mode = bFindHoles ? cv::RETR_LIST : cv::RETR_EXTERNAL; + int approx_mode = bUseApproximation ? cv::CHAIN_APPROX_SIMPLE : cv::CHAIN_APPROX_NONE; + + cv::findContours(grayImg, all_contours, retrieve_mode, approx_mode); + + cvSeqBlobs.clear(); + cvSeqBlobs.reserve(all_contours.size()); + + for (const auto& contour : all_contours) + { + std::vector approx_contour; + cv::approxPolyDP(contour, approx_contour, 3.0, true); + + double area = std::fabs(cv::contourArea(approx_contour)); + if ((area >= minArea) && (area < maxArea)) + { + cvSeqBlobs.push_back(SeqArea(approx_contour, area)); + } + } + + std::sort(cvSeqBlobs.begin(), cvSeqBlobs.end(), [](const SeqArea& a, const SeqArea& b) { + return a.Area > b.Area; + }); + + size_t nCvSeqsFound = cvSeqBlobs.size(); + nCvSeqsFound = std::min(nConsidered, nCvSeqsFound); + + blobs.resize(nCvSeqsFound); + + for (size_t i = 0; i < nCvSeqsFound; ++i) + { + SeqArea& seqBlob = cvSeqBlobs[i]; + iFloorBlob& blob = blobs[i]; + + cv::Moments myMoments = cv::moments(seqBlob.Seq); + + cv::Rect rect = cv::boundingRect(seqBlob.Seq); + blob.boundingRect.x = rect.x; + blob.boundingRect.y = rect.y; + blob.boundingRect.width = rect.width; + blob.boundingRect.height = rect.height; + + cv::RotatedRect box = cv::minAreaRect(seqBlob.Seq); + + blob.angleBoundingRect.x = box.center.x; + blob.angleBoundingRect.y = box.center.y; + blob.angleBoundingRect.width = box.size.height; + blob.angleBoundingRect.height = box.size.width; + blob.angle = box.angle; + + blob.area = seqBlob.Area; + + if (myMoments.m00 != 0) { + blob.centroid.x = (myMoments.m10 / myMoments.m00); + blob.centroid.y = (myMoments.m01 / myMoments.m00); + } + else { + blob.centroid.x = 0; + blob.centroid.y = 0; + } + + blob.lastCentroid.x = 0; + blob.lastCentroid.y = 0; + + FillBlob(seqBlob, blob); + } + + return static_cast(blobs.size()); +} \ No newline at end of file diff --git a/MotionDetectorCore/ContourFinder.h b/MotionDetectorCore/ContourFinder.h new file mode 100644 index 0000000..d4f68c4 --- /dev/null +++ b/MotionDetectorCore/ContourFinder.h @@ -0,0 +1,69 @@ +#ifndef IFLOORCONTOUR_FINDER_H +#define IFLOORCONTOUR_FINDER_H + +#if defined(__WXMSW__) +#include +#include +#include "iFloorBlob.h" +#include "MotionDetectorCorePlugin.h" + +struct SeqArea +{ + SeqArea() + : Area(0) {} + SeqArea(const std::vector& seq, double area) + : Seq(seq) + , Area(area) + { + + } + SeqArea(const SeqArea & seqArea) + : Seq(seqArea.Seq) + , Area(seqArea.Area) + { + + } + SeqArea & operator=(const SeqArea & seqArea) + { + if (this != &seqArea) + { + Seq = seqArea.Seq; + Area = seqArea.Area; + } + return *this; + } + std::vector Seq; + double Area; +}; + +class MOTION_DETECTOR_CORE_API ContourFinder +{ +public: + ContourFinder(); + ~ContourFinder(); + + int findContours( /*ofxCvGrayscaleImage& input,*/ + cv::Mat img, + int minArea, int maxArea, + size_t nConsidered, bool bFindHoles, + bool bUseApproximation = true); + // approximation = don't do points for all points of the contour, if the contour runs + // along a straight line, for example... + + iFloorBlobVector blobs; // the blobs, in a std::vector... +protected: + + // this is stuff, not for general public to touch -- we need + // this to do the blob detection, etc. + //ofxCvGrayscaleImage inputCopy; + + // internally, we find cvSeqs, they will become blobs. + std::vector cvSeqBlobs; + + // important!! + void reset(); + void FillBlob(SeqArea& seqBlob, iFloorBlob& blob); +}; + +#endif +#endif \ No newline at end of file diff --git a/MotionDetectorCore/CropFilter.cpp b/MotionDetectorCore/CropFilter.cpp new file mode 100644 index 0000000..dcaaba8 --- /dev/null +++ b/MotionDetectorCore/CropFilter.cpp @@ -0,0 +1,169 @@ +// Filter description +// Name: Crop Filter +// Purpose: Allows the user to crop the source image +// Original author: Laurence Muller (aka Falcon4ever) + +/* +example of usage: + + + + + + + +posX and posY specifies an offset from upperleft corner. +heigth and width specifies the crop size. +*/ +#include "stdwx.h" +#include "CropFilter.h" + +IMPLEMENT_DYNAMIC_CLASS(CropFilter, Filter); + +CropFilter::CropFilter() +{ + img_rect.x = 0; + img_rect.y = 0; + img_rect.height = DEFAULT_CROPHEIGHT; + img_rect.width = DEFAULT_CROPWIDTH; + + firsttime = true; + + XS_SERIALIZE(img_rect.x, wxT("x")); + XS_SERIALIZE(img_rect.y, wxT("y")); + XS_SERIALIZE(img_rect.width, wxT("width")); + XS_SERIALIZE(img_rect.height, wxT("height")); +} + +CropFilter::~CropFilter() +{ +} + +wxString CropFilter::GetName() const +{ + return _("Crop"); +} + +//void CropFilter::getParameters(iFloorParamMap& pMap) +//{ +// pMap[std::string("posX")] = toString(img_rect.x); +// pMap[std::string("posY")] = toString(img_rect.y); +// pMap[std::string("height")] = toString(img_rect.height); +// pMap[std::string("width")] = toString(img_rect.width); +//} +// +//void CropFilter::setParameter(const char *name, const char *value) +//{ +// if(strcmp(name, "posX") == 0) +// { +// img_rect.x = (int) atof(value); +// level_posX_slider = img_rect.x; +// +// if(show) +// cvSetTrackbarPos("posX", this->name.c_str(), level_posX_slider); +// } +// else if(strcmp(name, "posY") == 0) +// { +// img_rect.y = (int) atof(value); +// level_posY_slider = img_rect.x; +// +// if(show) +// cvSetTrackbarPos("posY", this->name.c_str(), level_posY_slider); +// } +// else if(strcmp(name, "width") == 0) +// { +// img_rect.width = (int) atof(value); +// level_width_slider = img_rect.width; +// +// //if(show) +// // cvSetTrackbarPos("width", this->name.c_str(), level_width_slider); +// +// if(destination) +// cvReleaseImage(&destination); +// +// destination = cvCreateImage(cvSize(img_rect.width,img_rect.height), 8, 1); +// } +// else if(strcmp(name, "height") == 0) +// { +// img_rect.height = (int) atof(value); +// level_height_slider = img_rect.height; +// +// //if(show) +// // cvSetTrackbarPos("height", this->name.c_str(), level_height_slider); +// +// if(destination) +// cvReleaseImage(&destination); +// +// destination = cvCreateImage(cvSize(img_rect.width,img_rect.height), 8, 1); +// } +//} + +bool CropFilter::Kernel() +{ + if (source.empty()) + return false; + + if (firsttime) + { + max_x = source.cols; + max_y = source.rows; + firsttime = false; + } + + //if (show) + { +/* + // Todo: Fix filter chain... + // Status: Currently disabled. + // + // Problem: + // When changing the width and height, a new destination image has to be created. + // The current destination image should be released first, the a new destination image should be + // created from the img_rect values. + // By dynamicly changing the destination size the next filter in the filterchain should adjust + // all its allocated images aswell (width and height). + // Currently this isnt done, which causes openCV to choke and crash. + // + // Current workaround: + // Set the width and height manual in the config.xml before starting the configapp or your application + + // Uncomment the following part if dynamic resizing is allowed: + if(img_rect.width != level_width_slider) + { + if(level_width_slider + img_rect.x < max_x) + img_rect.width = level_width_slider; + + if(destination) + cvReleaseImage(&destination); + } + + if(img_rect.height != level_height_slider) + { + if(level_height_slider + img_rect.y < max_y) + img_rect.height = level_height_slider; + + if(destination) + cvReleaseImage(&destination); + } +*/ + } + + if (img_rect.x < 0) img_rect.x = 0; + if (img_rect.y < 0) img_rect.y = 0; + if (img_rect.x >= source.cols) img_rect.x = source.cols - 1; + if (img_rect.y >= source.rows) img_rect.y = source.rows - 1; + + if (img_rect.x + img_rect.width > source.cols) + img_rect.width = source.cols - img_rect.x; + if (img_rect.y + img_rect.height > source.rows) + img_rect.height = source.rows - img_rect.y; + + if (img_rect.width <= 0 || img_rect.height <= 0) + return false; + + source(img_rect).copyTo(destination); + + return true; +} + +wxFORCE_LINK_THIS_MODULE(CropFilter); \ No newline at end of file diff --git a/MotionDetectorCore/CropFilter.h b/MotionDetectorCore/CropFilter.h new file mode 100644 index 0000000..98f71e1 --- /dev/null +++ b/MotionDetectorCore/CropFilter.h @@ -0,0 +1,35 @@ +// Filter description +// Name: Crop Filter +// Purpose: Allows the user to crop the source image +// Original author: Laurence Muller (aka Falcon4ever) + +#ifndef __TOUCHLIB_FILTER_CROP__ +#define __TOUCHLIB_FILTER_CROP__ + +#include "FilterTemplate.h" +#include + +#define DEFAULT_CROPWIDTH 640 +#define DEFAULT_CROPHEIGHT 480 + +class MOTION_DETECTOR_CORE_API CropFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(CropFilter) +public: + CropFilter(); + virtual ~CropFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(){return false;} +#endif + virtual wxString GetName() const; + +private: + bool firsttime; + int max_x; + int max_y; + cv::Rect img_rect; +}; + +#endif // __TOUCHLIB_FILTER_CROP__ diff --git a/MotionDetectorCore/DisplayGeometryWindow.cpp b/MotionDetectorCore/DisplayGeometryWindow.cpp new file mode 100644 index 0000000..dffed40 --- /dev/null +++ b/MotionDetectorCore/DisplayGeometryWindow.cpp @@ -0,0 +1,135 @@ +#include "stdwx.h" +#include "DisplayGeometryWindow.h" +#include + +#if defined(USE_VLD) +#include +#endif + +IMPLEMENT_DYNAMIC_CLASS(DisplayGeometryWindow, wxWindow) + +BEGIN_EVENT_TABLE(DisplayGeometryWindow, wxWindow) + EVT_SIZE(DisplayGeometryWindow::OnSize) + EVT_PAINT(DisplayGeometryWindow::OnPaint) + EVT_ERASE_BACKGROUND(DisplayGeometryWindow::OnEraseBackground) +END_EVENT_TABLE() + +DisplayGeometryWindow::DisplayGeometryWindow() + : m_GeometryProvider(GeometryProvider(nullptr, nullptr, nullptr)) +{ + Init(); +} + +DisplayGeometryWindow::DisplayGeometryWindow(wxWindow* parent, const GeometryProvider & geometryProvider, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) + : m_GeometryProvider(geometryProvider) +{ + Init(); + Create(parent, id, pos, size, style); +} + +bool DisplayGeometryWindow::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) +{ + wxWindow::Create(parent, id, pos, size, style); + return true; +} + +DisplayGeometryWindow::~DisplayGeometryWindow() +{ +} + +void DisplayGeometryWindow::Init() +{ + m_Scale = 1; + m_Border = 1; +} + +void DisplayGeometryWindow::OnEraseBackground(wxEraseEvent& event) +{ +} + +void DisplayGeometryWindow::OnPaint(wxPaintEvent& event) +{ + wxBufferedPaintDC dc(this); + dc.SetBackground(wxBrush(GetBackgroundColour())); + dc.Clear(); + + if (m_Bitmap.IsOk()) + dc.DrawBitmap(m_Bitmap, m_DrawRect.GetTopLeft()); +} + +void DisplayGeometryWindow::OnSize(wxSizeEvent& event) +{ + CalcDrawRect(); +} + +void DisplayGeometryWindow::CalcDrawRect() +{ + wxRectVector displays; + m_GeometryProvider.GetGeometry(displays); + m_DisplayRect = GetDisplayRect(displays); + + wxSize clientSize = GetClientSize(); + wxSize bestSize = clientSize - wxSize(m_Border * 2, m_Border * 2); // Add border + wxSize bitmapSize = m_DisplayRect.GetSize(); + double kx = (double) bestSize.x / bitmapSize.x; + double ky = (double) bestSize.y / bitmapSize.y; + if (kx < ky) + { + m_DrawRect.width = bestSize.x; + m_DrawRect.height = (kx * bitmapSize.y); + m_Scale = kx; + } + else + { + m_DrawRect.height = bestSize.y; + m_DrawRect.width = (ky * bitmapSize.x); + m_Scale = ky; + } + m_DrawRect = m_DrawRect.CenterIn(wxRect(clientSize)); + m_DrawRect.x = m_Border; + + CreateBitmap(); + + Refresh(); +} + +wxRect DisplayGeometryWindow::GetDisplayRect(const wxRectVector & displays) +{ + wxRect resolution; + for (auto i = 0; i < displays.size(); ++i) + resolution.Union(displays[i]); + return resolution; +} + +void DisplayGeometryWindow::CreateBitmap() +{ + m_Bitmap = wxBitmap(m_DrawRect.GetSize() + wxSize(1, 1)); + wxMemoryDC mdc(m_Bitmap); + mdc.SetBackground(wxBrush(GetBackgroundColour())); + mdc.Clear(); + mdc.SetBrush(*wxTRANSPARENT_BRUSH); + mdc.SetPen(*wxBLACK_PEN); + mdc.SetTextForeground(*wxBLACK); + + wxRectVector displays; + m_GeometryProvider.GetGeometry(displays); + wxRect resolution = GetDisplayRect(displays); + + for (auto i = 0; i < displays.size(); ++i) + { + wxRect rect = displays[i]; + rect.Offset(-resolution.GetTopLeft()); + wxPoint p1 = rect.GetTopLeft(); + wxPoint p2 = rect.GetBottomRight(); + p1.x *= m_Scale; + p1.y *= m_Scale; + p2.x *= m_Scale; + p2.y *= m_Scale; + rect = wxRect(p1, p2); + + mdc.DrawRectangle(rect); + + mdc.DrawLabel(wxString::Format(wxT("#%d"), i + 1), rect, wxALIGN_CENTER); + } + +} \ No newline at end of file diff --git a/MotionDetectorCore/DisplayGeometryWindow.h b/MotionDetectorCore/DisplayGeometryWindow.h new file mode 100644 index 0000000..0509a0a --- /dev/null +++ b/MotionDetectorCore/DisplayGeometryWindow.h @@ -0,0 +1,39 @@ +#ifndef _DISPLAYGEOMETRYWINDOW_H +#define _DISPLAYGEOMETRYWINDOW_H + +#include "MotionDetectorCorePlugin.h" +#include + +class MOTION_DETECTOR_CORE_API DisplayGeometryWindow: public wxWindow +{ + DECLARE_DYNAMIC_CLASS(DisplayGeometryWindow) + DECLARE_EVENT_TABLE() +public: + DisplayGeometryWindow(); + DisplayGeometryWindow(wxWindow * parent, const GeometryProvider & geometryPrivoder, wxWindowID id = wxID_STATIC, const wxPoint & pos = wxDefaultPosition, const wxSize & size = wxDefaultSize, long style = wxSIMPLE_BORDER); + + bool Create(wxWindow * parent, wxWindowID id = wxID_STATIC, const wxPoint & pos = wxDefaultPosition, const wxSize & size = wxDefaultSize, long style = wxSIMPLE_BORDER); + + ~DisplayGeometryWindow(); + + void Init(); + +protected: + void OnSize(wxSizeEvent & event); + void OnPaint(wxPaintEvent & event); + void OnEraseBackground(wxEraseEvent & event); + + void CalcDrawRect(); + static wxRect GetDisplayRect(const wxRectVector & displays); + void CreateBitmap(); + +protected: + const GeometryProvider & m_GeometryProvider; + wxRect m_DrawRect; + wxBitmap m_Bitmap; + wxRect m_DisplayRect; + double m_Scale; + int m_Border; +}; + +#endif // _DISPLAYGEOMETRYWINDOW_H diff --git a/MotionDetectorCore/DummyFilter.cpp b/MotionDetectorCore/DummyFilter.cpp new file mode 100644 index 0000000..01a97fc --- /dev/null +++ b/MotionDetectorCore/DummyFilter.cpp @@ -0,0 +1,28 @@ +#include "stdwx.h" +#include "DummyFilter.h" + +IMPLEMENT_DYNAMIC_CLASS(DummyFilter, Filter); + +DummyFilter::DummyFilter() +{ +} + +DummyFilter::~DummyFilter() +{ +} + +wxString DummyFilter::GetName() const +{ + return _("Camera Preview"); +} + +bool DummyFilter::Kernel() +{ + return false; +} + +void DummyFilter::CreateParamInputs() +{ +} + +wxFORCE_LINK_THIS_MODULE(DummyFilter); \ No newline at end of file diff --git a/MotionDetectorCore/DummyFilter.h b/MotionDetectorCore/DummyFilter.h new file mode 100644 index 0000000..c446b98 --- /dev/null +++ b/MotionDetectorCore/DummyFilter.h @@ -0,0 +1,29 @@ +#ifndef _DUMMYFILTER_H +#define _DUMMYFILTER_H + +#include "FilterTemplate.h" + +class MOTION_DETECTOR_CORE_API DummyFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(DummyFilter) +public: + DummyFilter(); + virtual ~DummyFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(){return false;} +#endif + virtual wxString GetName() const; + + // This filter is always disabled + virtual bool IsEnabled() { return false; }; + virtual bool IsMandatory() { return true; }; + +protected: + void CreateParamInputs(); +private: + +}; + +#endif // _DUMMYFILTER_H diff --git a/MotionDetectorCore/DynamicBGFilter.cpp b/MotionDetectorCore/DynamicBGFilter.cpp new file mode 100644 index 0000000..7c1836c --- /dev/null +++ b/MotionDetectorCore/DynamicBGFilter.cpp @@ -0,0 +1,140 @@ +#include "stdwx.h" +#include "DynamicBGFilter.h" + +#if defined(__LINUX__) +#include "LinuxUtils.h" +#endif +// LINUX_ + +IMPLEMENT_DYNAMIC_CLASS(DynamicBGFilter, Filter); + +DynamicBGFilter::DynamicBGFilter() +{ + m_bLearnBackground = false; + m_bTrackDark = false; + m_LearnRate = 400; + m_CameraExposureTime = 2200; +#if defined(HAVE_CUDA) + bStart = false; +#endif + + m_ExposureStartTime = timeGetTime(); + XS_SERIALIZE(m_bTrackDark, wxT("TrackDark")); + XS_SERIALIZE(m_LearnRate, wxT("LearnRate")); + XS_SERIALIZE(m_bLearnBackground, wxT("LearnBackground")); + XS_SERIALIZE(m_CameraExposureTime, wxT("CameraExposureTime")); + +} + +DynamicBGFilter::~DynamicBGFilter() +{ + +} + +wxString DynamicBGFilter::GetName() const +{ + return _("Dynamic BG"); +} + +#if defined(HAVE_CUDA) +bool DynamicBGFilter::KernelGPU() +{ + if ((int)(timeGetTime() - m_ExposureStartTime) > m_CameraExposureTime) + m_bLearnBackground = true; + + //Capture full background + if (m_bLearnBackground) + { + m_src->convertTo(m_matFloatBgImg, CV_32FC1); + m_bLearnBackground = false; + bStart = true; + m_ExposureStartTime = timeGetTime(); + } + if(!bStart) + return false; + //step1 + m_src->convertTo(m_matFloatBgImgTemp, CV_32FC1); + cv::Scalar alpha = (float)m_LearnRate * 0.001f; + cv::Scalar beta = 1.0f - (float)m_LearnRate * 0.001f; + cv::cuda::multiply(m_matFloatBgImgTemp, alpha, m_matFloatBgImgTemp); + cv::cuda::multiply(m_matFloatBgImg, beta, m_matFloatBgImg); + //step2 + cv::cuda::add(m_matFloatBgImgTemp, m_matFloatBgImg, m_matFloatBgImg); + //step3 + m_matFloatBgImg.convertTo(m_matGrayBg, m_dst.type()); + // Subtract background + if (m_bTrackDark){ + cv::cuda::subtract(m_matGrayBg, *m_src, m_dst); + } + else{ + cv::cuda::subtract(*m_src, m_matGrayBg, m_dst); + } + return true; +} +#endif + +bool DynamicBGFilter::Kernel() +{ + // derived class responsible for allocating storage for filtered image + if (source.empty()) + return false; + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), CV_8UC1); + } + if (floatBgImg.empty()) + { + floatBgImg = cv::Mat::zeros(source.size(), CV_16UC1); + floatBgImgTemp = cv::Mat::zeros(source.size(), CV_16UC1); + } + + if ((int)(timeGetTime() - m_ExposureStartTime) > m_CameraExposureTime) + m_bLearnBackground = true; + + //Capture full background + if (m_bLearnBackground) + { + source.convertTo(floatBgImg, CV_16UC1, 65535.0f / 255.0f, 0); + + if (grayBg.empty()) + { + grayBg = cv::Mat::zeros(source.size(), CV_8UC1); + } + //cvCopy(source, grayBg); + m_ExposureStartTime = timeGetTime(); + m_bLearnBackground = false; + } + if (grayBg.empty()) + return false; + + //step1 + source.convertTo(floatBgImgTemp, CV_16UC1, 65535.0f / 255.0f, 0); + //step2 + float fLearnRate = (float)m_LearnRate * 0.001f; + cv::addWeighted(floatBgImgTemp, fLearnRate, floatBgImg, 1.0f - fLearnRate, 0, floatBgImg); + //step3 + floatBgImg.convertTo(grayBg, CV_8UC1, 255.0f / 65535.0f, 0); + + //// Subtract background + if (m_bTrackDark) + cv::subtract(grayBg, source, destination); + else + cv::subtract(source, grayBg, destination); + //IplImage* destination1 = cvCreateImage(cvSize(source->width, source->height), IPL_DEPTH_8U, 1); + //cvSub(grayBg, source, destination1); + ////else + //cvSub(source, grayBg, destination); + //cvOr(destination, destination1, destination); + return true; +} + +void DynamicBGFilter::CreateParamInputs() +{ + AddParameterBoolInput(_("Learn background"), &m_bLearnBackground); + AddParameterBoolInput(_("Track dark blobs"), &m_bTrackDark); + AddParameterSpinInput(_("Background learn rate:"), &m_LearnRate, 1000, 0); + AddParameterSpinInput(_("Camera exposure time:"), &m_CameraExposureTime, 20000, 0); +} + +wxFORCE_LINK_THIS_MODULE(DynamicBGFilter); \ No newline at end of file diff --git a/MotionDetectorCore/DynamicBGFilter.h b/MotionDetectorCore/DynamicBGFilter.h new file mode 100644 index 0000000..600523d --- /dev/null +++ b/MotionDetectorCore/DynamicBGFilter.h @@ -0,0 +1,41 @@ +#ifndef __TOUCHLIB_FILTER_DYNAMICBG__ +#define __TOUCHLIB_FILTER_DYNAMICBG__ + +#include "FilterTemplate.h" +#include +#include + +class MOTION_DETECTOR_CORE_API DynamicBGFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(DynamicBGFilter) +public: + DynamicBGFilter(); + virtual ~DynamicBGFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(); +#endif + virtual wxString GetName() const; + +protected: + void CreateParamInputs(); + +private: + cv::Mat floatBgImg; + cv::Mat floatBgImgTemp; + cv::Mat grayBg; +#if defined(HAVE_CUDA) + cv::cuda::GpuMat m_matFloatBgImg; + cv::cuda::GpuMat m_matFloatBgImgTemp; + cv::cuda::GpuMat m_matGrayBg; + bool bStart; +#endif + bool m_bTrackDark; + bool m_bLearnBackground; + int m_ExposureStartTime; + int m_CameraExposureTime; + int m_LearnRate; +}; + +#endif // __TOUCHLIB_FILTER_DYNAMICBG__ diff --git a/MotionDetectorCore/EqualizeHistFilter.cpp b/MotionDetectorCore/EqualizeHistFilter.cpp new file mode 100644 index 0000000..b6142e1 --- /dev/null +++ b/MotionDetectorCore/EqualizeHistFilter.cpp @@ -0,0 +1,61 @@ +#include "stdwx.h" +#include "EqualizeHistFilter.h" + +IMPLEMENT_DYNAMIC_CLASS(EqualizeHistFilter, Filter); + +EqualizeHistFilter::EqualizeHistFilter() +{ + level = 0; +} + +EqualizeHistFilter::~EqualizeHistFilter() +{ + +} + +wxString EqualizeHistFilter::GetName() const +{ + return _("Equalize Histogram"); +} + +#if defined(HAVE_CUDA) +bool EqualizeHistFilter::KernelGPU() +{ + return false; +} +#endif + +bool EqualizeHistFilter::Kernel() +{ + // derived class responsible for allocating storage for filtered image + if (source.empty()) + return false; + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), source.type()); + + if (source.channels() == 3) + { + cv::Mat hsv; + cv::cvtColor(source, hsv, cv::COLOR_BGR2HSV); + std::vector hsvChannels; + cv::split(hsv, hsvChannels); + cv::merge(hsvChannels, hsv); + cv::cvtColor(hsv, destination, cv::COLOR_HSV2BGR); + } + } + + else if (source.channels() == 1) + { + cv::equalizeHist(source, destination); + } + + return true; +} + +void EqualizeHistFilter::CreateParamInputs() +{ +} + +wxFORCE_LINK_THIS_MODULE(EqualizeHistFilter); \ No newline at end of file diff --git a/MotionDetectorCore/EqualizeHistFilter.h b/MotionDetectorCore/EqualizeHistFilter.h new file mode 100644 index 0000000..fd7ea0b --- /dev/null +++ b/MotionDetectorCore/EqualizeHistFilter.h @@ -0,0 +1,28 @@ +#ifndef __TOUCHLIB_FILTER_EQ_HIST__ +#define __TOUCHLIB_FILTER_EQ_HIST__ + +#include "FilterTemplate.h" +#include + +class MOTION_DETECTOR_CORE_API EqualizeHistFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(EqualizeHistFilter) +public: + EqualizeHistFilter(); + virtual ~EqualizeHistFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(); + cv::cuda::GpuMat m_floatGpuMat; +#endif + virtual wxString GetName() const; + + int level; + +protected: + virtual void CreateParamInputs(); + +}; + +#endif // __TOUCHLIB_FILTER_EQ_HIST__ diff --git a/MotionDetectorCore/FilterFactory.cpp b/MotionDetectorCore/FilterFactory.cpp new file mode 100644 index 0000000..cff56f2 --- /dev/null +++ b/MotionDetectorCore/FilterFactory.cpp @@ -0,0 +1,41 @@ +#include "stdwx.h" +#include "FilterFactory.h" +#include "FilterTemplate.h" + +Filter * FilterFactory::CreateFilter(const wxString & type) +{ + wxClassInfo * info = wxClassInfo::FindClass(type); + if (!info) return nullptr; + wxObject * obj = info->CreateObject(); + Filter * filter = wxDynamicCast(obj, Filter); + if (!filter) wxDELETE(obj); + return filter; +} + +// Keep linker from discarding filters +wxFORCE_LINK_MODULE(AmplifyFilter); +wxFORCE_LINK_MODULE(BackgroundFilter); +wxFORCE_LINK_MODULE(BarrelDistortionCorrectionFilter); +wxFORCE_LINK_MODULE(BrightnessContrastFilter); +wxFORCE_LINK_MODULE(CropFilter); +wxFORCE_LINK_MODULE(DynamicBGFilter); +wxFORCE_LINK_MODULE(EqualizeHistFilter); +wxFORCE_LINK_MODULE(FlipFilter); +wxFORCE_LINK_MODULE(HighpassFilter); +wxFORCE_LINK_MODULE(InvertFilter); +wxFORCE_LINK_MODULE(MonoFilter); +wxFORCE_LINK_MODULE(PerspectiveFilter); +wxFORCE_LINK_MODULE(RectifyFilter); +wxFORCE_LINK_MODULE(ResizeFilter); +wxFORCE_LINK_MODULE(ScalerFilter); +wxFORCE_LINK_MODULE(ShapeFilter); +wxFORCE_LINK_MODULE(SimpleBGFilter); +wxFORCE_LINK_MODULE(SimpleHighpassFilter); +wxFORCE_LINK_MODULE(SmoothingFilter); +wxFORCE_LINK_MODULE(ThresholdFilter); + +wxFORCE_LINK_MODULE(KinectBGFilter); +wxFORCE_LINK_MODULE(KinectMonoFilter); +wxFORCE_LINK_MODULE(KinectThresholdFilter); + +wxFORCE_LINK_MODULE(DummyFilter); diff --git a/MotionDetectorCore/FilterFactory.h b/MotionDetectorCore/FilterFactory.h new file mode 100644 index 0000000..6946d0a --- /dev/null +++ b/MotionDetectorCore/FilterFactory.h @@ -0,0 +1,12 @@ +#ifndef _FILTERFACTORY_H +#define _FILTERFACTORY_H + +#include "FilterTemplate.h" + +class FilterFactory +{ +public: + static Filter * CreateFilter(const wxString & type); +}; + +#endif // _FILTERFACTORY_H \ No newline at end of file diff --git a/MotionDetectorCore/FilterPreviewWindow.cpp b/MotionDetectorCore/FilterPreviewWindow.cpp new file mode 100644 index 0000000..eae8486 --- /dev/null +++ b/MotionDetectorCore/FilterPreviewWindow.cpp @@ -0,0 +1,100 @@ +#include "stdwx.h" +#include "FilterPreviewWindow.h" +#include + +IMPLEMENT_DYNAMIC_CLASS(FilterPreviewWindow, wxWindow) + +BEGIN_EVENT_TABLE(FilterPreviewWindow, wxWindow) + EVT_SIZE(FilterPreviewWindow::OnSize) + EVT_PAINT(FilterPreviewWindow::OnPaint) + EVT_ERASE_BACKGROUND(FilterPreviewWindow::OnEraseBackground) +END_EVENT_TABLE() + +FilterPreviewWindow::FilterPreviewWindow() +{ + Init(); +} + +FilterPreviewWindow::FilterPreviewWindow(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) +{ + Init(); + Create(parent, id, pos, size, style); +} + +bool FilterPreviewWindow::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) +{ + wxWindow::Create(parent, id, pos, size, style); + return true; +} + +FilterPreviewWindow::~FilterPreviewWindow() +{ +} + +void FilterPreviewWindow::Init() +{ +} + +void FilterPreviewWindow::OnEraseBackground(wxEraseEvent& event) +{ +} + +void FilterPreviewWindow::OnPaint(wxPaintEvent& event) +{ + wxBufferedPaintDC dc(this); + dc.SetBackground(wxBrush(GetBackgroundColour())); + dc.Clear(); + + if (m_Bitmap.IsOk()) + { + wxMemoryDC mdc(m_Bitmap); + dc.StretchBlit(m_DrawRect.GetTopLeft(), m_DrawRect.GetSize(), &mdc, wxPoint(0, 0), m_Bitmap.GetSize()); + } + else // No Image + { + dc.SetBrush(*wxBLACK_BRUSH); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRectangle(m_DrawRect); + dc.SetTextForeground(*wxWHITE); + dc.DrawLabel(_("No Image"), m_DrawRect, wxALIGN_CENTER); + } +} + +void FilterPreviewWindow::OnSize(wxSizeEvent& event) +{ + CalcDrawRect(); +} + +void FilterPreviewWindow::SetBitmap(const wxBitmap & bitmap) +{ + m_Bitmap = bitmap; + CalcDrawRect(); + Refresh(); +} + +void FilterPreviewWindow::CalcDrawRect() +{ + wxSize size = GetClientSize(); + if (m_Bitmap.IsOk()) + { + wxSize bitmapSize = m_Bitmap.GetSize(); + double kx = (double) size.x / bitmapSize.x; + double ky = (double) size.y / bitmapSize.y; + if (kx < ky) + { + m_DrawRect.width = size.x; + m_DrawRect.height = (kx * bitmapSize.y); + } + else + { + m_DrawRect.height = size.y; + m_DrawRect.width = (ky * bitmapSize.x); + } + m_DrawRect = m_DrawRect.CenterIn(wxRect(size)); + } + else + { + m_DrawRect = wxRect(size); + } + Refresh(); +} diff --git a/MotionDetectorCore/FilterPreviewWindow.h b/MotionDetectorCore/FilterPreviewWindow.h new file mode 100644 index 0000000..6789fd8 --- /dev/null +++ b/MotionDetectorCore/FilterPreviewWindow.h @@ -0,0 +1,34 @@ +#ifndef _EFFECTPREVIEWWINDOW_H +#define _EFFECTPREVIEWWINDOW_H + +#include "MotionDetectorCorePlugin.h" + +class MOTION_DETECTOR_CORE_API FilterPreviewWindow: public wxWindow +{ + DECLARE_DYNAMIC_CLASS(FilterPreviewWindow) + DECLARE_EVENT_TABLE() +public: + FilterPreviewWindow(); + FilterPreviewWindow(wxWindow * parent, wxWindowID id = wxID_STATIC, const wxPoint & pos = wxDefaultPosition, const wxSize & size = wxDefaultSize, long style = wxSIMPLE_BORDER); + + bool Create(wxWindow * parent, wxWindowID id = wxID_STATIC, const wxPoint & pos = wxDefaultPosition, const wxSize & size = wxDefaultSize, long style = wxSIMPLE_BORDER); + + ~FilterPreviewWindow(); + + void Init(); + + void SetBitmap(const wxBitmap & bitmap); + +protected: + void OnSize(wxSizeEvent & event); + void OnPaint(wxPaintEvent & event); + void OnEraseBackground(wxEraseEvent & event); + + void CalcDrawRect(); + +protected: + wxRect m_DrawRect; + wxBitmap m_Bitmap; +}; + +#endif // _EFFECTPREVIEWWINDOW_H diff --git a/MotionDetectorCore/FilterTemplate.cpp b/MotionDetectorCore/FilterTemplate.cpp new file mode 100644 index 0000000..3481a7d --- /dev/null +++ b/MotionDetectorCore/FilterTemplate.cpp @@ -0,0 +1,218 @@ +#include "stdwx.h" +#include "FilterTemplate.h" +#include +#include + +IMPLEMENT_ABSTRACT_CLASS(Filter, xsSerializable); + +Filter::Filter() +{ + Init(); +} +//#ifdef HAVE_CUDA +//#undef HAVE_CUDA +//#endif +void Filter::Init() +{ +#ifdef HAVE_CUDA + bUseGPU = false;//cv::gpu::getCudaEnabledDeviceCount(); + m_src = NULL; +#else + bUseGPU = false; +#endif + + m_ChainedFilter = NULL; + m_FuncImageCallback = NULL; + m_CallbackData = NULL; + m_bEnabled = true; + XS_SERIALIZE(m_bEnabled, wxT("Enabled")); +} + +Filter::~Filter() +{ +#ifdef HAVE_CUDA + m_dst.release(); + m_srcGpu.release(); + m_resMat.release(); + dstMat.release(); + cvReleaseImage(&m_ResultImage); +#endif +} + +#ifdef HAVE_CUDA +cv::cuda::GpuMat& Filter::ProcessGPU(cv::cuda::GpuMat& frameMat) +{ + m_src = &frameMat; + if (IsEnabled()) + { + try + { + // Subclasses must implement this abstract method + if (!this->KernelGPU()){ + frameMat.copyTo(m_dst); + } + } + catch (...) + { + // There was error in the filter + frameMat.copyTo(m_dst); + throw 1; + } + } + else + frameMat.copyTo(m_dst); + + // We need to show result of current filter before it was processed by other filters + if (m_FuncImageCallback) + { + cv::Mat resMat; + m_dst.download(resMat); + m_FuncImageCallback(m_CameraID, GetClassInfo()->GetClassName(), &(IplImage)resMat, m_CallbackData); + } + + if (m_ChainedFilter) + return m_ChainedFilter->ProcessGPU(m_dst); + return m_dst; +} +#endif + +cv::Mat Filter::Process(cv::Mat frame) +{ + source = frame; + +#ifdef HAVE_CUDA +// cv::gpu::GpuMat srcGpu; + m_srcGpu.upload(source); + m_dst = ProcessGPU(m_srcGpu); + m_dst.download(dstMat); + //m_ResultImage = cvCreateImage(dstMat.size(), dstMat.depth(), dstMat.channels()); + m_ResultImage = dstMat.clone(); + return m_ResultImage; +#else + m_ResultImage = source; // If the filter is not enabled, then we should pass source image to the next filter + if (IsEnabled()) + { + try + { + // Subclasses must implement this abstract method + if (this->Kernel() && !destination.empty()) + m_ResultImage = destination; + } + catch (std::exception ex) + { + wxString str = ex.what(); + } + catch (...) + { + // There was error in the filter + + } + } + + // We need to show result of current filter before it was processed by other filters + if (m_FuncImageCallback) + { + m_FuncImageCallback(m_CameraID, GetClassInfo()->GetClassName(), m_ResultImage, m_CallbackData); + } + + // Pass the result to the next filter + if (m_ChainedFilter) + return m_ChainedFilter->Process(m_ResultImage); + + return m_ResultImage; +#endif +} + +void Filter::ConnectTo(Filter * chainedFilter) +{ + m_ChainedFilter = chainedFilter; +} + +void Filter::CreatePreviewAndParams(wxWindow * parent, wxSizer * parentSizer, wxWindow * previewWindow) +{ + parent->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY); + + wxStaticBox * itemStaticBox = new wxStaticBox(parent, wxID_ANY, GetName()); + wxSizer * mainFilterSizer = new wxStaticBoxSizer(itemStaticBox, wxHORIZONTAL); + parentSizer->Add(mainFilterSizer, 0, wxGROW|wxLEFT|wxRIGHT|wxBOTTOM, 5); + + m_ParentPanel = new wxPanel(parent); + m_ParentPanel->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY); + mainFilterSizer->Add(m_ParentPanel, 1, wxGROW, 0); + + mainFilterSizer = new wxBoxSizer(wxHORIZONTAL); + m_ParentPanel->SetSizer(mainFilterSizer); + + wxBoxSizer * previewSizer = new wxBoxSizer(wxVERTICAL); + mainFilterSizer->Add(previewSizer, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT, 5); + + previewWindow->Reparent(m_ParentPanel); + previewSizer->Add(previewWindow, 0, wxALIGN_LEFT|wxBOTTOM, 5); + + m_ParamsContainerSizer = new wxBoxSizer(wxVERTICAL); + mainFilterSizer->Add(m_ParamsContainerSizer, 1, wxGROW, 5); + + wxCheckBox * cb = AddParameterBoolInput(_("Enabled"), &m_bEnabled); + if (IsMandatory()) + cb->Disable(); + + CreateParamInputs(); +} + +void Filter::CreateParamInputs() +{ +} + +void Filter::AddParameterSpinInput(wxString name, int * param, int maxValue, int minValue) +{ + wxBoxSizer * paramSizer = new wxBoxSizer(wxHORIZONTAL); + m_ParamsContainerSizer->Add(paramSizer, 0, wxGROW|wxBOTTOM, 5); + + wxStaticText * paramName = new wxStaticText(m_ParentPanel, wxID_STATIC, name); + paramSizer->Add(paramName, 0, wxALIGN_LEFT|wxRIGHT, 5); + + wxSpinCtrl * paramValue = new wxSpinCtrl(m_ParentPanel, wxID_ANY, wxT("0"), wxDefaultPosition, wxSize(100, -1), wxSP_ARROW_KEYS, minValue, maxValue, 0); + paramSizer->Add(paramValue, 0, wxALIGN_LEFT, 5); + + paramValue->SetValidator(wxGenericValidator(param)); + + paramValue->Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, &Filter::OnSpinChanged, this); +} + +wxCheckBox * Filter::AddParameterBoolInput(wxString name, bool * param) +{ + wxCheckBox * paramValue = new wxCheckBox(m_ParentPanel, wxID_ANY, name); + paramValue->SetValue(*param); + m_ParamsContainerSizer->Add(paramValue, 0, wxBOTTOM, 5); + + paramValue->SetValidator(wxGenericValidator(param)); + + paramValue->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &Filter::OnCheckBoxClicked, this); + return paramValue; +} + +void Filter::SetImageCallback(const FuncGetImage & val, int cameraID, void * userData /*= NULL*/) +{ + m_FuncImageCallback = val; + m_CameraID = cameraID; + m_CallbackData = userData; +} + +void Filter::OnCheckBoxClicked(wxCommandEvent & event) +{ + TransferFromWindow(event.GetEventObject()); +} + +void Filter::OnSpinChanged(wxSpinEvent & event) +{ + TransferFromWindow(event.GetEventObject()); +} + +void Filter::TransferFromWindow(wxObject * obj) +{ + wxWindow * win = wxDynamicCast(obj, wxWindow); + wxCHECK_MSG(win, , wxT("Where is the window?")); + wxValidator * validator = win->GetValidator(); + if (validator) + validator->TransferFromWindow(); +} \ No newline at end of file diff --git a/MotionDetectorCore/FilterTemplate.h b/MotionDetectorCore/FilterTemplate.h new file mode 100644 index 0000000..db34a1e --- /dev/null +++ b/MotionDetectorCore/FilterTemplate.h @@ -0,0 +1,96 @@ +#ifndef __TOUCHLIB_FILTER__ +#define __TOUCHLIB_FILTER__ + +#if defined(__WXMSW__) +#include +#include +#include "MotionDetectorCorePlugin.h" +#if defined(HAVE_CUDA) +#include +#endif +#include +// IMPORTANT NOTE: +// Linker will discard entire object file without this: +// wxFORCE_LINK_THIS_MODULE(FilterName); +// So add this line with the correct filter class name to the bottom of the cpp file +// with the filter class definition +// +// Also add line +// wxFORCE_LINK_MODULE(FilterName); +// to the FilterFactory.cpp file to keep linker from discarding the filter + +// Preview size +#define PREVIEW_WIDTH 120 +#define PREVIEW_HEIGHT 90 + +class FilterFactory; + +typedef void (*FuncGetImage)(int cameraID, const wxString & filterName, cv::Mat image, void * userData); + +class MOTION_DETECTOR_CORE_API Filter: public xsSerializable +{ + DECLARE_ABSTRACT_CLASS(Filter) + friend class FilterFactory; +public: + Filter(); + virtual ~Filter(); + + void Init(); + + cv::Mat Process(cv::Mat frame); + + virtual bool Kernel() = 0; +#if defined(HAVE_CUDA) + cv::cuda::GpuMat& ProcessGPU(cv::cuda::GpuMat& frameMat); + virtual bool KernelGPU(){return true;} +#endif + virtual wxString GetName() const = 0; + virtual bool IsEnabled() { return m_bEnabled; } + virtual bool IsMandatory() { return false; } + + void ConnectTo(Filter * chainedFilter); + cv::Mat GetOutput() { return m_ResultImage; } + void SetImageCallback(const FuncGetImage & val, int cameraID, void * userData = NULL); + + void CreatePreviewAndParams(wxWindow * parent, wxSizer * parentSizer, wxWindow * previewWindow); + void SetEnabled(bool enabled){m_bEnabled = enabled;} + +protected: + bool m_bEnabled; + bool bUseGPU; + cv::Mat source; + cv::Mat destination; +#if defined(HAVE_CUDA) + cv::cuda::GpuMat* m_src; + cv::cuda::GpuMat m_dst; + cv::cuda::GpuMat m_srcGpu; + cv::Mat m_resMat; +#endif + + Filter * m_ChainedFilter; + FuncGetImage m_FuncImageCallback; + void * m_CallbackData; + int m_CameraID; + + //Parameters setting panel + void AddParameterSpinInput(wxString name, int * param, int maxValue = 255, int minValue = 0); + wxCheckBox * AddParameterBoolInput(wxString name, bool * param); + virtual void CreateParamInputs(); + void OnCheckBoxClicked(wxCommandEvent & event); + void OnSpinChanged(wxSpinEvent & event); + + void TransferFromWindow(wxObject * obj); + + wxWindow * m_ParentPanel; + wxSizer * m_ParamsContainerSizer; + +private: + cv::Mat m_ResultImage; +#if defined(HAVE_CUDA) + cv::Mat dstMat; +#endif + +}; + +#endif //__TOUCHLIB_FILTER__ +#endif // __WXMSW__ diff --git a/MotionDetectorCore/FlipFilter.cpp b/MotionDetectorCore/FlipFilter.cpp new file mode 100644 index 0000000..92e7538 --- /dev/null +++ b/MotionDetectorCore/FlipFilter.cpp @@ -0,0 +1,89 @@ +#include "stdwx.h" +#include "FlipFilter.h" +#include + +IMPLEMENT_DYNAMIC_CLASS(FlipFilter, Filter); +FlipFilter::FlipFilter() +{ + bFlipVertically = false; + bFlipHorizontally = false; + //XS_SERIALIZE(bFlipVertically, wxT("FlipVertically")); + //XS_SERIALIZE(bFlipHorizontally, wxT("FlipHorizontally")); + +} + +FlipFilter::~FlipFilter() +{ +} + +wxString FlipFilter::GetName() const +{ + return _("Flip"); +} +#if defined(HAVE_CUDA) +bool FlipFilter::KernelGPU() +{ + if (m_src->empty()) + return false; + + int flipMode = 0; + + if (bFlipVertically && !bFlipHorizontally) + flipMode = 0; + else if (!bFlipVertically && bFlipHorizontally) + flipMode = 1; + else if (bFlipVertically && bFlipHorizontally) + flipMode = -1; + else + return false; + cv::cuda::flip(*m_src, m_dst, flipMode); + return true; +} +#endif + +bool FlipFilter::Kernel() +{ + // derived class responsible for allocating storage for filtered image + if (source.empty()) + return false; + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), source.type()); + } + int flipMode = 0; + + if (bFlipVertically && !bFlipHorizontally) + flipMode = 0; + else if (!bFlipVertically && bFlipHorizontally) + flipMode = 1; + else if (bFlipVertically && bFlipHorizontally) + flipMode = -1; + else + { + source.copyTo(destination); + return true; + }; + + cv::flip(source, destination, flipMode); + return true; +} + +void FlipFilter::CreateParamInputs() +{ + //AddParameterBoolInput(_("Flip image vertically"), &bFlipVertically); + //AddParameterBoolInput(_("Flip image horizontally"), &bFlipHorizontally); +} + +bool FlipFilter::IsEnabled() +{ + return m_bEnabled && (bFlipVertically || bFlipHorizontally); +} + +void FlipFilter::SetSettings(const IFloorCameraSettings & settings) +{ + bFlipHorizontally = settings.bHorizontalMirror; + bFlipVertically = settings.bVerticalMirror; +} + +wxFORCE_LINK_THIS_MODULE(FlipFilter); \ No newline at end of file diff --git a/MotionDetectorCore/FlipFilter.h b/MotionDetectorCore/FlipFilter.h new file mode 100644 index 0000000..e00a638 --- /dev/null +++ b/MotionDetectorCore/FlipFilter.h @@ -0,0 +1,33 @@ +#ifndef __TOUCHLIB_FILTER_FLIP__ +#define __TOUCHLIB_FILTER_FLIP__ + +#include "FilterTemplate.h" +#include + +class IFloorCameraSettings; + +class MOTION_DETECTOR_CORE_API FlipFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(FlipFilter) +public: + FlipFilter(); + virtual ~FlipFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(); +#endif + virtual wxString GetName() const; + virtual bool IsEnabled(); + + void SetSettings(const IFloorCameraSettings & settings); + + bool bFlipVertically; + bool bFlipHorizontally; +protected: + void CreateParamInputs(); +private: + +}; + +#endif // __TOUCHLIB_FILTER_FLIP__ diff --git a/MotionDetectorCore/HighpassFilter.cpp b/MotionDetectorCore/HighpassFilter.cpp new file mode 100644 index 0000000..d7eb721 --- /dev/null +++ b/MotionDetectorCore/HighpassFilter.cpp @@ -0,0 +1,126 @@ +#include "stdwx.h" +#include "HighpassFilter.h" + +IMPLEMENT_DYNAMIC_CLASS(HighpassFilter, Filter); + +HighpassFilter::HighpassFilter() +{ + element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3)); + element2 = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(9, 9)); + + filterLevel = 5; + filterLevel_slider = filterLevel; + + scale = 32; + scale_slider = scale; + + bErodeDialate = false; + XS_SERIALIZE(bErodeDialate, wxT("ErodeDialate")); + XS_SERIALIZE(filterLevel_slider, wxT("HighpassLevel")); + XS_SERIALIZE(scale_slider, wxT("HighpassScale")); + +} + + +HighpassFilter::~HighpassFilter() +{ + +} + +wxString HighpassFilter::GetName() const +{ + return _("Highpass"); +} + +//void HighpassFilter::getParameters(iFloorParamMap& pMap) +//{ +// pMap[std::string("filter")] = toString(filterLevel); +// pMap[std::string("scale")] = toString(scale); +// +// if(noErodeDialate) +// pMap[std::string("mode")] = "1"; +//} +// +// +//void HighpassFilter::setParameter(const char *name, const char *value) +//{ +// if(strcmp(name, "filter") == 0) +// { +// filterLevel = (int) atof(value); +// filterLevel_slider = filterLevel; +// if(show) +// cvSetTrackbarPos("filter", this->name.c_str(), filterLevel); +// } +// +// if(strcmp(name, "scale") == 0) +// { +// scale = (int) atof(value); +// scale_slider = scale; +// if(show) +// cvSetTrackbarPos("scale", this->name.c_str(), scale); +// } +// +// if(strcmp(name, "mode") == 0) +// { +// if(strcmp(value, "1") == 0) +// { +// noErodeDialate = true; +// +// } +// } +//} + +bool HighpassFilter::Kernel() +{ + if (source.empty()) + return false; + + filterLevel = filterLevel_slider; + scale = scale_slider; + + // derived class responsible for allocating storage for filtered image + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), source.type()); + } + cv::erode(source, destination, element2, cv::Point(-1, -1), 2); + cv::dilate(destination, destination, element2, cv::Point(-1, -1), 2); + //cvConvertScale(source, outra); + ////CV_MEDIAN + //cvSmooth(outra, outra2, CV_GAUSSIAN, (filterLevel * 2) + 3, (filterLevel * 2) + 3, 0, 0); + + //cvSub(outra, outra2, outra2); + + //if (bErodeDialate) + //{ + // cvConvertScale(outra2, destination, ((double)scale + 1.0), 32); + // cvErode(destination, destination, element, 2); + // cvSmooth(destination, destination, CV_GAUSSIAN, 7, 7, 0, 0); + // cvDilate(destination, destination, element2, 1); + // cvDilate(destination, destination, element, 1); + //} + //else + //{ + // cvConvertScale(outra2, destination, ((double)scale + 1.0), 0); + // cvErode(destination, destination, element, 1); + // cvSmooth(destination, destination, CV_GAUSSIAN, 11, 11, 0, 0); + // cvDilate(destination, destination, element, 1); + //} + //TODO: remove this + //showOutput(false, 0, 0); + return true; +} + +void HighpassFilter::CreateParamInputs() +{ + //AddParameterBoolInput(_("Erode/Dialate"), &bErodeDialate); + //AddParameterSpinInput(_("Filter level:"), &filterLevel_slider, 255); + //AddParameterSpinInput(_("Filter scale:"), &scale_slider, 255); +} + +//void showOutput(bool value, int windowx, int windowy) +//{ +// wxLogDebug(_("sss")); +//} + +wxFORCE_LINK_THIS_MODULE(HighpassFilter); \ No newline at end of file diff --git a/MotionDetectorCore/HighpassFilter.h b/MotionDetectorCore/HighpassFilter.h new file mode 100644 index 0000000..c3f70a7 --- /dev/null +++ b/MotionDetectorCore/HighpassFilter.h @@ -0,0 +1,35 @@ +#ifndef __TOUCHSCREEN_FILTER_HIGHPASS__ +#define __TOUCHSCREEN_FILTER_HIGHPASS__ + +#include "FilterTemplate.h" + +class MOTION_DETECTOR_CORE_API HighpassFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(HighpassFilter) +public: + HighpassFilter(); + virtual ~HighpassFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(){return false;} +#endif + virtual wxString GetName() const; + +protected: + void CreateParamInputs(); + +private: + int filterLevel; + int filterLevel_slider; + + int scale; + int scale_slider; + + cv::Mat element; + cv::Mat element2; + + bool bErodeDialate; +}; + +#endif // __TOUCHSCREEN_FILTER_HIGHPASS__ diff --git a/MotionDetectorCore/IFloorImagePreprocessor.cpp b/MotionDetectorCore/IFloorImagePreprocessor.cpp new file mode 100644 index 0000000..4980f4b --- /dev/null +++ b/MotionDetectorCore/IFloorImagePreprocessor.cpp @@ -0,0 +1,178 @@ +#include "stdwx.h" +#include "IFloorImagePreprocessor.h" + +#if defined(USE_VLD) +#include +#endif + +IFloorImagePreprocessor::IFloorImagePreprocessor(const IFloorCameraSettings * settings, void * buffer, size_t bufLength) + : m_Settings(settings) + , m_bNeedToResize(false) + , m_pBuffer(buffer) + , m_BufLength(bufLength) + , m_bHasRoi(false) +{ + if (m_pBuffer && m_Settings) + { + int numChannels = bufLength / (settings->CamWidth * settings->CamHeight); + + int type; + + if (numChannels == 4) + { + type = CV_8UC4; + } + else + { + if (numChannels == 3) + { + type = CV_8UC3; + } + else + { + type = CV_8UC1; + } + } + m_ImgCamera = cv::Mat(settings->CamHeight, settings->CamWidth, type, m_pBuffer); + } +} + +IFloorImagePreprocessor::~IFloorImagePreprocessor() +{ + wxYield(); + for (auto* filter : m_Filters) + { + delete filter; + } + m_Filters.clear(); +} + +void IFloorImagePreprocessor::QueryImage() +{ + if (m_bNeedToResize && !m_ImgCamera.empty()) + { + cv::resize(m_ImgCamera, m_ImgFlash, m_ImgFlash.size(), 0, 0, cv::INTER_LINEAR); + } +} + +void IFloorImagePreprocessor::PrepareImage(int nWidth, int nHeight) +{ + m_bNeedToResize = (nHeight != m_Settings->CamHeight) || (nWidth != m_Settings->CamWidth); + // If the image needs to resize then create destination image + if (m_bNeedToResize && !m_ImgCamera.empty()) + { + m_ImgFlash = cv::Mat::zeros(nHeight, nWidth, m_ImgCamera.type()); + } + else + { + m_ImgFlash = m_ImgCamera; + } +} + +cv::Mat IFloorImagePreprocessor::ProcessImage() +{ + // Get an image from camera + QueryImage(); + // Apply a chain of filters + if (m_ImgFlash.empty()) + return cv::Mat(); + + cv::Mat currentFrame = m_bHasRoi ? m_ImgFlash(m_Roi) : m_ImgFlash; + + cv::Mat result = currentFrame; + + if (!m_Filters.empty()) + { + Filter* firstFilter = m_Filters.front(); + result = firstFilter->Process(currentFrame); + } + + return result; +} + +bool IFloorImagePreprocessor::AddFilterToChain(const wxString & filterType, const wxString & config /*= wxEmptyString*/) +{ + Filter * f = FilterFactory::CreateFilter(filterType); + if (f != nullptr) + { + SetFilterSettings(f, config); + if (!m_Filters.empty()) + m_Filters.back()->ConnectTo(f); + m_Filters.push_back(f); + return true; + } + + return false; +} + +const IFloorCameraSettings * IFloorImagePreprocessor::GetSettings() const +{ + return m_Settings; +} + +bool IFloorImagePreprocessor::SetROI(int x, int y, int width, int height) +{ + if (m_ImgFlash.empty()) + return false; + + x = std::max(0, std::min(x, m_ImgFlash.cols)); + y = std::max(0, std::min(y, m_ImgFlash.rows)); + width = std::max(0, std::min(width, m_ImgFlash.cols - x)); + height = std::max(0, std::min(height, m_ImgFlash.rows - y)); + + // Check and correct coords and size + if (width > 0 && height > 0) + { + m_Roi = cv::Rect(x, y, width, height); + m_bHasRoi = true; + return true; + } + + m_bHasRoi = false; + return false; +} + +cv::Size IFloorImagePreprocessor::GetImageSize() const +{ + if (m_bHasRoi) + { + return m_Roi.size(); + } + if (!m_ImgFlash.empty()) + { + return m_ImgFlash.size(); + } + return cv::Size(m_Settings->CamWidth, m_Settings->CamHeight); +} + +ChainOfFilters & IFloorImagePreprocessor::GetFilters() +{ + return m_Filters; +} + +Filter * IFloorImagePreprocessor::GetFilter(const wxString & filterType) +{ + if(!m_Filters.empty()){ + auto end = m_Filters.end(); + for (auto it = m_Filters.begin(); it != end; ++it) + { + Filter * filter = *it; + if (filter->GetClassInfo()->GetClassName() == filterType) + return filter; + } + } + return nullptr; +} + +bool IFloorImagePreprocessor::SetFilterSettings(const wxString & filterType, const wxString & config) +{ + Filter * filter = GetFilter(filterType); + return SetFilterSettings(filter, config); +} + +bool IFloorImagePreprocessor::SetFilterSettings(Filter * filter, const wxString & config) +{ + if (!filter || config.IsEmpty()) + return false; + return SerializableBase::Deserialize(config, *filter); +} \ No newline at end of file diff --git a/MotionDetectorCore/IFloorImagePreprocessor.h b/MotionDetectorCore/IFloorImagePreprocessor.h new file mode 100644 index 0000000..364f82f --- /dev/null +++ b/MotionDetectorCore/IFloorImagePreprocessor.h @@ -0,0 +1,56 @@ +#ifndef IFLOORIMAGEPREPROCESSOR_H +#define IFLOORIMAGEPREPROCESSOR_H + +#include +#include "FilterFactory.h" +#include +#include +#include + +typedef std::vector ChainOfFilters; + +class MOTION_DETECTOR_CORE_API IFloorImagePreprocessor +{ +public: + IFloorImagePreprocessor(const IFloorCameraSettings * settings, void * buffer, size_t bufLength); + ~IFloorImagePreprocessor(); + // Create an image for resizing + void PrepareImage(int nWidth, int nHeight); + // Capture image and process all filters + cv::Mat ProcessImage(); + // Add a new filter to chain + bool AddFilterToChain(const wxString & filterType, const wxString & config = wxEmptyString); + // Returns current camera settings + const IFloorCameraSettings * GetSettings() const; + // Set the region of interest for the camera + bool SetROI(int x, int y, int width, int height); + // Return size of roi if it exists or size of the image otherwise + cv::Size GetImageSize() const; + // Returns filter from the chain with the specified type + Filter * GetFilter(const wxString & filterType); + // Deserializes filter in chain with specified type from the config string + bool SetFilterSettings(const wxString & filterType, const wxString & config); + // Deserializes filter from the config string + static bool SetFilterSettings(Filter * filter, const wxString & config); + + ChainOfFilters & GetFilters(); +protected: + void QueryImage(); + +protected: + const IFloorCameraSettings * m_Settings; + cv::Mat m_ImgCamera; + cv::Mat m_ImgFlash; + cv::Rect m_Roi; + bool m_bHasRoi; + + ChainOfFilters m_Filters; + bool m_bNeedToResize; + void * m_pBuffer; + size_t m_BufLength; +}; + +// Type definition for cameras vector +typedef std::vector IFloorImagePreprocessorVector; + +#endif //IFLOORIMAGEPREPROCESSOR_H \ No newline at end of file diff --git a/MotionDetectorCore/IFloorImagePreprocessorSettings.cpp b/MotionDetectorCore/IFloorImagePreprocessorSettings.cpp new file mode 100644 index 0000000..f8e47ce --- /dev/null +++ b/MotionDetectorCore/IFloorImagePreprocessorSettings.cpp @@ -0,0 +1,63 @@ +#include "stdwx.h" +#include "IFloorImagePreprocessorSettings.h" + +XS_IMPLEMENT_CLONABLE_CLASS(IFloorImagePreprocessorSettings, xsSerializable); + +#include +WX_DEFINE_OBJARRAY(IFloorImagePreprocessorSettingsArray); + +#if defined(USE_VLD) +#include +#endif + +IFloorImagePreprocessorSettings::IFloorImagePreprocessorSettings() +{ + InitSerialization(); +} + +IFloorImagePreprocessorSettings::IFloorImagePreprocessorSettings(const IFloorImagePreprocessorSettings & obj) +{ + InitSerialization(); + CopyFrom(obj); +} + +IFloorImagePreprocessorSettings& IFloorImagePreprocessorSettings::operator=(const IFloorImagePreprocessorSettings & obj) +{ + if (&obj != this) + { + CopyFrom(obj); + } + return *this; +} + +IFloorImagePreprocessorSettings::~IFloorImagePreprocessorSettings() +{ +} + +void IFloorImagePreprocessorSettings::InitSerialization() +{ + XS_SERIALIZE(m_Filters, wxT("Filters")); +} + +void IFloorImagePreprocessorSettings::CopyFrom(const IFloorImagePreprocessorSettings & obj) +{ + m_Filters = obj.m_Filters; +} + +wxString IFloorImagePreprocessorSettings::GetFilterConfig(const wxString & filterName) +{ + StringMap::iterator it = m_Filters.find(filterName); + if (it == m_Filters.end()) + return wxEmptyString; + return it->second; +} + +wxString IFloorImagePreprocessorSettings::operator[](const wxString & filterName) +{ + return GetFilterConfig(filterName); +} + +void IFloorImagePreprocessorSettings::SetFilterConfig(const wxString & filterName, const wxString & config) +{ + m_Filters[filterName] = config; +} \ No newline at end of file diff --git a/MotionDetectorCore/IFloorImagePreprocessorSettings.h b/MotionDetectorCore/IFloorImagePreprocessorSettings.h new file mode 100644 index 0000000..ffc32b9 --- /dev/null +++ b/MotionDetectorCore/IFloorImagePreprocessorSettings.h @@ -0,0 +1,29 @@ +#ifndef _IFLOORIMAGEPREPROCESSORSETTINGS_H +#define _IFLOORIMAGEPREPROCESSORSETTINGS_H + +#include +#include "MotionDetectorCorePlugin.h" + +class MOTION_DETECTOR_CORE_API IFloorImagePreprocessorSettings : public xsSerializable +{ + XS_DECLARE_CLONABLE_CLASS(IFloorImagePreprocessorSettings); +public: + IFloorImagePreprocessorSettings(); + IFloorImagePreprocessorSettings(const IFloorImagePreprocessorSettings & obj); + IFloorImagePreprocessorSettings& operator=(const IFloorImagePreprocessorSettings & obj); + virtual ~IFloorImagePreprocessorSettings(); + + wxString GetFilterConfig(const wxString & filterName); + void SetFilterConfig(const wxString & filterName, const wxString & config); + wxString operator[](const wxString & filterName); + +protected: + void InitSerialization(); + void CopyFrom(const IFloorImagePreprocessorSettings & obj); +private: + StringMap m_Filters; +}; + +WX_DECLARE_USER_EXPORTED_OBJARRAY(IFloorImagePreprocessorSettings, IFloorImagePreprocessorSettingsArray, MOTION_DETECTOR_CORE_API); + +#endif // _IFLOORIMAGEPREPROCESSORSETTINGS_H diff --git a/MotionDetectorCore/Image.h b/MotionDetectorCore/Image.h new file mode 100644 index 0000000..0fa841f --- /dev/null +++ b/MotionDetectorCore/Image.h @@ -0,0 +1,62 @@ +#ifndef __TOUCHLIB_IMAGE__ +#define __TOUCHLIB_IMAGE__ + +#include +//#include + +namespace touchlib +{ + + // This class serves as a wrapper to OpenCV's image class + // to provide a simple interface to pixels and height/width info. + + template + class /*TOUCHLIB_CORE_EXPORT*/ Image + { + public: + Image(cv::Mat* img = nullptr) { m_img = img; } + ~Image() { m_img = nullptr; } + + int getHeight() + { + if (m_img && !m_img->empty()) + return m_img->rows; + else + return 0; + } + + int getWidth() + { + if (m_img && !m_img->empty()) + return m_img->cols; + else + return 0; + } + + void operator=(cv::Mat* img) { m_img = img; } + + inline T* operator[](const int rowIndx) + { + return (T*)(m_img->data + rowIndx * m_img->step); + } + + cv::Mat* m_img; + }; + + typedef struct + { + unsigned char b,g,r; + } RgbPixel; + + typedef struct + { + float b,g,r; + } RgbPixelFloat; + + typedef Image RgbImage; + typedef Image RgbImageFloat; + typedef Image BwImage; + typedef Image BwImageFloat; +} + +#endif // __TOUCHLIB_IMAGE__ diff --git a/MotionDetectorCore/InvertFilter.cpp b/MotionDetectorCore/InvertFilter.cpp new file mode 100644 index 0000000..817308f --- /dev/null +++ b/MotionDetectorCore/InvertFilter.cpp @@ -0,0 +1,35 @@ +#include "stdwx.h" +#include "InvertFilter.h" + +IMPLEMENT_DYNAMIC_CLASS(InvertFilter, Filter); + +InvertFilter::InvertFilter() +{ +} + +InvertFilter::~InvertFilter() +{ +} + +wxString InvertFilter::GetName() const +{ + return _("Invert"); +} + +// The smooth filter really needs the blur size as a param +bool InvertFilter::Kernel() +{ + if (source.empty()) + return false; + + // derived class responsible for allocating storage for filtered image + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), source.type()); + } + + destination = ~source; + return true; +} + +wxFORCE_LINK_THIS_MODULE(InvertFilter); \ No newline at end of file diff --git a/MotionDetectorCore/InvertFilter.h b/MotionDetectorCore/InvertFilter.h new file mode 100644 index 0000000..f12f75f --- /dev/null +++ b/MotionDetectorCore/InvertFilter.h @@ -0,0 +1,24 @@ +#ifndef __TOUCHSCREEN_FILTER_INVERT__ +#define __TOUCHSCREEN_FILTER_INVERT__ + +#include "FilterTemplate.h" +#include + +class MOTION_DETECTOR_CORE_API InvertFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(InvertFilter) +public: + InvertFilter(); + virtual ~InvertFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(){return false;} +#endif + virtual wxString GetName() const; + +private: + +}; + +#endif // __TOUCHSCREEN_FILTER_INVERT__ diff --git a/MotionDetectorCore/KinectBGFilter.cpp b/MotionDetectorCore/KinectBGFilter.cpp new file mode 100644 index 0000000..999fb18 --- /dev/null +++ b/MotionDetectorCore/KinectBGFilter.cpp @@ -0,0 +1,138 @@ +#include "stdwx.h" +#include "KinectBGFilter.h" +//#include +#include +#if defined(__linux__) +#include "LinuxUtils.h" +#endif +// LINUX_ + +IMPLEMENT_DYNAMIC_CLASS(KinectBGFilter, Filter); + +KinectBGFilter::KinectBGFilter() +{ + m_bTrackDark = false; + m_ExposureStartTime = timeGetTime(); + m_bLearnBackground = false; + m_bStart = false; + m_CameraExposureTime = 2200; + m_bCalibrated = false; + XS_SERIALIZE(m_bTrackDark, wxT("TrackDark")); + XS_SERIALIZE(m_CameraExposureTime, wxT("CameraExposureTime")); + XS_SERIALIZE(m_bCalibrated, wxT("Calibrated")); + XS_SERIALIZE(m_filename, wxT("filename")); +} + +KinectBGFilter::~KinectBGFilter() +{ + +} + +wxString KinectBGFilter::GetName() const +{ + return _("Simple BG"); +} + +#if defined(HAVE_CUDA) +bool KinectBGFilter::KernelGPU() +{ + if (!m_bStart){ + int curTime = timeGetTime(); + if((int)(curTime - m_ExposureStartTime) > m_CameraExposureTime){ + m_bLearnBackground = true; + m_bStart = true; + } + else + return false; + } + //Capture full background + if (m_bLearnBackground) + { + m_src->copyTo(m_matBg); + m_bLearnBackground = false; + } + // Subtract background + if (m_bTrackDark){ + cv::cuda::subtract(m_matBg, *m_src, m_dst); + } + else{ + cv::cuda::subtract(*m_src, m_matBg, m_dst); + } + + return true; +} +#endif + + +bool KinectBGFilter::Kernel() +{ + // derived class responsible for allocating storage for filtered image + if (source.empty()) + return false; + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), source.type()); + } + if (!m_bStart){ + int curTime = timeGetTime(); + if((int)(curTime - m_ExposureStartTime) > m_CameraExposureTime){ + m_bLearnBackground = true; + m_bStart = true; + } + else + return false; + } + //Capture full background + if (m_bLearnBackground) + { + if(m_bCalibrated && wxFile::Exists(m_filename)){ + + background = cv::imread("c:\\background.jpg", cv::IMREAD_UNCHANGED); + } + else{ + if (background.empty()) + { + background = cv::Mat::zeros(source.size(), source.type()); + } + source.copyTo(background); + //ResetCalibration(); + } + m_bLearnBackground = false; + } + if (background.empty()) + return false; + + // Subtract background + if (m_bTrackDark) + cv::subtract(background, source, destination); + else + cv::subtract(source, background, destination); + + return true; +} + +void KinectBGFilter::CreateParamInputs() +{ + AddParameterBoolInput(_("Learn background"), &m_bLearnBackground); + AddParameterBoolInput(_("Track dark blobs"), &m_bTrackDark); + AddParameterSpinInput(_("Camera exposure time:"), &m_CameraExposureTime, 20000, 0); +} + +void KinectBGFilter::SaveBackground(wxString filename) +{ + m_bCalibrated = !background.empty(); + if(m_bCalibrated) + { + m_filename = filename; + cv::imwrite("c:\\background.jpg", background); + } +} + +void KinectBGFilter::ResetCalibration() +{ + m_bCalibrated = false; + m_bLearnBackground = true; +} + +wxFORCE_LINK_THIS_MODULE(KinectBGFilter); \ No newline at end of file diff --git a/MotionDetectorCore/KinectBGFilter.h b/MotionDetectorCore/KinectBGFilter.h new file mode 100644 index 0000000..bd1af4b --- /dev/null +++ b/MotionDetectorCore/KinectBGFilter.h @@ -0,0 +1,42 @@ +#ifndef __TOUCHLIB_FILTER_KINECTBG__ +#define __TOUCHLIB_FILTER_KINECTBG__ + +#include "FilterTemplate.h" +#include + +class MOTION_DETECTOR_CORE_API KinectBGFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(KinectBGFilter) +public: + KinectBGFilter(); + virtual ~KinectBGFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(); +#endif + virtual wxString GetName() const; + void SaveBackground(wxString filename); + void ResetCalibration(); +protected: + void CreateParamInputs(); + +private: + cv::Mat background; + bool m_bTrackDark; + bool m_bLearnBackground; + int m_ExposureStartTime; + int m_CameraExposureTime; + bool m_bCalibrated; + bool m_bErodeDilate; + wxString m_filename; + cv::Mat m_erodeKernel; + cv::Mat m_dilateKernel; + bool m_bStart; + #if defined(HAVE_CUDA) + cv::cuda::GpuMat m_matBg; + #endif + +}; + +#endif // __TOUCHLIB_FILTER_KINECTBG__ diff --git a/MotionDetectorCore/KinectDepthBGFilter.cpp b/MotionDetectorCore/KinectDepthBGFilter.cpp new file mode 100644 index 0000000..c1b9290 --- /dev/null +++ b/MotionDetectorCore/KinectDepthBGFilter.cpp @@ -0,0 +1,91 @@ +#include "stdwx.h" +#include "KinectDepthBGFilter.h" + +#if defined(__linux__) +#include "LinuxUtils.h" +typedef unsigned short WORD; +#endif + +IMPLEMENT_DYNAMIC_CLASS(KinectDepthBGFilter, Filter); + +KinectDepthBGFilter::KinectDepthBGFilter() +{ + m_bStart = false; + m_bLearnBackground = false; + m_ExposureStartTime = timeGetTime(); + m_CameraExposureTime = 2200; + XS_SERIALIZE(m_CameraExposureTime, wxT("CameraExposureTime")); +} + +KinectDepthBGFilter::~KinectDepthBGFilter() +{ +} + +wxString KinectDepthBGFilter::GetName() const +{ + return _("Depth BG"); +} + +bool KinectDepthBGFilter::Kernel() +{ + if (source.empty()) + return false; + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), source.type()); + } + if (!m_bStart){ + int curTime = timeGetTime(); + if ((int)(curTime - m_ExposureStartTime) > m_CameraExposureTime){ + m_bLearnBackground = true; + m_bStart = true; + } + else + return false; + } + //Capture full background + if (m_bLearnBackground) + { + if (background.empty()) + { + background = cv::Mat::zeros(source.size(), source.type()); + } + source.copyTo(background); + + m_bLearnBackground = false; + } + if (background.empty()) + return false; + + int rows = source.rows; + int cols = source.cols; + + for (int y = 0; y < rows; y++) + { + const float* pSrc = source.ptr(y); + const float* pBg = background.ptr(y); + float* pDst = destination.ptr(y); + + for (int x = 0; x < cols; x++) + { + if (pSrc[x] == 0.0f || pBg[x] == 0.0f || pSrc[x] >= pBg[x]) + { + pDst[x] = 0.0f; + } + else + { + pDst[x] = pBg[x] - pSrc[x]; + } + } + } + return true; + +} +void KinectDepthBGFilter::CreateParamInputs() +{ + AddParameterBoolInput(_("Learn background"), &m_bLearnBackground); + AddParameterSpinInput(_("Camera exposure time:"), &m_CameraExposureTime, 20000, 0); +} + +wxFORCE_LINK_THIS_MODULE(KinectDepthBGFilter); \ No newline at end of file diff --git a/MotionDetectorCore/KinectDepthBGFilter.h b/MotionDetectorCore/KinectDepthBGFilter.h new file mode 100644 index 0000000..2049f2a --- /dev/null +++ b/MotionDetectorCore/KinectDepthBGFilter.h @@ -0,0 +1,30 @@ +#ifndef __TOUCHLIB_FILTER_KINECTDEPTHBG__ +#define __TOUCHLIB_FILTER_KINECTDEPTHBG__ + +#include "FilterTemplate.h" +#include +#include + +class MOTION_DETECTOR_CORE_API KinectDepthBGFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(KinectDepthBGFilter) +public: + KinectDepthBGFilter(); + virtual ~KinectDepthBGFilter(); + + bool Kernel(); + virtual wxString GetName() const; + // This filter cannot be disabled in settings + //virtual bool IsMandatory() { return true; } +protected: + void CreateParamInputs(); + +private: + cv::Mat background; + bool m_bLearnBackground; + int m_ExposureStartTime; + int m_CameraExposureTime; + bool m_bStart; +}; + +#endif // __TOUCHLIB_FILTER_KinectDepthBGFilter__ diff --git a/MotionDetectorCore/KinectMonoFilter.cpp b/MotionDetectorCore/KinectMonoFilter.cpp new file mode 100644 index 0000000..27146a3 --- /dev/null +++ b/MotionDetectorCore/KinectMonoFilter.cpp @@ -0,0 +1,77 @@ +#include "stdwx.h" +#include "KinectMonoFilter.h" + +#if defined(__linux__) +typedef unsigned short WORD; +#endif + +IMPLEMENT_DYNAMIC_CLASS(KinectMonoFilter, Filter); + +KinectMonoFilter::KinectMonoFilter() +{ +} + +KinectMonoFilter::~KinectMonoFilter() +{ +} + +wxString KinectMonoFilter::GetName() const +{ + return _("Mono"); +} + +bool KinectMonoFilter::Kernel() +{ + if (source.empty()) + return false; + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), CV_32FC1); + } + + if (source.channels() == 3) + { + int rows = source.rows; + int cols = source.cols; + + for (int y = 0; y < rows; ++y) + { + const unsigned char* srcRow = source.ptr(y); + float* dstRow = destination.ptr(y); + + for (int x = 0; x < cols; ++x) + { + const unsigned char* dataPtr = srcRow + (x * 3) + 1; + + WORD depthValue = *reinterpret_cast(dataPtr); + dstRow[x] = static_cast(depthValue) / 4095.0f; + } + } + } + else if (source.channels() == 1) + { + + source.convertTo(destination, CV_32F, 1.0 / 4095.0); + } + else + { + return false; + } + //if (source->nChannels != 1 && destination->nChannels == 1) + //{ + // if (strcmpi(source->colorModel, "BGRA") == 0) + // cvCvtColor(source, destination, CV_BGRA2GRAY); + // else if (strcmpi(source->colorModel, "BGR") == 0) + // cvCvtColor(source, destination, CV_BGR2GRAY); + // else if (strcmpi(source->colorModel, "RGB") == 0) + // cvCvtColor(source, destination, CV_RGB2GRAY); + // else + // return false; + //} + //else + // return false; + return true; +} + +wxFORCE_LINK_THIS_MODULE(KinectMonoFilter); \ No newline at end of file diff --git a/MotionDetectorCore/KinectMonoFilter.h b/MotionDetectorCore/KinectMonoFilter.h new file mode 100644 index 0000000..f380d34 --- /dev/null +++ b/MotionDetectorCore/KinectMonoFilter.h @@ -0,0 +1,23 @@ +#ifndef __TOUCHLIB_FILTER_KINECTMONO__ +#define __TOUCHLIB_FILTER_KINECTMONO__ + +#include "FilterTemplate.h" +#include + +class MOTION_DETECTOR_CORE_API KinectMonoFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(KinectMonoFilter) +public: + KinectMonoFilter(); + virtual ~KinectMonoFilter(); + + bool Kernel(); + virtual wxString GetName() const; + // This filter cannot be disabled in settings + virtual bool IsMandatory() { return true; } + +private: + +}; + +#endif // __TOUCHLIB_FILTER_KINECTMONO__ diff --git a/MotionDetectorCore/KinectThresholdFilter.cpp b/MotionDetectorCore/KinectThresholdFilter.cpp new file mode 100644 index 0000000..36d80e8 --- /dev/null +++ b/MotionDetectorCore/KinectThresholdFilter.cpp @@ -0,0 +1,93 @@ +#include "stdwx.h" +#include "KinectThresholdFilter.h" + +#if defined(__linux__) +#include "LinuxUtils.h" +#endif + +IMPLEMENT_DYNAMIC_CLASS(KinectThresholdFilter, Filter); + +KinectThresholdFilter::KinectThresholdFilter() +{ + thresholdSlider1 = 0; + thresholdSlider2 = 4095; + m_bLearnBackground = false; + m_LearnRate = 400; + m_CameraExposureTime = 2200; +#if defined(HAVE_CUDA) + bStart = false; +#endif + + m_ExposureStartTime = timeGetTime(); + XS_SERIALIZE(m_LearnRate, wxT("LearnRate")); + XS_SERIALIZE(m_bLearnBackground, wxT("LearnBackground")); + XS_SERIALIZE(m_CameraExposureTime, wxT("CameraExposureTime")); + XS_SERIALIZE(thresholdSlider1, wxT("Threshold1")); + XS_SERIALIZE(thresholdSlider2, wxT("Threshold2")); + +} + +KinectThresholdFilter::~KinectThresholdFilter() +{ +} + +wxString KinectThresholdFilter::GetName() const +{ + return _("Threshold & Dynamic BG"); +} + +bool KinectThresholdFilter::Kernel() +{ + if (source.empty()) + return false; + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), CV_8UC1); + } + //if (!floatBgImg) + //{ + // floatBgImg = cvCreateImage(cvSize(source->width, source->height), source->depth, source->nChannels); + // floatBgImgTemp = cvCreateImage(cvSize(source->width, source->height), source->depth, source->nChannels); + //} + + //if ((int)(timeGetTime() - m_ExposureStartTime) > m_CameraExposureTime) + // m_bLearnBackground = true; + + ////Capture full background + //if (m_bLearnBackground) + //{ + // //cvConvertScale(source, floatBgImg, 65535.0f / 255.0f, 0); + // cvCopy(source, floatBgImg); + // if (!grayBg) + // { + // grayBg = cvCreateImage(cvSize(source->width, source->height), 8, 1); + // } + // m_ExposureStartTime = timeGetTime(); + // m_bLearnBackground = false; + //} + //if (grayBg == NULL) + // return false; + + //float fLearnRate = (float)m_LearnRate * 0.001f; + //cvAddWeighted(source, fLearnRate, floatBgImg, 1.0f - fLearnRate, 0, floatBgImg); + //cvSub(source, floatBgImg, floatBgImg); + //cvConvertScale(floatBgImg, grayBg, 128.0f, 0); + + float minLevel = static_cast(std::min(thresholdSlider1, thresholdSlider2)) / 4095.0f; + float maxLevel = static_cast(std::max(thresholdSlider1, thresholdSlider2)) / 4095.0f; + + cv::inRange(source, cv::Scalar(minLevel), cv::Scalar(maxLevel), destination); + return true; +} + +void KinectThresholdFilter::CreateParamInputs() +{ + AddParameterSpinInput(_("Threshold level 1:"), &thresholdSlider1, 0xfff); + AddParameterSpinInput(_("Threshold level 2:"), &thresholdSlider2, 0xfff); + //AddParameterBoolInput(_("Learn background"), &m_bLearnBackground); + //AddParameterSpinInput(_("Background learn rate:"), &m_LearnRate, 1000, 0); + //AddParameterSpinInput(_("Camera exposure time:"), &m_CameraExposureTime, 20000, 0); +} + +wxFORCE_LINK_THIS_MODULE(KinectThresholdFilter); \ No newline at end of file diff --git a/MotionDetectorCore/KinectThresholdFilter.h b/MotionDetectorCore/KinectThresholdFilter.h new file mode 100644 index 0000000..050a98a --- /dev/null +++ b/MotionDetectorCore/KinectThresholdFilter.h @@ -0,0 +1,33 @@ +#ifndef __TOUCHSCREEN_FILTER_KINECTTHRESHOLD__ +#define __TOUCHSCREEN_FILTER_KINECTTHRESHOLD__ + +#include "FilterTemplate.h" +#include +#include + +// This filter has two modes. One that dynamically changes the threshold with the help +// of statistics that are recorded, and one which is static. Idea by Damian. +class MOTION_DETECTOR_CORE_API KinectThresholdFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(KinectThresholdFilter) +public: + KinectThresholdFilter(); + virtual ~KinectThresholdFilter(); + + bool Kernel(); + virtual wxString GetName() const; + +private: + + int thresholdSlider1; + int thresholdSlider2; + bool m_bLearnBackground; + int m_ExposureStartTime; + int m_CameraExposureTime; + int m_LearnRate; + +protected: + void CreateParamInputs(); +}; + +#endif // __TOUCHSCREEN_FILTER_KINECTTHRESHOLD__ diff --git a/MotionDetectorCore/LinuxUtils.cpp b/MotionDetectorCore/LinuxUtils.cpp new file mode 100644 index 0000000..60437d7 --- /dev/null +++ b/MotionDetectorCore/LinuxUtils.cpp @@ -0,0 +1,11 @@ +#include "stdwx.h" +#if defined(__LINUX__) +#include + + unsigned int timeGetTime() +{ + struct timeval now; + gettimeofday(&now, NULL); + return (now.tv_sec) * 1000 + (now.tv_usec) / 1000; +} +#endif diff --git a/MotionDetectorCore/LinuxUtils.h b/MotionDetectorCore/LinuxUtils.h new file mode 100644 index 0000000..dc6435a --- /dev/null +++ b/MotionDetectorCore/LinuxUtils.h @@ -0,0 +1,4 @@ + +#include +unsigned int timeGetTime(); + diff --git a/MotionDetectorCore/MonoFilter.cpp b/MotionDetectorCore/MonoFilter.cpp new file mode 100644 index 0000000..1d17963 --- /dev/null +++ b/MotionDetectorCore/MonoFilter.cpp @@ -0,0 +1,67 @@ +#include "stdwx.h" +#include "MonoFilter.h" + + +IMPLEMENT_DYNAMIC_CLASS(MonoFilter, Filter); + +MonoFilter::MonoFilter() +{ +} + +MonoFilter::~MonoFilter() +{ +} + +wxString MonoFilter::GetName() const +{ + return _("Mono"); +} + +#if defined(HAVE_CUDA) +bool MonoFilter::KernelGPU() +{ + if(!m_src) + return false; + //if(!m_dst) m_dst = new cv::gpu::GpuMat(m_src->size(), CV_8UC1); + if (m_src->channels() == 4) + cv::cuda::cvtColor(*m_src, m_dst, cv::COLOR_BGRA2GRAY); + else if (m_src->channels() == 3) + cv::cuda::cvtColor(*m_src, m_dst, cv::COLOR_BGR2GRAY); + else + return false; + return true; +} +#endif + +bool MonoFilter::Kernel() +{ + if (source.empty()) + return false; + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), CV_8UC1); + } + + + if (source.channels() == 4) + { + cv::cvtColor(source, destination, cv::COLOR_BGRA2GRAY); + } + else if (source.channels() == 3) + { + cv::cvtColor(source, destination, cv::COLOR_BGR2GRAY); + } + else if (source.channels() == 1) + { + source.copyTo(destination); + } + else + { + return false; + } + + return true; +} + +wxFORCE_LINK_THIS_MODULE(MonoFilter); diff --git a/MotionDetectorCore/MonoFilter.h b/MotionDetectorCore/MonoFilter.h new file mode 100644 index 0000000..bdd26d4 --- /dev/null +++ b/MotionDetectorCore/MonoFilter.h @@ -0,0 +1,26 @@ +#ifndef __TOUCHLIB_FILTER_MONO__ +#define __TOUCHLIB_FILTER_MONO__ + +#include "FilterTemplate.h" +#include + +class MOTION_DETECTOR_CORE_API MonoFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(MonoFilter) +public: + MonoFilter(); + virtual ~MonoFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + virtual bool KernelGPU(); +#endif + virtual wxString GetName() const; + // This filter cannot be disabled in settings + virtual bool IsMandatory() { return true; } + +private: + +}; + +#endif // __TOUCHLIB_FILTER_MONO__ diff --git a/MotionDetectorCore/MonoKinectFilter.cpp b/MotionDetectorCore/MonoKinectFilter.cpp new file mode 100644 index 0000000..e69de29 diff --git a/MotionDetectorCore/MotionDetectorCorePlugin.h b/MotionDetectorCore/MotionDetectorCorePlugin.h new file mode 100644 index 0000000..e1068f5 --- /dev/null +++ b/MotionDetectorCore/MotionDetectorCorePlugin.h @@ -0,0 +1,10 @@ +#ifndef _MOTIONDETECTORCOREPLUGIN_H +#define _MOTIONDETECTORCOREPLUGIN_H + +#ifdef MOTION_DETECTOR_CORE_EXPORTS +# define MOTION_DETECTOR_CORE_API WXEXPORT +#else +# define MOTION_DETECTOR_CORE_API WXIMPORT +#endif + +#endif // _MOTIONDETECTORCOREPLUGIN_H diff --git a/MotionDetectorCore/PerspectiveFilter.cpp b/MotionDetectorCore/PerspectiveFilter.cpp new file mode 100644 index 0000000..606b3eb --- /dev/null +++ b/MotionDetectorCore/PerspectiveFilter.cpp @@ -0,0 +1,128 @@ +#include "stdwx.h" +#include "PerspectiveFilter.h" +#include +#include + +IMPLEMENT_DYNAMIC_CLASS(PerspectiveFilter, Filter); + +PerspectiveFilter::PerspectiveFilter() +{ + cvsrc.resize(4, cv::Point2f(0.0f, 0.0f)); + cvdst.resize(4, cv::Point2f(0.0f, 0.0f)); + + xMax = xMin = yMin = yMax = 0.0f; + +} + +PerspectiveFilter::~PerspectiveFilter() +{ + +} + +wxString PerspectiveFilter::GetName() const +{ + return _("Perspective"); +} + +#if defined(HAVE_CUDA) +bool PerspectiveFilter::KernelGPU() +{ + if(!Translate()) return false; + cv::Mat translateMat(translate); + m_src->download(src); + //cv::gpu::warpPerspective(*m_src, m_dst, translateMat, cv::Size(xMax - xMin, yMax - yMin)); + cv::warpPerspective(src, dst, translateMat, cv::Size(xMax - xMin, yMax - yMin)); + m_dst.upload(dst); + return true; +} +#endif + + //original code + /** + * A +-------------+ B + * / \ + * / \ + * / \ + * D +-------------------- + C + */ + //CvPoint2D32f cvsrc[4]; + //CvPoint2D32f cvdst[4]; + //CvMat* translate = cvCreateMat(3,3, CV_32FC1); + //cvSetZero(translate); + + //cvdst[0].x = 0; + //cvdst[0].y = 0; + //cvdst[1].x = width; + //cvdst[1].y = 0; + //cvdst[2].x = width; + //cvdst[2].y = height; + //cvdst[3].x = 0; + //cvdst[3].y = height; + + //cvsrc[0].x = A.x; + //cvsrc[0].y = A.y; + //cvsrc[1].x = B.x; + //cvsrc[1].y = B.y; + //cvsrc[2].x = C.x; + //cvsrc[2].y = C.y; + //cvsrc[3].x = D.x; + //cvsrc[3].y = D.y; + + //cvWarpPerspectiveQMatrix(cvsrc, cvdst, translate); // calculate homography + //cvWarpPerspective(cvImage, cvImageTemp, translate); + //swapTemp(); + //flagImageChanged(); + //cvReleaseMat(&translate); + +bool PerspectiveFilter::Translate() +{ + if (cvdst.empty() || cvdst.size() < 4) + return false; + + xMax = cvdst[0].x; + xMin = cvdst[0].x; + yMin = cvdst[0].y; + yMax = cvdst[0].y; + + for (int i = 1; i < 4; i++) + { + xMax = wxMax(xMax, cvdst[i].x); + xMin = wxMin(xMin, cvdst[i].x); + yMax = wxMax(yMax, cvdst[i].y); + yMin = wxMin(yMin, cvdst[i].y); + } + + if (xMin == xMax || yMin == yMax) + return false; + + _translate = cv::getPerspectiveTransform(cvsrc, cvdst); + + return !_translate.empty(); +} + +bool PerspectiveFilter::Kernel() +{ + if(!Translate()) return false; + // derived class responsible for allocating storage for filtered image + if (destination.empty()) + { + destination = cv::Mat::zeros(cv::Size(static_cast(xMax - xMin), static_cast(yMax - yMin)), source.type()); + } + //cvWarpPerspective(source, destination, translate); + cv::warpPerspective(source, destination, _translate, destination.size()); + return true; +} + +void PerspectiveFilter::SetSettings(const IFloorCameraSettings& settings) +{ + cvsrc[0] = cv::Point2f(settings.TopLeftX, settings.TopLeftY); + cvsrc[1] = cv::Point2f(settings.TopRightX, settings.TopRightY); + cvsrc[2] = cv::Point2f(settings.BottomRightX, settings.BottomRightY); + cvsrc[3] = cv::Point2f(settings.BottomLeftX, settings.BottomLeftY); + + cvdst[0] = cv::Point2f(0.0f, 0.0f); + cvdst[1] = cv::Point2f((float)settings.CamWidth, 0.0f); + cvdst[2] = cv::Point2f((float)settings.CamWidth, (float)settings.CamHeight); + cvdst[3] = cv::Point2f(0.0f, (float)settings.CamHeight); +} +wxFORCE_LINK_THIS_MODULE(PerspectiveFilter); \ No newline at end of file diff --git a/MotionDetectorCore/PerspectiveFilter.h b/MotionDetectorCore/PerspectiveFilter.h new file mode 100644 index 0000000..642b035 --- /dev/null +++ b/MotionDetectorCore/PerspectiveFilter.h @@ -0,0 +1,35 @@ +#ifndef __TOUCHSCREEN_FILTER_PERSPECTIVE__ +#define __TOUCHSCREEN_FILTER_PERSPECTIVE__ + +#include "FilterTemplate.h" + +class IFloorCameraSettings; + +class MOTION_DETECTOR_CORE_API PerspectiveFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(PerspectiveFilter) +public: + PerspectiveFilter(); + virtual ~PerspectiveFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(); + cv::Mat src; + cv::Mat dst; + +#endif + virtual wxString GetName() const; + + void SetSettings(const IFloorCameraSettings & settings); + +private: + std::vector cvsrc; + std::vector cvdst; + cv::Mat _translate; + bool Translate(); + float xMax, xMin, yMin, yMax; + +}; + +#endif // __TOUCHSCREEN_FILTER_INVERT__ diff --git a/MotionDetectorCore/RectifyFilter.cpp b/MotionDetectorCore/RectifyFilter.cpp new file mode 100644 index 0000000..a363858 --- /dev/null +++ b/MotionDetectorCore/RectifyFilter.cpp @@ -0,0 +1,90 @@ +#include "stdwx.h" +#include "RectifyFilter.h" +#include "Image.h" + +IMPLEMENT_DYNAMIC_CLASS(RectifyFilter, Filter); + +RectifyFilter::RectifyFilter() +{ + level = (unsigned int) DEFAULT_RECTIFYLEVEL; + level_slider = level; + + bAutoSet = false; + XS_SERIALIZE(bAutoSet, wxT("AutoSet")); + XS_SERIALIZE(level_slider, wxT("Threshold")); +} + +RectifyFilter::~RectifyFilter() +{ +} + +wxString RectifyFilter::GetName() const +{ + return _("Rectify"); +} + +//void RectifyFilter::getParameters(iFloorParamMap& pMap) +//{ +// pMap[std::string("level")] = bAutoSet ? std::string("auto") : toString(level); +//} +// +//void RectifyFilter::setParameter(const char *name, const char *value) +//{ +// if(strcmp(name, "level") == 0) +// { +// if(strcmp(value, "auto") == 0) +// { +// bAutoSet = true; +// printf("Auto set\n"); +// } else +// { +// level = (int) atof(value); +// level_slider = level; +// if(show) +// cvSetTrackbarPos("level", this->name.c_str(), level); +// } +// } +// +//} + +bool RectifyFilter::Kernel() +{ + level = level_slider; + // derived class responsible for allocating storage for filtered image + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), CV_8UC1); + } + + if (bAutoSet) + { + touchlib::BwImage img(&source); + + int h, w; + h = img.getHeight(); + w = img.getWidth(); + + unsigned char highest = 0; + + for (int y=0; y highest) + highest = img[y][x]; + } + + setLevel((unsigned int)highest); + bAutoSet = false; + } + + cv::threshold(source, destination, level, 255, cv::THRESH_TOZERO); //CV_THRESH_BINARY + return true; +} + +void RectifyFilter::CreateParamInputs() +{ + AddParameterBoolInput(_("Automatic level"), &bAutoSet); + AddParameterSpinInput(_("Threshold level:"), &level_slider, 255); +} + +wxFORCE_LINK_THIS_MODULE(RectifyFilter); \ No newline at end of file diff --git a/MotionDetectorCore/RectifyFilter.h b/MotionDetectorCore/RectifyFilter.h new file mode 100644 index 0000000..36e68d1 --- /dev/null +++ b/MotionDetectorCore/RectifyFilter.h @@ -0,0 +1,32 @@ +#ifndef __TOUCHSCREEN_FILTER_RECTIFY__ +#define __TOUCHSCREEN_FILTER_RECTIFY__ + +#include "FilterTemplate.h" + +#define DEFAULT_RECTIFYLEVEL 20 + +class MOTION_DETECTOR_CORE_API RectifyFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(RectifyFilter) +public: + RectifyFilter(); + virtual ~RectifyFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(){return false;} +#endif + virtual wxString GetName() const; + + void setLevel(unsigned int value) {level = value; level_slider = level;} + unsigned int getLevel(void) {return level;} +protected: + void CreateParamInputs(); + +private: + bool bAutoSet; + int level_slider; + int level; +}; + +#endif // __TOUCHSCREEN_FILTER_RECTIFY__ diff --git a/MotionDetectorCore/ResizeFilter.cpp b/MotionDetectorCore/ResizeFilter.cpp new file mode 100644 index 0000000..62ce8ac --- /dev/null +++ b/MotionDetectorCore/ResizeFilter.cpp @@ -0,0 +1,66 @@ +#include "stdwx.h" +#include "ResizeFilter.h" + +IMPLEMENT_DYNAMIC_CLASS(ResizeFilter, Filter); + +ResizeFilter::ResizeFilter() +{ + sizeX = DEFAULT_RESIZEWIDTH; + sizeY = DEFAULT_RESIZEHEIGHT; +} + +ResizeFilter::~ResizeFilter() +{ + +} + +wxString ResizeFilter::GetName() const +{ + return _("Resize"); +} + +//void ResizeFilter::getParameters(iFloorParamMap& pMap) +//{ +// pMap[std::string("sizeX")] = toString(sizeX); +// pMap[std::string("sizeY")] = toString(sizeY); +//} +// +// +//void ResizeFilter::setParameter(const char *name, const char *value) +//{ +// if(strcmp(name, "sizeX") == 0) +// { +// sizeX = (int) atof(value); +// +// if(destination) +// cvReleaseImage(&destination); +// +// destination = cvCreateImage(cvSize(sizeX,sizeY), 8, 1); +// } +// if(strcmp(name, "sizeY") == 0) +// { +// sizeY = (int) atof(value); +// +// if(destination) +// cvReleaseImage(&destination); +// +// destination = cvCreateImage(cvSize(sizeX,sizeY), 8, 1); +// } +//} + +// We are assuming 8 bit depth, 1 channel.. so this filter should happen after the mono filter.. +bool ResizeFilter::Kernel() +{ + // derived class responsible for allocating storage for filtered image + if (source.empty()) + return false; + + if (sizeX <= 0 || sizeY <= 0) + return false; + + cv::resize(source, destination, cv::Size(sizeX, sizeY), 0, 0, cv::INTER_LINEAR); + + return true; +} + +wxFORCE_LINK_THIS_MODULE(ResizeFilter); \ No newline at end of file diff --git a/MotionDetectorCore/ResizeFilter.h b/MotionDetectorCore/ResizeFilter.h new file mode 100644 index 0000000..f5f27cb --- /dev/null +++ b/MotionDetectorCore/ResizeFilter.h @@ -0,0 +1,29 @@ +#ifndef __TOUCHLIB_FILTER_RESIZE__ +#define __TOUCHLIB_FILTER_RESIZE__ + +#include "FilterTemplate.h" +#include + +#define DEFAULT_RESIZEWIDTH 480 +#define DEFAULT_RESIZEHEIGHT 640 + +class MOTION_DETECTOR_CORE_API ResizeFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(ResizeFilter) +public: + ResizeFilter(); + virtual ~ResizeFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(){return false;} +#endif + virtual wxString GetName() const; + +private: + + int sizeX; + int sizeY; +}; + +#endif // __TOUCHLIB_FILTER_RESIZE__ diff --git a/MotionDetectorCore/ScalerFilter.cpp b/MotionDetectorCore/ScalerFilter.cpp new file mode 100644 index 0000000..299b5e5 --- /dev/null +++ b/MotionDetectorCore/ScalerFilter.cpp @@ -0,0 +1,50 @@ +#include "stdwx.h" +#include "ScalerFilter.h" +#include "Image.h" + +IMPLEMENT_DYNAMIC_CLASS(ScalerFilter, Filter); + +ScalerFilter::ScalerFilter() +{ + level = (unsigned int) DEFAULT_RECTIFYLEVEL; +} + +ScalerFilter::~ScalerFilter() +{ +} + +wxString ScalerFilter::GetName() const +{ + return _("Scaler"); +} + +//void ScalerFilter::getParameters(iFloorParamMap& pMap) +//{ +// pMap[std::string("level")] = toString(level); +//} +// +//void ScalerFilter::setParameter(const char *name, const char *value) +//{ +// if(strcmp(name, "level") == 0) +// { +// level = (int) atof(value); +// level_slider = level; +// if(show) +// cvSetTrackbarPos("level", this->name.c_str(), level); +// } +//} + +bool ScalerFilter::Kernel() +{ + // derived class responsible for allocating storage for filtered image + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), CV_8UC1); + } + + float scale = (float)level / 128.0f; + destination = source.mul(source) * scale; + return true; +} + +wxFORCE_LINK_THIS_MODULE(ScalerFilter); \ No newline at end of file diff --git a/MotionDetectorCore/ScalerFilter.h b/MotionDetectorCore/ScalerFilter.h new file mode 100644 index 0000000..9d091b2 --- /dev/null +++ b/MotionDetectorCore/ScalerFilter.h @@ -0,0 +1,29 @@ +#ifndef __TOUCHSCREEN_FILTER_SCALER__ +#define __TOUCHSCREEN_FILTER_SCALER__ + +#include "FilterTemplate.h" + +#define DEFAULT_RECTIFYLEVEL 20 + +class MOTION_DETECTOR_CORE_API ScalerFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(ScalerFilter) +public: + ScalerFilter(); + virtual ~ScalerFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(){return false;} +#endif + virtual wxString GetName() const; + + void setLevel(unsigned int value) { level = value; } + unsigned int getLevel(void) { return level; } + +private: + bool bAutoSet; + unsigned int level; +}; + +#endif // __TOUCHSCREEN_FILTER_RECTIFY__ diff --git a/MotionDetectorCore/ShapeFilter.cpp b/MotionDetectorCore/ShapeFilter.cpp new file mode 100644 index 0000000..81666b5 --- /dev/null +++ b/MotionDetectorCore/ShapeFilter.cpp @@ -0,0 +1,102 @@ +#include "stdwx.h" +#include "ShapeFilter.h" +#include + +// ---- initialization of non-integral constants ---------------------------- + + +const char *ShapeFilter::TRACKBAR_LABEL_BLUR = "blur"; +const char *ShapeFilter::PARAMETER_BLUR = "blur"; + +const char *ShapeFilter::TRACKBAR_LABEL_LEVEL = "level"; +const char *ShapeFilter::PARAMETER_LEVEL = "level"; + + +// ---- implementations ----------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(ShapeFilter, Filter); + +ShapeFilter::ShapeFilter() +{ + blurLevel = DEFAULT_BLUR_LEVEL; + levelLevel = DEFAULT_LEVEL_LEVEL; +} + + +ShapeFilter::~ShapeFilter() +{ + +} + +wxString ShapeFilter::GetName() const +{ + return _("Shape"); +} + +bool ShapeFilter::Kernel() +{ + if (source.empty()) + { + return false; + } + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), source.type()); + } + if (buffer.empty()) + { + buffer = cv::Mat::zeros(source.size(), source.type()); + } + + destination.setTo(cv::Scalar::all(0)); + + // create the unsharp mask using a linear average filter + int blurParameter = blurLevel * 2 + 1; + cv::blur(source, buffer, cv::Size(blurParameter, blurParameter)); + + //cvSub(source, buffer, buffer); +// cvAbsDiff(source, buffer, buffer); + + cv::Mat tempSource = source.clone(); + cv::threshold(tempSource, tempSource, levelLevel, 255, cv::THRESH_TOZERO); + cv::Canny(tempSource, destination, (float)blurParameter, (float)blurParameter * 3, 3); + + return true; + +/* + //cvSmooth(buffer, buffer, CV_MEDIAN, 3, 1); + + CvMemStorage* storage = cvCreateMemStorage(0); + CvSeq* contours = 0; + CvSeq *result; + cvFindContours( buffer, storage, &contours, sizeof(CvContour), CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE ); + + for( ; contours != 0; contours = contours->h_next ) + { + int count = contours->total; // This is number point in contour + + // First we check to see if this contour looks like a square.. + + result = cvApproxPoly( contours, sizeof(CvContour), storage, + CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 ); + + CvRect r = cvBoundingRect(result); + double area = fabs(cvContourArea(result,CV_WHOLE_SEQ)); + cvDrawContours(destination, result, CV_RGB(255,255,255), CV_RGB(255,255,255), 3, 2, CV_FILLED); + if( result->total > 2 && + area > 20 && r.width < 50 && r.height < 50) + { + + + } + + //contours = cvApproxPoly( contours, sizeof(CvContour), storage, CV_POLY_APPROX_DP, 3, 1 ); + + + } + cvReleaseMemStorage(&storage); +*/ +} + +wxFORCE_LINK_THIS_MODULE(ShapeFilter); \ No newline at end of file diff --git a/MotionDetectorCore/ShapeFilter.h b/MotionDetectorCore/ShapeFilter.h new file mode 100644 index 0000000..0330fc0 --- /dev/null +++ b/MotionDetectorCore/ShapeFilter.h @@ -0,0 +1,36 @@ +#ifndef __TOUCHSCREEN_FILTER_SHAPE__ +#define __TOUCHSCREEN_FILTER_SHAPE__ + +#include "FilterTemplate.h" + +class MOTION_DETECTOR_CORE_API ShapeFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(ShapeFilter) +public: + ShapeFilter(); + virtual ~ShapeFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(){return false;} +#endif + virtual wxString GetName() const; + +private: + static const int DEFAULT_BLUR_LEVEL = 10; + static const char *TRACKBAR_LABEL_BLUR; + static const char *PARAMETER_BLUR; + + static const int DEFAULT_LEVEL_LEVEL = 0; + static const char *TRACKBAR_LABEL_LEVEL; + static const char *PARAMETER_LEVEL; + + int blurLevel; + int levelLevel; + + cv::Mat buffer; + + void setNoiseSmoothType(int noiseMethod); +}; + +#endif // __TOUCHSCREEN_FILTER_SIMPLE_HIGHPASS__ diff --git a/MotionDetectorCore/SimpleBGFilter.cpp b/MotionDetectorCore/SimpleBGFilter.cpp new file mode 100644 index 0000000..c52ebdf --- /dev/null +++ b/MotionDetectorCore/SimpleBGFilter.cpp @@ -0,0 +1,155 @@ +#include "stdwx.h" +#include "SimpleBGFilter.h" +//#include +#include + +#if defined(__LINUX__) +#include "LinuxUtils.h" +#endif +// LINUX_ + +IMPLEMENT_DYNAMIC_CLASS(SimpleBGFilter, Filter); + +SimpleBGFilter::SimpleBGFilter() +{ + m_bTrackDark = false; + m_ExposureStartTime = timeGetTime(); + m_bLearnBackground = false; + m_bStart = false; + m_CameraExposureTime = 2200; + m_bCalibrated = false; + XS_SERIALIZE(m_bTrackDark, wxT("TrackDark")); + XS_SERIALIZE(m_CameraExposureTime, wxT("CameraExposureTime")); + XS_SERIALIZE(m_bCalibrated, wxT("Calibrated")); + XS_SERIALIZE(m_filename, wxT("filename")); +} + +SimpleBGFilter::~SimpleBGFilter() +{ + +} + +wxString SimpleBGFilter::GetName() const +{ + return _("Simple BG"); +} + +#if defined(HAVE_CUDA) +bool SimpleBGFilter::KernelGPU() +{ + if (!m_bStart){ + int curTime = timeGetTime(); + if((int)(curTime - m_ExposureStartTime) > m_CameraExposureTime){ + m_bLearnBackground = true; + m_bStart = true; + } + else + return false; + } + //Capture full background + if (m_bLearnBackground) + { + m_src->copyTo(m_matBg); + m_bLearnBackground = false; + } + // Subtract background + if (m_bTrackDark){ + cv::gpu::subtract(m_matBg, *m_src, m_dst); + } + else{ + cv::gpu::subtract(*m_src, m_matBg, m_dst); + } + + return true; +} +#endif + + +bool SimpleBGFilter::Kernel() +{ + // derived class responsible for allocating storage for filtered image + if (source.empty()) + { + return false; + } + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), CV_8UC1); + } + if (!m_bStart) + { + int curTime = timeGetTime(); + //wxLogDebug(wxT("%i, %i %i > %i"), curTime, m_ExposureStartTime, curTime - m_ExposureStartTime, m_CameraExposureTime); + if((int)(curTime - m_ExposureStartTime) > m_CameraExposureTime) + { + m_bLearnBackground = true; + m_bStart = true; + } + else + { + return false; + } + } + //Capture full background + if (m_bLearnBackground) + { + if(m_bCalibrated && wxFile::Exists(m_filename)) + { + background = cv::imread("c:\\background.jpg", cv::IMREAD_GRAYSCALE); + } + else + { + if (background.empty()) + { + background = cv::Mat::zeros(source.size(), CV_8UC1); + } + source.copyTo(background); + //ResetCalibration(); + } + m_bLearnBackground = false; + } + if (background.empty()) + { + return false; + } + + //IplImage* destination1 = cvCreateImage(cvSize(source->width, source->height), IPL_DEPTH_8U, 1); + //cvSub(background, source, destination1); + //else + /*cvSub(source, background, destination); + cvOr(destination, destination1, destination); +*/ + // Subtract background + if (m_bTrackDark) + cv::subtract(background, source, destination); + else + cv::subtract(source, background, destination); + + return true; +} + +void SimpleBGFilter::CreateParamInputs() +{ + AddParameterBoolInput(_("Learn background"), &m_bLearnBackground); + AddParameterBoolInput(_("Track dark blobs"), &m_bTrackDark); + AddParameterSpinInput(_("Camera exposure time:"), &m_CameraExposureTime, 20000, 0); +} + +void SimpleBGFilter::SaveBackground(wxString filename) +{ + m_bCalibrated = background.empty(); + if(m_bCalibrated) + { + m_filename = filename; + cv::imwrite("c:\\background.jpg", background); + } +} + +void SimpleBGFilter::ResetCalibration() +{ + m_bCalibrated = false; + m_bLearnBackground = true; +} + +wxFORCE_LINK_THIS_MODULE(SimpleBGFilter); diff --git a/MotionDetectorCore/SimpleBGFilter.h b/MotionDetectorCore/SimpleBGFilter.h new file mode 100644 index 0000000..1270265 --- /dev/null +++ b/MotionDetectorCore/SimpleBGFilter.h @@ -0,0 +1,43 @@ +#ifndef __TOUCHLIB_FILTER_SIMPLEBG__ +#define __TOUCHLIB_FILTER_SIMPLEBG__ + +#include "FilterTemplate.h" +#include +#include + +class MOTION_DETECTOR_CORE_API SimpleBGFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(SimpleBGFilter) +public: + SimpleBGFilter(); + virtual ~SimpleBGFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(); +#endif + virtual wxString GetName() const; + void SaveBackground(wxString filename); + void ResetCalibration(); +protected: + void CreateParamInputs(); + +private: + cv::Mat background; + bool m_bTrackDark; + bool m_bLearnBackground; + int m_ExposureStartTime; + int m_CameraExposureTime; + bool m_bCalibrated; + bool m_bErodeDilate; + wxString m_filename; + cv::Mat m_erodeKernel; + cv::Mat m_dilateKernel; + bool m_bStart; + #if defined(HAVE_CUDA) + cv::cuda::GpuMat m_matBg; + #endif + +}; + +#endif // __TOUCHLIB_FILTER_SIMPLEBG__ diff --git a/MotionDetectorCore/SimpleHighpassFilter.cpp b/MotionDetectorCore/SimpleHighpassFilter.cpp new file mode 100644 index 0000000..c0a1d0a --- /dev/null +++ b/MotionDetectorCore/SimpleHighpassFilter.cpp @@ -0,0 +1,98 @@ +#include "stdwx.h" +#include "SimpleHighpassFilter.h" + +IMPLEMENT_DYNAMIC_CLASS(SimpleHighpassFilter, Filter); + +SimpleHighpassFilter::SimpleHighpassFilter() +{ + noiseSmoothType = 1; + blurLevel = DEFAULT_BLUR_LEVEL; + + setNoiseSmoothType(DEFAULT_NOISE_METHOD); + + noiseLevel = DEFAULT_NOISE_LEVEL; + + XS_SERIALIZE(blurLevel, wxT("BlurLevel")); + XS_SERIALIZE(noiseLevel, wxT("NoiseLevel")); + XS_SERIALIZE(noiseSmoothType, wxT("NoiseSmoothType")); +} + +SimpleHighpassFilter::~SimpleHighpassFilter() +{ + +} + +wxString SimpleHighpassFilter::GetName() const +{ + return _("Simple Highpass"); +} + +void SimpleHighpassFilter::setNoiseSmoothType(int noiseMethod) +{ + //switch (noiseMethod) + //{ + //case NOISE_METHOD_MEDIAN: + // noiseSmoothType = CV_MEDIAN; + // break; + //case NOISE_METHOD_BLUR: + noiseSmoothType = 1; + // break; + //} +} +#if defined(HAVE_CUDA) +bool SimpleHighpassFilter::KernelGPU() +{ + int blurParameter = blurLevel * 2 + 1; + int noiseParameter = noiseLevel * 2 + 1; + cv::Mat tmp, tmpDst; + if(blurLevel){ + cv::cuda::blur(*m_src, m_tmpGpuMat, cv::Size(blurParameter, blurParameter)); + cv::cuda::subtract(*m_src, m_tmpGpuMat, m_tmpGpuMat); + m_tmpGpuMat.download(tmp); + } + else + m_src->download(tmp); + + cv::medianBlur(tmp, tmpDst, noiseParameter); + m_dst.upload(tmpDst); + return true; +} +#endif + + +bool SimpleHighpassFilter::Kernel() +{ + if (source.empty()) + { + return false; + } + + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), source.type()); + } + if (buffer.empty()) + { + buffer = cv::Mat::zeros(source.size(), source.type()); + } + + int blurParameter = blurLevel * 2 + 1; + int noiseParameter = noiseLevel * 2 + 1; + // create the unsharp mask using a linear average filter + cv::blur(source, buffer, cv::Size(blurParameter, blurParameter)); + //cvAbsDiff(source, buffer, buffer); + cv::subtract(source, buffer, buffer); + + // filter out the noise using a median filter + cv::medianBlur(buffer, destination, noiseParameter); + return true; +} + +void SimpleHighpassFilter::CreateParamInputs() +{ + AddParameterSpinInput(_("Blur level:"), &blurLevel, 200, 0); + AddParameterSpinInput(_("Noise level:"), &noiseLevel, 30, 0); +} + +wxFORCE_LINK_THIS_MODULE(SimpleHighpassFilter); diff --git a/MotionDetectorCore/SimpleHighpassFilter.h b/MotionDetectorCore/SimpleHighpassFilter.h new file mode 100644 index 0000000..105ace0 --- /dev/null +++ b/MotionDetectorCore/SimpleHighpassFilter.h @@ -0,0 +1,50 @@ +#ifndef __TOUCHSCREEN_FILTER_SIMPLE_HIGHPASS__ +#define __TOUCHSCREEN_FILTER_SIMPLE_HIGHPASS__ + +#include "FilterTemplate.h" +#include + +// This filter is used for filtering out sharp-edged objects from an image. +class MOTION_DETECTOR_CORE_API SimpleHighpassFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(SimpleHighpassFilter) +public: + SimpleHighpassFilter(); + virtual ~SimpleHighpassFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(); +#endif + virtual wxString GetName() const; + +private: + + // ---- constants ---------------------------------------------------------- + + static const int DEFAULT_BLUR_LEVEL = 10; + static const int DEFAULT_NOISE_METHOD = 1; + static const int DEFAULT_NOISE_LEVEL = 3; + + static const int NOISE_METHOD_MEDIAN = 0; + static const int NOISE_METHOD_BLUR = 1; + + // ---- instance variables ------------------------------------------------- + + int blurLevel; + int noiseSmoothType; + int noiseLevel; + + cv::Mat buffer; +#if defined(HAVE_CUDA) + cv::cuda::GpuMat m_matBg; +#endif + + // ---- methods ------------------------------------------------------------ + + void setNoiseSmoothType(int noiseMethod); +protected: + void CreateParamInputs(); +}; + +#endif // __TOUCHSCREEN_FILTER_SIMPLE_HIGHPASS__ diff --git a/MotionDetectorCore/SmoothingFilter.cpp b/MotionDetectorCore/SmoothingFilter.cpp new file mode 100644 index 0000000..a07da02 --- /dev/null +++ b/MotionDetectorCore/SmoothingFilter.cpp @@ -0,0 +1,70 @@ +#include "stdwx.h" +#include "SmoothingFilter.h" + +IMPLEMENT_DYNAMIC_CLASS(SmoothingFilter, Filter); + +SmoothingFilter::SmoothingFilter() +{ + level = 0; + XS_SERIALIZE(level, "Level"); + +} + +SmoothingFilter::~SmoothingFilter() +{ +} + +wxString SmoothingFilter::GetName() const +{ + return _("Smoothing"); +} + +#if defined(HAVE_CUDA) +bool SmoothingFilter::KernelGPU() +{ + if (m_src->empty()) + return false; + + int lvl = level * 2 + 1; + if (lvl > 1) + { + cv::cuda::blur(*m_src, m_dst, cv::Size(lvl, lvl)); + } + else + { + m_src->copyTo(m_dst); + } + return true; +} +#endif + +// The smooth filter really needs the blur size as a param +bool SmoothingFilter::Kernel() +{ + if (source.empty()) + return false; + + // derived class responsible for allocating storage for filtered image + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), source.type()); + } + + int lvl = level * 2 + 1; + + if (lvl > 1) + { + cv::blur(source, destination, cv::Size(lvl, lvl)); + } + else + { + source.copyTo(destination); + } +} + +void SmoothingFilter::CreateParamInputs() +{ + AddParameterSpinInput(_("Smooth level:"), &level, 15); +} + +wxFORCE_LINK_THIS_MODULE(SmoothingFilter); \ No newline at end of file diff --git a/MotionDetectorCore/SmoothingFilter.h b/MotionDetectorCore/SmoothingFilter.h new file mode 100644 index 0000000..d7aa699 --- /dev/null +++ b/MotionDetectorCore/SmoothingFilter.h @@ -0,0 +1,25 @@ +#ifndef __TOUCHSCREEN_FILTER_SMOOTHING__ +#define __TOUCHSCREEN_FILTER_SMOOTHING__ + +#include "FilterTemplate.h" +#include + +class MOTION_DETECTOR_CORE_API SmoothingFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(SmoothingFilter) +public: + SmoothingFilter(); + virtual ~SmoothingFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(); +#endif + virtual wxString GetName() const; + + int level; +protected: + void CreateParamInputs(); +}; + +#endif // __TOUCHSCREEN_FILTER_SMOOTHING__ diff --git a/MotionDetectorCore/SubOrBGFilter.cpp b/MotionDetectorCore/SubOrBGFilter.cpp new file mode 100644 index 0000000..a4ecd46 --- /dev/null +++ b/MotionDetectorCore/SubOrBGFilter.cpp @@ -0,0 +1,151 @@ +#include "stdwx.h" +#include "SubOrBGFilter.h" +#include + +#if defined(__LINUX__) +#include "LinuxUtils.h" +#endif +// LINUX_ + +IMPLEMENT_DYNAMIC_CLASS(SubOrBGFilter, Filter); + +SubOrBGFilter::SubOrBGFilter() +{ + m_ExposureStartTime = timeGetTime(); + + m_bLearnBackground = false; + m_bStart = false; + m_CameraExposureTime = 2200; + m_bCalibrated = false; + XS_SERIALIZE(m_CameraExposureTime, wxT("CameraExposureTime")); + XS_SERIALIZE(m_bCalibrated, wxT("Calibrated")); + XS_SERIALIZE(m_filename, wxT("filename")); +} + +SubOrBGFilter::~SubOrBGFilter() +{ + +} + +wxString SubOrBGFilter::GetName() const +{ + return _("Substruct OR BG"); +} + +#if defined(HAVE_CUDA) +bool SubOrBGFilter::KernelGPU() +{ + if (!m_bStart){ + int curTime = timeGetTime(); + if ((int)(curTime - m_ExposureStartTime) > m_CameraExposureTime){ + m_bLearnBackground = true; + m_bStart = true; + } + else + return false; + } + //Capture full background + if (m_bLearnBackground) + { + m_src->copyTo(m_matBg); + m_bLearnBackground = false; + } + // Subtract background + if (m_bTrackDark){ + cv::cuda::subtract(m_matBg, *m_src, m_dst); + } + else{ + cv::cuda::subtract(*m_src, m_matBg, m_dst); + } + + return true; +} +#endif + + +bool SubOrBGFilter::Kernel() +{ + // derived class responsible for allocating storage for filtered image + if (source.empty()) + { + return false; + } + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), CV_8UC1); + } + if (!m_bStart) + { + int curTime = timeGetTime(); + //wxLogDebug(wxT("%i, %i %i > %i"), curTime, m_ExposureStartTime, curTime - m_ExposureStartTime, m_CameraExposureTime); + if ((int)(curTime - m_ExposureStartTime) > m_CameraExposureTime) + { + m_bLearnBackground = true; + m_bStart = true; + } + else + { + return false; + } + } + //Capture full background + if (m_bLearnBackground) + { + if (m_bCalibrated && wxFile::Exists(m_filename)) + { + background = cv::imread("c:\\background.jpg", cv::IMREAD_GRAYSCALE); + } + else + { + if (background.empty()) + { + background = cv::Mat::zeros(source.size(), CV_8UC1); + } + if (destination1.empty()) + { + destination1 = cv::Mat::zeros(source.size(), CV_8UC1); + } + source.copyTo(background); + //ResetCalibration(); + } + m_bLearnBackground = false; + } + if (background.empty()) + { + return false; + } + + cv::subtract(background, source, destination1); + cv::subtract(source, background, destination); + cv::bitwise_or(destination, destination1, destination); + return true; +} + +void SubOrBGFilter::CreateParamInputs() +{ + AddParameterBoolInput(_("Learn background"), &m_bLearnBackground); + AddParameterSpinInput(_("Camera exposure time:"), &m_CameraExposureTime, 20000, 0); +} + +void SubOrBGFilter::SaveBackground(wxString filename) +{ + m_bCalibrated = !background.empty(); + if (m_bCalibrated) + { + m_filename = filename; + // cvSaveImage(/*filename.c_str()*/"c:\\background.jpg", background); + } +} + +void SubOrBGFilter::ResetCalibration() +{ + m_bCalibrated = false; + m_bLearnBackground = true; +} + +wxFORCE_LINK_THIS_MODULE(SubOrBGFilter); +//cvSub(background, source, destination1); +////else +//cvSub(source, background, destination); +//cvOr(destination, destination1, destination); diff --git a/MotionDetectorCore/SubOrBGFilter.h b/MotionDetectorCore/SubOrBGFilter.h new file mode 100644 index 0000000..351359a --- /dev/null +++ b/MotionDetectorCore/SubOrBGFilter.h @@ -0,0 +1,43 @@ +#ifndef __TOUCHLIB_FILTER_SUBORBG__ +#define __TOUCHLIB_FILTER_SUBORBG__ + +#include "FilterTemplate.h" +#include +#include + +class MOTION_DETECTOR_CORE_API SubOrBGFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(SubOrBGFilter) +public: + SubOrBGFilter(); + virtual ~SubOrBGFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(); +#endif + virtual wxString GetName() const; + void SaveBackground(wxString filename); + void ResetCalibration(); +protected: + void CreateParamInputs(); + +private: + cv::Mat background; + cv::Mat destination1; + bool m_bLearnBackground; + int m_ExposureStartTime; + int m_CameraExposureTime; + bool m_bCalibrated; + bool m_bErodeDilate; + wxString m_filename; + cv::Mat m_erodeKernel; + cv::Mat m_dilateKernel; + bool m_bStart; +#if defined(HAVE_CUDA) + cv::cuda::GpuMat m_matBg; +#endif + +}; + +#endif // __TOUCHLIB_FILTER_SUBORBG__ diff --git a/MotionDetectorCore/ThresholdFilter.cpp b/MotionDetectorCore/ThresholdFilter.cpp new file mode 100644 index 0000000..42c6e3f --- /dev/null +++ b/MotionDetectorCore/ThresholdFilter.cpp @@ -0,0 +1,58 @@ +#include "stdwx.h" +#include "ThresholdFilter.h" + + +// ---- initialization of non-integral constants ---------------------------- + + +// ---- implementations ----------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(ThresholdFilter, Filter); + +ThresholdFilter::ThresholdFilter() +{ + thresholdSlider1 = 1; + + XS_SERIALIZE(thresholdSlider1, wxT("Threshold1")); + +} + +ThresholdFilter::~ThresholdFilter() +{ +} + +wxString ThresholdFilter::GetName() const +{ + return _("Threshold"); +} + +#if defined(HAVE_CUDA) +bool ThresholdFilter::KernelGPU() +{ + cv::cuda::threshold(*m_src, m_dst, thresholdSlider1, 255, cv::THRESH_BINARY); + return true; +} +#endif + + +bool ThresholdFilter::Kernel() +{ + if (source.empty()) + return false; + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), source.type()); + } + + cv::threshold(source, destination, thresholdSlider1, 255, cv::THRESH_BINARY); + + return true; +} + +void ThresholdFilter::CreateParamInputs() +{ + AddParameterSpinInput(_("Threshold level:"), &thresholdSlider1, 255); +} + +wxFORCE_LINK_THIS_MODULE(ThresholdFilter); \ No newline at end of file diff --git a/MotionDetectorCore/ThresholdFilter.h b/MotionDetectorCore/ThresholdFilter.h new file mode 100644 index 0000000..8c17cc4 --- /dev/null +++ b/MotionDetectorCore/ThresholdFilter.h @@ -0,0 +1,30 @@ +#ifndef __TOUCHSCREEN_FILTER_THRESHOLD__ +#define __TOUCHSCREEN_FILTER_THRESHOLD__ + +#include "FilterTemplate.h" +#include + +// This filter has two modes. One that dynamically changes the threshold with the help +// of statistics that are recorded, and one which is static. Idea by Damian. +class MOTION_DETECTOR_CORE_API ThresholdFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(ThresholdFilter) +public: + ThresholdFilter(); + virtual ~ThresholdFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(); +#endif + virtual wxString GetName() const; + +private: + + int thresholdSlider1; + +protected: + void CreateParamInputs(); +}; + +#endif // __TOUCHSCREEN_FILTER_THRESHOLD__ diff --git a/MotionDetectorCore/Tracking.cpp b/MotionDetectorCore/Tracking.cpp new file mode 100644 index 0000000..ca4d062 --- /dev/null +++ b/MotionDetectorCore/Tracking.cpp @@ -0,0 +1,219 @@ +#include "stdwx.h" +#include "Tracking.h" + +#if defined(USE_VLD) +#include +#endif + +BlobTracker::BlobTracker() +{ + IDCounter = 0; + isCalibrating = false; +} + +BlobTracker::~BlobTracker(){ + +} + +// Assigns IDs to each blob in the contourFinder +void BlobTracker::track(ContourFinder* newBlobs) +{ + //initialize ID's of all blobs + for(size_t i=0; iblobs.size(); i++) + newBlobs->blobs[i].id=-1; + + //go through all tracked blobs to compute nearest new point + for (size_t i=0; iblobs[winner].id!=-1) + { + //find the currently assigned blob + size_t j = 0; //j will be the index of it + for (j = 0; j < trackedBlobs.size(); j++) + { + if (trackedBlobs[j].id==newBlobs->blobs[winner].id) break; + } + + if (j==trackedBlobs.size())//got to end without finding it + { + newBlobs->blobs[winner].id = trackedBlobs[i].id; + trackedBlobs[i] = newBlobs->blobs[winner]; + } + else //found it, compare with current blob + { + double x = newBlobs->blobs[winner].centroid.x; + double y = newBlobs->blobs[winner].centroid.y; + double xOld = trackedBlobs[j].centroid.x; + double yOld = trackedBlobs[j].centroid.y; + double xNew = trackedBlobs[i].centroid.x; + double yNew = trackedBlobs[i].centroid.y; + double distOld = (x-xOld)*(x-xOld)+(y-yOld)*(y-yOld); + double distNew = (x-xNew)*(x-xNew)+(y-yNew)*(y-yNew); + + //if this track is closer, update the ID of the blob + //otherwise delete this track.. it's dead + if (distNew < distOld) //update + { + newBlobs->blobs[winner].id = trackedBlobs[i].id; + trackedBlobs[j].id = -1; +//------------------------------------------------------------------------------ + } + else //delete + { + trackedBlobs[i].id = -1; + } + } + } + else //no conflicts, so simply update + { + newBlobs->blobs[winner].id = trackedBlobs[i].id; + } + } + } + + //--Update All Current Tracks + //remove every track labeled as dead (ID='-1') + //find every track that's alive and copy it's data from newBlobs + + auto new_end = std::remove_if(trackedBlobs.begin(), trackedBlobs.end(), + [](const iFloorBlob& blob) { return blob.id == -1; }); + trackedBlobs.erase(new_end, trackedBlobs.end()); + + for (size_t i = 0; i < trackedBlobs.size(); i++) + { + for (size_t j = 0; j < newBlobs->blobs.size(); j++) + { + if (trackedBlobs[i].id == newBlobs->blobs[j].id) + { + //update track + iFloorPoint tempLastCentroid = trackedBlobs[i].centroid; // assign the new centroid to the old + trackedBlobs[i] = newBlobs->blobs[j]; + trackedBlobs[i].lastCentroid = tempLastCentroid; + } + } + } + //--Add New Living Tracks + //now every new blob should be either labeled with a tracked ID or\ + //have ID of -1... if the ID is -1... we need to make a new track + for(size_t i=0; iblobs.size(); i++) + { + if(newBlobs->blobs[i].id==-1) + { + //add new track + newBlobs->blobs[i].id=IDCounter++; + trackedBlobs.push_back(newBlobs->blobs[i]); + } + } +} + +const iFloorBlobVector & BlobTracker::getTrackedBlobs() const +{ + return trackedBlobs; +} + +/************************************************************************* +* Finds the blob in 'newBlobs' that is closest to the trackedBlob with index +* 'ind' according to the KNN algorithm and returns the index of the winner +* newBlobs = list of blobs detected in the latest frame +* track = current tracked blob being tested +* k = number of nearest neighbors to consider\ +* 1,3,or 5 are common numbers..\ +* must always be an odd number to avoid tying +* thresh = threshold for optimization +**************************************************************************/ + +int BlobTracker::trackKnn(ContourFinder *newBlobs, iFloorBlob *track, int k, double thresh = 0) +{ + + int winner = -1; //initially label track as '-1'=dead + if ((k%2)==0) k++; //if k is not an odd number, add 1 to it + + //if it exists, square the threshold to use as square distance + if (thresh>0) + thresh *= thresh; + + //list of neighbor point index and respective distances + std::list > nbors; + std::list >::iterator iter; + + //find 'k' closest neighbors of testpoint + double x, y, xT, yT, dist; + for (size_t i=0; iblobs.size(); i++) + { + x = newBlobs->blobs[i].centroid.x; + y = newBlobs->blobs[i].centroid.y; + + xT = track->centroid.x; + yT = track->centroid.y; + dist = (x-xT)*(x-xT)+(y-yT)*(y-yT); + + if (dist<=thresh)//it's good, apply label if no label yet and return + { + winner = i; + return winner; + } + + /**************************************************************** + * check if this blob is closer to the point than what we've seen + *so far and add it to the index/distance list if positive + ****************************************************************/ + + auto nborsEnd = nbors.end(); + //search the list for the first point with a longer distance + for (iter=nbors.begin(); iter != nborsEnd && dist >= iter->second; iter++); + + if ((iter != nborsEnd) || (nbors.size()<(size_t)k)) //it's valid, insert it + { + nbors.insert(iter, 1, std::pair(i, dist)); + //too many items in list, get rid of farthest neighbor + if (nbors.size()>(size_t)k) + nbors.pop_back(); + } + } + + /******************************************************************** + * we now have k nearest neighbors who cast a vote, and the majority + * wins. we use each class average distance to the target to break any + * possible ties. + *********************************************************************/ + + // a mapping from labels (IDs) to count/distance + std::map > votes; + + //remember: + //iter->first = index of newBlob + //iter->second = distance of newBlob to current tracked blob + auto nborsEnd = nbors.end(); + for (iter = nbors.begin(); iter != nborsEnd; iter++) + { + //add up how many counts each neighbor got + int count = ++(votes[iter->first].first); + double dist = (votes[iter->first].second+=iter->second); + + /* check for a possible tie and break with distance */ + if (count>votes[winner].first || count==votes[winner].first + && distfirst; + } + } + + return winner; +} diff --git a/MotionDetectorCore/Tracking.h b/MotionDetectorCore/Tracking.h new file mode 100644 index 0000000..166011a --- /dev/null +++ b/MotionDetectorCore/Tracking.h @@ -0,0 +1,31 @@ +#ifndef _TRACKING_H +#define _TRACKING_H + +#include +#include + +#include "ContourFinder.h" + +class MOTION_DETECTOR_CORE_API BlobTracker +{ +public: + BlobTracker(); + ~BlobTracker(); + + // Assigns IDs to each blob in the contourFinder + void track(ContourFinder* newBlobs); + bool isCalibrating; + int MIN_MOVEMENT_THRESHOLD; + const iFloorBlobVector & getTrackedBlobs() const; + +private: + int trackKnn(ContourFinder *newBlobs, iFloorBlob *track, int k, double thresh); + +private: + int IDCounter; //counter of last blob + int fightMongrel; + iFloorBlobVector trackedBlobs; //tracked blobs + std::map calibratedBlobs; +}; + +#endif diff --git a/MotionDetectorCore/Win/MotionDetectorCore.vcxproj b/MotionDetectorCore/Win/MotionDetectorCore.vcxproj new file mode 100644 index 0000000..8a9e3e2 --- /dev/null +++ b/MotionDetectorCore/Win/MotionDetectorCore.vcxproj @@ -0,0 +1,481 @@ + + + + x64 + + + + Debug + x64 + + + Release + x64 + + + + {6E933546-0B62-311B-8D7E-6CE2ECD4CAD0} + Win32Proj + 10.0.26100.0 + x64 + MotionDetectorCore + NoUpgrade + + + + DynamicLibrary + Unicode + v143 + + + DynamicLibrary + Unicode + v143 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + MotionDetectorCore.dir\Debug\ + MotionDetectorCore + .dll + true + true + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + MotionDetectorCore.dir\Release\ + MotionDetectorCore + .dll + false + true + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /external:I "C:/Users/Admin/IFloor/libs/opencv/build/include" + $(IntDir) + EnableFastChecks + + + ProgramDatabase + 4996 + Sync + TurnOffAllWarnings + + + Disabled + stdcpp17 + + true + Disabled + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/MotionDetectorCore.dir/Debug//cmake_pch.pch + + MultiThreadedDebugDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;MOTION_DETECTOR_CORE_EXPORTS;CMAKE_INTDIR="Debug";MotionDetectorCore_EXPORTS + $(IntDir) + false + + + %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;MOTION_DETECTOR_CORE_EXPORTS;CMAKE_INTDIR=\"Debug\";MotionDetectorCore_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -E make_directory C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin/plugins/motion_detector +if %errorlevel% neq 0 goto :cmEnd +"C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/MotionDetectorCore.dll C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin/plugins/motion_detector/MotionDetectorCore.dll +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\MotionDetectorPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\MotionPrimitives.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\CommonPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxXS.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxJSON.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + true + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Debug/MotionDetectorCore.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/MotionDetectorCore.pdb + + Console + + + false + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /external:I "C:/Users/Admin/IFloor/libs/opencv/build/include" + $(IntDir) + Default + + + 4996 + Sync + TurnOffAllWarnings + + + AnySuitable + stdcpp17 + + true + MaxSpeed + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/MotionDetectorCore.dir/Release//cmake_pch.pch + + MultiThreadedDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;MOTION_DETECTOR_CORE_EXPORTS;CMAKE_INTDIR="Release";MotionDetectorCore_EXPORTS + $(IntDir) + + + false + + + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;MOTION_DETECTOR_CORE_EXPORTS;CMAKE_INTDIR=\"Release\";MotionDetectorCore_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -E make_directory C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin/plugins/motion_detector +if %errorlevel% neq 0 goto :cmEnd +"C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/MotionDetectorCore.dll C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin/plugins/motion_detector/MotionDetectorCore.dll +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\MotionDetectorPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\MotionPrimitives.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\CommonPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxXS.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxJSON.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + false + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Release/MotionDetectorCore.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/MotionDetectorCore.pdb + + Console + + + false + + + + + Always + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorCore\Win\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorCore\Win\CMakeFiles\generate.stamp + false + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/MotionDetectorCore.dir/Debug//cmake_pch.pch + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/MotionDetectorCore.dir/Release//cmake_pch.pch + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorCore/Win/CMakeFiles/MotionDetectorCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + ZERO_CHECK + false + Never + + + {751A15C0-76C2-3506-AB9D-0CD3545003FA} + CommonPluginBase + + + {1F4B7EAD-4694-3453-AD34-1757E387661E} + MotionDetectorPluginBase + + + {1903244B-9312-3A09-8AAD-8D78C1A4F977} + MotionPrimitives + + + {14D82890-BB7F-3748-8713-43304E91CFA1} + Utils + + + {7887B55C-77B9-3262-AFAD-ABA738C61029} + wxJSON + + + {78CFCEBE-5466-3128-9717-547416DBFFE5} + wxXS + + + + + + \ No newline at end of file diff --git a/MotionDetectorCore/Win/MotionDetectorCore.vcxproj.filters b/MotionDetectorCore/Win/MotionDetectorCore.vcxproj.filters new file mode 100644 index 0000000..a22b346 --- /dev/null +++ b/MotionDetectorCore/Win/MotionDetectorCore.vcxproj.filters @@ -0,0 +1,273 @@ + + + + + Source Files + + + Source Files + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Source Files + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Source Files + + + Source Files + + + Filters\Sources + + + Filters\Sources + + + Source Files + + + Source Files + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Filters\Sources + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Header Files + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Header Files + + + Header Files + + + Filters\Headers + + + Filters\Headers + + + Header Files + + + Header Files + + + Header Files + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Filters\Headers + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Precompile Header File + + + Precompile Header File + + + + + + + + {C253D8A8-FCEA-396C-8BC7-8C747007130B} + + + {47E23639-2555-37C5-95A9-E470DDCF6088} + + + {77D62B12-3DB6-37F6-B202-947DD58AC568} + + + {4951AEE1-75F2-3C38-B593-C6BC8C809FB0} + + + {112D4227-BB51-3360-BB5B-5EA5DBA5A65F} + + + {05450AB2-CB7B-34EA-83DF-1EE86424EDF0} + + + diff --git a/MotionDetectorCore/XorBGFilter.cpp b/MotionDetectorCore/XorBGFilter.cpp new file mode 100644 index 0000000..12cc8f1 --- /dev/null +++ b/MotionDetectorCore/XorBGFilter.cpp @@ -0,0 +1,146 @@ +#include "stdwx.h" +#include "XorBGFilter.h" +//#include +#include + +#if defined(__LINUX__) +#include "LinuxUtils.h" +#endif +// LINUX_ + +IMPLEMENT_DYNAMIC_CLASS(XorBGFilter, Filter); + +XorBGFilter::XorBGFilter() +{ + m_ExposureStartTime = timeGetTime(); + m_bLearnBackground = false; + m_bStart = false; + m_CameraExposureTime = 2200; + m_bCalibrated = false; + XS_SERIALIZE(m_CameraExposureTime, wxT("CameraExposureTime")); + XS_SERIALIZE(m_bCalibrated, wxT("Calibrated")); + XS_SERIALIZE(m_filename, wxT("filename")); +} + +XorBGFilter::~XorBGFilter() +{ +} + +wxString XorBGFilter::GetName() const +{ + return _("XOR Background"); +} + +#if defined(HAVE_CUDA) +bool XorBGFilter::KernelGPU() +{ + if (!m_bStart){ + int curTime = timeGetTime(); + if ((int)(curTime - m_ExposureStartTime) > m_CameraExposureTime){ + m_bLearnBackground = true; + m_bStart = true; + } + else + return false; + } + //Capture full background + if (m_bLearnBackground) + { + m_src->copyTo(m_matBg); + m_bLearnBackground = false; + } + // Subtract background + if (m_bTrackDark){ + cv::cuda::subtract(m_matBg, *m_src, m_dst); + } + else{ + cv::cuda::subtract(*m_src, m_matBg, m_dst); + } + + return true; +} +#endif + + +bool XorBGFilter::Kernel() +{ + // derived class responsible for allocating storage for filtered image + if (source.empty()) + { + return false; + } + + if (destination.empty()) + { + destination = cv::Mat::zeros(source.size(), source.type()); + } + if (!m_bStart) + { + int curTime = timeGetTime(); + //wxLogDebug(wxT("%i, %i %i > %i"), curTime, m_ExposureStartTime, curTime - m_ExposureStartTime, m_CameraExposureTime); + if ((int)(curTime - m_ExposureStartTime) > m_CameraExposureTime) + { + m_bLearnBackground = true; + m_bStart = true; + } + else + { + return false; + } + } + //Capture full background + if (m_bLearnBackground) + { + if (m_bCalibrated && wxFile::Exists(m_filename)) + { + background = cv::imread("c:\\background.jpg", cv::IMREAD_UNCHANGED); + } + else + { + if (background.empty()) + { + background = cv::Mat::zeros(source.size(), source.type()); + } + + // Êîï³þºìî âì³ñò ÷åðåç ñó÷àñíèé C++ ìåòîä + source.copyTo(background); + } + m_bLearnBackground = false; + } + + if (background.empty()) + { + return false; + } + + cv::bitwise_xor(background, source, destination); + return true; +} + +void XorBGFilter::CreateParamInputs() +{ + AddParameterBoolInput(_("Learn background"), &m_bLearnBackground); + AddParameterSpinInput(_("Camera exposure time:"), &m_CameraExposureTime, 20000, 0); +} + +void XorBGFilter::SaveBackground(wxString filename) +{ + m_bCalibrated = !background.empty(); + if (m_bCalibrated) + { + m_filename = filename; + cv::imwrite("c:\\background.jpg", background); + } +} + +void XorBGFilter::ResetCalibration() +{ + m_bCalibrated = false; + m_bLearnBackground = true; +} + +wxFORCE_LINK_THIS_MODULE(XorBGFilter); +//cvSub(background, source, destination1); +////else +//cvSub(source, background, destination); +//cvOr(destination, destination1, destination); diff --git a/MotionDetectorCore/XorBGFilter.h b/MotionDetectorCore/XorBGFilter.h new file mode 100644 index 0000000..b89dd80 --- /dev/null +++ b/MotionDetectorCore/XorBGFilter.h @@ -0,0 +1,43 @@ +#ifndef __TOUCHLIB_FILTER_XORBG__ +#define __TOUCHLIB_FILTER_XORBG__ + +#include "FilterTemplate.h" +#include +#include + +class MOTION_DETECTOR_CORE_API XorBGFilter : public Filter +{ + DECLARE_DYNAMIC_CLASS_NO_COPY(XorBGFilter) +public: + XorBGFilter(); + virtual ~XorBGFilter(); + + bool Kernel(); +#if defined(HAVE_CUDA) + bool KernelGPU(); +#endif + virtual wxString GetName() const; + void SaveBackground(wxString filename); + void ResetCalibration(); +protected: + void CreateParamInputs(); + +private: + cv::Mat background; + cv::Mat destination1; + bool m_bLearnBackground; + int m_ExposureStartTime; + int m_CameraExposureTime; + bool m_bCalibrated; + bool m_bErodeDilate; + wxString m_filename; + cv::Mat m_erodeKernel; + cv::Mat m_dilateKernel; + bool m_bStart; +#if defined(HAVE_CUDA) + cv::cuda::GpuMat m_matBg; +#endif + +}; + +#endif // __TOUCHLIB_FILTER_XORBG__ diff --git a/MotionDetectorCore/vector2d.h b/MotionDetectorCore/vector2d.h new file mode 100644 index 0000000..2fa449a --- /dev/null +++ b/MotionDetectorCore/vector2d.h @@ -0,0 +1,253 @@ +#ifndef __TOUCHLIB_VECTOR2D__ +#define __TOUCHLIB_VECTOR2D__ + + +//#include +#include +#define GRID_X 4 +#define GRID_Y 3 + +namespace touchlib +{ + + // The following code was originally written by Nikolaus Gebhardt as part of Irrlicht. + // See www.irrlicht3d.org + + // The Irrlicht Engine License + // Copyright © 2002-2005 Nikolaus Gebhardt + // This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held + // liable for any damages arising from the use of this software. + // + // Permission is granted to anyone to use this software for any purpose, including commercial applications, and to + // alter it and redistribute it freely, subject to the following restrictions: + // + // 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. + // If you use this software in a product, an acknowledgment in the product documentation would be appreciated but + // is not required. + // 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + // 3. This notice may not be removed or altered from any source distribution. + + + const float GRAD_PI = 180.0f / 3.14159f; + const float GRAD_PI2 = 3.14159f / 180.0f; + const float PI = 3.14159f; + const float ROUNDING_ERROR = 0.0001f; + + + + template + class vector2d + { + public: + + vector2d(): X(0), Y(0) {}; + vector2d(T nx, T ny) : X(nx), Y(ny) {}; + vector2d(const vector2d& other) :X(other.X), Y(other.Y) {}; + + // operators + + vector2d operator-() const { return vector2d(-X, -Y); } + + vector2d& operator=(const vector2d& other) { X = other.X; Y = other.Y; return *this; } + + vector2d operator+(const vector2d& other) const { return vector2d(X + other.X, Y + other.Y); } + vector2d& operator+=(const vector2d& other) { X+=other.X; Y+=other.Y; return *this; } + + vector2d operator-(const vector2d& other) const { return vector2d(X - other.X, Y - other.Y); } + vector2d& operator-=(const vector2d& other) { X-=other.X; Y-=other.Y; return *this; } + + vector2d operator*(const vector2d& other) const { return vector2d(X * other.X, Y * other.Y); } + vector2d& operator*=(const vector2d& other) { X*=other.X; Y*=other.Y; return *this; } + vector2d operator*(const T v) const { return vector2d(X * v, Y * v); } + vector2d& operator*=(const T v) { X*=v; Y*=v; return *this; } + + vector2d operator/(const vector2d& other) const { return vector2d(X / other.X, Y / other.Y); } + vector2d& operator/=(const vector2d& other) { X/=other.X; Y/=other.Y; return *this; } + vector2d operator/(const T v) const { return vector2d(X / v, Y / v); } + vector2d& operator/=(const T v) { X/=v; Y/=v; return *this; } + + bool operator==(const vector2d& other) const { return other.X==X && other.Y==Y; } + bool operator!=(const vector2d& other) const { return other.X!=X || other.Y!=Y; } + + // functions + + void set(const T& nx, const T& ny) {X=nx; Y=ny; } + void set(const vector2d& p) { X=p.X; Y=p.Y;} + + //! Returns the length of the vector + //! \return Returns the length of the vector. + float getLength() const { return sqrt(X*X + Y*Y); } + float getLengthSQ() const { return (X*X + Y*Y); } + + //! Returns the dot product of this vector with an other. + T dotProduct(const vector2d& other) const + { + return X*other.X + Y*other.Y; + } + + //! Calculates the cross product with another vector + T crossProduct(const vector2d& p) const + { + return X * p.Y - Y * p.X; + } + + + //! Returns distance from an other point. Here, the vector is interpreted as + //! point in 2 dimensional space. + float getDistanceFrom(const vector2d& other) const + { + float vx = X - other.X; float vy = Y - other.Y; + return sqrt(vx*vx + vy*vy); + } + + //! Returns distance from an other point. Here, the vector is interpreted as + //! point in 2 dimensional space. + float getDistanceFromSQ(const vector2d& other) const + { + float vx = X - other.X; + float vy = Y - other.Y; + + return (vx*vx + vy*vy); + } + + //! rotates the point around a center by an amount of degrees. + void rotateBy(float degrees, const vector2d& center) + { + degrees *= GRAD_PI2; + T cs = (T)cos(degrees); + T sn = (T)sin(degrees); + + X -= center.X; + Y -= center.Y; + + set(X*cs - Y*sn, X*sn + Y*cs); + + X += center.X; + Y += center.Y; + } + + //! normalizes the vector. + vector2d& normalize() + { + T l = (T)getLength(); + if (l == 0) + return *this; + + l = (T)1.0 / l; + X *= l; + Y *= l; + return *this; + } + + //! Calculates the angle of this vector in grad in the trigonometric sense. + //! This method has been suggested by Pr3t3nd3r. + //! \return Returns a value between 0 and 360. + inline float getAngleTrig() const + { + if (X == 0.0) + return Y < 0.0 ? 270.0 : 90.0; + else + if (Y == 0) + return X < 0.0 ? 180.0 : 0.0; + + if ( Y > 0.0) + if (X > 0.0) + return atan(Y/X) * GRAD_PI; + else + return 180.0-atan(Y/-X) * GRAD_PI; + else + if (X > 0.0) + return 360.0-atan(-Y/X) * GRAD_PI; + else + return 180.0+atan(-Y/-X) * GRAD_PI; + } + + //! Calculates the angle of this vector in grad in the counter trigonometric sense. + //! \return Returns a value between 0 and 360. + inline float getAngle() const + { + if (Y == 0.0) // corrected thanks to a suggestion by Jox + return X < 0.0 ? 180.0 : 0.0; + else if (X == 0.0) + return Y < 0.0 ? 90.0 : 270.0; + + float tmp = Y / sqrt(X*X + Y*Y); + tmp = atan(sqrt(1 - tmp*tmp) / tmp) * GRAD_PI; + + if (X>0.0 && Y>0.0) + return tmp + 270; + else + if (X>0.0 && Y<0.0) + return tmp + 90; + else + if (X<0.0 && Y<0.0) + return 90 - tmp; + else + if (X<0.0 && Y>0.0) + return 270 - tmp; + + return tmp; + } + + //! Calculates the angle between this vector and another one in grad. + //! \return Returns a value between 0 and 90. + inline float getAngleWith(const vector2d& b) const + { + float tmp = X*b.X + Y*b.Y; + + if (tmp == 0.0) + return 90.0; + + tmp = tmp / sqrt((X*X + Y*Y) * (b.X*b.X + b.Y*b.Y)); + if (tmp < 0.0) tmp = -tmp; + + return atan(sqrt(1 - tmp*tmp) / tmp) * GRAD_PI; + } + + + //! returns interpolated vector + //! \param other: other vector to interpolate between + //! \param d: value between 0.0f and 1.0f. + vector2d getInterpolated(const vector2d& other, float d) const + { + float inv = 1.0f - d; + return vector2d(other.X*inv + X*d, + other.Y*inv + Y*d); + } + + //! Returns if this vector interpreted as a point is on a line between two other points. + /** It is assumed that the point is on the line. */ + bool isBetweenPoints(const vector2d& begin, const vector2d& end) const + { + float f = (float)(end - begin).getLengthSQ(); + return (float)getDistanceFromSQ(begin) < f && + (float)getDistanceFromSQ(end) < f; + } + + static bool isOnSameSide(vector2d p1, vector2d p2, vector2d a, vector2d b) + { + vector2d ba = b - a; + + float cp1 = ba.crossProduct(p1-a); + float cp2 = ba.crossProduct(p2-a); + + if (cp1*cp2 >= 0.0f) + return true; + else + return false; + } + + + // member variables + T X, Y; + }; + + //! Typedef for float 2d vector. + typedef vector2d vector2df; + //! Typedef for integer 2d vector. + typedef vector2d vector2di; + +} // end namespace touchscreen + + +#endif diff --git a/MotionDetectorCore/wxBitmapEvent.h b/MotionDetectorCore/wxBitmapEvent.h new file mode 100644 index 0000000..e13e911 --- /dev/null +++ b/MotionDetectorCore/wxBitmapEvent.h @@ -0,0 +1,52 @@ +#ifndef _WXBITMAPEVENT_H +#define _WXBITMAPEVENT_H + +class wxBitmapEvent: public wxCommandEvent +{ +public: + wxBitmapEvent(wxBitmap * bitmap = NULL, wxEventType commandType = wxEVT_NULL, int winid = 0) + : wxCommandEvent(commandType, winid) + , m_Bitmap(bitmap) + { + } + + wxBitmapEvent(const wxBitmapEvent & event) + : wxCommandEvent(event) + { + if (event.m_Bitmap) + m_Bitmap = new wxBitmap(*event.m_Bitmap); + else + m_Bitmap = NULL; + } + + ~wxBitmapEvent() + { + wxDELETE(m_Bitmap); + } + + void SetBitmap(wxBitmap * val) { m_Bitmap = val; } + wxBitmap * GetBitmap() const { return m_Bitmap; } + wxBitmap * DetachBitmap() + { + wxBitmap * tmp = m_Bitmap; + m_Bitmap = NULL; + return tmp; + } + + // implement the base class pure virtual + virtual wxEvent *Clone() const { return new wxBitmapEvent(*this); } + +private: + wxBitmap * m_Bitmap; +}; + + +wxDEFINE_EVENT(EVT_IMAGE_CALLBACK, wxBitmapEvent); + +#define wxBitmapEventHandler(func) (&func) + +#define EVT_BITMAP_SEND(id, func) \ + wx__DECLARE_EVT1(EVT_IMAGE_CALLBACK, id, wxBitmapEventHandler(func)) + + +#endif // _WXBITMAPEVENT_H \ No newline at end of file diff --git a/MotionDetectorMultiCam/CMakeLists.txt b/MotionDetectorMultiCam/CMakeLists.txt new file mode 100644 index 0000000..9da232c --- /dev/null +++ b/MotionDetectorMultiCam/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 3.15) +project(MotionDetectorMultiCam) + +set(INCLUDE_DIRECTORIES ${BASE_INCLUDE_DIRECTORIES} + ${CMAKE_CURRENT_SOURCE_DIR} + ${PROJECT_ROOT_DIR}/MotionDetectorCore + ${PROJECT_ROOT_DIR}/MotionDetectorPluginBase + ${PROJECT_ROOT_DIR}/wxGuiPluginBase + ${PROJECT_ROOT_DIR}/CommonPluginBase + ${PROJECT_ROOT_DIR}/Utils + ${THIRD_PARTY_DIR}/wxXS/include + ${OpenCV_INCLUDE_DIRS} + ${THIRD_PARTY_DIR}/MotionPrimitives +) + +if(CUDA_FOUND) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/DHAVE_CUDA) +endif(CUDA_FOUND) + +if(WIN32) + set(INCLUDE_DIRECTORIES ${INCLUDE_DIRECTORIES} ${QEDIT_PATH}) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D_USRDLL;/D_WIN32_WINNT=0x0501) +endif(WIN32) + +add_definitions(${PREPROCESSOR_DEFINITIONS}) +include_directories(${INCLUDE_DIRECTORIES}) + +set(STD_WX ${PROJECT_ROOT_DIR}/include/stdwx.h ${PROJECT_ROOT_DIR}/include/stdwx.cpp) + +set(NONGUI_NAME MotionDetectorMultiCam) +set(NONGUI_SRCS + MotionDetectorMultiCamPlugin.cpp + MotionDetectorMultiCamExports.cpp + MotionDetectorMultiCam.cpp + MultiCamCameraManager.cpp + ${STD_WX} +) + +add_library(${NONGUI_NAME} SHARED ${NONGUI_SRCS}) +target_compile_definitions(${NONGUI_NAME} PRIVATE -DMOTIONDETECTOR_MULTICAM_EXPORTS) + +target_link_libraries(${NONGUI_NAME} ${wxWidgets_LIBRARIES} CommonPluginBase Utils MotionDetectorPluginBase MotionDetectorCore MotionPrimitives videoInput ${OpenCV_LIBS}) +add_dependencies(${NONGUI_NAME} MotionDetectorPluginBase CommonPluginBase Utils MotionDetectorCore) +target_precompile_headers(${NONGUI_NAME} PRIVATE "${PROJECT_ROOT_DIR}/include/stdwx.h") + +set(TARGET_NONGUI_DIR "${OUTPUT_BIN_DIR}") +add_custom_command(TARGET ${NONGUI_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "${TARGET_NONGUI_DIR}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "${TARGET_NONGUI_DIR}/$" +) + +set(GUI_NAME MotionDetectorMultiCamGui) +set(GUI_SRCS + MotionDetectorMultiCamGuiPlugin.cpp + MultiCamSettingsPanel.cpp + ${STD_WX} +) + +add_library(${GUI_NAME} SHARED ${GUI_SRCS}) + +target_link_libraries(${GUI_NAME} ${wxWidgets_LIBRARIES} ${NONGUI_NAME} CommonPluginBase Utils wxGuiPluginBase MotionDetectorCore) +add_dependencies(${GUI_NAME} ${NONGUI_NAME} wxGuiPluginBase CommonPluginBase Utils MotionDetectorCore) +target_precompile_headers(${GUI_NAME} PRIVATE "${PROJECT_ROOT_DIR}/include/stdwx.h") + +set(TARGET_GUI_DIR "${OUTPUT_BIN_DIR}/plugins/gui") +add_custom_command(TARGET ${GUI_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "${TARGET_GUI_DIR}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "${TARGET_GUI_DIR}/$" +) \ No newline at end of file diff --git a/MotionDetectorMultiCam/MotionDetectorMultiCam.cpp b/MotionDetectorMultiCam/MotionDetectorMultiCam.cpp new file mode 100644 index 0000000..3863f9d --- /dev/null +++ b/MotionDetectorMultiCam/MotionDetectorMultiCam.cpp @@ -0,0 +1,261 @@ +#include "stdwx.h" +#include "MotionDetectorMultiCam.h" +#include "MultiCamSettingsPanel.h" +#include "MultiCamCameraManager.h" +#include "ContourFinder.h" +#include "Tracking.h" + +#include +#include "PerspectiveFilter.h" +#include "FlipFilter.h" + +#if defined(USE_VLD) +#include +#endif + +const wxString MotionDetectorMultiCam::DEFAULT_FILTERS[] = +{ + wxT("DummyFilter"), + //wxT("EqualizeHistFilter"), + wxT("BrightnessContrastFilter"), + wxT("MonoFilter"), + wxT("FlipFilter"), + wxT("SimpleBGFilter"), + wxT("DynamicBGFilter"), + wxT("SubOrBGFilter"), + wxT("XorBGFilter"), + wxT("PerspectiveFilter"), + wxT("SmoothingFilter"), + wxT("SimpleHighpassFilter"), + wxT("AmplifyFilter"), + wxT("InvertFilter"), + wxT("ThresholdFilter"), +}; + +IMPLEMENT_DYNAMIC_CLASS(MotionDetectorMultiCam, MotionDetectorBase); + +MotionDetectorMultiCam::MotionDetectorMultiCam() +: MotionDetectorBase(nullptr, GeometryProvider(nullptr, nullptr, nullptr)) +, m_CameraManager(NULL) +, m_ContourFinder(NULL) +, m_BlobTracker(NULL) +, m_minBlobArea(100), m_maxBlobArea(1000000), m_maxBlobCount(5), m_bUseOneOnMulti(false) +{ + wxLogDebug(wxT("Size of MotionDetectorMultiCam : %i"), (int)sizeof(MotionDetectorMultiCam)); + m_Settings.DeleteContents(true); + //m_hash = 8180; + //m_hash = 18540; //cpu1 + //m_hash = 23132; //cpu2 +} + +MotionDetectorMultiCam::MotionDetectorMultiCam(MotionDetectorPluginBase * owner, + GeometryProvider && geometryProvider) +: MotionDetectorBase(owner, std::move(geometryProvider)) +, m_CameraManager(NULL) +, m_ContourFinder(NULL) +, m_BlobTracker(NULL) +, m_minBlobArea(100), m_maxBlobArea(1000000), m_maxBlobCount(5), m_bUseOneOnMulti(false) +{ + wxLogDebug(wxT("Size of MotionDetectorMultiCam : %i"), (int)sizeof(MotionDetectorMultiCam)); + wxLogDebug(wxT("Size of IFLoorImageProcessorSettings : %i"), (int)sizeof(IFloorImagePreprocessorSettings)); + XS_SERIALIZE(m_minBlobArea, wxT("minBlobArea")); + XS_SERIALIZE(m_maxBlobArea, wxT("maxBlobArea")); + XS_SERIALIZE(m_maxBlobCount, wxT("maxBlobCount")); + XS_SERIALIZE(m_bUseOneOnMulti, wxT("useOneOnMulti")); + m_Settings.DeleteContents(true); + //m_hash = 8180; + //m_hash = 18540; //cpu1 + //m_hash = 23132; //cpu2 +} + +MotionDetectorMultiCam::~MotionDetectorMultiCam() +{ + Clear(); + m_Settings.Clear(); + m_Buffers.Clear(); + m_BufferSizes.Clear(); + m_CameraSettings.Clear(); + //StopDetection(); +} + +wxString MotionDetectorMultiCam::GetName() const +{ + static wxString id = wxT("MultiCam detector"); + return id; +} + +wxString MotionDetectorMultiCam::GetID() const +{ + static wxString id = wxT("{BFED0460-5C8D-4114-861B-96DE3FE9C607}"); + return id; +} + +void MotionDetectorMultiCam::StartDetection() +{ + Clear(); + + if (m_Settings.IsEmpty()) // wxT("There is no any camera settings") + return; + + m_CameraManager = new MultiCamCameraManager(m_GeometryProvider); + + m_ContourFinder = new ContourFinder(); + m_BlobTracker = new BlobTracker(); + + size_t index = 0; + + m_CameraManager->SetUseOneOnMulti(m_bUseOneOnMulti); + + for (IFloorCameraSettingsList::iterator it = m_Settings.begin(); it != m_Settings.end(); ++it, ++index) + { + m_CameraManager->AddCamera(*it, m_Buffers[index], m_BufferSizes[index]); + // Add filters for the camera + bool hasConfig = index < m_CameraSettings.Count(); + for (size_t i = 0; i < WXSIZEOF(DEFAULT_FILTERS); ++i) + m_CameraManager->AddFilter(index, DEFAULT_FILTERS[i], hasConfig ? m_CameraSettings[index][DEFAULT_FILTERS[i]] : wxString(wxEmptyString)); + + IFloorImagePreprocessor * camera = m_CameraManager->GetCameraByID(index); + + PerspectiveFilter * pf = wxDynamicCast(camera->GetFilter(wxT("PerspectiveFilter")), PerspectiveFilter); + if (pf) + pf->SetSettings(**it); + + FlipFilter * ff = wxDynamicCast(camera->GetFilter(wxT("FlipFilter")), FlipFilter); + if (ff) + ff->SetSettings(**it); + } + m_CameraManager->InitCameraParams(); + m_CameraManager->CreateFullView(); +} + +void MotionDetectorMultiCam::StopDetection() +{ + Clear(); + m_Settings.Clear(); + m_Buffers.Clear(); + m_BufferSizes.Clear(); +} + +IFloorImagePreprocessor * MotionDetectorMultiCam::GetCameraImagePreprocessor(int cameraID) +{ + if (!m_CameraManager) + return NULL; + return m_CameraManager->GetCameraByID(cameraID); +} + +int MotionDetectorMultiCam::GetBlobs(iFloorBlobVector * blobs) +{ + if (m_ContourFinder) + { + if (m_BlobTracker){ + *blobs = m_BlobTracker->getTrackedBlobs(); + }else{ + *blobs = m_ContourFinder->blobs; + } + for(size_t i = 0; i < blobs->size(); ++i){ + iFloorBlob& blob = (*blobs)[i]; + //blob.centroid.x *= m_hash; + //blob.centroid.y /= m_hash; + } + } + return 0; +} + +bool MotionDetectorMultiCam::Calibrate() +{ + return true; +} + +CommonConfigWindowBase * MotionDetectorMultiCam::CreateSettingsEditor(wxWindow * parent) +{ + return NULL; +} + +void MotionDetectorMultiCam::SetCameraSettings(const IFloorCameraSettings & settings, const int index) +{ + wxASSERT(index >= 0); + IFloorCameraSettings * newSettings = new IFloorCameraSettings(settings); + while (index > (int)m_Settings.GetCount()) + { + m_Settings.Append(new IFloorCameraSettings); // Add dummy settings to the list + } + if (index == m_Settings.GetCount()) + m_Settings.Append(newSettings); + else + m_Settings.Item(index)->SetData(newSettings); + + m_Buffers.SetCount(m_Settings.GetCount()); + m_BufferSizes.SetCount(m_Settings.GetCount()); +} + +void MotionDetectorMultiCam::SetDataBuffer(unsigned char * buffer, const size_t length, const int index) +{ + wxCHECK(index < (int)m_Buffers.GetCount(), ); + m_Buffers[index] = buffer; + m_BufferSizes[index] = length; +} + +void MotionDetectorMultiCam::ProcessData() +{ + wxCHECK_MSG(m_CameraManager && m_ContourFinder && m_BlobTracker, , wxT("You should call StartDetection() first")); + + cv::Mat image = m_CameraManager->GetImage(); + if (image.empty()) + return; + + m_ContourFinder->findContours(image, m_minBlobArea, m_maxBlobArea, m_maxBlobCount, false); + if (m_BlobTracker){ + m_BlobTracker->track(m_ContourFinder); + } +} + +bool MotionDetectorMultiCam::Deserialize(wxInputStream & instream) +{ + bool res = SerializableBase::Deserialize(instream, *this); + if (res) + { + m_CameraSettings.Clear(); + xsSerializable * child; + while (child = xsSerializable::GetFirstChild(CLASSINFO(IFloorImagePreprocessorSettings))) + { + child->Reparent(NULL); + child->SetParentManager(NULL); + m_CameraSettings.Add(wxDynamicCast(child, IFloorImagePreprocessorSettings)); + } + } + return res; +} + +bool MotionDetectorMultiCam::Serialize(wxOutputStream & outstream) +{ + for (size_t i = 0; i < m_CameraSettings.Count(); ++i) + { + xsSerializable::AddChild(&m_CameraSettings[i]); + } + bool res = SerializableBase::Serialize(outstream, *this); + + xsSerializable * child; + while ((child = xsSerializable::GetFirstChild(CLASSINFO(IFloorImagePreprocessorSettings)))) + { + child->Reparent(NULL); + child->SetParentManager(NULL); + } + return res; +} + +void MotionDetectorMultiCam::Clear() +{ + wxDELETE(m_BlobTracker); + wxDELETE(m_ContourFinder); + wxDELETE(m_CameraManager); +} + +IFloorImagePreprocessorSettingsArray & MotionDetectorMultiCam::GetCameraSettings() +{ + return m_CameraSettings; +} + +bool MotionDetectorMultiCam::IsRunning() +{ + return m_CameraManager != NULL; +} diff --git a/MotionDetectorMultiCam/MotionDetectorMultiCam.def b/MotionDetectorMultiCam/MotionDetectorMultiCam.def new file mode 100644 index 0000000..e0810f9 --- /dev/null +++ b/MotionDetectorMultiCam/MotionDetectorMultiCam.def @@ -0,0 +1,6 @@ +LIBRARY "MotionDetectorMultiCam" + +EXPORTS + CreatePlugin=CreatePlugin + DeletePlugin=DeletePlugin + \ No newline at end of file diff --git a/MotionDetectorMultiCam/MotionDetectorMultiCam.h b/MotionDetectorMultiCam/MotionDetectorMultiCam.h new file mode 100644 index 0000000..7ed8278 --- /dev/null +++ b/MotionDetectorMultiCam/MotionDetectorMultiCam.h @@ -0,0 +1,60 @@ +#ifndef _MOTIONDETECTORMULTICAM_H +#define _MOTIONDETECTORMULTICAM_H + +#include +#include +#include +#include + +class MultiCamCameraManager; +class ContourFinder; +class BlobTracker; +class IFloorImagePreprocessor; + +class __declspec(dllexport) MotionDetectorMultiCam : public MotionDetectorBase +{ + DECLARE_DYNAMIC_CLASS(MotionDetectorMultiCam); +public: + MotionDetectorMultiCam(); + MotionDetectorMultiCam(MotionDetectorPluginBase * owner, GeometryProvider && geometryProvider); + virtual ~MotionDetectorMultiCam(); + virtual wxString GetName() const; + virtual wxString GetID() const; + virtual bool Calibrate(); + virtual void StartDetection(); + virtual void StopDetection(); + virtual int GetBlobs(iFloorBlobVector * blobs); + virtual CommonConfigWindowBase * CreateSettingsEditor(wxWindow * parent = NULL); + virtual void SetCameraSettings(const IFloorCameraSettings & settings, const int index);; + virtual void SetDataBuffer(unsigned char * buffer, const size_t length, const int index); + virtual void ProcessData(); + IFloorImagePreprocessor * GetCameraImagePreprocessor(int cameraID); + + virtual bool Deserialize(wxInputStream & instream); + virtual bool Serialize(wxOutputStream & outstream); + + IFloorImagePreprocessorSettingsArray & GetCameraSettings(); + bool IsRunning(); + int m_minBlobArea, m_maxBlobArea, m_maxBlobCount; + bool m_bUseOneOnMulti; +protected: + void Clear(); + +private: + MultiCamCameraManager * m_CameraManager; + ContourFinder * m_ContourFinder; + BlobTracker * m_BlobTracker; + + // Settings that will be passed to the Camera Manager + IFloorCameraSettingsList m_Settings; + wxArrayPtrVoid m_Buffers; + wxArrayInt m_BufferSizes; + + IFloorImagePreprocessorSettingsArray m_CameraSettings; + + static const wxString DEFAULT_FILTERS[]; + + float m_hash; +}; + +#endif // _MOTIONDETECTORMULTICAM_H \ No newline at end of file diff --git a/SampleGuiPlugin1/SampleGuiPlugin1.pjd b/MotionDetectorMultiCam/MotionDetectorMultiCam.pjd similarity index 58% rename from SampleGuiPlugin1/SampleGuiPlugin1.pjd rename to MotionDetectorMultiCam/MotionDetectorMultiCam.pjd index 7f15f2c..21638ec 100644 --- a/SampleGuiPlugin1/SampleGuiPlugin1.pjd +++ b/MotionDetectorMultiCam/MotionDetectorMultiCam.pjd @@ -1,572 +1,606 @@ - - -
- 0 - "" - "" - "" - "" - "" - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - "Volodymyr (T-Rex) Triapichko" - "Volodymyr (T-Rex) Triapichko, 2013" - "" - 0 - 0 - 0 - 0 - "<All platforms>" - "2.9.5" - "Standard" - "///////////////////////////////////////////////////////////////////////////// -// Name: %HEADER-FILENAME% -// Purpose: -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "///////////////////////////////////////////////////////////////////////////// -// Name: %SOURCE-FILENAME% -// Purpose: -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "///////////////////////////////////////////////////////////////////////////// -// Name: %SYMBOLS-FILENAME% -// Purpose: Symbols file -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "" - "// For compilers that support precompilation, includes "wx/wx.h". -#include "wx/wxprec.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#ifndef WX_PRECOMP -#include "wx/wx.h" -#endif - -" - " /// %BODY% -" - " -/* - * %BODY% - */ - -" - "app_resources.h" - "app_resources.cpp" - "AppResources" - "app.h" - "app.cpp" - "Application" - 0 - "" - "<None>" - "iso-8859-1" - "utf-8" - "utf-8" - "" - 0 - 0 - 4 - " " - "" - 0 - 0 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 -
- - - "" - "data-document" - "" - "" - 0 - 1 - 0 - 0 - - "Configurations" - "config-data-document" - "" - "" - 0 - 1 - 0 - 0 - "" - 1 - -8519680 - "" - "Debug" - "Unicode" - "Static" - "Modular" - "GUI" - "wxMSW" - "Default" - "Dynamic" - "Yes" - "No" - "Yes" - "No" - "No" - "Yes" - "Yes" - "Yes" - "Yes" - "Yes" - "builtin" - "Yes" - "%EXECUTABLE%" - "" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%WXVERSION%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - 0 - 1 - - - - - - - "Projects" - "root-document" - "" - "project" - 1 - 1 - 0 - 1 - - "Windows" - "html-document" - "" - "dialogsfolder" - 1 - 1 - 0 - 1 - - "SampleGuiPluginWindow1" - "dialog-document" - "" - "dialog" - 0 - 1 - 0 - 0 - "wbDialogProxy" - 10000 - 0 - "" - 0 - "" - "Standard" - 0 - 0 - "ID_SAMPLEGUIPLUGINWINDOW1" - 10000 - "SampleGuiPluginWindow1" - "wxGuiPluginWindowBase" - "wxPanel" - "SampleGuiPluginWindow1.cpp" - "SampleGuiPluginWindow1.h" - "" - "SampleGuiPluginWindow1" - 1 - "" - 0 - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - "" - "" - "" - "" - "" - "" - "Tiled" - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - "" - 0 - 1 - -1 - -1 - 400 - 300 - 0 - "" - - "wxBoxSizer V" - "dialog-control-document" - "" - "sizer" - 0 - 1 - 0 - 0 - "wbBoxSizerProxy" - "Vertical" - "" - 0 - 0 - 0 - 0 - "<Any platform>" - - "wxStaticText: wxID_STATIC" - "dialog-control-document" - "" - "statictext" - 0 - 1 - 0 - 0 - "wbStaticTextProxy" - "wxID_STATIC" - 5105 - "" - "wxStaticText" - "wxStaticText" - 1 - 0 - "" - "" - "" - "Enter some text here:" - -1 - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - "" - "" - "" - "" - "" - "" - "" - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - "" - -1 - -1 - -1 - -1 - "Left" - "Centre" - 0 - 5 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - "" - "" - - - "wxTextCtrl: ID_SAMPLE_TEXTCTRL" - "dialog-control-document" - "" - "textctrl" - 0 - 1 - 0 - 0 - "wbTextCtrlProxy" - "ID_SAMPLE_TEXTCTRL" - 10001 - "" - "wxTextCtrl" - "wxTextCtrl" - 1 - 0 - "" - "" - "m_SamppleTextCtrl" - "Hello, GUI Plugin 2!" - 0 - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - "" - "" - "" - "" - "" - "" - "" - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - "" - -1 - -1 - -1 - -1 - "Expand" - "Centre" - 0 - 5 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - "" - "" - - - "wxButton: ID_SEND_EVENT_BUTTON" - "dialog-control-document" - "" - "dialogcontrol" - 0 - 1 - 0 - 0 - "wbButtonProxy" - "wxEVT_COMMAND_BUTTON_CLICKED|OnSENDEVENTBUTTONClick|NONE||SampleGuiPluginWindow1" - "ID_SEND_EVENT_BUTTON" - 10002 - "" - "wxButton" - "wxButton" - 1 - 0 - "" - "" - "" - "Send event" - 0 - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - "" - -1 - -1 - -1 - -1 - "Centre" - "Centre" - 0 - 5 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - "" - "" - - - - - - "Sources" - "html-document" - "" - "sourcesfolder" - 1 - 1 - 0 - 1 - - "SampleGuiPlugin1.rc" - "source-editor-document" - "SampleGuiPlugin1.rc" - "source-editor" - 0 - 0 - 1 - 0 - "10/9/2013" - "" - - - - "Images" - "html-document" - "" - "bitmapsfolder" - 1 - 1 - 0 - 1 - - - - -
+ + +
+ 0 + "" + "" + "" + "" + "" + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + "IT-Dimension" + "" + "" + 0 + 1 + 0 + 0 + "<All platforms>" + "2.9.1" + "Standard" + "///////////////////////////////////////////////////////////////////////////// +// Name: %HEADER-FILENAME% +// Purpose: +// Author: %AUTHOR% +// Modified by: +// Created: %DATE% +// RCS-ID: +// Copyright: %COPYRIGHT% +// Licence: +///////////////////////////////////////////////////////////////////////////// + +" + "///////////////////////////////////////////////////////////////////////////// +// Name: %SOURCE-FILENAME% +// Purpose: +// Author: %AUTHOR% +// Modified by: +// Created: %DATE% +// RCS-ID: +// Copyright: %COPYRIGHT% +// Licence: +///////////////////////////////////////////////////////////////////////////// + +" + "///////////////////////////////////////////////////////////////////////////// +// Name: %SYMBOLS-FILENAME% +// Purpose: Symbols file +// Author: %AUTHOR% +// Modified by: +// Created: %DATE% +// RCS-ID: +// Copyright: %COPYRIGHT% +// Licence: +///////////////////////////////////////////////////////////////////////////// + +" + "" + "// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#include "wx/wx.h" +#endif + +" + " /// %BODY% +" + " +/* + * %BODY% + */ + +" + "app_resources.h" + "app_resources.cpp" + "AppResources" + "app.h" + "app.cpp" + "Application" + 0 + "" + "<None>" + "iso-8859-1" + "utf-8" + "utf-8" + "" + 0 + 1 + 4 + " " + "" + 0 + 0 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 +
+ + + "" + "data-document" + "" + "" + 0 + 1 + 0 + 0 + + "Configurations" + "config-data-document" + "" + "" + 0 + 1 + 0 + 0 + "" + 1 + -8519680 + "" + "Debug" + "Unicode" + "Static" + "Modular" + "GUI" + "wxMSW" + "Default" + "Dynamic" + "Yes" + "No" + "Yes" + "No" + "No" + "Yes" + "Yes" + "Yes" + "Yes" + "Yes" + "sys" + "Yes" + "%EXECUTABLE%" + "" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%WXVERSION%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + 0 + 1 + + + + + + + "Projects" + "root-document" + "" + "project" + 1 + 1 + 0 + 1 + + "Windows" + "html-document" + "" + "dialogsfolder" + 1 + 1 + 0 + 1 + + "MultiCamSettingsPanel: ID_MULTICAMSETTINGSPANEL" + "dialog-document" + "" + "panel" + 0 + 1 + 0 + 0 + "wbPanelProxy" + 10000 + 0 + "" + 0 + "" + "Standard" + 0 + 0 + "ID_MULTICAMSETTINGSPANEL" + 10000 + "" + "MultiCamSettingsPanel" + "MotionDetectorConfigWindowBase" + 0 + 1 + "MultiCamSettingsPanel.cpp" + "MultiCamSettingsPanel.h" + "" + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "Tiled" + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + "" + 1 + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + "" + 0 + + "wxBoxSizer V" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbBoxSizerProxy" + "Vertical" + "" + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "<Any platform>" + + "wxStaticBoxSizer H" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbStaticBoxSizerProxy" + "wxID_ANY" + -1 + "Display Settings" + "" + "" + "" + "" + 0 + 1 + "Use wxWidgets version" + "wxStaticBox" + "Horizontal" + "Expand" + "Centre" + 0 + 5 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + "<Any platform>" + + "wxStaticText: wxID_STATIC" + "dialog-control-document" + "" + "statictext" + 0 + 1 + 0 + 0 + "wbStaticTextProxy" + "wxID_STATIC" + 5105 + "" + "wxStaticText" + "wxStaticText" + 1 + 0 + "" + "" + "" + "Displays layout:" + -1 + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Left" + "Top" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "DisplayGeometryWindow: ID_DisplayGeometry" + "dialog-control-document" + "" + "foreign" + 0 + 1 + 0 + 0 + "wbForeignCtrlProxy" + "ID_DisplayGeometry" + 10002 + "" + "DisplayGeometryWindow" + "wxWindow" + 1 + 0 + "" + "DisplayGeometryWindow.h" + "" + 1 + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + 120 + 80 + "Centre" + "Expand" + 1 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + "" + + + + "wxListbook: ID_LISTBOOK" + "dialog-control-document" + "" + "notebook" + 0 + 1 + 0 + 0 + "wbListbookProxy" + "ID_LISTBOOK" + 10001 + "" + "wxListbook" + "wxListbook" + 1 + 0 + "" + "" + "m_Notebook" + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Expand" + "Centre" + 1 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + + + + "Sources" + "html-document" + "" + "sourcesfolder" + 1 + 1 + 0 + 1 + + "MotionDetectorMultiCam.rc" + "source-editor-document" + "MotionDetectorMultiCam.rc" + "source-editor" + 0 + 0 + 1 + 0 + "28/10/2010" + "" + + + + "Images" + "html-document" + "" + "bitmapsfolder" + 1 + 1 + 0 + 1 + + + + +
diff --git a/MotionDetectorMultiCam/MotionDetectorMultiCamExports.cpp b/MotionDetectorMultiCam/MotionDetectorMultiCamExports.cpp new file mode 100644 index 0000000..2d0f62c --- /dev/null +++ b/MotionDetectorMultiCam/MotionDetectorMultiCamExports.cpp @@ -0,0 +1,14 @@ +#include "stdwx.h" +#include +#include "MotionDetectorMultiCamPlugin.h" +#include "MotionDetectorMultiCamGuiPlugin.h" + +PLUGIN_EXPORTED_API MotionDetectorPluginBase * CreatePlugin() +{ + return new MotionDetectorMultiCamPlugin; +} + +PLUGIN_EXPORTED_API void DeletePlugin(MotionDetectorPluginBase * plugin) +{ + wxDELETE(plugin); +} diff --git a/MotionDetectorMultiCam/MotionDetectorMultiCamGuiPlugin.cpp b/MotionDetectorMultiCam/MotionDetectorMultiCamGuiPlugin.cpp new file mode 100644 index 0000000..3874067 --- /dev/null +++ b/MotionDetectorMultiCam/MotionDetectorMultiCamGuiPlugin.cpp @@ -0,0 +1,32 @@ +#include "stdwx.h" +#include "MotionDetectorMultiCamGuiPlugin.h" +#include "MultiCamSettingsPanel.h" + +IMPLEMENT_DYNAMIC_CLASS(MotionDetectorMultiCamGuiPlugin, wxGuiPluginBase) + +MotionDetectorMultiCamGuiPlugin::MotionDetectorMultiCamGuiPlugin(wxEvtHandler* handler) + : wxGuiPluginBase(handler) +{ +} + +MotionDetectorMultiCamGuiPlugin::~MotionDetectorMultiCamGuiPlugin() +{ +} + +wxString MotionDetectorMultiCamGuiPlugin::GetId() const +{ + return wxT("{DC7382A2-1813-414c-9BD4-4BDF09058A0E}"); +} + +wxString MotionDetectorMultiCamGuiPlugin::GetName() const +{ + return wxT("MultiCam Motion Detector"); +} + +wxWindow* MotionDetectorMultiCamGuiPlugin::CreatePanel(wxWindow* parent) +{ + MultiCamSettingsPanel* panel = new MultiCamSettingsPanel(nullptr, parent); + + return static_cast(panel); +} + diff --git a/MotionDetectorMultiCam/MotionDetectorMultiCamGuiPlugin.h b/MotionDetectorMultiCam/MotionDetectorMultiCamGuiPlugin.h new file mode 100644 index 0000000..698e350 --- /dev/null +++ b/MotionDetectorMultiCam/MotionDetectorMultiCamGuiPlugin.h @@ -0,0 +1,14 @@ +#pragma once +#include + +class MotionDetectorMultiCamGuiPlugin : public wxGuiPluginBase +{ + DECLARE_DYNAMIC_CLASS(MotionDetectorMultiCamGuiPlugin) +public: + MotionDetectorMultiCamGuiPlugin(wxEvtHandler* handler = nullptr); + virtual ~MotionDetectorMultiCamGuiPlugin(); + + virtual wxString GetName() const override; + virtual wxString GetId() const override; + virtual wxWindow* CreatePanel(wxWindow* parent) override; +}; \ No newline at end of file diff --git a/MotionDetectorMultiCam/MotionDetectorMultiCamPlugin.cpp b/MotionDetectorMultiCam/MotionDetectorMultiCamPlugin.cpp new file mode 100644 index 0000000..eed9e9b --- /dev/null +++ b/MotionDetectorMultiCam/MotionDetectorMultiCamPlugin.cpp @@ -0,0 +1,36 @@ +#include "stdwx.h" +#include "MotionDetectorMultiCamPlugin.h" +#include "MotionDetectorMultiCam.h" +#include "MultiCamSettingsPanel.h" +#if defined(USE_VLD) +#include s +#endif + +IMPLEMENT_DYNAMIC_CLASS(MotionDetectorMultiCamPlugin, MotionDetectorPluginBase) + +MotionDetectorMultiCamPlugin::MotionDetectorMultiCamPlugin() +: m_ID(wxT("{DC7382A2-1813-414c-9BD4-4BDF09058A0E}")) +{ + +} + +MotionDetectorMultiCamPlugin::~MotionDetectorMultiCamPlugin() +{ + +} + +wxString MotionDetectorMultiCamPlugin::GetID() const +{ + return m_ID; +} + +wxString MotionDetectorMultiCamPlugin::GetName() const +{ + return _("MultiCam Motion Detector"); +} + +MotionDetectorBase * MotionDetectorMultiCamPlugin::CreateDetector(GeometryProvider && geometryProvider) +{ + return new MotionDetectorMultiCam(this, std::move(geometryProvider)); +} + diff --git a/MotionDetectorMultiCam/MotionDetectorMultiCamPlugin.h b/MotionDetectorMultiCam/MotionDetectorMultiCamPlugin.h new file mode 100644 index 0000000..39fe25d --- /dev/null +++ b/MotionDetectorMultiCam/MotionDetectorMultiCamPlugin.h @@ -0,0 +1,21 @@ +#ifndef _MOTIONDETECTORMULTICAMPLUGIN_H +#define _MOTIONDETECTORMULTICAMPLUGIN_H + +#include + +/// Base class for all iFloor effect plugins +class MotionDetectorMultiCamPlugin : public MotionDetectorPluginBase +{ + DECLARE_DYNAMIC_CLASS(MotionDetectorMultiCamPlugin) +public: + MotionDetectorMultiCamPlugin(); + ~MotionDetectorMultiCamPlugin(); + virtual wxString GetID() const; + virtual wxString GetName() const; + + virtual MotionDetectorBase * CreateDetector(GeometryProvider && geometryProvider); +private: + wxString m_ID; +}; + +#endif // _MOTIONDETECTORMULTICAMPLUGIN_H \ No newline at end of file diff --git a/MotionDetectorMultiCam/MultiCamCameraManager.cpp b/MotionDetectorMultiCam/MultiCamCameraManager.cpp new file mode 100644 index 0000000..50121fe --- /dev/null +++ b/MotionDetectorMultiCam/MultiCamCameraManager.cpp @@ -0,0 +1,234 @@ +#include "stdwx.h" +#include +#include "MultiCamCameraManager.h" +#include +#include + +#if defined(USE_VLD) +#include +#endif + +#define CMAN_ERR_NO_ERROR 0 +#define CMAN_ERR_NO_INDEX 2 +#define CMAN_ERR_WRONG_SIZE 3 +#define CMAN_ERR_NO_FILTER 4 + +const int MultiCamCameraManager::MAX_WIDTH = INT_MAX; +const int MultiCamCameraManager::MAX_HEIGHT = INT_MAX; +const wxString MultiCamCameraManager::ERROR_MESSAGES[] = +{ + _("No error"), + _("The depth or the number of channels differ in cameras images"), + _("There is no camera with such index"), + _("Wrong height or width of the full view image"), + _("There is no filter with such name"), +}; + +MultiCamCameraManager::MultiCamCameraManager(GeometryProvider & geometryProvider) + : m_Height(MAX_WIDTH) + , m_Width(MAX_HEIGHT) + , m_LastError(0) + , m_bUseOneOnMulti(false) + , m_GeometryProvider(geometryProvider) +{ + //cvNamedWindow("1"); +} + +MultiCamCameraManager::~MultiCamCameraManager(void) +{ + //cvDestroyWindow("1"); + CleanDisplayImages(); + + for (IFloorImagePreprocessorVector::iterator it = m_ArrayOfCameras.begin(); it != m_ArrayOfCameras.end(); ++it) + { + delete *it; + } + m_ArrayOfCameras.clear(); +} + +IFloorImagePreprocessor * MultiCamCameraManager::GetCameraByID(int cameraID) +{ + if (cameraID < (int)m_ArrayOfCameras.size() ) + return m_ArrayOfCameras[cameraID]; + else + return nullptr; +} + +void MultiCamCameraManager::SetUseOneOnMulti(bool useOne) +{ + m_bUseOneOnMulti = useOne; +} + +void MultiCamCameraManager::AddCamera(const IFloorCameraSettings * settings, void * buffer, size_t bufLength) +{ + m_ArrayOfCameras.push_back(new IFloorImagePreprocessor(settings, buffer, bufLength)); +} + +bool MultiCamCameraManager::InitCameraParams() +{ + // Look for minimum sizes + for (size_t i = 0; i < m_ArrayOfCameras.size(); i++) + { + IFloorImagePreprocessor * capture = m_ArrayOfCameras[i]; + if (capture != nullptr) + { + m_Height = wxMin(capture->GetSettings()->CamHeight, m_Height); + m_Width = wxMin(capture->GetSettings()->CamWidth, m_Width); + } + } + + // Decided what capture we must resize + for (size_t i = 0; i < m_ArrayOfCameras.size(); i++) + { + IFloorImagePreprocessor * capture = m_ArrayOfCameras[i]; + if (capture != nullptr) + { + capture->PrepareImage(m_Width, m_Height); + } + } + return (m_Height != MAX_HEIGHT) || (m_Width != MAX_WIDTH); +} + +cv::Mat MultiCamCameraManager::GetImage() +{ + wxPoint pointIn; + wxRectVector displays; + m_GeometryProvider.GetGeometry(displays); + size_t count = wxMin(displays.size(), m_ArrayOfCameras.size()); + + if (m_ImgFullView.empty() && count > 0) + { + m_ImgFullView = cv::Mat::zeros(cv::Size(m_Width, m_Height), CV_8UC3); + } + + for (auto i = 0; i < count; ++i) + { + IFloorImagePreprocessor * capture = m_ArrayOfCameras[i]; + if (capture != nullptr) + { + wxRect & display = displays[i]; + cv::Mat img = capture->ProcessImage(); + if (img.empty()) + continue; + + // Create image if necessary + if (m_DispImages.size() < i + 1) + { + m_DispImages.push_back(cv::Mat::zeros(cv::Size(display.GetWidth(), display.GetHeight()), img.type())); + } + + if (m_bUseOneOnMulti) + { + cv::resize(img, m_ImgFullView, m_ImgFullView.size()); + } + else // If we use default system monitors geometry and one camera per monitor + { + + // Resize image to fit display size + cv::Mat displayImg = m_DispImages[i]; + cv::resize(img, displayImg, displayImg.size()); + // Calculate insertion point + pointIn = display.GetLeftTop(); + + pointIn -= m_LeftTop; + + cv::Rect roi(pointIn.x, pointIn.y, displayImg.cols, displayImg.rows); + + if (roi.x >= 0 && roi.y >= 0 && (roi.x + roi.width) <= m_ImgFullView.cols && (roi.y + roi.height) <= m_ImgFullView.rows) + { + displayImg.copyTo(m_ImgFullView(roi)); + } + } + } + } + /*if(rand() % 20 == 0) + { + cvSaveImage("test.bmp", m_ImgFullView); + IplImage * t = cvCreateImage(cvSize(m_ImgFullView->width*0.3, m_ImgFullView->height*0.3), m_ImgFullView->depth, m_ImgFullView->nChannels); + cvResize(m_ImgFullView, t); + cvShowImage("1", t); + cvReleaseImage(&t); + }*/ + + return m_ImgFullView; +} + + +bool MultiCamCameraManager::SetROI(int x, int y, int width, int height, int cameraID) +{ + + if (cameraID < (int)m_ArrayOfCameras.size()) + { + m_ArrayOfCameras[cameraID]->SetROI(x, y, width, height); + m_LastError = CMAN_ERR_NO_ERROR; + return true; + } + else{ + m_LastError = CMAN_ERR_NO_INDEX; + return false; + } +} + +bool MultiCamCameraManager::CreateFullView() +{ + wxRect workingArea; + + CleanDisplayImages(); + wxRectVector displays; + m_GeometryProvider.GetGeometry(displays); + for (auto i = 0; i < displays.size(); ++i) + { + wxRect & display = displays[i]; + workingArea.Union(display); + } + m_Height = workingArea.height; + m_Width = workingArea.width; + m_LeftTop = workingArea.GetLeftTop(); + m_ImgFullView.release(); + + return true; +} + +wxString MultiCamCameraManager::GetLastError() +{ + return ERROR_MESSAGES[m_LastError]; +} + +bool MultiCamCameraManager::AddFilter(int cameraID, const wxString & filterType, const wxString & config /*= wxEmptyString*/) +{ + if (cameraID < (int)m_ArrayOfCameras.size()) + { + if (m_ArrayOfCameras[cameraID]->AddFilterToChain(filterType, config)) + { + m_LastError = CMAN_ERR_NO_ERROR; + return true; + } + else + { + m_LastError = CMAN_ERR_NO_FILTER; + } + } + else + { + m_LastError = CMAN_ERR_NO_INDEX; + } + return false; +} + +bool MultiCamCameraManager::SetFilterSettings(int cameraID, const wxString & filterType, const wxString & config) +{ + IFloorImagePreprocessor * camera = GetCameraByID(cameraID); + if (!camera) + return false; + + return camera->SetFilterSettings(filterType, config); +} + +void MultiCamCameraManager::CleanDisplayImages() +{ + for (size_t i=0; i < m_DispImages.size(); i++) + { + m_DispImages[i].release(); + } + m_DispImages.clear(); +} diff --git a/MotionDetectorMultiCam/MultiCamCameraManager.h b/MotionDetectorMultiCam/MultiCamCameraManager.h new file mode 100644 index 0000000..e3350da --- /dev/null +++ b/MotionDetectorMultiCam/MultiCamCameraManager.h @@ -0,0 +1,70 @@ +#ifndef _MULTICAMCAMERAMANAGER_H +#define _MULTICAMCAMERAMANAGER_H +#include +#include + +// Type definition for display image vector +typedef std::vector ImageVector; + +class GeometryProvider; + +class MultiCamCameraManager +{ +public: + MultiCamCameraManager(GeometryProvider & geometryProvider); + ~MultiCamCameraManager(void); + // Add camera reference + void AddCamera(const IFloorCameraSettings * settings, void * buffer, size_t bufLength); + // Calculate camera view + bool InitCameraParams(); + // Set the region of interest for camera with specific ID + bool SetROI(int x, int y, int width, int height, int cameraID); + // Need to create a full camera view after all initializations + bool CreateFullView(); + // Get last error msg + wxString GetLastError(); + // Add a filter to the camera + bool AddFilter(int cameraID, const wxString & filterType, const wxString & config = wxEmptyString); + // Change filter settings + bool SetFilterSettings(int cameraID, const wxString & filterType, const wxString & config); + // Get concatenate view + cv::Mat GetImage(); + // Clean the display image vector + void CleanDisplayImages(); + // Get camera filter preprocessor by ID + IFloorImagePreprocessor * GetCameraByID(int cameraID); + // Use one sensor for all monitors + void SetUseOneOnMulti(bool useOne); + + bool IsUsingCustomGeometry(); +protected: + // Cameras map + IFloorImagePreprocessorVector m_ArrayOfCameras; + // Full camera view + cv::Mat m_ImgFullView; + // Display image vector + ImageVector m_DispImages; + // Base image size + int m_Height; + int m_Width; + // Arrays of heights and widths + wxArrayInt m_RowHeights; + wxArrayInt m_ColWidths; + // Arrays of offsets + wxArrayInt m_OffsetsX; + wxArrayInt m_OffsetsY; + // Last error number + int m_LastError; + // Left-top point of union display rectangle + wxPoint m_LeftTop; + // Use one sensor for all monitors + bool m_bUseOneOnMulti; + + GeometryProvider & m_GeometryProvider; +private: + static const int MAX_HEIGHT; + static const int MAX_WIDTH; + static const wxString ERROR_MESSAGES[]; +}; + +#endif // _MULTICAMCAMERAMANAGER_H \ No newline at end of file diff --git a/MotionDetectorMultiCam/MultiCamSettingsPanel.cpp b/MotionDetectorMultiCam/MultiCamSettingsPanel.cpp new file mode 100644 index 0000000..3616f47 --- /dev/null +++ b/MotionDetectorMultiCam/MultiCamSettingsPanel.cpp @@ -0,0 +1,390 @@ +#include "stdwx.h" +#include "MultiCamSettingsPanel.h" +#include "MotionDetectorMultiCam.h" +#include "IFloorImagePreprocessor.h" +#include "FilterPreviewWindow.h" +#include +#include +#include +#include + +////@begin includes +#include "DisplayGeometryWindow.h" +#include "wx/imaglist.h" +////@end includes + +#if defined(USE_VLD) +#include +#endif + +////@begin XPM images +////@end XPM images + +/* + * MultiCamSettingsPanel type definition + */ + +IMPLEMENT_DYNAMIC_CLASS( MultiCamSettingsPanel, MotionDetectorConfigWindowBase ) + + +/* + * MultiCamSettingsPanel event table definition + */ + +BEGIN_EVENT_TABLE( MultiCamSettingsPanel, MotionDetectorConfigWindowBase ) + +////@begin MultiCamSettingsPanel event table entries +////@end MultiCamSettingsPanel event table entries +EVT_BITMAP_SEND(wxID_ANY, MultiCamSettingsPanel::OnImageCallback) + +END_EVENT_TABLE() + + +/* + * MultiCamSettingsPanel constructors + */ + + MultiCamSettingsPanel::MultiCamSettingsPanel() +{ + Init(); +} + +MultiCamSettingsPanel::MultiCamSettingsPanel(MotionDetectorMultiCam * detector, wxWindow * parent) +{ + Init(); + Create(detector, parent); +} + + +/* + * MultiCamSettingsPanel creator + */ + +bool MultiCamSettingsPanel::Create(MotionDetectorMultiCam * detector, wxWindow * parent) +{ + MotionDetectorConfigWindowBase::Create(detector, parent); + CreateControls(); + ReadConfig(); + return true; +} + + +/* + * MultiCamSettingsPanel destructor + */ + +MultiCamSettingsPanel::~MultiCamSettingsPanel() +{ +////@begin MultiCamSettingsPanel destruction +////@end MultiCamSettingsPanel destruction + m_CameraSettings.Clear(); +} + + +/* + * Member initialisation + */ + +void MultiCamSettingsPanel::Init() +{ +////@begin MultiCamSettingsPanel member initialisation + m_Notebook = NULL; +////@end MultiCamSettingsPanel member initialisation +} + + +/* + * Control creation for MultiCamSettingsPanel + */ + +void MultiCamSettingsPanel::CreateControls() +{ +////@begin MultiCamSettingsPanel content construction + MultiCamSettingsPanel* itemMotionDetectorConfigWindowBase1 = this; + + wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL); + itemMotionDetectorConfigWindowBase1->SetSizer(itemBoxSizer2); + + wxStaticBox* itemStaticBoxSizer3Static = new wxStaticBox(itemMotionDetectorConfigWindowBase1, wxID_ANY, _("Display Settings")); + wxStaticBoxSizer* itemStaticBoxSizer3 = new wxStaticBoxSizer(itemStaticBoxSizer3Static, wxHORIZONTAL); + itemBoxSizer2->Add(itemStaticBoxSizer3, 0, wxGROW|wxLEFT|wxRIGHT|wxBOTTOM, 5); + + wxStaticText* itemStaticText4 = new wxStaticText( itemStaticBoxSizer3->GetStaticBox(), wxID_STATIC, _("Displays layout:"), wxDefaultPosition, wxDefaultSize, 0 ); + itemStaticBoxSizer3->Add(itemStaticText4, 0, wxALIGN_TOP|wxALL, 5); + + DisplayGeometryWindow* itemWindow5 = new DisplayGeometryWindow( itemStaticBoxSizer3->GetStaticBox(), m_Detector->GetGeometryProvider(), ID_DisplayGeometry, wxDefaultPosition, wxSize(120, 80), wxNO_BORDER ); + itemStaticBoxSizer3->Add(itemWindow5, 1, wxGROW|wxALL, 5); + + m_Notebook = new wxListbook( itemMotionDetectorConfigWindowBase1, ID_LISTBOOK, wxDefaultPosition, wxDefaultSize, wxBK_TOP ); + + itemBoxSizer2->Add(m_Notebook, 1, wxGROW|wxALL, 5); + +////@end MultiCamSettingsPanel content construction + m_Notebook->GetListView()->SetSizeHints(-1, 50, -1, 50); + + wxStaticBox* itemStaticBoxSizer6Static = new wxStaticBox(itemMotionDetectorConfigWindowBase1, wxID_ANY, _("Blobs Limits")); + wxStaticBoxSizer* itemStaticBoxSizer6 = new wxStaticBoxSizer(itemStaticBoxSizer6Static, wxHORIZONTAL); + itemBoxSizer2->Add(itemStaticBoxSizer6, 0, wxGROW|wxLEFT|wxRIGHT|wxBOTTOM, 5); + + wxStaticText* itemStaticText7 = new wxStaticText( itemMotionDetectorConfigWindowBase1, wxID_STATIC, _("Maximum Blob Area Limit:"), wxDefaultPosition, wxDefaultSize, 0 ); + itemStaticBoxSizer6->Add(itemStaticText7, 0, wxALIGN_TOP|wxALL, 5); + + m_cbMaxBlobArea = new wxSpinCtrl( itemMotionDetectorConfigWindowBase1, ID_MAXBLOBAREA, _T("10000"), wxDefaultPosition, wxSize(70, -1), wxSP_ARROW_KEYS, 1000, 1000000, 0 ); + itemStaticBoxSizer6->Add(m_cbMaxBlobArea, 0, wxGROW|wxLEFT|wxRIGHT|wxBOTTOM, 5); + + wxStaticText* itemStaticText8 = new wxStaticText( itemMotionDetectorConfigWindowBase1, wxID_STATIC, _("Minimum Blob Area Limit:"), wxDefaultPosition, wxDefaultSize, 0 ); + itemStaticBoxSizer6->Add(itemStaticText8, 0, wxALIGN_TOP|wxALL, 5); + + m_cbMinBlobArea = new wxSpinCtrl( itemMotionDetectorConfigWindowBase1, ID_MINBLOBAREA, _T("100"), wxDefaultPosition, wxSize(70, -1), wxSP_ARROW_KEYS, 10, 10000, 0 ); + itemStaticBoxSizer6->Add(m_cbMinBlobArea, 0, wxGROW|wxLEFT|wxRIGHT|wxBOTTOM, 5); + + wxStaticText* itemStaticText9 = new wxStaticText( itemMotionDetectorConfigWindowBase1, wxID_STATIC, _("Maximum Blob Count:"), wxDefaultPosition, wxDefaultSize, 0 ); + itemStaticBoxSizer6->Add(itemStaticText9, 0, wxALIGN_TOP|wxALL, 5); + + m_cbMaxBlobCount = new wxSpinCtrl( itemMotionDetectorConfigWindowBase1, ID_MAXBLOBCOUNT, _T("5"), wxDefaultPosition, wxSize(70, -1), wxSP_ARROW_KEYS, 1, 200, 0 ); + itemStaticBoxSizer6->Add(m_cbMaxBlobCount, 0, wxGROW|wxLEFT|wxRIGHT|wxBOTTOM, 5); + + m_cbUseOneOnMulti = new wxCheckBox( itemMotionDetectorConfigWindowBase1, ID_MAXBLOBCOUNT, _T("Use one sensor on multiple monitors")); + itemStaticBoxSizer6->Add(m_cbUseOneOnMulti , 0, wxGROW|wxLEFT|wxRIGHT|wxBOTTOM, 5); + if(m_Detector != NULL){ + MotionDetectorMultiCam* detector = dynamic_cast(m_Detector); + m_cbMaxBlobArea->SetValidator(wxGenericValidator(&detector->m_maxBlobArea)); + m_cbMaxBlobArea->GetValidator()->TransferToWindow(); + + m_cbMinBlobArea->SetValidator(wxGenericValidator(&detector->m_minBlobArea)); + m_cbMinBlobArea->GetValidator()->TransferToWindow(); + + m_cbMaxBlobCount->SetValidator(wxGenericValidator(&detector->m_maxBlobCount)); + m_cbMaxBlobCount->GetValidator()->TransferToWindow(); + + m_cbUseOneOnMulti->SetValidator(wxGenericValidator(&detector->m_bUseOneOnMulti)); + m_cbUseOneOnMulti->GetValidator()->TransferToWindow(); + } +#if defined(__WXGTK__) + SetBackgroundColour(*wxWHITE); +#endif +} + + +/* + * Should we show tooltips? + */ + +bool MultiCamSettingsPanel::ShowToolTips() +{ + return true; +} + +/* + * Get bitmap resources + */ + +wxBitmap MultiCamSettingsPanel::GetBitmapResource( const wxString& name ) +{ + // Bitmap retrieval +////@begin MultiCamSettingsPanel bitmap retrieval + wxUnusedVar(name); + return wxNullBitmap; +////@end MultiCamSettingsPanel bitmap retrieval +} + +/* + * Get icon resources + */ + +wxIcon MultiCamSettingsPanel::GetIconResource( const wxString& name ) +{ + // Icon retrieval +////@begin MultiCamSettingsPanel icon retrieval + wxUnusedVar(name); + return wxNullIcon; +////@end MultiCamSettingsPanel icon retrieval +} + +bool MultiCamSettingsPanel::ReadConfig() +{ + if (m_Detector == nullptr) + { + return false; + } + + MotionDetectorMultiCam * detector = (MotionDetectorMultiCam *)m_Detector; + m_CameraSettings = detector->GetCameraSettings(); + return true; +} + +bool MultiCamSettingsPanel::SaveConfig() +{ + + if (m_Detector == nullptr) + { + return false; + } + + MotionDetectorMultiCam * detector = (MotionDetectorMultiCam *)m_Detector; + ReadCameraSettings(); + detector->GetCameraSettings() = m_CameraSettings; + return true; +} + +void MultiCamSettingsPanel::StartDetection() +{ + wxWindowUpdateLocker lock(this); + + int pos = m_Notebook->GetSelection(); + m_Notebook->DeleteAllPages(); + m_PreviewMap.clear(); + for (size_t i = 0; i < m_Detector->GetSupportedCamerasCount(); ++i) + { + CreateCameraSettings(i); + } + + TransferDataToWindow(); + + if (pos == wxNOT_FOUND) + pos = 0; + if (m_Notebook->GetPageCount() > 0) + m_Notebook->SetSelection(pos); +} + +void MultiCamSettingsPanel::StopDetection() +{ + ReadCameraSettings(); +} + +void MultiCamSettingsPanel::CreateCameraSettings(int index) +{ + MotionDetectorMultiCam * detector = (MotionDetectorMultiCam *)m_Detector; + IFloorImagePreprocessor * camera = detector->GetCameraImagePreprocessor(index); + + if (!camera) + return; + + bool hasConfig = index < (int)m_CameraSettings.GetCount(); + + wxScrolledWindow * page = new wxScrolledWindow(m_Notebook); +#if defined(__WXGTK__) + page->SetBackgroundColour(*wxWHITE); +#endif + page->SetClientData(camera); + wxSizer * sizer = new wxFlexGridSizer(2); + page->SetSizer(sizer); + ChainOfFilters & filters = camera->GetFilters(); + for (size_t i = 0; i < filters.size(); ++i) + { + Filter * filter = filters[i]; + if (hasConfig) + IFloorImagePreprocessor::SetFilterSettings(filter, m_CameraSettings[index][filter->GetClassInfo()->GetClassName()]); + FilterPreviewWindow * preview = new FilterPreviewWindow(page, wxID_STATIC, wxDefaultPosition, wxSize(PREVIEW_WIDTH, PREVIEW_HEIGHT), wxNO_BORDER); + m_PreviewMap[filter] = preview; + filter->CreatePreviewAndParams(page, sizer, preview); + filter->SetImageCallback(&MultiCamSettingsPanel::ImageCallback, index, this); + } + page->Layout(); + page->SetScrollbars(1, 1, 0, 0); + page->FitInside(); + + m_Notebook->AddPage(page, wxString::Format(_("Camera #%d"), index)); +} + +void MultiCamSettingsPanel::ImageCallback(int cameraID, const wxString& filterName, cv::Mat image, void* userData) +{ + MultiCamSettingsPanel * _this = (MultiCamSettingsPanel *)userData; + int pos = _this->m_Notebook->GetSelection(); + if (pos != cameraID || image.empty()) + return; + + cv::Mat resizedImg; + cv::resize(image, resizedImg, cv::Size(PREVIEW_WIDTH, PREVIEW_HEIGHT), 0, 0, cv::INTER_LINEAR); + + cv::Mat destination; + if (resizedImg.channels() == 1) + { + cv::cvtColor(resizedImg, destination, cv::COLOR_GRAY2RGB); + } + else if (resizedImg.channels() == 3) + { + cv::cvtColor(resizedImg, destination, cv::COLOR_BGR2RGB); + } + else if (resizedImg.channels() == 4) + { + cv::cvtColor(resizedImg, destination, cv::COLOR_BGRA2RGB); + } + else + wxFAIL_MSG(wxT("Unknown color model")); + + + if (!destination.empty()) + { + wxImage img(destination.cols, destination.rows, destination.data, true); + wxBitmap* bmp = new wxBitmap(img); + + wxBitmapEvent* event = new wxBitmapEvent(bmp, EVT_IMAGE_CALLBACK); + event->SetString(filterName); + event->SetInt(cameraID); + _this->GetEventHandler()->QueueEvent(event); + } +} + +void MultiCamSettingsPanel::OnImageCallback(wxBitmapEvent & event) +{ + wxBitmap * bmp = event.GetBitmap(); + + if (!bmp) + return; + + do + { + if (m_Notebook->GetSelection() != event.GetInt()) // CameraID + break; + + IFloorImagePreprocessor * camera = (IFloorImagePreprocessor *)m_Notebook->GetPage(event.GetInt())->GetClientData(); + if (!camera) + break; + + Filter * filter = camera->GetFilter(event.GetString()); + if (!filter) + break; + + FilterPreviewWindow * preview = m_PreviewMap[filter]; + if (!preview) + break; + preview->SetBitmap(*bmp); + } while (false); +} + +void MultiCamSettingsPanel::ReadCameraSettings() +{ + MotionDetectorMultiCam * detector = (MotionDetectorMultiCam *)m_Detector; + if (!detector->IsRunning()) + return; + m_CameraSettings.Clear(); + for (int i = 0; i < detector->GetSupportedCamerasCount(); ++i) + { + IFloorImagePreprocessorSettings * settings = new IFloorImagePreprocessorSettings(); + m_CameraSettings.Add(settings); + IFloorImagePreprocessor * camera = detector->GetCameraImagePreprocessor(i); + if (!camera) + continue; + ChainOfFilters & filters = camera->GetFilters(); + for (size_t j = 0; j < filters.size(); ++j) + { + Filter * filter = filters[j]; + if (!filter) + continue; + wxString config = SerializableBase::Serialize(*filter); + settings->SetFilterConfig(filter->GetClassInfo()->GetClassName(), config); + } + } +} + +bool MultiCamSettingsPanel::TransferDataFromWindow() +{ + MotionDetectorMultiCam * detector = (MotionDetectorMultiCam *)m_Detector; + m_cbMaxBlobArea->GetValidator()->TransferFromWindow(); + m_cbMinBlobArea->GetValidator()->TransferFromWindow(); + m_cbMaxBlobCount->GetValidator()->TransferFromWindow(); + if (!detector->IsRunning()) + return true; + return wxWindow::TransferDataFromWindow(); +} diff --git a/MotionDetectorMultiCam/MultiCamSettingsPanel.h b/MotionDetectorMultiCam/MultiCamSettingsPanel.h new file mode 100644 index 0000000..cc5512a --- /dev/null +++ b/MotionDetectorMultiCam/MultiCamSettingsPanel.h @@ -0,0 +1,112 @@ +#ifndef _MULTICAMSETTINGSPANEL_H +#define _MULTICAMSETTINGSPANEL_H + + +/*! + * Includes + */ + +////@begin includes +#include "wx/listbook.h" +////@end includes +#include "wx/spinctrl.h" // the base class +#include +#include +#include + +/*! + * Forward declarations + */ + +////@begin forward declarations +class MultiCamSettingsPanel; +class wxListbook; +////@end forward declarations +class MotionDetectorMultiCam; +class IFloorImagePreprocessor; +class FilterPreviewWindow; +class wxBitmapEvent; + +WX_DECLARE_VOIDPTR_HASH_MAP(FilterPreviewWindow *, FilterPreviewMap); + +/*! + * MultiCamSettingsPanel class declaration + */ + +class MultiCamSettingsPanel: public MotionDetectorConfigWindowBase +{ + DECLARE_DYNAMIC_CLASS( MultiCamSettingsPanel ) + DECLARE_EVENT_TABLE() + +public: + /// Constructors + MultiCamSettingsPanel(); + MultiCamSettingsPanel(MotionDetectorMultiCam * detector, wxWindow * parent); + + /// Creation + bool Create(MotionDetectorMultiCam * detector, wxWindow * parent); + + /// Destructor + ~MultiCamSettingsPanel(); + + /// Initialises member variables + void Init(); + + /// Creates the controls and sizers + void CreateControls(); + + // IFloorConfigureManager implementation + virtual bool ReadConfig(); + virtual bool SaveConfig(); + + virtual void StartDetection(); + virtual void StopDetection(); + + virtual bool TransferDataFromWindow(); + +////@begin MultiCamSettingsPanel event handler declarations + +////@end MultiCamSettingsPanel event handler declarations + void OnImageCallback(wxBitmapEvent & event); + +////@begin MultiCamSettingsPanel member function declarations + + /// Retrieves bitmap resources + wxBitmap GetBitmapResource( const wxString& name ); + + /// Retrieves icon resources + wxIcon GetIconResource( const wxString& name ); +////@end MultiCamSettingsPanel member function declarations + + /// Should we show tooltips? + static bool ShowToolTips(); + + void CreateCameraSettings(int index); + static void ImageCallback(int cameraID, const wxString& filterName, cv::Mat image, void* userData); + + void ReadCameraSettings(); + +////@begin MultiCamSettingsPanel member variables + wxListbook* m_Notebook; + /// Control identifiers + enum { + ID_MULTICAMSETTINGSPANEL = 10000, + ID_DisplayGeometry = 10002, + ID_LISTBOOK = 10001 + }; +////@end MultiCamSettingsPanel member variables + wxSpinCtrl* m_cbMaxBlobArea; + wxSpinCtrl* m_cbMinBlobArea; + wxSpinCtrl* m_cbMaxBlobCount; + wxCheckBox* m_cbUseOneOnMulti; + enum{ + ID_MAXBLOBAREA = 10003, + ID_MINBLOBAREA = 10004, + ID_MAXBLOBCOUNT = 10005, + ID_USEONE = 10006 + }; + FilterPreviewMap m_PreviewMap; + IFloorImagePreprocessorSettingsArray m_CameraSettings; +}; + +#endif // _MULTICAMSETTINGSPANEL_H diff --git a/MotionDetectorMultiCam/Win/ALL_BUILD.vcxproj b/MotionDetectorMultiCam/Win/ALL_BUILD.vcxproj new file mode 100644 index 0000000..2cab1fa --- /dev/null +++ b/MotionDetectorMultiCam/Win/ALL_BUILD.vcxproj @@ -0,0 +1,123 @@ + + + + x64 + + + false + + + + Debug + x64 + + + Release + x64 + + + + {79459F13-BE3F-3ABE-B665-62AD563E5B08} + Win32Proj + 10.0.26100.0 + x64 + ALL_BUILD + NoUpgrade + + + + Utility + MultiByte + v143 + + + Utility + MultiByte + v143 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + $(Platform)\$(Configuration)\$(ProjectName)\ + $(Platform)\$(Configuration)\$(ProjectName)\ + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + + Always + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam\Win\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam\Win\CMakeFiles\generate.stamp + false + + + + + + + + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + ZERO_CHECK + false + Never + + + {4877C470-9466-37C0-A451-03973F6EDABD} + MotionDetectorMultiCam + + + {38ABD20B-B450-3DE7-A759-71587CAB9A2A} + MotionDetectorMultiCamGui + + + + + + \ No newline at end of file diff --git a/MotionDetectorMultiCam/Win/ALL_BUILD.vcxproj.filters b/MotionDetectorMultiCam/Win/ALL_BUILD.vcxproj.filters new file mode 100644 index 0000000..4e1fc36 --- /dev/null +++ b/MotionDetectorMultiCam/Win/ALL_BUILD.vcxproj.filters @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/MotionDetectorMultiCam/Win/MotionDetectorMultiCam.sln b/MotionDetectorMultiCam/Win/MotionDetectorMultiCam.sln new file mode 100644 index 0000000..1dba1a1 --- /dev/null +++ b/MotionDetectorMultiCam/Win/MotionDetectorMultiCam.sln @@ -0,0 +1,175 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ALL_BUILD", "ALL_BUILD.vcxproj", "{79459F13-BE3F-3ABE-B665-62AD563E5B08}" + ProjectSection(ProjectDependencies) = postProject + {4877C470-9466-37C0-A451-03973F6EDABD} = {4877C470-9466-37C0-A451-03973F6EDABD} + {38ABD20B-B450-3DE7-A759-71587CAB9A2A} = {38ABD20B-B450-3DE7-A759-71587CAB9A2A} + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} = {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommonPluginBase", "C:\Users\Admin\IFloor\projects\wxVideoProcessing\CommonPluginBase\Win\CommonPluginBase.vcxproj", "{751A15C0-76C2-3506-AB9D-0CD3545003FA}" + ProjectSection(ProjectDependencies) = postProject + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} = {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + {7887B55C-77B9-3262-AFAD-ABA738C61029} = {7887B55C-77B9-3262-AFAD-ABA738C61029} + {78CFCEBE-5466-3128-9717-547416DBFFE5} = {78CFCEBE-5466-3128-9717-547416DBFFE5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MotionDetectorCore", "C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorCore\Win\MotionDetectorCore.vcxproj", "{6E933546-0B62-311B-8D7E-6CE2ECD4CAD0}" + ProjectSection(ProjectDependencies) = postProject + {751A15C0-76C2-3506-AB9D-0CD3545003FA} = {751A15C0-76C2-3506-AB9D-0CD3545003FA} + {1F4B7EAD-4694-3453-AD34-1757E387661E} = {1F4B7EAD-4694-3453-AD34-1757E387661E} + {1903244B-9312-3A09-8AAD-8D78C1A4F977} = {1903244B-9312-3A09-8AAD-8D78C1A4F977} + {14D82890-BB7F-3748-8713-43304E91CFA1} = {14D82890-BB7F-3748-8713-43304E91CFA1} + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} = {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + {7887B55C-77B9-3262-AFAD-ABA738C61029} = {7887B55C-77B9-3262-AFAD-ABA738C61029} + {78CFCEBE-5466-3128-9717-547416DBFFE5} = {78CFCEBE-5466-3128-9717-547416DBFFE5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MotionDetectorMultiCam", "MotionDetectorMultiCam.vcxproj", "{4877C470-9466-37C0-A451-03973F6EDABD}" + ProjectSection(ProjectDependencies) = postProject + {751A15C0-76C2-3506-AB9D-0CD3545003FA} = {751A15C0-76C2-3506-AB9D-0CD3545003FA} + {6E933546-0B62-311B-8D7E-6CE2ECD4CAD0} = {6E933546-0B62-311B-8D7E-6CE2ECD4CAD0} + {1F4B7EAD-4694-3453-AD34-1757E387661E} = {1F4B7EAD-4694-3453-AD34-1757E387661E} + {1903244B-9312-3A09-8AAD-8D78C1A4F977} = {1903244B-9312-3A09-8AAD-8D78C1A4F977} + {14D82890-BB7F-3748-8713-43304E91CFA1} = {14D82890-BB7F-3748-8713-43304E91CFA1} + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} = {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + {23CF91DE-A1B5-3EE0-827D-ACAFD80C7CB2} = {23CF91DE-A1B5-3EE0-827D-ACAFD80C7CB2} + {007E33A1-3B69-3DBB-8C44-8A54188A3A21} = {007E33A1-3B69-3DBB-8C44-8A54188A3A21} + {7887B55C-77B9-3262-AFAD-ABA738C61029} = {7887B55C-77B9-3262-AFAD-ABA738C61029} + {78CFCEBE-5466-3128-9717-547416DBFFE5} = {78CFCEBE-5466-3128-9717-547416DBFFE5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MotionDetectorMultiCamGui", "MotionDetectorMultiCamGui.vcxproj", "{38ABD20B-B450-3DE7-A759-71587CAB9A2A}" + ProjectSection(ProjectDependencies) = postProject + {751A15C0-76C2-3506-AB9D-0CD3545003FA} = {751A15C0-76C2-3506-AB9D-0CD3545003FA} + {6E933546-0B62-311B-8D7E-6CE2ECD4CAD0} = {6E933546-0B62-311B-8D7E-6CE2ECD4CAD0} + {4877C470-9466-37C0-A451-03973F6EDABD} = {4877C470-9466-37C0-A451-03973F6EDABD} + {1F4B7EAD-4694-3453-AD34-1757E387661E} = {1F4B7EAD-4694-3453-AD34-1757E387661E} + {1903244B-9312-3A09-8AAD-8D78C1A4F977} = {1903244B-9312-3A09-8AAD-8D78C1A4F977} + {14D82890-BB7F-3748-8713-43304E91CFA1} = {14D82890-BB7F-3748-8713-43304E91CFA1} + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} = {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + {23CF91DE-A1B5-3EE0-827D-ACAFD80C7CB2} = {23CF91DE-A1B5-3EE0-827D-ACAFD80C7CB2} + {007E33A1-3B69-3DBB-8C44-8A54188A3A21} = {007E33A1-3B69-3DBB-8C44-8A54188A3A21} + {016D40A8-D2BA-3C2B-8741-718BD5CE7B51} = {016D40A8-D2BA-3C2B-8741-718BD5CE7B51} + {7887B55C-77B9-3262-AFAD-ABA738C61029} = {7887B55C-77B9-3262-AFAD-ABA738C61029} + {78CFCEBE-5466-3128-9717-547416DBFFE5} = {78CFCEBE-5466-3128-9717-547416DBFFE5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MotionDetectorPluginBase", "C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorPluginBase\Win\MotionDetectorPluginBase.vcxproj", "{1F4B7EAD-4694-3453-AD34-1757E387661E}" + ProjectSection(ProjectDependencies) = postProject + {751A15C0-76C2-3506-AB9D-0CD3545003FA} = {751A15C0-76C2-3506-AB9D-0CD3545003FA} + {14D82890-BB7F-3748-8713-43304E91CFA1} = {14D82890-BB7F-3748-8713-43304E91CFA1} + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} = {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + {7887B55C-77B9-3262-AFAD-ABA738C61029} = {7887B55C-77B9-3262-AFAD-ABA738C61029} + {78CFCEBE-5466-3128-9717-547416DBFFE5} = {78CFCEBE-5466-3128-9717-547416DBFFE5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MotionPrimitives", "C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\build\MotionPrimitives\Win\MotionPrimitives.vcxproj", "{1903244B-9312-3A09-8AAD-8D78C1A4F977}" + ProjectSection(ProjectDependencies) = postProject + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} = {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Utils", "C:\Users\Admin\IFloor\projects\wxVideoProcessing\Utils\Win\Utils.vcxproj", "{14D82890-BB7F-3748-8713-43304E91CFA1}" + ProjectSection(ProjectDependencies) = postProject + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} = {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZERO_CHECK", "C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\Win\ZERO_CHECK.vcxproj", "{6F4BDD20-5B99-3029-BDF0-7D719B283AF5}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "strmbas", "C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\build\strmbas\Win\strmbas.vcxproj", "{23CF91DE-A1B5-3EE0-827D-ACAFD80C7CB2}" + ProjectSection(ProjectDependencies) = postProject + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} = {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "videoInput", "C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\build\videoInput\Win\videoInput.vcxproj", "{007E33A1-3B69-3DBB-8C44-8A54188A3A21}" + ProjectSection(ProjectDependencies) = postProject + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} = {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + {23CF91DE-A1B5-3EE0-827D-ACAFD80C7CB2} = {23CF91DE-A1B5-3EE0-827D-ACAFD80C7CB2} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxGuiPluginBase", "C:\Users\Admin\IFloor\projects\wxVideoProcessing\wxGuiPluginBase\Win\wxGuiPluginBase.vcxproj", "{016D40A8-D2BA-3C2B-8741-718BD5CE7B51}" + ProjectSection(ProjectDependencies) = postProject + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} = {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxJSON", "C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\build\wxJSON\build\Win\wxJSON.vcxproj", "{7887B55C-77B9-3262-AFAD-ABA738C61029}" + ProjectSection(ProjectDependencies) = postProject + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} = {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxXS", "C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\build\wxXS\build\Win\wxXS.vcxproj", "{78CFCEBE-5466-3128-9717-547416DBFFE5}" + ProjectSection(ProjectDependencies) = postProject + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} = {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + {7887B55C-77B9-3262-AFAD-ABA738C61029} = {7887B55C-77B9-3262-AFAD-ABA738C61029} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {79459F13-BE3F-3ABE-B665-62AD563E5B08}.Debug|x64.ActiveCfg = Debug|x64 + {79459F13-BE3F-3ABE-B665-62AD563E5B08}.Release|x64.ActiveCfg = Release|x64 + {751A15C0-76C2-3506-AB9D-0CD3545003FA}.Debug|x64.ActiveCfg = Debug|x64 + {751A15C0-76C2-3506-AB9D-0CD3545003FA}.Debug|x64.Build.0 = Debug|x64 + {751A15C0-76C2-3506-AB9D-0CD3545003FA}.Release|x64.ActiveCfg = Release|x64 + {751A15C0-76C2-3506-AB9D-0CD3545003FA}.Release|x64.Build.0 = Release|x64 + {6E933546-0B62-311B-8D7E-6CE2ECD4CAD0}.Debug|x64.ActiveCfg = Debug|x64 + {6E933546-0B62-311B-8D7E-6CE2ECD4CAD0}.Debug|x64.Build.0 = Debug|x64 + {6E933546-0B62-311B-8D7E-6CE2ECD4CAD0}.Release|x64.ActiveCfg = Release|x64 + {6E933546-0B62-311B-8D7E-6CE2ECD4CAD0}.Release|x64.Build.0 = Release|x64 + {4877C470-9466-37C0-A451-03973F6EDABD}.Debug|x64.ActiveCfg = Debug|x64 + {4877C470-9466-37C0-A451-03973F6EDABD}.Debug|x64.Build.0 = Debug|x64 + {4877C470-9466-37C0-A451-03973F6EDABD}.Release|x64.ActiveCfg = Release|x64 + {4877C470-9466-37C0-A451-03973F6EDABD}.Release|x64.Build.0 = Release|x64 + {38ABD20B-B450-3DE7-A759-71587CAB9A2A}.Debug|x64.ActiveCfg = Debug|x64 + {38ABD20B-B450-3DE7-A759-71587CAB9A2A}.Debug|x64.Build.0 = Debug|x64 + {38ABD20B-B450-3DE7-A759-71587CAB9A2A}.Release|x64.ActiveCfg = Release|x64 + {38ABD20B-B450-3DE7-A759-71587CAB9A2A}.Release|x64.Build.0 = Release|x64 + {1F4B7EAD-4694-3453-AD34-1757E387661E}.Debug|x64.ActiveCfg = Debug|x64 + {1F4B7EAD-4694-3453-AD34-1757E387661E}.Debug|x64.Build.0 = Debug|x64 + {1F4B7EAD-4694-3453-AD34-1757E387661E}.Release|x64.ActiveCfg = Release|x64 + {1F4B7EAD-4694-3453-AD34-1757E387661E}.Release|x64.Build.0 = Release|x64 + {1903244B-9312-3A09-8AAD-8D78C1A4F977}.Debug|x64.ActiveCfg = Debug|x64 + {1903244B-9312-3A09-8AAD-8D78C1A4F977}.Debug|x64.Build.0 = Debug|x64 + {1903244B-9312-3A09-8AAD-8D78C1A4F977}.Release|x64.ActiveCfg = Release|x64 + {1903244B-9312-3A09-8AAD-8D78C1A4F977}.Release|x64.Build.0 = Release|x64 + {14D82890-BB7F-3748-8713-43304E91CFA1}.Debug|x64.ActiveCfg = Debug|x64 + {14D82890-BB7F-3748-8713-43304E91CFA1}.Debug|x64.Build.0 = Debug|x64 + {14D82890-BB7F-3748-8713-43304E91CFA1}.Release|x64.ActiveCfg = Release|x64 + {14D82890-BB7F-3748-8713-43304E91CFA1}.Release|x64.Build.0 = Release|x64 + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5}.Debug|x64.ActiveCfg = Debug|x64 + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5}.Debug|x64.Build.0 = Debug|x64 + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5}.Release|x64.ActiveCfg = Release|x64 + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5}.Release|x64.Build.0 = Release|x64 + {23CF91DE-A1B5-3EE0-827D-ACAFD80C7CB2}.Debug|x64.ActiveCfg = Debug|x64 + {23CF91DE-A1B5-3EE0-827D-ACAFD80C7CB2}.Debug|x64.Build.0 = Debug|x64 + {23CF91DE-A1B5-3EE0-827D-ACAFD80C7CB2}.Release|x64.ActiveCfg = Release|x64 + {23CF91DE-A1B5-3EE0-827D-ACAFD80C7CB2}.Release|x64.Build.0 = Release|x64 + {007E33A1-3B69-3DBB-8C44-8A54188A3A21}.Debug|x64.ActiveCfg = Debug|x64 + {007E33A1-3B69-3DBB-8C44-8A54188A3A21}.Debug|x64.Build.0 = Debug|x64 + {007E33A1-3B69-3DBB-8C44-8A54188A3A21}.Release|x64.ActiveCfg = Release|x64 + {007E33A1-3B69-3DBB-8C44-8A54188A3A21}.Release|x64.Build.0 = Release|x64 + {016D40A8-D2BA-3C2B-8741-718BD5CE7B51}.Debug|x64.ActiveCfg = Debug|x64 + {016D40A8-D2BA-3C2B-8741-718BD5CE7B51}.Debug|x64.Build.0 = Debug|x64 + {016D40A8-D2BA-3C2B-8741-718BD5CE7B51}.Release|x64.ActiveCfg = Release|x64 + {016D40A8-D2BA-3C2B-8741-718BD5CE7B51}.Release|x64.Build.0 = Release|x64 + {7887B55C-77B9-3262-AFAD-ABA738C61029}.Debug|x64.ActiveCfg = Debug|x64 + {7887B55C-77B9-3262-AFAD-ABA738C61029}.Debug|x64.Build.0 = Debug|x64 + {7887B55C-77B9-3262-AFAD-ABA738C61029}.Release|x64.ActiveCfg = Release|x64 + {7887B55C-77B9-3262-AFAD-ABA738C61029}.Release|x64.Build.0 = Release|x64 + {78CFCEBE-5466-3128-9717-547416DBFFE5}.Debug|x64.ActiveCfg = Debug|x64 + {78CFCEBE-5466-3128-9717-547416DBFFE5}.Debug|x64.Build.0 = Debug|x64 + {78CFCEBE-5466-3128-9717-547416DBFFE5}.Release|x64.ActiveCfg = Release|x64 + {78CFCEBE-5466-3128-9717-547416DBFFE5}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3652083C-5B60-3F2D-A8B0-DB7D6E247A14} + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/MotionDetectorMultiCam/Win/MotionDetectorMultiCam.vcxproj b/MotionDetectorMultiCam/Win/MotionDetectorMultiCam.vcxproj new file mode 100644 index 0000000..4830c46 --- /dev/null +++ b/MotionDetectorMultiCam/Win/MotionDetectorMultiCam.vcxproj @@ -0,0 +1,325 @@ + + + + x64 + + + + Debug + x64 + + + Release + x64 + + + + {4877C470-9466-37C0-A451-03973F6EDABD} + Win32Proj + 10.0.26100.0 + x64 + MotionDetectorMultiCam + NoUpgrade + + + + DynamicLibrary + Unicode + v143 + + + DynamicLibrary + Unicode + v143 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + MotionDetectorMultiCam.dir\Debug\ + MotionDetectorMultiCam + .dll + true + true + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + MotionDetectorMultiCam.dir\Release\ + MotionDetectorMultiCam + .dll + false + true + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput\..\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /external:I "C:/Users/Admin/IFloor/libs/opencv/build/include" + $(IntDir) + EnableFastChecks + + + ProgramDatabase + 4996 + Sync + TurnOffAllWarnings + + + Disabled + stdcpp17 + + true + Disabled + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/MotionDetectorMultiCam.dir/Debug//cmake_pch.pch + + MultiThreadedDebugDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;__WXDEBUG__=1;MOTIONDETECTOR_MULTICAM_EXPORTS;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;_WIN32_WINNT=0x0501;CMAKE_INTDIR="Debug";MotionDetectorMultiCam_EXPORTS + $(IntDir) + false + + + %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;MOTIONDETECTOR_MULTICAM_EXPORTS;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;_WIN32_WINNT=0x0501;CMAKE_INTDIR=\"Debug\";MotionDetectorMultiCam_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput\..\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput\..\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -E make_directory C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin +if %errorlevel% neq 0 goto :cmEnd +"C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/MotionDetectorMultiCam.dll C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin/MotionDetectorMultiCam.dll +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\MotionDetectorCore.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\MotionPrimitives.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\videoInput.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\MotionDetectorPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\CommonPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxXS.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxJSON.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\strmbas.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + true + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Debug/MotionDetectorMultiCam.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/MotionDetectorMultiCam.pdb + + Console + + + false + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput\..\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /external:I "C:/Users/Admin/IFloor/libs/opencv/build/include" + $(IntDir) + Default + + + 4996 + Sync + TurnOffAllWarnings + + + AnySuitable + stdcpp17 + + true + MaxSpeed + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/MotionDetectorMultiCam.dir/Release//cmake_pch.pch + + MultiThreadedDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;MOTIONDETECTOR_MULTICAM_EXPORTS;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;_WIN32_WINNT=0x0501;CMAKE_INTDIR="Release";MotionDetectorMultiCam_EXPORTS + $(IntDir) + + + false + + + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;MOTIONDETECTOR_MULTICAM_EXPORTS;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;_WIN32_WINNT=0x0501;CMAKE_INTDIR=\"Release\";MotionDetectorMultiCam_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput\..\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput\..\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -E make_directory C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin +if %errorlevel% neq 0 goto :cmEnd +"C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/MotionDetectorMultiCam.dll C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin/MotionDetectorMultiCam.dll +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\MotionDetectorCore.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\MotionPrimitives.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\videoInput.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\MotionDetectorPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\CommonPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxXS.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxJSON.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\strmbas.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + false + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Release/MotionDetectorMultiCam.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/MotionDetectorMultiCam.pdb + + Console + + + false + + + + + Always + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam\Win\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam\Win\CMakeFiles\generate.stamp + false + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/MotionDetectorMultiCam.dir/Debug//cmake_pch.pch + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/MotionDetectorMultiCam.dir/Release//cmake_pch.pch + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCam.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + ZERO_CHECK + false + Never + + + {751A15C0-76C2-3506-AB9D-0CD3545003FA} + CommonPluginBase + + + {6E933546-0B62-311B-8D7E-6CE2ECD4CAD0} + MotionDetectorCore + + + {1F4B7EAD-4694-3453-AD34-1757E387661E} + MotionDetectorPluginBase + + + {1903244B-9312-3A09-8AAD-8D78C1A4F977} + MotionPrimitives + + + {14D82890-BB7F-3748-8713-43304E91CFA1} + Utils + + + {23CF91DE-A1B5-3EE0-827D-ACAFD80C7CB2} + strmbas + + + {007E33A1-3B69-3DBB-8C44-8A54188A3A21} + videoInput + + + {7887B55C-77B9-3262-AFAD-ABA738C61029} + wxJSON + + + {78CFCEBE-5466-3128-9717-547416DBFFE5} + wxXS + + + + + + \ No newline at end of file diff --git a/MotionDetectorMultiCam/Win/MotionDetectorMultiCam.vcxproj.filters b/MotionDetectorMultiCam/Win/MotionDetectorMultiCam.vcxproj.filters new file mode 100644 index 0000000..9b250a5 --- /dev/null +++ b/MotionDetectorMultiCam/Win/MotionDetectorMultiCam.vcxproj.filters @@ -0,0 +1,48 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Precompile Header File + + + Precompile Header File + + + + + + + + {4951AEE1-75F2-3C38-B593-C6BC8C809FB0} + + + {112D4227-BB51-3360-BB5B-5EA5DBA5A65F} + + + {05450AB2-CB7B-34EA-83DF-1EE86424EDF0} + + + diff --git a/MotionDetectorMultiCam/Win/MotionDetectorMultiCamGui.vcxproj b/MotionDetectorMultiCam/Win/MotionDetectorMultiCamGui.vcxproj new file mode 100644 index 0000000..8196d36 --- /dev/null +++ b/MotionDetectorMultiCam/Win/MotionDetectorMultiCamGui.vcxproj @@ -0,0 +1,325 @@ + + + + x64 + + + + Debug + x64 + + + Release + x64 + + + + {38ABD20B-B450-3DE7-A759-71587CAB9A2A} + Win32Proj + 10.0.26100.0 + x64 + MotionDetectorMultiCamGui + NoUpgrade + + + + DynamicLibrary + Unicode + v143 + + + DynamicLibrary + Unicode + v143 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + MotionDetectorMultiCamGui.dir\Debug\ + MotionDetectorMultiCamGui + .dll + true + true + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + MotionDetectorMultiCamGui.dir\Release\ + MotionDetectorMultiCamGui + .dll + false + true + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput\..\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /external:I "C:/Users/Admin/IFloor/libs/opencv/build/include" + $(IntDir) + EnableFastChecks + + + ProgramDatabase + 4996 + Sync + TurnOffAllWarnings + + + Disabled + stdcpp17 + + true + Disabled + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCamGui.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/MotionDetectorMultiCamGui.dir/Debug//cmake_pch.pch + + MultiThreadedDebugDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;_WIN32_WINNT=0x0501;CMAKE_INTDIR="Debug";MotionDetectorMultiCamGui_EXPORTS + $(IntDir) + false + + + %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;_WIN32_WINNT=0x0501;CMAKE_INTDIR=\"Debug\";MotionDetectorMultiCamGui_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput\..\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput\..\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -E make_directory C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin/plugins/gui +if %errorlevel% neq 0 goto :cmEnd +"C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/MotionDetectorMultiCamGui.dll C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin/plugins/gui/MotionDetectorMultiCamGui.dll +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\MotionDetectorMultiCam.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxGuiPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\MotionDetectorCore.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\MotionDetectorPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\CommonPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxXS.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxJSON.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\MotionPrimitives.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\videoInput.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\strmbas.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + true + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Debug/MotionDetectorMultiCamGui.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/MotionDetectorMultiCamGui.pdb + + Console + + + false + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput\..\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /external:I "C:/Users/Admin/IFloor/libs/opencv/build/include" + $(IntDir) + Default + + + 4996 + Sync + TurnOffAllWarnings + + + AnySuitable + stdcpp17 + + true + MaxSpeed + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCamGui.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/MotionDetectorMultiCamGui.dir/Release//cmake_pch.pch + + MultiThreadedDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;_WIN32_WINNT=0x0501;CMAKE_INTDIR="Release";MotionDetectorMultiCamGui_EXPORTS + $(IntDir) + + + false + + + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;_WIN32_WINNT=0x0501;CMAKE_INTDIR=\"Release\";MotionDetectorMultiCamGui_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput\..\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\videoInput\..\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -E make_directory C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin/plugins/gui +if %errorlevel% neq 0 goto :cmEnd +"C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/MotionDetectorMultiCamGui.dll C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin/plugins/gui/MotionDetectorMultiCamGui.dll +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\MotionDetectorMultiCam.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxGuiPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\MotionDetectorCore.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\MotionDetectorPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\CommonPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxXS.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxJSON.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\MotionPrimitives.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\videoInput.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\strmbas.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + false + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Release/MotionDetectorMultiCamGui.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/MotionDetectorMultiCamGui.pdb + + Console + + + false + + + + + Always + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam\Win\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorMultiCam\Win\CMakeFiles\generate.stamp + false + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCamGui.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCamGui.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/MotionDetectorMultiCamGui.dir/Debug//cmake_pch.pch + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCamGui.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCamGui.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/MotionDetectorMultiCamGui.dir/Release//cmake_pch.pch + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCamGui.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCamGui.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCamGui.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCamGui.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCamGui.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorMultiCam/Win/CMakeFiles/MotionDetectorMultiCamGui.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + ZERO_CHECK + false + Never + + + {751A15C0-76C2-3506-AB9D-0CD3545003FA} + CommonPluginBase + + + {6E933546-0B62-311B-8D7E-6CE2ECD4CAD0} + MotionDetectorCore + + + {4877C470-9466-37C0-A451-03973F6EDABD} + MotionDetectorMultiCam + + + {1F4B7EAD-4694-3453-AD34-1757E387661E} + MotionDetectorPluginBase + + + {1903244B-9312-3A09-8AAD-8D78C1A4F977} + MotionPrimitives + + + {14D82890-BB7F-3748-8713-43304E91CFA1} + Utils + + + {23CF91DE-A1B5-3EE0-827D-ACAFD80C7CB2} + strmbas + + + {007E33A1-3B69-3DBB-8C44-8A54188A3A21} + videoInput + + + {016D40A8-D2BA-3C2B-8741-718BD5CE7B51} + wxGuiPluginBase + + + {7887B55C-77B9-3262-AFAD-ABA738C61029} + wxJSON + + + {78CFCEBE-5466-3128-9717-547416DBFFE5} + wxXS + + + + + + \ No newline at end of file diff --git a/MotionDetectorMultiCam/Win/MotionDetectorMultiCamGui.vcxproj.filters b/MotionDetectorMultiCam/Win/MotionDetectorMultiCamGui.vcxproj.filters new file mode 100644 index 0000000..ba68f63 --- /dev/null +++ b/MotionDetectorMultiCam/Win/MotionDetectorMultiCamGui.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Precompile Header File + + + Precompile Header File + + + + + + + + {4951AEE1-75F2-3C38-B593-C6BC8C809FB0} + + + {112D4227-BB51-3360-BB5B-5EA5DBA5A65F} + + + {05450AB2-CB7B-34EA-83DF-1EE86424EDF0} + + + diff --git a/MotionDetectorPluginBase/CMakeLists.txt b/MotionDetectorPluginBase/CMakeLists.txt new file mode 100644 index 0000000..fc44787 --- /dev/null +++ b/MotionDetectorPluginBase/CMakeLists.txt @@ -0,0 +1,86 @@ +# +# Stuff the average programmer needs to change +# +set(SRCS + GeometryProvider.cpp + MotionDetectorPluginBase.cpp + MotionDetectorBase.cpp + MotionDetectorConfigWindowBase.cpp + IFloorCameraSettings.cpp +) +set(HFILES + GeometryProvider.h + MotionDetectorPluginBase.h + MotionDetectorBase.h + MotionDetectorConfigWindowBase.h + MotionDetectorPlugin.h + IFloorCameraSettings.h +) +set(INCLUDE_DIRECTORIES ${BASE_INCLUDE_DIRECTORIES} + ${THIRD_PARTY_DIR}/wxXS/include + ${THIRD_PARTY_DIR}/wxJSON/include + ${THIRD_PARTY_DIR}/MotionPrimitives + ${PROJECT_ROOT_DIR}/CommonPluginBase + ${PROJECT_ROOT_DIR}/Utils +) +set(LIBRARY_NAME MotionDetectorPluginBase) +if(WIN32) + set(LINK_DIRECTORIES + ${PROJECT_ROOT_DIR}/CommonPluginBase/${OS_BASE_NAME}${LIB_SUFFIX}/$(ConfigurationName) + ${PROJECT_ROOT_DIR}/Utils/${OS_BASE_NAME}${LIB_SUFFIX}/$(ConfigurationName) + ${THIRD_PARTY_DIR}/wxXS/build/${OS_BASE_NAME}${LIB_SUFFIX}/$(ConfigurationName) + ${THIRD_PARTY_DIR}/wxJSON/build/${OS_BASE_NAME}${LIB_SUFFIX}/$(ConfigurationName) + ) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D_USRDLL;/DIFLOOR_EXPORTS) + set(IFLOOR_LIBS CommonPluginBase.lib Utils.lib) + set(THIRDPARTY_LIBS wxXS.lib wxJSON.lib) +endif(WIN32) +if(LINUX) + set(LINK_DIRECTORIES + ${PROJECT_ROOT_DIR}/CommonPluginBase/${OS_BASE_NAME}${LIB_SUFFIX} + ${PROJECT_ROOT_DIR}/Utils/${OS_BASE_NAME}${LIB_SUFFIX} + ${THIRD_PARTY_DIR}/wxXS/build/${OS_BASE_NAME}${LIB_SUFFIX} + ${THIRD_PARTY_DIR}/wxJSON/build/${OS_BASE_NAME}${LIB_SUFFIX} + ) + #set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D_USRDLL;/DIFLOOR_EXPORTS) + set(IFLOOR_LIBS CommonPluginBase Utils) + set(THIRDPARTY_LIBS wxXS wxJSON) +endif(LINUX) +set(SRCS ${SRCS} ${HFILES} ${PROJECT_ROOT_DIR}/include/stdwx.h ${PROJECT_ROOT_DIR}/include/stdwx.cpp) + +add_definitions(${PREPROCESSOR_DEFINITIONS}) +include_directories(${INCLUDE_DIRECTORIES}) +link_directories(${LINK_DIRECTORIES}) +add_library(${LIBRARY_NAME} SHARED ${SRCS}) + +set(DLL_DIR bin) +set(TARGET_LOCATION ${PROJECT_SOURCE_DIR}/${DLL_DIR}${LIB_SUFFIX}) +set_target_properties(${LIBRARY_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TARGET_LOCATION}) + +target_link_libraries(${LIBRARY_NAME} + CommonPluginBase + Utils + wxXS + wxJSON + ${wxWidgets_LIBRARIES} +) +add_dependencies(${LIBRARY_NAME} + wxXS + CommonPluginBase +) + +# Precompiled header stuff must be after the target is added +#set_precompiled_header(${LIBRARY_NAME} ${PROJECT_ROOT_DIR}/include/stdwx.h ${PROJECT_ROOT_DIR}/include/stdwx.cpp) +target_precompile_headers(${LIBRARY_NAME} + PRIVATE + "${PROJECT_ROOT_DIR}/include/stdwx.h" +) + + +if(LINUX) + add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/${OS_BASE_NAME}${LIB_SUFFIX}/lib${LIBRARY_NAME}.so" "${PROJECT_SOURCE_DIR}/${DLL_DIR}${LIB_SUFFIX}/lib${LIBRARY_NAME}.so" + ) +endif(LINUX) + +add_dependencies(MotionDetectorPluginBase wxXS) diff --git a/MotionDetectorPluginBase/GeometryProvider.cpp b/MotionDetectorPluginBase/GeometryProvider.cpp new file mode 100644 index 0000000..47de8db --- /dev/null +++ b/MotionDetectorPluginBase/GeometryProvider.cpp @@ -0,0 +1,28 @@ +#include "stdwx.h" +#include "GeometryProvider.h" + +GeometryProvider::GeometryProvider( + GeometryProvider::GetSupportedCameraCountCallback getSupportedCameraCountCallback + , GeometryProvider::GetGeometryCallback getGeometryCallback + , GetDisplaySizeCallback getDisplaySizeCallback) + : m_GetSupportedCameraCountCallback(getSupportedCameraCountCallback) + , m_GetGeometryCallback(getGeometryCallback) + , m_GetDisplaySizeCallback(getDisplaySizeCallback) +{ + +} + +size_t GeometryProvider::GetSupportedCameraCount() const +{ + return m_GetSupportedCameraCountCallback(); +} + +void GeometryProvider::GetGeometry(wxRectVector & result) const +{ + m_GetGeometryCallback(result); +} + +wxRect GeometryProvider::GetDisplaySize() const +{ + return m_GetDisplaySizeCallback(); +} \ No newline at end of file diff --git a/MotionDetectorPluginBase/GeometryProvider.h b/MotionDetectorPluginBase/GeometryProvider.h new file mode 100644 index 0000000..7477121 --- /dev/null +++ b/MotionDetectorPluginBase/GeometryProvider.h @@ -0,0 +1,26 @@ +#pragma once + +#include "MotionDetectorPlugin.h" + +typedef std::vector wxRectVector; + +class IFLOOR_API GeometryProvider +{ + + typedef std::function GetSupportedCameraCountCallback; + typedef std::function GetGeometryCallback; + typedef std::function GetDisplaySizeCallback; +public: + GeometryProvider(GetSupportedCameraCountCallback getSupportedCameraCountCallback, + GetGeometryCallback getGeometryCallback, + GetDisplaySizeCallback getDisplaySizeCallback); + + size_t GetSupportedCameraCount() const; + void GetGeometry(wxRectVector & result) const; + wxRect GetDisplaySize() const; + +private: + GetSupportedCameraCountCallback m_GetSupportedCameraCountCallback; + GetGeometryCallback m_GetGeometryCallback; + GetDisplaySizeCallback m_GetDisplaySizeCallback; +}; \ No newline at end of file diff --git a/MotionDetectorPluginBase/IFloorCameraSettings.cpp b/MotionDetectorPluginBase/IFloorCameraSettings.cpp new file mode 100644 index 0000000..78b41da --- /dev/null +++ b/MotionDetectorPluginBase/IFloorCameraSettings.cpp @@ -0,0 +1,91 @@ +#include "stdwx.h" +#include "IFloorCameraSettings.h" + +IMPLEMENT_DYNAMIC_CLASS(IFloorCameraSettings, xsSerializable) + +#include +WX_DEFINE_LIST(IFloorCameraSettingsList); + +IFloorCameraSettings::IFloorCameraSettings(void) +: bEnabled(false) +, TopLeftX(0), TopLeftY(0), TopRightX(639), TopRightY(0) +, BottomLeftX(0), BottomLeftY(479), BottomRightX(639), BottomRightY(479) +, WinWidth(640), WinHeight(480) +, CamWidth(640), CamHeight(480) +, bVerticalMirror(false) +, bHorizontalMirror(false) +{ + InitSerialization(); +} + +IFloorCameraSettings::IFloorCameraSettings(const IFloorCameraSettings & settings) +{ + InitSerialization(); + CopyFrom(settings); +} + +void IFloorCameraSettings::InitSerialization() +{ + XS_SERIALIZE(bEnabled, wxT("bEnabled")); + + XS_SERIALIZE(TopLeftX, wxT("TopLeftX")); + XS_SERIALIZE(TopLeftY, wxT("TopLeftY")); + XS_SERIALIZE(TopRightX, wxT("TopRightX")); + XS_SERIALIZE(TopRightY, wxT("TopRightY")); + XS_SERIALIZE(BottomLeftX, wxT("BottomLeftX")); + XS_SERIALIZE(BottomLeftY, wxT("BottomLeftY")); + XS_SERIALIZE(BottomRightX, wxT("BottomRightX")); + XS_SERIALIZE(BottomRightY, wxT("BottomRightY")); + XS_SERIALIZE(WinWidth, wxT("WinWidth")); + XS_SERIALIZE(WinHeight, wxT("WinHeight")); + XS_SERIALIZE(CamWidth, wxT("CamWidth")); + XS_SERIALIZE(CamHeight, wxT("CamHeight")); + + XS_SERIALIZE(bVerticalMirror, wxT("bVerticalMirror")); + XS_SERIALIZE(bHorizontalMirror, wxT("bHorizontalMirror")); + + XS_SERIALIZE(DeviceID, wxT("DeviceID")); + XS_SERIALIZE(VideoSourceID, wxT("VideoSourceID")); +} + +IFloorCameraSettings& IFloorCameraSettings::operator=(const IFloorCameraSettings & settings) +{ + if (&settings != this) + CopyFrom(settings); + return *this; +} + +IFloorCameraSettings::~IFloorCameraSettings(void) +{ +} + +bool IFloorCameraSettings::Deserialize(wxInputStream & instream) +{ + return SerializableBase::Deserialize(instream, *this); +} + +bool IFloorCameraSettings::Serialize(wxOutputStream & outstream) +{ + return SerializableBase::Serialize(outstream, *this); +} + +void IFloorCameraSettings::CopyFrom(const IFloorCameraSettings& settings) +{ + bEnabled = settings.bEnabled; + TopLeftX = settings.TopLeftX; + TopLeftY = settings.TopLeftY; + TopRightX = settings.TopRightX; + TopRightY = settings.TopRightY; + BottomLeftX = settings.BottomLeftX; + BottomLeftY = settings.BottomLeftY; + BottomRightX = settings.BottomRightX; + BottomRightY = settings.BottomRightY; + WinWidth = settings.WinWidth; + WinHeight = settings.WinHeight; + CamWidth = settings.CamWidth; + CamHeight = settings.CamHeight; + bVerticalMirror = settings.bVerticalMirror; + bHorizontalMirror = settings.bHorizontalMirror; + VideoSourceID = settings.VideoSourceID; + DeviceID = settings.DeviceID; +} \ No newline at end of file diff --git a/MotionDetectorPluginBase/IFloorCameraSettings.h b/MotionDetectorPluginBase/IFloorCameraSettings.h new file mode 100644 index 0000000..286e622 --- /dev/null +++ b/MotionDetectorPluginBase/IFloorCameraSettings.h @@ -0,0 +1,51 @@ +#ifndef _IFLOORCAMERASETTINGS_H +#define _IFLOORCAMERASETTINGS_H + +#include "MotionDetectorPlugin.h" +#include + +class IFLOOR_API IFloorCameraSettings : public xsSerializable +{ + DECLARE_DYNAMIC_CLASS(IFloorCameraSettings) +public: + IFloorCameraSettings(void); + IFloorCameraSettings(const IFloorCameraSettings & settings); + IFloorCameraSettings& operator=(const IFloorCameraSettings & settings); + + ~IFloorCameraSettings(void); + + bool Deserialize(wxInputStream & instream); + bool Serialize(wxOutputStream & outstream); + +private: + void InitSerialization(); + void CopyFrom(const IFloorCameraSettings & settings); + +public: + bool bEnabled; // Are these settings enabled + + int + TopLeftX, + TopLeftY, + TopRightX, + TopRightY, + BottomLeftX, + BottomLeftY, + BottomRightX, + BottomRightY, + WinWidth, + WinHeight, + CamWidth, + CamHeight; + bool + bVerticalMirror, + bHorizontalMirror; + + wxString + VideoSourceID, + DeviceID; +}; + +WX_DECLARE_USER_EXPORTED_LIST(IFloorCameraSettings, IFloorCameraSettingsList, IFLOOR_API); + +#endif // _IFLOORCAMERASETTINGS_H diff --git a/MotionDetectorPluginBase/MotionDetectorBase.cpp b/MotionDetectorPluginBase/MotionDetectorBase.cpp new file mode 100644 index 0000000..ad37d52 --- /dev/null +++ b/MotionDetectorPluginBase/MotionDetectorBase.cpp @@ -0,0 +1,109 @@ +#include "stdwx.h" +#include "MotionDetectorBase.h" +#include "MotionDetectorPluginBase.h" +#include "GeometryProvider.h" +#include +#include +#include + +#include + +#if defined(USE_VLD) +#include +#endif + +IMPLEMENT_ABSTRACT_CLASS(MotionDetectorBase, SerializableBase); + +WX_DEFINE_USER_EXPORTED_LIST(MotionDetectorBaseList); + +MotionDetectorBase::MotionDetectorBase() +: m_MotionDetector(nullptr) +, m_CalibrationStep(0) +, m_CalibrationCameraID(0) +, m_bShowCalibrationBlobs(false) +, m_bServiceMode(false) +, m_GeometryProvider(std::move(GeometryProvider(nullptr, nullptr, nullptr))) +{ +} + +MotionDetectorBase::MotionDetectorBase(MotionDetectorPluginBase * owner, GeometryProvider && geometryProvider) +: m_MotionDetector(owner) +, m_GeometryProvider(std::move(geometryProvider)) +, m_CalibrationCameraID(0) +, m_bServiceMode(false) +{ +} + +MotionDetectorBase::~MotionDetectorBase() +{ +} + +void MotionDetectorBase::SetServiceMode(bool mode) +{ + m_bServiceMode = mode; +} + +MotionDetectorPluginBase * MotionDetectorBase::GetMotionDetector() +{ + return m_MotionDetector; +} + +bool MotionDetectorBase::StartCalibration() +{ + return true; +} + +bool MotionDetectorBase::StopCalibration() +{ + return true; +} + +void MotionDetectorBase::ConfimCalibrationStep(int code) +{ + +} + +bool MotionDetectorBase::IsNextStepCalibrationEnabled() +{ + return true; +} + +void MotionDetectorBase::SetCalibrationCameraID(const int index) +{ + m_CalibrationCameraID = index; +} + +void MotionDetectorBase::StartDetection() +{ + +} + +void MotionDetectorBase::StopDetection() +{ + +} + +int MotionDetectorBase::GetBlobs(iFloorBlobVector * blobs) +{ + return 0; +} + +void MotionDetectorBase::SetCameraSettings(const IFloorCameraSettings & settings, const int index) +{ + +} + +bool MotionDetectorBase::IsServiceMode() +{ + return m_bServiceMode; +} + +size_t MotionDetectorBase::GetSupportedCamerasCount() +{ + return m_GeometryProvider.GetSupportedCameraCount(); +} + +const GeometryProvider & MotionDetectorBase::GetGeometryProvider() const +{ + return m_GeometryProvider; +} diff --git a/MotionDetectorPluginBase/MotionDetectorBase.h b/MotionDetectorPluginBase/MotionDetectorBase.h new file mode 100644 index 0000000..9367bb3 --- /dev/null +++ b/MotionDetectorPluginBase/MotionDetectorBase.h @@ -0,0 +1,68 @@ +#ifndef _MOTIONDETECTORBASE_H +#define _MOTIONDETECTORBASE_H + +#include "MotionDetectorPlugin.h" +#include +#include +#include + +typedef std::map MotionDetectorParametersMap; + +class MotionDetectorPluginBase; +class IFloorCameraSettings; +class MotionDetectorBase; +class GeometryProvider; + +class IFLOOR_API MotionDetectorBase : public SerializableBase +{ + + DECLARE_ABSTRACT_CLASS(MotionDetectorBase); +public: + MotionDetectorBase(); + MotionDetectorBase(MotionDetectorPluginBase * owner, GeometryProvider && geometryProvider); + virtual ~MotionDetectorBase(); + virtual void SetServiceMode(bool mode = true); +//Calibration API + virtual bool Calibrate() = 0; + virtual void SetCalibrationCameraID(const int index); + + virtual bool StartCalibration(); + virtual bool StopCalibration(); + unsigned int GetCalibrationStep() {return m_CalibrationStep;} + virtual void ConfimCalibrationStep(int code); + virtual bool IsNextStepCalibrationEnabled(); + bool IsCalibrationBlobsShowed(){return m_bShowCalibrationBlobs;} +//Common detection API + virtual void StartDetection(); + virtual void StopDetection(); + virtual void SetDataBuffer(unsigned char * buffer, const size_t length, const int index) = 0; + virtual void ProcessData() = 0; + // Returns how many cameras supports this detector + virtual size_t GetSupportedCamerasCount(); + virtual int GetBlobs(iFloorBlobVector * blobs); + virtual void SetCameraSettings(const IFloorCameraSettings & settings, const int index); + const GeometryProvider & GetGeometryProvider() const; + + //Service mode control + bool IsServiceMode(); + bool IsJSONmsgsMode(); + bool IsSendBlobsJmsgMode(); + MotionDetectorPluginBase * GetMotionDetector(); + +protected: + MotionDetectorPluginBase * m_MotionDetector; + GeometryProvider && m_GeometryProvider; + unsigned int m_CalibrationStep; + int m_CalibrationCameraID; + bool m_bShowCalibrationBlobs; + bool m_bServiceMode; +}; + + + +WX_DECLARE_USER_EXPORTED_LIST(MotionDetectorBase, MotionDetectorBaseList, IFLOOR_API); + +typedef MotionDetectorPluginBase * (*CreateMotionDetectorPlugin_function)(); +typedef void (*DeleteMotionDetectorPlugin_function)(MotionDetectorPluginBase * plugin); + +#endif // _MOTIONDETECTORBASE_H \ No newline at end of file diff --git a/MotionDetectorPluginBase/MotionDetectorConfigWindowBase.cpp b/MotionDetectorPluginBase/MotionDetectorConfigWindowBase.cpp new file mode 100644 index 0000000..3575f3e --- /dev/null +++ b/MotionDetectorPluginBase/MotionDetectorConfigWindowBase.cpp @@ -0,0 +1,50 @@ +#include "stdwx.h" +#include "MotionDetectorConfigWindowBase.h" + +IMPLEMENT_DYNAMIC_CLASS(MotionDetectorConfigWindowBase, CommonConfigWindowBase) + + +MotionDetectorConfigWindowBase::MotionDetectorConfigWindowBase() +: m_Detector(NULL), m_Started(false) +{ +} + +MotionDetectorConfigWindowBase::MotionDetectorConfigWindowBase(MotionDetectorBase * detector, wxWindow * parent) +{ + Create(detector, parent); +} + +bool MotionDetectorConfigWindowBase::Create(MotionDetectorBase * detector, wxWindow * parent) +{ + m_Detector = detector; + m_Started = false; + return CommonConfigWindowBase::Create(parent); +} + +MotionDetectorConfigWindowBase::~MotionDetectorConfigWindowBase(void) +{ +} + +bool MotionDetectorConfigWindowBase::ReadConfig() +{ + return false; +} + +bool MotionDetectorConfigWindowBase::SaveConfig() +{ + return false; +} + +void MotionDetectorConfigWindowBase::StartDetection() +{ + m_Started = true; +} +void MotionDetectorConfigWindowBase::StopDetection() +{ + m_Started = false; +} + +MotionDetectorBase * MotionDetectorConfigWindowBase::GetDetector() +{ + return m_Detector; +} \ No newline at end of file diff --git a/MotionDetectorPluginBase/MotionDetectorConfigWindowBase.h b/MotionDetectorPluginBase/MotionDetectorConfigWindowBase.h new file mode 100644 index 0000000..6bd3793 --- /dev/null +++ b/MotionDetectorPluginBase/MotionDetectorConfigWindowBase.h @@ -0,0 +1,32 @@ +#ifndef _MOTIONDETECTORCONFIGWINDOWBASE_H +#define _MOTIONDETECTORCONFIGWINDOWBASE_H +#include "MotionDetectorPlugin.h" +#include + +class MotionDetectorBase; + +class IFLOOR_API MotionDetectorConfigWindowBase : public CommonConfigWindowBase +{ + DECLARE_DYNAMIC_CLASS(MotionDetectorConfigWindowBase) +public: + MotionDetectorConfigWindowBase(); + MotionDetectorConfigWindowBase(MotionDetectorBase * detector, wxWindow * parent); + + bool Create(MotionDetectorBase * detector, wxWindow * parent); + virtual ~MotionDetectorConfigWindowBase(void); + + /// Reads config from the motion detector + virtual bool ReadConfig(); + + /// Saves config to the motion detector + virtual bool SaveConfig(); + + virtual MotionDetectorBase * GetDetector(); + virtual void StartDetection(); + virtual void StopDetection(); + +protected: + MotionDetectorBase * m_Detector; + bool m_Started; +}; +#endif // _MOTIONDETECTORCONFIGWINDOWBASE_H diff --git a/MotionDetectorPluginBase/MotionDetectorPlugin.h b/MotionDetectorPluginBase/MotionDetectorPlugin.h new file mode 100644 index 0000000..b9426cf --- /dev/null +++ b/MotionDetectorPluginBase/MotionDetectorPlugin.h @@ -0,0 +1,14 @@ +#ifndef _MOTIONDETECTORPLUGIN_H +#define _MOTIONDETECTORPLUGIN_H + +#if defined(__WXMSW__) +#ifdef IFLOOR_EXPORTS +#define IFLOOR_API __declspec(dllexport) +#else +#define IFLOOR_API __declspec(dllimport) +#endif +#else +#define IFLOOR_API +#endif + +#endif // _MOTIONDETECTORPLUGIN_H diff --git a/MotionDetectorPluginBase/MotionDetectorPluginBase.cpp b/MotionDetectorPluginBase/MotionDetectorPluginBase.cpp new file mode 100644 index 0000000..0d74c2c --- /dev/null +++ b/MotionDetectorPluginBase/MotionDetectorPluginBase.cpp @@ -0,0 +1,14 @@ +#include "stdwx.h" +#include "MotionDetectorPluginBase.h" +#include "MotionDetectorBase.h" + +IMPLEMENT_ABSTRACT_CLASS(MotionDetectorPluginBase, wxObject) + +MotionDetectorPluginBase::~MotionDetectorPluginBase() +{ +} + +void MotionDetectorPluginBase::DeleteDetector(MotionDetectorBase * detector) +{ + wxDELETE(detector); +} diff --git a/MotionDetectorPluginBase/MotionDetectorPluginBase.h b/MotionDetectorPluginBase/MotionDetectorPluginBase.h new file mode 100644 index 0000000..f32ee36 --- /dev/null +++ b/MotionDetectorPluginBase/MotionDetectorPluginBase.h @@ -0,0 +1,28 @@ +#ifndef _MOTIONDETECTORPLUGINBASE_H +#define _MOTIONDETECTORPLUGINBASE_H + +#include "MotionDetectorPlugin.h" + +class MotionDetectorBase; +class GeometryProvider; + +/// Base class for all iFloor effect plugins +class IFLOOR_API MotionDetectorPluginBase : public wxObject +{ + DECLARE_ABSTRACT_CLASS(MotionDetectorPluginBase) +public: + virtual ~MotionDetectorPluginBase(); + /// Returns GUID (unique identifier) of plugin + /// \return string which contains unique identifier of plugin + virtual wxString GetID() const = 0; + /// Returns name of plugin + /// \return string which contains human-readable name of plugin + virtual wxString GetName() const = 0; + virtual MotionDetectorBase * CreateDetector(GeometryProvider && geometryProvider) = 0; + virtual void DeleteDetector(MotionDetectorBase * detector); +}; + +typedef MotionDetectorPluginBase * (*CreateMotionDetectorPlugin_function)(); +typedef void (*DeleteMotionDetectorPlugin_function)(MotionDetectorPluginBase * plugin); + +#endif // _MOTIONDETECTORPLUGINBASE_H \ No newline at end of file diff --git a/MotionDetectorPluginBase/Win/MotionDetectorPluginBase.vcxproj b/MotionDetectorPluginBase/Win/MotionDetectorPluginBase.vcxproj new file mode 100644 index 0000000..8ba7969 --- /dev/null +++ b/MotionDetectorPluginBase/Win/MotionDetectorPluginBase.vcxproj @@ -0,0 +1,283 @@ + + + + x64 + + + + Debug + x64 + + + Release + x64 + + + + {1F4B7EAD-4694-3453-AD34-1757E387661E} + Win32Proj + 10.0.26100.0 + x64 + MotionDetectorPluginBase + NoUpgrade + + + + DynamicLibrary + Unicode + v143 + + + DynamicLibrary + Unicode + v143 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + MotionDetectorPluginBase.dir\Debug\ + MotionDetectorPluginBase + .dll + true + true + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + MotionDetectorPluginBase.dir\Release\ + MotionDetectorPluginBase + .dll + false + true + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + $(IntDir) + EnableFastChecks + + + ProgramDatabase + 4996 + Sync + + + Disabled + stdcpp17 + + true + Disabled + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/MotionDetectorPluginBase.dir/Debug//cmake_pch.pch + + MultiThreadedDebugDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;IFLOOR_EXPORTS;CMAKE_INTDIR="Debug";MotionDetectorPluginBase_EXPORTS + $(IntDir) + false + + + %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;IFLOOR_EXPORTS;CMAKE_INTDIR=\"Debug\";MotionDetectorPluginBase_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\CommonPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxXS.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxJSON.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../CommonPluginBase/Win/$(ConfigurationName);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../CommonPluginBase/Win/$(ConfigurationName)/$(Configuration);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../Utils/Win/$(ConfigurationName);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../Utils/Win/$(ConfigurationName)/$(Configuration);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../ThirdParty/wxXS/build/Win/$(ConfigurationName);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../ThirdParty/wxXS/build/Win/$(ConfigurationName)/$(Configuration);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../ThirdParty/wxJSON/build/Win/$(ConfigurationName);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../ThirdParty/wxJSON/build/Win/$(ConfigurationName)/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + true + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Debug/MotionDetectorPluginBase.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/MotionDetectorPluginBase.pdb + + Console + + + false + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + $(IntDir) + Default + + + 4996 + Sync + + + AnySuitable + stdcpp17 + + true + MaxSpeed + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/MotionDetectorPluginBase.dir/Release//cmake_pch.pch + + MultiThreadedDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;IFLOOR_EXPORTS;CMAKE_INTDIR="Release";MotionDetectorPluginBase_EXPORTS + $(IntDir) + + + false + + + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;IFLOOR_EXPORTS;CMAKE_INTDIR=\"Release\";MotionDetectorPluginBase_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\CommonPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxXS.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxJSON.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../CommonPluginBase/Win/$(ConfigurationName);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../CommonPluginBase/Win/$(ConfigurationName)/$(Configuration);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../Utils/Win/$(ConfigurationName);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../Utils/Win/$(ConfigurationName)/$(Configuration);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../ThirdParty/wxXS/build/Win/$(ConfigurationName);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../ThirdParty/wxXS/build/Win/$(ConfigurationName)/$(Configuration);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../ThirdParty/wxJSON/build/Win/$(ConfigurationName);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../ThirdParty/wxJSON/build/Win/$(ConfigurationName)/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + false + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Release/MotionDetectorPluginBase.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/MotionDetectorPluginBase.pdb + + Console + + + false + + + + + Always + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorPluginBase\Win\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\MotionDetectorPluginBase\Win\CMakeFiles\generate.stamp + false + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/MotionDetectorPluginBase.dir/Debug//cmake_pch.pch + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/MotionDetectorPluginBase.dir/Release//cmake_pch.pch + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/MotionDetectorPluginBase/Win/CMakeFiles/MotionDetectorPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + ZERO_CHECK + false + Never + + + {751A15C0-76C2-3506-AB9D-0CD3545003FA} + CommonPluginBase + + + {14D82890-BB7F-3748-8713-43304E91CFA1} + Utils + + + {7887B55C-77B9-3262-AFAD-ABA738C61029} + wxJSON + + + {78CFCEBE-5466-3128-9717-547416DBFFE5} + wxXS + + + + + + \ No newline at end of file diff --git a/MotionDetectorPluginBase/Win/MotionDetectorPluginBase.vcxproj.filters b/MotionDetectorPluginBase/Win/MotionDetectorPluginBase.vcxproj.filters new file mode 100644 index 0000000..2cab44e --- /dev/null +++ b/MotionDetectorPluginBase/Win/MotionDetectorPluginBase.vcxproj.filters @@ -0,0 +1,69 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Precompile Header File + + + Precompile Header File + + + + + + + + {4951AEE1-75F2-3C38-B593-C6BC8C809FB0} + + + {112D4227-BB51-3360-BB5B-5EA5DBA5A65F} + + + {05450AB2-CB7B-34EA-83DF-1EE86424EDF0} + + + diff --git a/SampleGuiPlugin1/CMakeLists.txt b/SampleGuiPlugin1/CMakeLists.txt deleted file mode 100644 index 700a0f8..0000000 --- a/SampleGuiPlugin1/CMakeLists.txt +++ /dev/null @@ -1,78 +0,0 @@ -set (SRCS - SampleGuiPlugin1.cpp - SampleGuiPlugin1Exports.cpp - SampleGuiPluginWindow1.cpp) -set (HEADERS - SampleGuiPlugin1.h - SampleGuiPluginWindow1.h) - -set(LIBRARY_NAME SampleGuiPlugin1) - -if(WIN32) - set(SRCS ${SRCS} ${LIBRARY_NAME}.rc ${LIBRARY_NAME}.def) - set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D_USRDLL;/D__STDC_CONSTANT_MACROS) - set(LINK_DIRECTORIES - ${PROJECT_ROOT_DIR}/wxGuiPluginBase/${OS_BASE_NAME}${LIB_SUFFIX}/$(ConfigurationName)) - set(DEMO_LIBS wxGuiPluginBase.lib) -endif(WIN32) -if(LINUX OR APPLE) - set(DEMO_LIBS wxGuiPluginBase) - SET(CMAKE_SKIP_BUILD_RPATH FALSE) - SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) - SET(CMAKE_INSTALL_RPATH ".:./../../") -endif(LINUX OR APPLE) - -set(SRCS ${SRCS} ${HEADERS} - ${PROJECT_ROOT_DIR}/include/stdwx.h - ${PROJECT_ROOT_DIR}/include/stdwx.cpp) - -add_definitions(${PREPROCESSOR_DEFINITIONS}) - -include_directories(${INCLUDE_DIRECTORIES} ${BASE_INCLUDE_DIRECTORIES} - ${PROJECT_ROOT_DIR}/wxGuiPluginBase) - -link_directories(${LINK_DIRECTORIES}) - -add_library(${LIBRARY_NAME} SHARED ${SRCS}) - -set(DLL_DIR bin) -if(APPLE) - set(BUNDLE_SUBFOLDER - "/$(CONFIGURATION)/${PROJECT_NAME}.app/Contents/PlugIns") -endif(APPLE) -if(WIN32) - set(TARGET_LOCATION - ${PROJECT_SOURCE_DIR}/${DLL_DIR}${LIB_SUFFIX}/${CMAKE_CFG_INTDIR}/plugins/gui) -elseif (LINUX) - set(TARGET_LOCATION - ${PROJECT_SOURCE_DIR}/${DLL_DIR}${LIB_SUFFIX}${BUNDLE_SUBFOLDER}/plugins/gui) -else() - set(TARGET_LOCATION - ${PROJECT_SOURCE_DIR}/${DLL_DIR}${LIB_SUFFIX}${BUNDLE_SUBFOLDER}/gui) -endif(WIN32) -if(LINUX OR APPLE) - get_target_property(RESULT_FULL_PATH ${LIBRARY_NAME} LOCATION) - get_filename_component(RESULT_FILE_NAME ${RESULT_FULL_PATH} NAME) -endif(LINUX OR APPLE) -set_target_properties(${LIBRARY_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TARGET_LOCATION}) - -target_link_libraries(${LIBRARY_NAME} ${DEMO_LIBS} ${wxWidgets_LIBRARIES}) - -add_dependencies(${LIBRARY_NAME} wxGuiPluginBase) - -target_precompile_headers(${LIBRARY_NAME} PRIVATE ${PROJECT_ROOT_DIR}/include/stdwx.h ${PROJECT_ROOT_DIR}/include/stdwx.cpp) - -if(APPLE) - FOREACH(DEP_LIB ${DEMO_LIBS}) - get_filename_component(ABS_ROOT_DIR ${PROJECT_ROOT_DIR} ABSOLUTE) - set(LIBNAME_FULL "${ABS_ROOT_DIR}/${DEP_LIB}/${OS_BASE_NAME}${LIB_SUFFIX}/$(CONFIGURATION)/lib${DEP_LIB}.dylib") - add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD - COMMAND install_name_tool -change "${LIBNAME_FULL}" "@executable_path/../Frameworks/lib${DEP_LIB}.dylib" $) - ENDFOREACH(DEP_LIB) -endif(APPLE) -if(LINUX OR APPLE) - add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory ${TARGET_LOCATION} - COMMAND ${CMAKE_COMMAND} -E copy $ ${TARGET_LOCATION}/${RESULT_FILE_NAME} - ) -endif(LINUX OR APPLE) diff --git a/SampleGuiPlugin1/SampleGuiPlugin1.cpp b/SampleGuiPlugin1/SampleGuiPlugin1.cpp deleted file mode 100644 index fdcaef9..0000000 --- a/SampleGuiPlugin1/SampleGuiPlugin1.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "stdwx.h" -#include "SampleGuiPlugin1.h" -#include "SampleGuiPluginWindow1.h" - -IMPLEMENT_DYNAMIC_CLASS(SampleGuiPlugin1, wxObject) - -SampleGuiPlugin1::SampleGuiPlugin1() -: wxGuiPluginBase(NULL) -{ - -} - -SampleGuiPlugin1::SampleGuiPlugin1(wxEvtHandler * handler) -: wxGuiPluginBase(handler) -{ -} - -SampleGuiPlugin1::~SampleGuiPlugin1() -{ -} - -wxString SampleGuiPlugin1::GetName() const -{ - return _("GUI Plugin 1"); -} - -wxString SampleGuiPlugin1::GetId() const -{ - return wxT("{4E97DF66-5FBB-4719-AF17-76C1C82D3FE1}"); -} - -wxWindow * SampleGuiPlugin1::CreatePanel(wxWindow * parent) -{ - return new SampleGuiPluginWindow1(this, parent); -} diff --git a/SampleGuiPlugin1/SampleGuiPlugin1.def b/SampleGuiPlugin1/SampleGuiPlugin1.def deleted file mode 100644 index 600afe1..0000000 --- a/SampleGuiPlugin1/SampleGuiPlugin1.def +++ /dev/null @@ -1,5 +0,0 @@ -LIBRARY "SampleGuiPlugin1" - -EXPORTS - CreatePlugin=CreatePlugin - DeletePlugin=DeletePlugin \ No newline at end of file diff --git a/SampleGuiPlugin1/SampleGuiPlugin1.h b/SampleGuiPlugin1/SampleGuiPlugin1.h deleted file mode 100644 index d792328..0000000 --- a/SampleGuiPlugin1/SampleGuiPlugin1.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include - -class SampleGuiPlugin1 : public wxGuiPluginBase -{ - DECLARE_DYNAMIC_CLASS(SampleGuiPlugin1) -public: - SampleGuiPlugin1(); - SampleGuiPlugin1(wxEvtHandler * handler); - virtual ~SampleGuiPlugin1(); - - virtual wxString GetName() const; - virtual wxString GetId() const; - virtual wxWindow * CreatePanel(wxWindow * parent); -}; \ No newline at end of file diff --git a/SampleGuiPlugin1/SampleGuiPlugin1.rc b/SampleGuiPlugin1/SampleGuiPlugin1.rc deleted file mode 100755 index f63e693..0000000 --- a/SampleGuiPlugin1/SampleGuiPlugin1.rc +++ /dev/null @@ -1 +0,0 @@ -#include "wx/msw/wx.rc" diff --git a/SampleGuiPlugin1/SampleGuiPlugin1Exports.cpp b/SampleGuiPlugin1/SampleGuiPlugin1Exports.cpp deleted file mode 100644 index 8d4fa0e..0000000 --- a/SampleGuiPlugin1/SampleGuiPlugin1Exports.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "stdwx.h" -#include -#include "SampleGuiPlugin1.h" - -PLUGIN_EXPORTED_API wxGuiPluginBase * CreatePlugin() -{ - return new SampleGuiPlugin1; -} - -PLUGIN_EXPORTED_API void DeletePlugin(wxGuiPluginBase * plugin) -{ - wxDELETE(plugin); -} diff --git a/SampleGuiPlugin1/SampleGuiPluginWindow1.cpp b/SampleGuiPlugin1/SampleGuiPluginWindow1.cpp deleted file mode 100644 index 5f30afb..0000000 --- a/SampleGuiPlugin1/SampleGuiPluginWindow1.cpp +++ /dev/null @@ -1,192 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: SampleGuiPluginWindow1.cpp -// Purpose: -// Author: Volodymyr (T-Rex) Triapichko -// Modified by: -// Created: 10/09/2013 00:01:49 -// RCS-ID: -// Copyright: Volodymyr (T-Rex) Triapichko, 2013 -// Licence: -///////////////////////////////////////////////////////////////////////////// - -// For compilers that support precompilation, includes "wx/wx.h". -#include "wx/wxprec.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#ifndef WX_PRECOMP -#include "wx/wx.h" -#endif - -////@begin includes -////@end includes - -#include "SampleGuiPluginWindow1.h" -#include - -////@begin XPM images -////@end XPM images - - -/* - * SampleGuiPluginWindow1 type definition - */ - -IMPLEMENT_DYNAMIC_CLASS( SampleGuiPluginWindow1, wxGuiPluginWindowBase ) - - -/* - * SampleGuiPluginWindow1 event table definition - */ - -BEGIN_EVENT_TABLE( SampleGuiPluginWindow1, wxGuiPluginWindowBase ) - -////@begin SampleGuiPluginWindow1 event table entries - EVT_BUTTON( ID_SEND_EVENT_BUTTON, SampleGuiPluginWindow1::OnSENDEVENTBUTTONClick ) -////@end SampleGuiPluginWindow1 event table entries - -END_EVENT_TABLE() - - -/* - * SampleGuiPluginWindow1 constructors - */ - -SampleGuiPluginWindow1::SampleGuiPluginWindow1() -{ - Init(); -} - -SampleGuiPluginWindow1::SampleGuiPluginWindow1( wxGuiPluginBase * plugin, - wxWindow* parent, wxWindowID id, - const wxPoint& pos, const wxSize& size, - long style ) -{ - Init(); - Create(plugin, parent, id, pos, size, style); -} - - -/* - * SampleGuiPluginWindow1 creator - */ - -bool SampleGuiPluginWindow1::Create(wxGuiPluginBase * plugin, - wxWindow* parent, wxWindowID id, - const wxPoint& pos, const wxSize& size, - long style ) -{ - wxGuiPluginWindowBase::Create(plugin, parent, id, pos, size, style ); - - CreateControls(); - if (GetSizer()) - { - GetSizer()->SetSizeHints(this); - } - Centre(); - return true; -} - - -/* - * SampleGuiPluginWindow1 destructor - */ - -SampleGuiPluginWindow1::~SampleGuiPluginWindow1() -{ -////@begin SampleGuiPluginWindow1 destruction -////@end SampleGuiPluginWindow1 destruction -} - - -/* - * Member initialisation - */ - -void SampleGuiPluginWindow1::Init() -{ -////@begin SampleGuiPluginWindow1 member initialisation - m_SamppleTextCtrl = NULL; -////@end SampleGuiPluginWindow1 member initialisation -} - - -/* - * Control creation for SampleGuiPluginWindow1 - */ - -void SampleGuiPluginWindow1::CreateControls() -{ -////@begin SampleGuiPluginWindow1 content construction - SampleGuiPluginWindow1* itemGuiPluginWindowBase1 = this; - - wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL); - itemGuiPluginWindowBase1->SetSizer(itemBoxSizer2); - - wxStaticText* itemStaticText3 = new wxStaticText( itemGuiPluginWindowBase1, wxID_STATIC, _("Enter some text here:"), wxDefaultPosition, wxDefaultSize, 0 ); - itemBoxSizer2->Add(itemStaticText3, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP, 5); - - m_SamppleTextCtrl = new wxTextCtrl( itemGuiPluginWindowBase1, ID_SAMPLE_TEXTCTRL, _("Hello, GUI Plugin 2!"), wxDefaultPosition, wxDefaultSize, 0 ); - itemBoxSizer2->Add(m_SamppleTextCtrl, 0, wxGROW|wxLEFT|wxRIGHT|wxTOP, 5); - - wxButton* itemButton5 = new wxButton( itemGuiPluginWindowBase1, ID_SEND_EVENT_BUTTON, _("Send event"), wxDefaultPosition, wxDefaultSize, 0 ); - itemBoxSizer2->Add(itemButton5, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5); - -////@end SampleGuiPluginWindow1 content construction -} - - -/* - * Should we show tooltips? - */ - -bool SampleGuiPluginWindow1::ShowToolTips() -{ - return true; -} - -/* - * Get bitmap resources - */ - -wxBitmap SampleGuiPluginWindow1::GetBitmapResource( const wxString& name ) -{ - // Bitmap retrieval -////@begin SampleGuiPluginWindow1 bitmap retrieval - wxUnusedVar(name); - return wxNullBitmap; -////@end SampleGuiPluginWindow1 bitmap retrieval -} - -/* - * Get icon resources - */ - -wxIcon SampleGuiPluginWindow1::GetIconResource( const wxString& name ) -{ - // Icon retrieval -////@begin SampleGuiPluginWindow1 icon retrieval - wxUnusedVar(name); - return wxNullIcon; -////@end SampleGuiPluginWindow1 icon retrieval -} - - -/* - * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_SEND_EVENT_BUTTON - */ - -void SampleGuiPluginWindow1::OnSENDEVENTBUTTONClick( wxCommandEvent& event ) -{ - wxCommandEvent e(wxEVT_GUI_PLUGIN_INTEROP); - e.SetString(m_SamppleTextCtrl->GetValue()); - GetPlugin()->GetEventHandler()->AddPendingEvent(e); - -////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_SEND_EVENT_BUTTON in SampleGuiPluginWindow1. - // Before editing this code, remove the block markers. - event.Skip(); -////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_SEND_EVENT_BUTTON in SampleGuiPluginWindow1. -} - diff --git a/SampleGuiPlugin1/SampleGuiPluginWindow1.h b/SampleGuiPlugin1/SampleGuiPluginWindow1.h deleted file mode 100644 index 937922e..0000000 --- a/SampleGuiPlugin1/SampleGuiPluginWindow1.h +++ /dev/null @@ -1,98 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: SampleGuiPluginWindow1.h -// Purpose: -// Author: Volodymyr (T-Rex) Triapichko -// Modified by: -// Created: 10/09/2013 00:01:49 -// RCS-ID: -// Copyright: Volodymyr (T-Rex) Triapichko, 2013 -// Licence: -///////////////////////////////////////////////////////////////////////////// - -#ifndef _SAMPLEGUIPLUGINWINDOW1_H_ -#define _SAMPLEGUIPLUGINWINDOW1_H_ - - -/*! - * Includes - */ - -////@begin includes -////@end includes -#include - -/*! - * Forward declarations - */ - -////@begin forward declarations -////@end forward declarations - -/*! - * Control identifiers - */ - -////@begin control identifiers -#define ID_SAMPLEGUIPLUGINWINDOW1 10000 -#define ID_SAMPLE_TEXTCTRL 10001 -#define ID_SEND_EVENT_BUTTON 10002 -#define SYMBOL_SAMPLEGUIPLUGINWINDOW1_STYLE wxTAB_TRAVERSAL -#define SYMBOL_SAMPLEGUIPLUGINWINDOW1_TITLE _("SampleGuiPluginWindow1") -#define SYMBOL_SAMPLEGUIPLUGINWINDOW1_IDNAME ID_SAMPLEGUIPLUGINWINDOW1 -#define SYMBOL_SAMPLEGUIPLUGINWINDOW1_SIZE wxSize(400, 300) -#define SYMBOL_SAMPLEGUIPLUGINWINDOW1_POSITION wxDefaultPosition -////@end control identifiers - - -/*! - * SampleGuiPluginWindow1 class declaration - */ - -class SampleGuiPluginWindow1: public wxGuiPluginWindowBase -{ - DECLARE_DYNAMIC_CLASS( SampleGuiPluginWindow1 ) - DECLARE_EVENT_TABLE() - -public: - /// Constructors - SampleGuiPluginWindow1(); - SampleGuiPluginWindow1(wxGuiPluginBase * plugin, wxWindow* parent, wxWindowID id = SYMBOL_SAMPLEGUIPLUGINWINDOW1_IDNAME, const wxPoint& pos = SYMBOL_SAMPLEGUIPLUGINWINDOW1_POSITION, const wxSize& size = SYMBOL_SAMPLEGUIPLUGINWINDOW1_SIZE, long style = SYMBOL_SAMPLEGUIPLUGINWINDOW1_STYLE ); - - /// Creation - bool Create(wxGuiPluginBase * plugin, wxWindow* parent, wxWindowID id = SYMBOL_SAMPLEGUIPLUGINWINDOW1_IDNAME, const wxPoint& pos = SYMBOL_SAMPLEGUIPLUGINWINDOW1_POSITION, const wxSize& size = SYMBOL_SAMPLEGUIPLUGINWINDOW1_SIZE, long style = SYMBOL_SAMPLEGUIPLUGINWINDOW1_STYLE ); - - /// Destructor - ~SampleGuiPluginWindow1(); - - /// Initialises member variables - void Init(); - - /// Creates the controls and sizers - void CreateControls(); - -////@begin SampleGuiPluginWindow1 event handler declarations - - /// wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_SEND_EVENT_BUTTON - void OnSENDEVENTBUTTONClick( wxCommandEvent& event ); - -////@end SampleGuiPluginWindow1 event handler declarations - -////@begin SampleGuiPluginWindow1 member function declarations - - /// Retrieves bitmap resources - wxBitmap GetBitmapResource( const wxString& name ); - - /// Retrieves icon resources - wxIcon GetIconResource( const wxString& name ); -////@end SampleGuiPluginWindow1 member function declarations - - /// Should we show tooltips? - static bool ShowToolTips(); - -////@begin SampleGuiPluginWindow1 member variables - wxTextCtrl* m_SamppleTextCtrl; -////@end SampleGuiPluginWindow1 member variables -}; - -#endif - // _SAMPLEGUIPLUGINWINDOW1_H_ diff --git a/SampleGuiPlugin2/CMakeLists.txt b/SampleGuiPlugin2/CMakeLists.txt deleted file mode 100644 index ee8234b..0000000 --- a/SampleGuiPlugin2/CMakeLists.txt +++ /dev/null @@ -1,79 +0,0 @@ -set (SRCS - SampleGuiPlugin2.cpp - SampleGuiPlugin2Exports.cpp - SampleGuiPluginWindow2.cpp) -set (HEADERS - SampleGuiPlugin2.h - SampleGuiPluginWindow2.h) - -set(LIBRARY_NAME SampleGuiPlugin2) - -if(WIN32) - set(SRCS ${SRCS} ${LIBRARY_NAME}.def) - set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D_USRDLL;/D__STDC_CONSTANT_MACROS) - set(LINK_DIRECTORIES - ${PROJECT_ROOT_DIR}/wxGuiPluginBase/${OS_BASE_NAME}${LIB_SUFFIX}/$(ConfigurationName)) - set(DEMO_LIBS wxGuiPluginBase.lib) -endif(WIN32) -if(LINUX OR APPLE) - set(DEMO_LIBS wxGuiPluginBase) - SET(CMAKE_SKIP_BUILD_RPATH FALSE) - SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) - SET(CMAKE_INSTALL_RPATH ".:./../../") -endif(LINUX OR APPLE) - -set(SRCS ${SRCS} ${HEADERS} - ${PROJECT_ROOT_DIR}/include/stdwx.h - ${PROJECT_ROOT_DIR}/include/stdwx.cpp) - -add_definitions(${PREPROCESSOR_DEFINITIONS}) - -include_directories(${INCLUDE_DIRECTORIES} ${BASE_INCLUDE_DIRECTORIES} - ${PROJECT_ROOT_DIR}/wxGuiPluginBase) - -link_directories(${LINK_DIRECTORIES}) - -add_library(${LIBRARY_NAME} SHARED ${SRCS}) - -set(DLL_DIR bin) -if(APPLE) - set(BUNDLE_SUBFOLDER - "/$(CONFIGURATION)/${PROJECT_NAME}.app/Contents/PlugIns") -endif(APPLE) -if(WIN32) - set(TARGET_LOCATION - ${PROJECT_SOURCE_DIR}/${DLL_DIR}${LIB_SUFFIX}/${CMAKE_CFG_INTDIR}/plugins/gui) -elseif (LINUX) - set(TARGET_LOCATION - ${PROJECT_SOURCE_DIR}/${DLL_DIR}${LIB_SUFFIX}${BUNDLE_SUBFOLDER}/plugins/gui) -else() - set(TARGET_LOCATION - ${PROJECT_SOURCE_DIR}/${DLL_DIR}${LIB_SUFFIX}${BUNDLE_SUBFOLDER}/gui) -endif(WIN32) -if(LINUX OR APPLE) - get_target_property(RESULT_FULL_PATH ${LIBRARY_NAME} LOCATION) - get_filename_component(RESULT_FILE_NAME ${RESULT_FULL_PATH} NAME) -endif(LINUX OR APPLE) - -set_target_properties(${LIBRARY_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TARGET_LOCATION}) - -target_link_libraries(${LIBRARY_NAME} ${DEMO_LIBS} ${wxWidgets_LIBRARIES}) - -add_dependencies(${LIBRARY_NAME} wxGuiPluginBase) - -target_precompile_headers(${LIBRARY_NAME} PRIVATE ${PROJECT_ROOT_DIR}/include/stdwx.h ${PROJECT_ROOT_DIR}/include/stdwx.cpp) - -if(APPLE) - FOREACH(DEP_LIB ${DEMO_LIBS}) - get_filename_component(ABS_ROOT_DIR ${PROJECT_ROOT_DIR} ABSOLUTE) - set(LIBNAME_FULL "${ABS_ROOT_DIR}/${DEP_LIB}/${OS_BASE_NAME}${LIB_SUFFIX}/$(CONFIGURATION)/lib${DEP_LIB}.dylib") - add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD - COMMAND install_name_tool -change "${LIBNAME_FULL}" "@executable_path/../Frameworks/lib${DEP_LIB}.dylib" $) - ENDFOREACH(DEP_LIB) -endif(APPLE) -if(LINUX OR APPLE) - add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory ${TARGET_LOCATION} - COMMAND ${CMAKE_COMMAND} -E copy $ ${TARGET_LOCATION}/${RESULT_FILE_NAME} - ) -endif(LINUX OR APPLE) diff --git a/SampleGuiPlugin2/SampleGuiPlugin2.cpp b/SampleGuiPlugin2/SampleGuiPlugin2.cpp deleted file mode 100644 index 451da39..0000000 --- a/SampleGuiPlugin2/SampleGuiPlugin2.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "stdwx.h" -#include "SampleGuiPlugin2.h" -#include "SampleGuiPluginWindow2.h" - -IMPLEMENT_DYNAMIC_CLASS(SampleGuiPlugin2, wxObject) - -SampleGuiPlugin2::SampleGuiPlugin2() -: wxGuiPluginBase(NULL) -{ - -} - -SampleGuiPlugin2::SampleGuiPlugin2(wxEvtHandler * handler) -: wxGuiPluginBase(handler) -{ -} - -SampleGuiPlugin2::~SampleGuiPlugin2() -{ -} - -wxString SampleGuiPlugin2::GetName() const -{ - return _("GUI Plugin 2"); -} - -wxString SampleGuiPlugin2::GetId() const -{ - return wxT("{1B226C84-6436-4092-9AB8-B2B0D6731EBE}"); -} - -wxWindow * SampleGuiPlugin2::CreatePanel(wxWindow * parent) -{ - return new SampleGuiPluginWindow2(this, parent); -} diff --git a/SampleGuiPlugin2/SampleGuiPlugin2.h b/SampleGuiPlugin2/SampleGuiPlugin2.h deleted file mode 100644 index 7e46db4..0000000 --- a/SampleGuiPlugin2/SampleGuiPlugin2.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include - -class SampleGuiPlugin2 : public wxGuiPluginBase -{ - DECLARE_DYNAMIC_CLASS(SampleGuiPlugin2) -public: - SampleGuiPlugin2(); - SampleGuiPlugin2(wxEvtHandler * handler); - virtual ~SampleGuiPlugin2(); - - virtual wxString GetName() const; - virtual wxString GetId() const; - virtual wxWindow * CreatePanel(wxWindow * parent); -}; \ No newline at end of file diff --git a/SampleGuiPlugin2/SampleGuiPlugin2.pjd b/SampleGuiPlugin2/SampleGuiPlugin2.pjd deleted file mode 100644 index f622f46..0000000 --- a/SampleGuiPlugin2/SampleGuiPlugin2.pjd +++ /dev/null @@ -1,506 +0,0 @@ - - -
- 0 - "" - "" - "" - "" - "" - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - "Volodymyr (T-Rex) Triapichko" - "Volodymyr (T-Rex) Triapichko, 2013" - "" - 0 - 0 - 0 - 0 - "<All platforms>" - "2.9.5" - "Standard" - "///////////////////////////////////////////////////////////////////////////// -// Name: %HEADER-FILENAME% -// Purpose: -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "///////////////////////////////////////////////////////////////////////////// -// Name: %SOURCE-FILENAME% -// Purpose: -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "///////////////////////////////////////////////////////////////////////////// -// Name: %SYMBOLS-FILENAME% -// Purpose: Symbols file -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "" - "// For compilers that support precompilation, includes "wx/wx.h". -#include "wx/wxprec.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#ifndef WX_PRECOMP -#include "wx/wx.h" -#endif - -" - " /// %BODY% -" - " -/* - * %BODY% - */ - -" - "app_resources.h" - "app_resources.cpp" - "AppResources" - "app.h" - "app.cpp" - "Application" - 0 - "" - "<None>" - "iso-8859-1" - "utf-8" - "utf-8" - "" - 0 - 0 - 4 - " " - "" - 0 - 0 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 -
- - - "" - "data-document" - "" - "" - 0 - 1 - 0 - 0 - - "Configurations" - "config-data-document" - "" - "" - 0 - 1 - 0 - 0 - "" - 1 - -8519680 - "" - "Debug" - "Unicode" - "Static" - "Modular" - "GUI" - "wxMSW" - "Default" - "Dynamic" - "Yes" - "No" - "Yes" - "No" - "No" - "Yes" - "Yes" - "Yes" - "Yes" - "Yes" - "builtin" - "Yes" - "%EXECUTABLE%" - "" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%WXVERSION%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - 0 - 1 - - - - - - - "Projects" - "root-document" - "" - "project" - 1 - 1 - 0 - 1 - - "Windows" - "html-document" - "" - "dialogsfolder" - 1 - 1 - 0 - 1 - - "SampleGuiPluginWindow2" - "dialog-document" - "" - "dialog" - 0 - 1 - 0 - 0 - "wbDialogProxy" - 10000 - 0 - "" - 0 - "" - "Standard" - 0 - 0 - "wxEVT_DESTROY|OnDestroy|NONE||" - "ID_SAMPLEGUIPLUGINWINDOW2" - 10000 - "SampleGuiPluginWindow2" - "wxGuiPluginWindowBase" - "wxPanel" - "SampleGuiPluginWindow2.cpp" - "SampleGuiPluginWindow2.h" - "" - "SampleGuiPluginWindow2" - 1 - "" - 0 - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - "" - "" - "" - "" - "" - "" - "Tiled" - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - "" - 0 - 1 - -1 - -1 - 400 - 300 - 0 - "" - - "wxBoxSizer V" - "dialog-control-document" - "" - "sizer" - 0 - 1 - 0 - 0 - "wbBoxSizerProxy" - "Vertical" - "" - 0 - 0 - 0 - 0 - "<Any platform>" - - "wxStaticText: wxID_STATIC" - "dialog-control-document" - "" - "statictext" - 0 - 1 - 0 - 0 - "wbStaticTextProxy" - "wxID_STATIC" - 5105 - "" - "wxStaticText" - "wxStaticText" - 1 - 0 - "" - "" - "" - "This text box receives messages from GUI Plugin 1:" - -1 - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - "" - "" - "" - "" - "" - "" - "" - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - "" - -1 - -1 - -1 - -1 - "Left" - "Centre" - 0 - 5 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - "" - "" - - - "wxTextCtrl: ID_GUI_PLUGIN2_MESSAGE_TEXTCTRL" - "dialog-control-document" - "" - "textctrl" - 0 - 1 - 0 - 0 - "wbTextCtrlProxy" - "ID_GUI_PLUGIN2_MESSAGE_TEXTCTRL" - 10001 - "" - "wxTextCtrl" - "wxTextCtrl" - 1 - 0 - "" - "" - "m_MessageTextCtrl" - "" - 0 - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - "" - "" - "" - "" - "" - "" - "" - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - "" - -1 - -1 - -1 - -1 - "Expand" - "Centre" - 0 - 5 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - "" - "" - - - - - - "Sources" - "html-document" - "" - "sourcesfolder" - 1 - 1 - 0 - 1 - - "SampleGuiPlugin2.rc" - "source-editor-document" - "SampleGuiPlugin2.rc" - "source-editor" - 0 - 0 - 1 - 0 - "18/9/2013" - "" - - - - "Images" - "html-document" - "" - "bitmapsfolder" - 1 - 1 - 0 - 1 - - - - -
diff --git a/SampleGuiPlugin2/SampleGuiPlugin2.rc b/SampleGuiPlugin2/SampleGuiPlugin2.rc deleted file mode 100755 index f63e693..0000000 --- a/SampleGuiPlugin2/SampleGuiPlugin2.rc +++ /dev/null @@ -1 +0,0 @@ -#include "wx/msw/wx.rc" diff --git a/SampleGuiPlugin2/SampleGuiPlugin2Exports.cpp b/SampleGuiPlugin2/SampleGuiPlugin2Exports.cpp deleted file mode 100644 index 6e386d2..0000000 --- a/SampleGuiPlugin2/SampleGuiPlugin2Exports.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "stdwx.h" -#include -#include "SampleGuiPlugin2.h" - -PLUGIN_EXPORTED_API wxGuiPluginBase * CreatePlugin() -{ - return new SampleGuiPlugin2; -} - -PLUGIN_EXPORTED_API void DeletePlugin(wxGuiPluginBase * plugin) -{ - wxDELETE(plugin); -} diff --git a/SampleGuiPlugin2/SampleGuiPluginWindow2.cpp b/SampleGuiPlugin2/SampleGuiPluginWindow2.cpp deleted file mode 100644 index 629c768..0000000 --- a/SampleGuiPlugin2/SampleGuiPluginWindow2.cpp +++ /dev/null @@ -1,190 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: SampleGuiPluginWindow2.cpp -// Purpose: -// Author: Volodymyr (T-Rex) Triapichko -// Modified by: -// Created: 18/09/2013 22:40:39 -// RCS-ID: -// Copyright: Volodymyr (T-Rex) Triapichko, 2013 -// Licence: -///////////////////////////////////////////////////////////////////////////// - -// For compilers that support precompilation, includes "wx/wx.h". -#include "wx/wxprec.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#ifndef WX_PRECOMP -#include "wx/wx.h" -#endif - -////@begin includes -////@end includes - -#include "SampleGuiPluginWindow2.h" -#include - -////@begin XPM images -////@end XPM images - - -/* - * SampleGuiPluginWindow2 type definition - */ - -IMPLEMENT_DYNAMIC_CLASS( SampleGuiPluginWindow2, wxGuiPluginWindowBase ) - - -/* - * SampleGuiPluginWindow2 event table definition - */ - -BEGIN_EVENT_TABLE( SampleGuiPluginWindow2, wxGuiPluginWindowBase ) - -////@begin SampleGuiPluginWindow2 event table entries - EVT_WINDOW_DESTROY( SampleGuiPluginWindow2::OnDestroy ) -////@end SampleGuiPluginWindow2 event table entries - -END_EVENT_TABLE() - - -/* - * SampleGuiPluginWindow2 constructors - */ - -SampleGuiPluginWindow2::SampleGuiPluginWindow2() -{ - Init(); -} - -SampleGuiPluginWindow2::SampleGuiPluginWindow2( wxGuiPluginBase * plugin, wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) -{ - Init(); - Create(plugin, parent, id, pos, size, style); -} - - -/* - * SampleGuiPluginWindow2 creator - */ - -bool SampleGuiPluginWindow2::Create( wxGuiPluginBase * plugin, wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) -{ - wxGuiPluginWindowBase::Create(plugin, parent, id, pos, size, style ); - - CreateControls(); - if (GetSizer()) - { - GetSizer()->SetSizeHints(this); - } - Centre(); - return true; -} - - -/* - * SampleGuiPluginWindow2 destructor - */ - -SampleGuiPluginWindow2::~SampleGuiPluginWindow2() -{ -////@begin SampleGuiPluginWindow2 destruction -////@end SampleGuiPluginWindow2 destruction -} - - -/* - * Member initialisation - */ - -void SampleGuiPluginWindow2::Init() -{ -////@begin SampleGuiPluginWindow2 member initialisation - m_MessageTextCtrl = NULL; -////@end SampleGuiPluginWindow2 member initialisation -} - - -/* - * Control creation for SampleGuiPluginWindow2 - */ - -void SampleGuiPluginWindow2::CreateControls() -{ -////@begin SampleGuiPluginWindow2 content construction - SampleGuiPluginWindow2* itemGuiPluginWindowBase1 = this; - - wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL); - itemGuiPluginWindowBase1->SetSizer(itemBoxSizer2); - - wxStaticText* itemStaticText3 = new wxStaticText( itemGuiPluginWindowBase1, wxID_STATIC, _("This text box receives messages from GUI Plugin 1:"), wxDefaultPosition, wxDefaultSize, 0 ); - itemBoxSizer2->Add(itemStaticText3, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP, 5); - - m_MessageTextCtrl = new wxTextCtrl( itemGuiPluginWindowBase1, ID_GUI_PLUGIN2_MESSAGE_TEXTCTRL, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY ); - itemBoxSizer2->Add(m_MessageTextCtrl, 0, wxGROW|wxALL, 5); - - // Connect events and objects - itemGuiPluginWindowBase1->Connect(ID_SAMPLEGUIPLUGINWINDOW2, wxEVT_DESTROY, wxWindowDestroyEventHandler(SampleGuiPluginWindow2::OnDestroy), NULL, this); -////@end SampleGuiPluginWindow2 content construction - GetPlugin()->GetEventHandler()->Bind(wxEVT_GUI_PLUGIN_INTEROP, - wxCommandEventHandler(SampleGuiPluginWindow2::OnInteropMessageReceived), this); -} - - -/* - * Should we show tooltips? - */ - -bool SampleGuiPluginWindow2::ShowToolTips() -{ - return true; -} - -/* - * Get bitmap resources - */ - -wxBitmap SampleGuiPluginWindow2::GetBitmapResource( const wxString& name ) -{ - // Bitmap retrieval -////@begin SampleGuiPluginWindow2 bitmap retrieval - wxUnusedVar(name); - return wxNullBitmap; -////@end SampleGuiPluginWindow2 bitmap retrieval -} - -/* - * Get icon resources - */ - -wxIcon SampleGuiPluginWindow2::GetIconResource( const wxString& name ) -{ - // Icon retrieval -////@begin SampleGuiPluginWindow2 icon retrieval - wxUnusedVar(name); - return wxNullIcon; -////@end SampleGuiPluginWindow2 icon retrieval -} - -void SampleGuiPluginWindow2::OnInteropMessageReceived(wxCommandEvent & event) -{ - m_MessageTextCtrl->SetValue(event.GetString()); -} - - -/* - * wxEVT_DESTROY event handler for ID_SAMPLEGUIPLUGINWINDOW2 - */ - -void SampleGuiPluginWindow2::OnDestroy( wxWindowDestroyEvent& event ) -{ - GetPlugin()->GetEventHandler()->Unbind(wxEVT_GUI_PLUGIN_INTEROP, - wxCommandEventHandler(SampleGuiPluginWindow2::OnInteropMessageReceived), this); -////@begin wxEVT_DESTROY event handler for ID_SAMPLEGUIPLUGINWINDOW2 in SampleGuiPluginWindow2. - // Before editing this code, remove the block markers. - event.Skip(); -////@end wxEVT_DESTROY event handler for ID_SAMPLEGUIPLUGINWINDOW2 in SampleGuiPluginWindow2. -} - diff --git a/SampleGuiPlugin2/SampleGuiPluginWindow2.h b/SampleGuiPlugin2/SampleGuiPluginWindow2.h deleted file mode 100644 index 8ccdf2e..0000000 --- a/SampleGuiPlugin2/SampleGuiPluginWindow2.h +++ /dev/null @@ -1,98 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: SampleGuiPluginWindow2.h -// Purpose: -// Author: Volodymyr (T-Rex) Triapichko -// Modified by: -// Created: 18/09/2013 22:40:39 -// RCS-ID: -// Copyright: Volodymyr (T-Rex) Triapichko, 2013 -// Licence: -///////////////////////////////////////////////////////////////////////////// - -#ifndef _SAMPLEGUIPLUGINWINDOW2_H_ -#define _SAMPLEGUIPLUGINWINDOW2_H_ - - -/*! - * Includes - */ - -////@begin includes -////@end includes -#include - -/*! - * Forward declarations - */ - -////@begin forward declarations -////@end forward declarations - -/*! - * Control identifiers - */ - -////@begin control identifiers -#define ID_SAMPLEGUIPLUGINWINDOW2 10000 -#define ID_GUI_PLUGIN2_MESSAGE_TEXTCTRL 10001 -#define SYMBOL_SAMPLEGUIPLUGINWINDOW2_STYLE wxTAB_TRAVERSAL -#define SYMBOL_SAMPLEGUIPLUGINWINDOW2_TITLE _("SampleGuiPluginWindow2") -#define SYMBOL_SAMPLEGUIPLUGINWINDOW2_IDNAME ID_SAMPLEGUIPLUGINWINDOW2 -#define SYMBOL_SAMPLEGUIPLUGINWINDOW2_SIZE wxSize(400, 300) -#define SYMBOL_SAMPLEGUIPLUGINWINDOW2_POSITION wxDefaultPosition -////@end control identifiers - - -/*! - * SampleGuiPluginWindow2 class declaration - */ - -class SampleGuiPluginWindow2: public wxGuiPluginWindowBase -{ - DECLARE_DYNAMIC_CLASS( SampleGuiPluginWindow2 ) - DECLARE_EVENT_TABLE() - -public: - /// Constructors - SampleGuiPluginWindow2(); - SampleGuiPluginWindow2( wxGuiPluginBase * plugin, wxWindow* parent, wxWindowID id = SYMBOL_SAMPLEGUIPLUGINWINDOW2_IDNAME, const wxPoint& pos = SYMBOL_SAMPLEGUIPLUGINWINDOW2_POSITION, const wxSize& size = SYMBOL_SAMPLEGUIPLUGINWINDOW2_SIZE, long style = SYMBOL_SAMPLEGUIPLUGINWINDOW2_STYLE ); - - /// Creation - bool Create( wxGuiPluginBase * plugin, wxWindow* parent, wxWindowID id = SYMBOL_SAMPLEGUIPLUGINWINDOW2_IDNAME, const wxPoint& pos = SYMBOL_SAMPLEGUIPLUGINWINDOW2_POSITION, const wxSize& size = SYMBOL_SAMPLEGUIPLUGINWINDOW2_SIZE, long style = SYMBOL_SAMPLEGUIPLUGINWINDOW2_STYLE ); - - /// Destructor - ~SampleGuiPluginWindow2(); - - /// Initialises member variables - void Init(); - - /// Creates the controls and sizers - void CreateControls(); - -////@begin SampleGuiPluginWindow2 event handler declarations - - /// wxEVT_DESTROY event handler for ID_SAMPLEGUIPLUGINWINDOW2 - void OnDestroy( wxWindowDestroyEvent& event ); - -////@end SampleGuiPluginWindow2 event handler declarations - void OnInteropMessageReceived(wxCommandEvent & event); - -////@begin SampleGuiPluginWindow2 member function declarations - - /// Retrieves bitmap resources - wxBitmap GetBitmapResource( const wxString& name ); - - /// Retrieves icon resources - wxIcon GetIconResource( const wxString& name ); -////@end SampleGuiPluginWindow2 member function declarations - - /// Should we show tooltips? - static bool ShowToolTips(); - -////@begin SampleGuiPluginWindow2 member variables - wxTextCtrl* m_MessageTextCtrl; -////@end SampleGuiPluginWindow2 member variables -}; - -#endif - // _SAMPLEGUIPLUGINWINDOW2_H_ diff --git a/SampleNonGuiPlugin/CMakeLists.txt b/SampleNonGuiPlugin/CMakeLists.txt deleted file mode 100644 index 90cb79a..0000000 --- a/SampleNonGuiPlugin/CMakeLists.txt +++ /dev/null @@ -1,81 +0,0 @@ -set (SRCS - SampleNonGuiPlugin.cpp - SampleNonGuiPluginExports.cpp) -set (HEADERS - SampleNonGuiPlugin.h) - -set(LIBRARY_NAME SampleNonGuiPlugin) - -if(WIN32) - set(SRCS ${SRCS} ${LIBRARY_NAME}.def) - set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D_USRDLL;/D__STDC_CONSTANT_MACROS) - set(LINK_DIRECTORIES - ${PROJECT_ROOT_DIR}/wxNonGuiPluginBase/${OS_BASE_NAME}${LIB_SUFFIX}/$(ConfigurationName)) - set(DEMO_LIBS wxNonGuiPluginBase.lib) -endif(WIN32) -if(LINUX OR APPLE) - set(DEMO_LIBS wxNonGuiPluginBase) - SET(CMAKE_SKIP_BUILD_RPATH FALSE) - SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) - if(LINUX) - SET(CMAKE_INSTALL_RPATH ".:./../../") - else() - SET(CMAKE_INSTALL_RPATH "@executable_path/../Frameworks") - endif(LINUX) -endif(LINUX OR APPLE) - -set(SRCS ${SRCS} ${HEADERS} - ${PROJECT_ROOT_DIR}/include/stdwx.h - ${PROJECT_ROOT_DIR}/include/stdwx.cpp) - -add_definitions(${PREPROCESSOR_DEFINITIONS}) - -include_directories(${INCLUDE_DIRECTORIES} ${BASE_INCLUDE_DIRECTORIES} - ${PROJECT_ROOT_DIR}/wxNonGuiPluginBase) - -link_directories(${LINK_DIRECTORIES}) - -add_library(${LIBRARY_NAME} SHARED ${SRCS}) - -set(DLL_DIR bin) -if(APPLE) - set(BUNDLE_SUBFOLDER - "/$(CONFIGURATION)/${PROJECT_NAME}.app/Contents/PlugIns") -endif(APPLE) -if(WIN32) - set(TARGET_LOCATION - ${PROJECT_SOURCE_DIR}/${DLL_DIR}${LIB_SUFFIX}/${CMAKE_CFG_INTDIR}/plugins/nongui) -elseif (LINUX) - set(TARGET_LOCATION - ${PROJECT_SOURCE_DIR}/${DLL_DIR}${LIB_SUFFIX}${BUNDLE_SUBFOLDER}/plugins/nongui) -else() - set(TARGET_LOCATION - ${PROJECT_SOURCE_DIR}/${DLL_DIR}${LIB_SUFFIX}${BUNDLE_SUBFOLDER}/nongui) -endif(WIN32) -if(LINUX OR APPLE) - get_target_property(RESULT_FULL_PATH ${LIBRARY_NAME} LOCATION) - get_filename_component(RESULT_FILE_NAME ${RESULT_FULL_PATH} NAME) -endif(LINUX OR APPLE) -set_target_properties(${LIBRARY_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TARGET_LOCATION}) - -target_link_libraries(${LIBRARY_NAME} ${DEMO_LIBS} ${wxWidgets_LIBRARIES}) - -add_dependencies(${LIBRARY_NAME} wxNonGuiPluginBase) - -target_precompile_headers(${LIBRARY_NAME} PRIVATE ${PROJECT_ROOT_DIR}/include/stdwx.h ${PROJECT_ROOT_DIR}/include/stdwx.cpp) - -if(APPLE) - FOREACH(DEP_LIB ${DEMO_LIBS}) - get_filename_component(ABS_ROOT_DIR ${PROJECT_ROOT_DIR} ABSOLUTE) - set(LIBNAME_FULL "${ABS_ROOT_DIR}/${DEP_LIB}/${OS_BASE_NAME}${LIB_SUFFIX}/$(CONFIGURATION)/lib${DEP_LIB}.dylib") - add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD - COMMAND install_name_tool -change "${LIBNAME_FULL}" "@executable_path/../Frameworks/lib${DEP_LIB}.dylib" $) - ENDFOREACH(DEP_LIB) -endif(APPLE) -if(LINUX OR APPLE) - add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory ${TARGET_LOCATION} - COMMAND ${CMAKE_COMMAND} -E copy $ - ${TARGET_LOCATION}/${RESULT_FILE_NAME} - ) -endif(LINUX OR APPLE) diff --git a/SampleNonGuiPlugin/SampleNonGuiPlugin.cpp b/SampleNonGuiPlugin/SampleNonGuiPlugin.cpp deleted file mode 100644 index d0ba3db..0000000 --- a/SampleNonGuiPlugin/SampleNonGuiPlugin.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "stdwx.h" -#include "SampleNonGuiPlugin.h" - -IMPLEMENT_DYNAMIC_CLASS(SampleNonGuiPlugin, wxObject) - -SampleNonGuiPlugin::SampleNonGuiPlugin() -{ -} - -SampleNonGuiPlugin::~SampleNonGuiPlugin() -{ -} - -int SampleNonGuiPlugin::Work() -{ - return 10; -} diff --git a/SampleNonGuiPlugin/SampleNonGuiPlugin.def b/SampleNonGuiPlugin/SampleNonGuiPlugin.def deleted file mode 100644 index 501eec2..0000000 --- a/SampleNonGuiPlugin/SampleNonGuiPlugin.def +++ /dev/null @@ -1,5 +0,0 @@ -LIBRARY "SampleNonGuiPlugin" - -EXPORTS - CreatePlugin=CreatePlugin - DeletePlugin=DeletePlugin \ No newline at end of file diff --git a/SampleNonGuiPlugin/SampleNonGuiPlugin.h b/SampleNonGuiPlugin/SampleNonGuiPlugin.h deleted file mode 100644 index ab833b4..0000000 --- a/SampleNonGuiPlugin/SampleNonGuiPlugin.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -class SampleNonGuiPlugin : public wxNonGuiPluginBase -{ - DECLARE_DYNAMIC_CLASS(SampleNonGuiPlugin) -public: - SampleNonGuiPlugin(); - virtual ~SampleNonGuiPlugin(); - - virtual int Work(); -}; \ No newline at end of file diff --git a/SampleNonGuiPlugin/SampleNonGuiPluginExports.cpp b/SampleNonGuiPlugin/SampleNonGuiPluginExports.cpp deleted file mode 100644 index d984954..0000000 --- a/SampleNonGuiPlugin/SampleNonGuiPluginExports.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "stdwx.h" -#include -#include "SampleNonGuiPlugin.h" - -PLUGIN_EXPORTED_API wxNonGuiPluginBase * CreatePlugin() -{ - return new SampleNonGuiPlugin; -} - -PLUGIN_EXPORTED_API void DeletePlugin(wxNonGuiPluginBase * plugin) -{ - wxDELETE(plugin); -} diff --git a/ThirdParty/AppIndicatorHelper/AIHTest.cpp b/ThirdParty/AppIndicatorHelper/AIHTest.cpp new file mode 100644 index 0000000..d26df86 --- /dev/null +++ b/ThirdParty/AppIndicatorHelper/AIHTest.cpp @@ -0,0 +1,158 @@ +/* + * File: AIHTest.cpp + * Author: nmset@netcourrier.com + * License : irrelevant + * + * Created on 11 septembre 2015, 16:58 + */ + +#include "AIHTest.h" +#include +#include +#include "stop.xpm" +#include +using namespace std; + +IMPLEMENT_APP(AIHTest) + +AIHTest::AIHTest() +{ +} + +AIHTest::~AIHTest() +{ +} + +bool AIHTest::OnInit() +{ + AIHTestFrame * main = new AIHTestFrame(NULL, wxID_ANY, _T("AppIndicatorHelper test")); + SetAppName(_T("AIHTest")); + SetTopWindow(main); + main->Show(); + return true; +} + +int AIHTest::OnExit() +{ + return wxApp::OnExit(); +} + +AIHTestFrame::AIHTestFrame(wxWindow* parent, wxWindowID id, const wxString& title) +: wxFrame(parent, id, title) +{ + wxBoxSizer * szMain = new wxBoxSizer(wxVERTICAL); + SetSizer(szMain); + m_itemID = -10000; + m_subID = 0; + m_mainMenu = NULL; + m_removedMenu = NULL; + SetToolTip(_T("Right click : Popup menu.\nDouble click : Delete menu.")); + m_mainMenu = CreateMenu(); + Bind(wxEVT_RIGHT_UP, &AIHTestFrame::ShowMenu, this); + Bind(wxEVT_LEFT_DCLICK, &AIHTestFrame::DeleteMenu, this); + const wxFileName exe(wxStandardPaths::Get().GetExecutablePath()); + m_indicator = new AppIndicatorHelper(_T("AIH"), + exe.GetPath(wxPATH_GET_SEPARATOR) + _T("kde.png"), + APP_INDICATOR_CATEGORY_APPLICATION_STATUS); + m_indicator->SetTitle((_T("AppIndicator helper test"))); + m_indicator->SetMenu(m_mainMenu); + m_indicator->SetStatus(APP_INDICATOR_STATUS_ACTIVE); +} + +AIHTestFrame::~AIHTestFrame() +{ + delete m_mainMenu; + delete m_indicator; +} + +wxMenu* AIHTestFrame::CreateMenu() +{ + wxMenu * menu = new wxMenu(); + wxString label; + label = _T("SUB ") + wxVariant(m_subID).GetString(); + if (m_mainMenu != NULL) menu->SetTitle(label); + label = _T("New ") + wxVariant(m_itemID).GetString(); + menu->Append(m_itemID, label); + m_itemID++; + label = _T("Delete ") + wxVariant(m_itemID).GetString(); + wxMenuItem * item = new wxMenuItem(menu, m_itemID, label); + item->SetBitmap(stop_xpm); + menu->Append(item); + m_itemID++; + menu->AppendSeparator(); + + label = _T("RadioA ") + wxVariant(m_itemID).GetString(); + menu->AppendRadioItem(m_itemID, label); + m_itemID++; + label = _T("RadioB ") + wxVariant(m_itemID).GetString(); + menu->AppendRadioItem(m_itemID, label); + m_itemID++; + menu->AppendSeparator(); + + label = _T("Check ") + wxVariant(m_itemID).GetString(); + menu->AppendCheckItem(m_itemID, label); + m_itemID++; + menu->AppendSeparator(); + + label = _T("RadioC ") + wxVariant(m_itemID).GetString(); + menu->AppendRadioItem(m_itemID, label); + m_itemID++; + label = _T("RadioD ") + wxVariant(m_itemID).GetString(); + menu->AppendRadioItem(m_itemID, label); + m_itemID++; + menu->AppendSeparator(); + + menu->Bind(wxEVT_COMMAND_MENU_SELECTED, &AIHTestFrame::OnMenuItemClick, this); + m_subID++; + return menu; +} + +void AIHTestFrame::ShowMenu(wxMouseEvent& evt) +{ + if (m_mainMenu != NULL) PopupMenu(m_mainMenu); +} + +void AIHTestFrame::DeleteMenu(wxMouseEvent& evt) +{ + wxDELETE(m_mainMenu); + // If we destroy the wxWidgets reference menu, we must get rid of + // the indicator, to avoid an inevitable crash on item select. + wxDELETE(m_indicator); +} + +/* + * The 'New' and 'Delete' actions are just to show the need of calling SetMenu() + * again. This should be done whenever items are removed, added or modified. + * If check or radio items are clicked in the wxWidgets application, we need not + * call SetMenu(), this is done by AppIndicatorHelper. + */ +void AIHTestFrame::OnMenuItemClick(wxCommandEvent& evt) +{ + wxMenu * menu = static_cast (evt.GetEventObject()); + wxMenuItem * item = menu->FindItem(evt.GetId()); + const wxString label = item->GetItemLabelText(); + if (label.StartsWith(_T("New "))) { + wxMenu * subMenu = CreateMenu(); + wxMenuItem * subItem = menu->AppendSubMenu(subMenu, subMenu->GetTitle()); + subMenu->SetClientData(subItem); + m_indicator->SetMenu(m_mainMenu); // <- + } + if (label.StartsWith(_T("Delete "))) { + if (menu != m_mainMenu) { + wxMenuItem * subItem = static_cast (menu->GetClientData()); + // Can't destroy the submenu when it is shown. + subItem->GetMenu()->Remove(subItem); + m_indicator->SetMenu(m_mainMenu); // <- + // We resort to a trick by deleting the removed menu in idle time. + m_removedMenu = menu; + Bind(wxEVT_IDLE, &AIHTestFrame::OnIdle, this); + } + } + evt.Skip(); +} + +void AIHTestFrame::OnIdle(wxIdleEvent& evt) +{ + wxDELETE(m_removedMenu); + Unbind(wxEVT_IDLE, &AIHTestFrame::OnIdle, this); +} diff --git a/ThirdParty/AppIndicatorHelper/AIHTest.h b/ThirdParty/AppIndicatorHelper/AIHTest.h new file mode 100644 index 0000000..5d885cf --- /dev/null +++ b/ThirdParty/AppIndicatorHelper/AIHTest.h @@ -0,0 +1,47 @@ +/* + * File: AIHTest.h + * Author: nmset@netcourrier.com + * License : irrelevant + * + * Created on 11 septembre 2015, 16:57 + */ + +#ifndef AIHTEST_H +#define AIHTEST_H + +#include +#include "appindic.h" + +class AIHTest : public wxApp { +public: + AIHTest(); + virtual ~AIHTest(); + + bool OnInit(); + int OnExit(); +private: + +}; + +class AIHTestFrame : public wxFrame { +public: + AIHTestFrame(wxWindow * parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString); + virtual ~AIHTestFrame(); +private: + wxMenu * m_mainMenu; + wxMenu * m_removedMenu; + long m_itemID; + long m_subID; + AppIndicatorHelper * m_indicator; + + wxMenu * CreateMenu(); + // The menus is shown here for the purpose of the test. + // A real application needs not show this menu at all. + void ShowMenu(wxMouseEvent& evt); + void DeleteMenu(wxMouseEvent& evt); + void OnMenuItemClick(wxCommandEvent& evt); + void OnIdle(wxIdleEvent& evt); +}; + +#endif /* AIHTEST_H */ + diff --git a/ThirdParty/AppIndicatorHelper/CMakeLists.txt b/ThirdParty/AppIndicatorHelper/CMakeLists.txt new file mode 100644 index 0000000..08d442a --- /dev/null +++ b/ThirdParty/AppIndicatorHelper/CMakeLists.txt @@ -0,0 +1,29 @@ +# +# Stuff the average programmer needs to change +# +set(SRCS + appindic.cpp +) +set(HFILES + appindic.h +) +set(INCLUDE_DIRECTORIES ${BASE_INCLUDE_DIRECTORIES} + /usr/include/libappindicator3-0.1 + /usr/include/gtk-3.0 + /usr/include/glib-2.0 /usr/lib/x86_64-linux-gnu/glib-2.0/include + /usr/include/pango-1.0 + /usr/include/cairo + /usr/include/gdk-pixbuf-2.0 + /usr/include/atk-1.0) +set(LIBRARY_NAME AppIndicatorHelper) +if(WIN32) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};${wxWidgets_DEFINITIONS};/D_LIB) +endif(WIN32) +set(SRCS ${SRCS} ${HFILES}) + +add_definitions(${PREPROCESSOR_DEFINITIONS}) +include_directories(${INCLUDE_DIRECTORIES}) + +add_library(${LIBRARY_NAME} STATIC ${SRCS}) + +target_link_libraries(${LIBRARY_NAME} ${wxWidgets_LIBRARIES}) diff --git a/ThirdParty/AppIndicatorHelper/Win/AppIndicatorHelper.vcxproj b/ThirdParty/AppIndicatorHelper/Win/AppIndicatorHelper.vcxproj new file mode 100644 index 0000000..52730f7 --- /dev/null +++ b/ThirdParty/AppIndicatorHelper/Win/AppIndicatorHelper.vcxproj @@ -0,0 +1,129 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {19B6E028-60C5-36E7-9F5A-2A047410B7D0} + 10.0.16299.0 + Win32Proj + x64 + AppIndicatorHelper + NoUpgrade + + + + StaticLibrary + Unicode + v141 + + + StaticLibrary + Unicode + v141 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + F:\IT-Dim\trunk\ThirdParty\AppIndicatorHelper\Win\Debug\ + AppIndicatorHelper.dir\Debug\ + AppIndicatorHelper + .lib + F:\IT-Dim\trunk\ThirdParty\AppIndicatorHelper\Win\Release\ + AppIndicatorHelper.dir\Release\ + AppIndicatorHelper + .lib + + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;\usr\include\libappindicator3-0.1;\usr\include\gtk-3.0;\usr\include\glib-2.0;\usr\lib\x86_64-linux-gnu\glib-2.0\include;\usr\include\pango-1.0;\usr\include\cairo;\usr\include\gdk-pixbuf-2.0;\usr\include\atk-1.0;%(AdditionalIncludeDirectories) + Debug/ + EnableFastChecks + CompileAsCpp + ProgramDatabase + 4996 + Sync + Disabled + true + Disabled + NotUsing + MultiThreadedDebugDLL + true + Level3 + WIN32;_WINDOWS;__WXDEBUG__=1;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_LIB;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_LIB;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;\usr\include\libappindicator3-0.1;\usr\include\gtk-3.0;\usr\include\glib-2.0;\usr\lib\x86_64-linux-gnu\glib-2.0\include;\usr\include\pango-1.0;\usr\include\cairo;\usr\include\gdk-pixbuf-2.0;\usr\include\atk-1.0;%(AdditionalIncludeDirectories) + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;\usr\include\libappindicator3-0.1;\usr\include\gtk-3.0;\usr\include\glib-2.0;\usr\lib\x86_64-linux-gnu\glib-2.0\include;\usr\include\pango-1.0;\usr\include\cairo;\usr\include\gdk-pixbuf-2.0;\usr\include\atk-1.0;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + %(AdditionalOptions) /machine:x64 + + + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;\usr\include\libappindicator3-0.1;\usr\include\gtk-3.0;\usr\include\glib-2.0;\usr\lib\x86_64-linux-gnu\glib-2.0\include;\usr\include\pango-1.0;\usr\include\cairo;\usr\include\gdk-pixbuf-2.0;\usr\include\atk-1.0;%(AdditionalIncludeDirectories) + Release/ + CompileAsCpp + 4996 + Sync + AnySuitable + true + MaxSpeed + NotUsing + MultiThreadedDLL + true + Level3 + WIN32;_WINDOWS;NDEBUG;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;__WXDEBUG__=1;_LIB;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + + + WIN32;_WINDOWS;NDEBUG;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;__WXDEBUG__=1;_LIB;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;\usr\include\libappindicator3-0.1;\usr\include\gtk-3.0;\usr\include\glib-2.0;\usr\lib\x86_64-linux-gnu\glib-2.0\include;\usr\include\pango-1.0;\usr\include\cairo;\usr\include\gdk-pixbuf-2.0;\usr\include\atk-1.0;%(AdditionalIncludeDirectories) + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;\usr\include\libappindicator3-0.1;\usr\include\gtk-3.0;\usr\include\glib-2.0;\usr\lib\x86_64-linux-gnu\glib-2.0\include;\usr\include\pango-1.0;\usr\include\cairo;\usr\include\gdk-pixbuf-2.0;\usr\include\atk-1.0;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + %(AdditionalOptions) /machine:x64 + + + + + + + + + + + + \ No newline at end of file diff --git a/ThirdParty/AppIndicatorHelper/Win/AppIndicatorHelper.vcxproj.filters b/ThirdParty/AppIndicatorHelper/Win/AppIndicatorHelper.vcxproj.filters new file mode 100644 index 0000000..e9f1875 --- /dev/null +++ b/ThirdParty/AppIndicatorHelper/Win/AppIndicatorHelper.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + Source Files + + + + + Header Files + + + + + {51D244FA-C21C-3174-8217-FDB3769212C0} + + + {A07A887B-0B8A-3ED7-BD7F-43C26975F88D} + + + diff --git a/ThirdParty/AppIndicatorHelper/appindic.cpp b/ThirdParty/AppIndicatorHelper/appindic.cpp new file mode 100644 index 0000000..c89ac81 --- /dev/null +++ b/ThirdParty/AppIndicatorHelper/appindic.cpp @@ -0,0 +1,171 @@ +/* + * File: appindic.cpp + * Author: nmset@netcourrier.com (Work done as hobbyist) + * License: LGPL version 2.1 + * Copyright: nmset@netcourrier.com + * + * Created on 8 septembre 2015, 21:33 + */ + +#ifdef __WXGTK__ + +#include "appindic.h" + +IMPLEMENT_DYNAMIC_CLASS(AppIndicatorHelper, wxObject) + +AppIndicatorHelper::AppIndicatorHelper() +:wxObject() +{ + m_appMenu = NULL; +} + +AppIndicatorHelper::AppIndicatorHelper(const wxString& id, + const wxString& iconFileName, + const wxString& iconDirPath, + AppIndicatorCategory category) +:wxObject() +{ + m_appMenu = NULL; + printf("Icon: %s\n", iconFileName.utf8_str().data()); + m_indicator = app_indicator_new_with_path(id.utf8_str().data(), + iconFileName.utf8_str().data(), + category, + iconDirPath.utf8_str().data()); +} + +AppIndicatorHelper::AppIndicatorHelper(const wxString& id, const wxString& iconFullFilePath, AppIndicatorCategory category) +:wxObject() +{ + m_appMenu = NULL; + printf("Icon: %s\n", iconFullFilePath.utf8_str().data()); + m_indicator = app_indicator_new(id.utf8_str().data(), + iconFullFilePath.utf8_str().data(), + category); + if(m_indicator != NULL) + { + printf("Indicator created.\n"); + } +} + + +AppIndicatorHelper::~AppIndicatorHelper() +{ + g_object_unref((gpointer) m_indicator); +} + +// Main wrapper functions. +void AppIndicatorHelper::SetTitle(const wxString& title) +{ + app_indicator_set_title(m_indicator, title.utf8_str().data()); +} + +const wxString AppIndicatorHelper::GetTitle() const +{ + return app_indicator_get_title(m_indicator); +} + +void AppIndicatorHelper::SetStatus(AppIndicatorStatus status) +{ + app_indicator_set_status(m_indicator, status); +} + +const AppIndicatorStatus AppIndicatorHelper::GetStatus() const +{ + return app_indicator_get_status(m_indicator); +} + +// The main functionality of this class. +void AppIndicatorHelper::SetMenu(wxMenu * appMenu) +{ + wxASSERT_MSG(appMenu != NULL, _T("appMenu is NULL.")); + m_appMenu = appMenu; + app_indicator_set_menu(m_indicator, GTK_MENU(m_appMenu->m_menu)); +} + +// A series of secondary wrapper functions. +const wxString AppIndicatorHelper::GetId() const +{ + return app_indicator_get_id(m_indicator); +} + +const AppIndicatorCategory AppIndicatorHelper::GetCategory() const +{ + return app_indicator_get_category(m_indicator); +} + +void AppIndicatorHelper::SetIconDir(const wxString& iconDir) +{ + app_indicator_set_icon_theme_path(m_indicator, iconDir.utf8_str().data()); +} + +const wxString AppIndicatorHelper::GetIconDir() const +{ + return app_indicator_get_icon_theme_path(m_indicator); +} + +void AppIndicatorHelper::SetIcon(const wxString& iconFileName) +{ + app_indicator_set_icon(m_indicator, iconFileName.utf8_str().data()); +} + +const wxString AppIndicatorHelper::GetIcon() const +{ + return app_indicator_get_icon(m_indicator); +} + +void AppIndicatorHelper::SetIconFull(const wxString& iconFileName, const wxString& iconDesc) +{ + app_indicator_set_icon_full(m_indicator, iconFileName.utf8_str().data(), iconDesc.utf8_str().data()); +} + +const wxString AppIndicatorHelper::GetIconDesc() const +{ + return app_indicator_get_icon_desc(m_indicator); +} + +void AppIndicatorHelper::SetAttentionIcon(const wxString& iconFileName) +{ + app_indicator_set_attention_icon(m_indicator, iconFileName.utf8_str().data()); +} + +const wxString AppIndicatorHelper::GetAttentionIcon() const +{ + return app_indicator_get_attention_icon(m_indicator); +} + +void AppIndicatorHelper::SetAttentionIconFull(const wxString& iconFileName, const wxString& iconDesc) +{ + app_indicator_set_attention_icon_full(m_indicator, iconFileName.utf8_str().data(), iconDesc.utf8_str().data()); +} + +const wxString AppIndicatorHelper::GetAttentionIconDesc() const +{ + return app_indicator_get_attention_icon_desc(m_indicator); +} + +void AppIndicatorHelper::SetLabel(const wxString& label, const wxString& guide) +{ + app_indicator_set_label(m_indicator, label.utf8_str().data(), guide.utf8_str().data()); +} + +const wxString AppIndicatorHelper::GetLabel() const +{ + return app_indicator_get_label(m_indicator); +} + +const wxString AppIndicatorHelper::GetLabelGuide() const +{ + return app_indicator_get_label_guide(m_indicator); +} + +void AppIndicatorHelper::SetOrderingIndex(uint orderingIndex) +{ + app_indicator_set_ordering_index(m_indicator, orderingIndex); +} + +const uint AppIndicatorHelper::GetOrderingIndex() const +{ + return app_indicator_get_ordering_index(m_indicator); +} + +#endif diff --git a/ThirdParty/AppIndicatorHelper/appindic.h b/ThirdParty/AppIndicatorHelper/appindic.h new file mode 100644 index 0000000..b4d3294 --- /dev/null +++ b/ThirdParty/AppIndicatorHelper/appindic.h @@ -0,0 +1,156 @@ +/* + * File: appindic.h + * Author: nmset@netcourrier.com (Work done as hobbyist) + * License: LGPL version 2.1 + * Copyright: nmset@netcourrier.com + * + * Created on 8 septembre 2015, 21:33 + */ + +#ifdef __WXGTK__ +#ifndef APPINDICATORHELPER_H +#define APPINDICATORHELPER_H + +#include +#include + +/** + * This class is a helper for the libappindicator library. It's aim is to + * facilitate 'put an icon' in the system tray with wxWidgets, while hiding + * all C/GTK code. It is intended for WXGTK builds only. + * + * An application must pass a wxMenu object to an instance of + * this class, and it will show the GTK menu member of the wxMenu with a right + * click on the system tray icon. The passed wxMenu may or may not be accessed + * in the wxWidgets application window. + * + * The notion of a 'GTK icon theme' is downplayed. An icon is passed to this + * class with its complete file name and the directory path separately. + * Alternatively, a constructor is provided for a full path to the icon. + * + * The following libappindicator functions are simply ignored : + * app_indicator_set_secondary_activate_target, + * app_indicator_get_secondary_activate_target, + * app_indicator_build_menu_from_desktop. + * + * Note : If an application must delete the wxWidgets reference menu, it must + * delete the AppIndicatorHelper instance. + * + * This project is inspired from + * https://github.com/jarod/libappindicator-qt + * + * @return + */ + +class AppIndicatorHelper : public wxObject { + DECLARE_DYNAMIC_CLASS(AppIndicatorHelper); +public: + AppIndicatorHelper(); + /** + * + * @param id A unique identifier. + * @param iconFileName The filename of an icon, with its extension. + * @param iconDirPath The full path to the icon + * @param category The category of the icon, listed in AppIndicatorCategory + * enum. + */ + AppIndicatorHelper(const wxString& id, + const wxString& iconFileName, + const wxString& iconDirPath, + AppIndicatorCategory category); + /** + * + * @param id A unique identifier. + * @param iconFullFilePath The absolute path of an icon, with its extension. + * @param iconDirPath The full path to the icon + * @param category The category of the icon, listed in AppIndicatorCategory + * enum. + */ + AppIndicatorHelper(const wxString& id, + const wxString& iconFullFilePath, + AppIndicatorCategory category); + virtual ~AppIndicatorHelper(); + + void SetTitle(const wxString& title); + const wxString GetTitle() const; + void SetStatus(AppIndicatorStatus status); + const AppIndicatorStatus GetStatus() const; + /** + * + * @param appMenu A wxMenu managed in your application, which may or may not + * show this menu. + * + * No icon will appear in the system tray without a menu. + */ + void SetMenu(wxMenu * appMenu); + + const wxString GetId() const; + const AppIndicatorCategory GetCategory() const; + void SetIconDir(const wxString& iconDir); + const wxString GetIconDir() const; + void SetIcon(const wxString& iconFileName); + const wxString GetIcon() const; + /** + * + * @param iconFileName + * @param iconDesc From app-indicator.c + * The description of the regular icon that is shown for the indicator. + */ + void SetIconFull(const wxString& iconFileName, const wxString& iconDesc); + const wxString GetIconDesc() const; + /** + * + * @param iconFileName The file name with extension of an icon to use when + * the status is set to APP_INDICATOR_STATUS_ATTENTION. The icon must be in + * the directory given by GetIconDir(). + */ + void SetAttentionIcon(const wxString& iconFileName); + const wxString GetAttentionIcon() const; + void SetAttentionIconFull(const wxString& iconFileName, const wxString& iconDesc); + const wxString GetAttentionIconDesc() const; + /** + * + * @param label From app-indicator.c + * A label that can be shown next to the string in the application + * indicator. The label will not be shown unless there is an icon + * as well. The label is useful for numerical and other frequently + * updated information. In general, it shouldn't be shown unless a + * user requests it as it can take up a significant amount of space + * on the user's panel. This may not be shown in all visualizations. + * @param guide From app-indicator.c + * An optional string to provide guidance to the panel on how big + * the #AppIndicator:label string could get. If this is set correctly + * then the panel should never 'jiggle' as the string adjusts through + * out the range of options. For instance, if you were providing a + * percentage like "54% thrust" in #AppIndicator:label you'd want to + * set this string to "100% thrust" to ensure space when Scotty can + * get you enough power. + */ + void SetLabel(const wxString& label, const wxString& guide); + const wxString GetLabel() const; + const wxString GetLabelGuide()const; + /** + * + * @param orderingIndex From app-indicator.c + * The ordering index is an odd parameter, and if you think you don't need + * it you're probably right. In general, the application indicator try + * to place the applications in a recreatable place taking into account + * which category they're in to try and group them. But, there are some + * cases where you'd want to ensure indicators are next to each other. + * To do that you can override the generated ordering index and replace it + * with a new one. Again, you probably don't want to be doing this, but + * in case you do, this is the way. + */ + void SetOrderingIndex(uint orderingIndex); + const uint GetOrderingIndex() const; +private: + AppIndicator * m_indicator; + //The application's wxMenu. + wxWeakRef m_appMenu; + //m_appMenu.SetIndicator(m_indicator); + +}; + +#endif /* APPINDICATORHELPER_H */ +#endif + diff --git a/ThirdParty/AppIndicatorHelper/build.sh b/ThirdParty/AppIndicatorHelper/build.sh new file mode 100644 index 0000000..ac8c9bd --- /dev/null +++ b/ThirdParty/AppIndicatorHelper/build.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +$(wx-config --cxx --cppflags --libs) \ + -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include \ + -I/usr/lib/x86_64-linux-gnu/glib-2.0/include \ + -I/usr/include/libappindicator3-0.1 \ + -I/usr/include/gtk-3.0 \ + -I/usr/include/glib-2.0 \ + -I/usr/lib/glib-2.0/include \ + -I/usr/include/cairo \ + -I/usr/include/pango-1.0 \ + -I/usr/lib/gtk-2.0/include \ + -I/usr/include/gdk-pixbuf-2.0 \ + -I/usr/include/atk-1.0 \ + -lappindicator3 \ + -lgobject-2.0 \ + -lgtk-x11-2.0 \ + appindic.cpp AIHTest.cpp -o aihtest `wx-config --libs` -lappindicator3 -lgtk-3 -lgobject-2.0 -lgtk-x11-2.0 -Wno-deprecated-declarations + +exit 0 diff --git a/ThirdParty/AppIndicatorHelper/gpl-2.0.txt b/ThirdParty/AppIndicatorHelper/gpl-2.0.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/ThirdParty/AppIndicatorHelper/gpl-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/ThirdParty/AppIndicatorHelper/kde.png b/ThirdParty/AppIndicatorHelper/kde.png new file mode 100644 index 0000000..f8f543d Binary files /dev/null and b/ThirdParty/AppIndicatorHelper/kde.png differ diff --git a/ThirdParty/AppIndicatorHelper/lgpl-2.1.txt b/ThirdParty/AppIndicatorHelper/lgpl-2.1.txt new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/ThirdParty/AppIndicatorHelper/lgpl-2.1.txt @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/ThirdParty/AppIndicatorHelper/stop.xpm b/ThirdParty/AppIndicatorHelper/stop.xpm new file mode 100644 index 0000000..fc2a7ab --- /dev/null +++ b/ThirdParty/AppIndicatorHelper/stop.xpm @@ -0,0 +1,400 @@ +/* XPM */ +static char * stop_xpm[] = { +"32 32 365 2", +" c None", +". c #AB2F2F", +"+ c #BF4242", +"@ c #BE4242", +"# c #BD4040", +"$ c #BD3F3F", +"% c #B33434", +"& c #C14545", +"* c #EC7676", +"= c #E35B5B", +"- c #E35A5A", +"; c #E35959", +"> c #E25858", +", c #E25656", +"' c #E25454", +") c #E96666", +"! c #CE4F4F", +"~ c #C24747", +"{ c #EC7272", +"] c #D94141", +"^ c #D94040", +"/ c #D93F3F", +"( c #D93E3E", +"_ c #D83D3D", +": c #D83C3C", +"< c #D83B3B", +"[ c #D83A3A", +"} c #E65E5E", +"| c #CD4D4D", +"1 c #C44949", +"2 c #EC7373", +"3 c #D94242", +"4 c #E65D5D", +"5 c #CC4949", +"6 c #C64B4B", +"7 c #EC7171", +"8 c #DA4343", +"9 c #DA4444", +"0 c #D83939", +"a c #E65C5C", +"b c #C84545", +"c c #EB7171", +"d c #DA4545", +"e c #D73838", +"f c #E55B5B", +"g c #C64242", +"h c #C64D4D", +"i c #EB7070", +"j c #DB4343", +"k c #DF3D3D", +"l c #DA4646", +"m c #D93B3B", +"n c #DE3232", +"o c #D73A3A", +"p c #D63838", +"q c #D53737", +"r c #E65959", +"s c #C43D3D", +"t c #C84F4F", +"u c #EB6E6E", +"v c #F32424", +"w c #F91B1B", +"x c #E23A3A", +"y c #DA3D3D", +"z c #F22424", +"A c #F91C1C", +"B c #E13030", +"C c #D63A3A", +"D c #D53939", +"E c #D33737", +"F c #D23636", +"G c #E35858", +"H c #C13B3B", +"I c #E96C6C", +"J c #DB4141", +"K c #F32525", +"L c #E1AAAA", +"M c #DBD0D0", +"N c #F43434", +"O c #E23939", +"P c #DA3E3E", +"Q c #E4A4A4", +"R c #DBD3D3", +"S c #F23838", +"T c #E02F2F", +"U c #D43939", +"V c #D13636", +"W c #D03535", +"X c #E35555", +"Y c #BD3737", +"Z c #950E0E", +"` c #F07E7E", +" . c #F81616", +".. c #DBDADA", +"+. c #DCDBDB", +"@. c #DED3D3", +"#. c #F43535", +"$. c #E23737", +"%. c #DA3F3F", +"&. c #F32626", +"*. c #E6A7A7", +"=. c #DDDCDC", +"-. c #DCD4D4", +";. c #F72A2A", +">. c #DC2F2F", +",. c #D23737", +"'. c #CE3333", +"). c #E75E5E", +"!. c #910A0A", +"~. c #970D0D", +"{. c #EC2C2C", +"]. c #EC6D6D", +"^. c #DEDDDD", +"/. c #DFDEDE", +"(. c #E1D6D6", +"_. c #F53B3B", +":. c #E13838", +"<. c #F32E2E", +"[. c #E8ABAB", +"}. c #E1E0E0", +"|. c #E0DFDF", +"1. c #E3BCBC", +"2. c #F33333", +"3. c #D73535", +"4. c #D13737", +"5. c #D03636", +"6. c #CF3434", +"7. c #950C0C", +"8. c #EC3333", +"9. c #ED7474", +"0. c #E2E1E1", +"a. c #E3E2E2", +"b. c #E5DBDB", +"c. c #F54545", +"d. c #F92727", +"e. c #EAB0B0", +"f. c #E4E3E3", +"g. c #E6C1C1", +"h. c #F43C3C", +"i. c #D53838", +"j. c #CF3535", +"k. c #CE3434", +"l. c #CD3333", +"m. c #E15454", +"n. c #930A0A", +"o. c #EC3838", +"p. c #EF7C7C", +"q. c #E5E4E4", +"r. c #E6E5E5", +"s. c #E8DEDE", +"t. c #EBC9C9", +"u. c #E7E6E6", +"v. c #E9C5C5", +"w. c #F44343", +"x. c #D13838", +"y. c #D03737", +"z. c #CF3636", +"A. c #CB3232", +"B. c #E05454", +"C. c #ED3F3F", +"D. c #F18484", +"E. c #E8E7E7", +"F. c #E9E8E8", +"G. c #EAE9E9", +"H. c #ECCACA", +"I. c #F54C4C", +"J. c #CE3535", +"K. c #CD3434", +"L. c #CB3333", +"M. c #CA3232", +"N. c #DF5151", +"O. c #EC4444", +"P. c #F57D7D", +"Q. c #EBEAEA", +"R. c #ECEBEB", +"S. c #EED8D8", +"T. c #F94C4C", +"U. c #D53A3A", +"V. c #CC2929", +"W. c #C92020", +"X. c #C51919", +"Y. c #C41616", +"Z. c #C21212", +"`. c #C11414", +" + c #DB3939", +".+ c #900404", +"++ c #EB6F6F", +"@+ c #D93C3C", +"#+ c #F45050", +"$+ c #F1BFBF", +"%+ c #EEEDED", +"&+ c #EFEEEE", +"*+ c #EFE7E7", +"=+ c #F76969", +"-+ c #D72A2A", +";+ c #C60C0C", +">+ c #C20101", +",+ c #C10000", +"'+ c #BF0000", +")+ c #BE0000", +"!+ c #BD0000", +"~+ c #BC0000", +"{+ c #BB0000", +"]+ c #D82727", +"^+ c #8E0000", +"/+ c #960C0C", +"(+ c #D73737", +"_+ c #D93A3A", +":+ c #F45757", +"<+ c #F1C3C3", +"[+ c #F0EFEF", +"}+ c #F1F0F0", +"|+ c #F2F1F1", +"1+ c #F1E9E9", +"2+ c #F56E6E", +"3+ c #D01414", +"4+ c #C00000", +"5+ c #BA0000", +"6+ c #D72626", +"7+ c #EB6D6D", +"8+ c #D73636", +"9+ c #D83838", +"0+ c #F35D5D", +"a+ c #F1C5C5", +"b+ c #F3F2F2", +"c+ c #F6DADA", +"d+ c #F7A4A4", +"e+ c #F4F3F3", +"f+ c #F1EAEA", +"g+ c #F57777", +"h+ c #CD1717", +"i+ c #B90000", +"j+ c #D72525", +"k+ c #EB6C6C", +"l+ c #D73434", +"m+ c #F36363", +"n+ c #F0C7C7", +"o+ c #F7DDDD", +"p+ c #F46969", +"q+ c #E84848", +"r+ c #F7A6A6", +"s+ c #F5F4F4", +"t+ c #F48080", +"u+ c #CC1A1A", +"v+ c #B80000", +"w+ c #D62424", +"x+ c #EB6969", +"y+ c #D63333", +"z+ c #F76868", +"A+ c #EFC7C7", +"B+ c #EDECEC", +"C+ c #F7DFDF", +"D+ c #F46F6F", +"E+ c #C90909", +"F+ c #C40000", +"G+ c #E44A4A", +"H+ c #F7ADAD", +"I+ c #F6F5F5", +"J+ c #EFE9E9", +"K+ c #F88686", +"L+ c #C81919", +"M+ c #B60000", +"N+ c #D42323", +"O+ c #8D0000", +"P+ c #910606", +"Q+ c #E76A6A", +"R+ c #DD4444", +"S+ c #D63232", +"T+ c #ED6363", +"U+ c #F2AFAF", +"V+ c #F5DEDE", +"W+ c #F47777", +"X+ c #C20000", +"Y+ c #E25050", +"Z+ c #F7B2B2", +"`+ c #F1E1E1", +" @ c #F38383", +".@ c #C41414", +"+@ c #B60101", +"@@ c #DA2727", +"#@ c #980E0E", +"$@ c #E46464", +"%@ c #DE4343", +"&@ c #D63131", +"*@ c #D52E2E", +"=@ c #D12222", +"-@ c #E95D5D", +";@ c #F3B3B3", +">@ c #F3DFDF", +",@ c #F47E7E", +"'@ c #C90A0A", +")@ c #C30000", +"!@ c #E25757", +"~@ c #F5B7B7", +"{@ c #F4E5E5", +"]@ c #F28B8B", +"^@ c #C10E0E", +"/@ c #B70000", +"(@ c #D21F1F", +"_@ c #AE1111", +":@ c #950A0A", +"<@ c #E14C4C", +"[@ c #D82020", +"}@ c #CC0505", +"|@ c #CA0000", +"1@ c #C90000", +"2@ c #C80000", +"3@ c #E75D5D", +"4@ c #F98A8A", +"5@ c #C90B0B", +"6@ c #E05A5A", +"7@ c #FA9494", +"8@ c #D32121", +"9@ c #AB1010", +"0@ c #910404", +"a@ c #DD3F3F", +"b@ c #D31616", +"c@ c #C70000", +"d@ c #C60000", +"e@ c #D32222", +"f@ c #A80F0F", +"g@ c #910303", +"h@ c #DC3D3D", +"i@ c #D21515", +"j@ c #B70202", +"k@ c #A50D0D", +"l@ c #DB3A3A", +"m@ c #CF1515", +"n@ c #B70303", +"o@ c #D52424", +"p@ c #A20C0C", +"q@ c #8D0303", +"r@ c #D83737", +"s@ c #CF1414", +"t@ c #B90303", +"u@ c #D32424", +"v@ c #9D0B0B", +"w@ c #880303", +"x@ c #D63434", +"y@ c #CD1313", +"z@ c #B80404", +"A@ c #D42626", +"B@ c #980A0A", +"C@ c #840202", +"D@ c #CD2D2D", +"E@ c #D43030", +"F@ c #D32F2F", +"G@ c #D32D2D", +"H@ c #D12D2D", +"I@ c #D12B2B", +"J@ c #D12A2A", +"K@ c #D02828", +"L@ c #D02727", +"M@ c #D02626", +"N@ c #CF2424", +"O@ c #CF2626", +"P@ c #940909", +"Q@ c #560000", +"R@ c #510000", +"S@ c #4F0000", +"T@ c #4C0000", +"U@ c #4B0000", +"V@ c #4A0000", +"W@ c #4E0000", +"X@ c #540000", +" . + + + + + + @ # # $ % ", +" & * = = - - - ; > > , ' ) ! ", +" ~ { ] ^ ^ ^ ^ / ( ( _ : < [ } | ", +" 1 2 3 3 3 3 3 ] ^ ^ / ( _ : < [ 4 5 ", +" 6 7 3 8 8 9 8 8 3 3 ] ^ / ( : < [ 0 a b ", +" 6 c 3 8 9 d d d 9 9 8 3 ] / ( _ : < 0 e f g ", +" h i 3 8 9 d j k l l d 8 3 ] ^ / m n < o p q r s ", +" t u ] 3 8 d j v w x l d 9 8 ] ^ y z A B C D E F G H ", +" t I / ] 3 8 J K L M N O d 9 3 ] P z Q R S T U E V W X Y ", +" Z ` ( / ^ ] 3 .L ..+.@.#.$.8 3 %.&.*.=.+.-.;.>.,.V W '.).!. ", +" ~.2 _ ( ^ ] 3 {.].=.^./.(._.:.%.<.[.}.|./.1.2.3.4.5.6.'., 7. ", +" ~.{ _ ( / / ^ ] 8.9.}.0.a.b.c.d.e.f.a.0.g.h.i.4.5.j.k.l.m.n. ", +" ~.{ : _ _ ( / ^ ^ o.p.f.q.r.s.t.u.r.r.v.w.i.x.y.z.k.l.A.B.n. ", +" ~.{ < < : _ ( ( / / C.D.E.F.F.G.F.F.H.I.D x.y.z.J.K.L.M.N.n. ", +" ~.7 0 [ < : : _ _ _ _ O.P.Q.R.R.R.S.T.U.x.6.V.W.X.Y.Z.`. +.+ ", +" ~.++e 0 [ [ < < < : @+#+$+%+&+&+&+*+=+-+;+>+,+'+)+!+~+{+]+^+ ", +" /+++(+e e 0 0 [ [ _+:+<+&+[+}+|+}+}+1+2+3+4+'+)+!+~+{+5+6+^+ ", +" /+7+8+8+(+(+e e 9+0+a+&+}+b+c+d+e+b+|+f+g+h+)+!+~+{+5+i+j+^+ ", +" /+k+l+3.3.8+8+9+m+n+&+}+b+o+p+q+r+s+e+|+f+t+u+~+{+5+i+v+w+^+ ", +" /+x+y+y+l+l+3.z+A+B+[+|+C+D+E+F+G+H+I+b+}+J+K+L+5+i+v+M+N+O+ ", +" P+Q+R+S+S+y+y+T+U+%+[+V+W+E+F+X+,+Y+Z+e+|+`+ @.@i+v+M++@@@O+ ", +" #@$@%@&@&@*@=@-@;@>@,@'@)@X+,+4+'+!@~@{@]@^@i+/@M++@(@_@ ", +" :@<@[@}@|@1@2@3@4@5@)@X+,+4+'+)+!+6@7@^@i+/@M++@8@9@ ", +" 0@a@b@1@2@c@d@F+)@X+,+4+'+)+!+~+{+5+v+/@M++@e@f@ ", +" g@h@i@c@d@F+)@X+,+4+'+)+!+~+{+5+v+/@M+j@N+k@ ", +" g@l@m@F+)@X+,+4+'+)+!+~+{+i+v+/@M+n@o@p@ ", +" q@r@s@X+,+4+'+)+!+~+5+i+v+/@M+t@u@v@ ", +" w@x@y@4+'+)+!+~+5+i+v+/@M+z@A@B@ ", +" C@D@E@F@G@H@I@J@K@L@M@N@O@P@ ", +" Q@R@S@T@U@V@V@U@W@R@X@ ", +" ", +" "}; diff --git a/ThirdParty/AppIndicatorHelper/tags b/ThirdParty/AppIndicatorHelper/tags new file mode 100644 index 0000000..230374d --- /dev/null +++ b/ThirdParty/AppIndicatorHelper/tags @@ -0,0 +1,175 @@ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ +!_TAG_PROGRAM_NAME Exuberant Ctags // +!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ +!_TAG_PROGRAM_VERSION 5.9~svn20110310 // +AIHTEST_H AIHTest.h 10;" d +AIHTest AIHTest.cpp /^AIHTest::AIHTest()$/;" f class:AIHTest signature:() +AIHTest AIHTest.h /^ AIHTest();$/;" p class:AIHTest access:public signature:() +AIHTest AIHTest.h /^class AIHTest : public wxApp {$/;" c inherits:wxApp +AIHTest::AIHTest AIHTest.cpp /^AIHTest::AIHTest()$/;" f class:AIHTest signature:() +AIHTest::AIHTest AIHTest.h /^ AIHTest();$/;" p class:AIHTest access:public signature:() +AIHTest::OnExit AIHTest.cpp /^int AIHTest::OnExit()$/;" f class:AIHTest signature:() +AIHTest::OnExit AIHTest.h /^ int OnExit();$/;" p class:AIHTest access:public signature:() +AIHTest::OnInit AIHTest.cpp /^bool AIHTest::OnInit()$/;" f class:AIHTest signature:() +AIHTest::OnInit AIHTest.h /^ bool OnInit();$/;" p class:AIHTest access:public signature:() +AIHTest::~AIHTest AIHTest.cpp /^AIHTest::~AIHTest()$/;" f class:AIHTest signature:() +AIHTest::~AIHTest AIHTest.h /^ virtual ~AIHTest();$/;" p class:AIHTest access:public signature:() +AIHTestFrame AIHTest.cpp /^AIHTestFrame::AIHTestFrame(wxWindow* parent, wxWindowID id, const wxString& title)$/;" f class:AIHTestFrame signature:(wxWindow* parent, wxWindowID id, const wxString& title) +AIHTestFrame AIHTest.h /^ AIHTestFrame(wxWindow * parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString);$/;" p class:AIHTestFrame access:public signature:(wxWindow * parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString) +AIHTestFrame AIHTest.h /^class AIHTestFrame : public wxFrame {$/;" c inherits:wxFrame +AIHTestFrame::AIHTestFrame AIHTest.cpp /^AIHTestFrame::AIHTestFrame(wxWindow* parent, wxWindowID id, const wxString& title)$/;" f class:AIHTestFrame signature:(wxWindow* parent, wxWindowID id, const wxString& title) +AIHTestFrame::AIHTestFrame AIHTest.h /^ AIHTestFrame(wxWindow * parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString);$/;" p class:AIHTestFrame access:public signature:(wxWindow * parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString) +AIHTestFrame::CreateMenu AIHTest.cpp /^wxMenu* AIHTestFrame::CreateMenu()$/;" f class:AIHTestFrame signature:() +AIHTestFrame::CreateMenu AIHTest.h /^ wxMenu * CreateMenu();$/;" p class:AIHTestFrame access:private signature:() +AIHTestFrame::DeleteMenu AIHTest.cpp /^void AIHTestFrame::DeleteMenu(wxMouseEvent& evt)$/;" f class:AIHTestFrame signature:(wxMouseEvent& evt) +AIHTestFrame::DeleteMenu AIHTest.h /^ void DeleteMenu(wxMouseEvent& evt);$/;" p class:AIHTestFrame access:private signature:(wxMouseEvent& evt) +AIHTestFrame::OnIdle AIHTest.cpp /^void AIHTestFrame::OnIdle(wxIdleEvent& evt)$/;" f class:AIHTestFrame signature:(wxIdleEvent& evt) +AIHTestFrame::OnIdle AIHTest.h /^ void OnIdle(wxIdleEvent& evt);$/;" p class:AIHTestFrame access:private signature:(wxIdleEvent& evt) +AIHTestFrame::OnMenuItemClick AIHTest.cpp /^void AIHTestFrame::OnMenuItemClick(wxCommandEvent& evt)$/;" f class:AIHTestFrame signature:(wxCommandEvent& evt) +AIHTestFrame::OnMenuItemClick AIHTest.h /^ void OnMenuItemClick(wxCommandEvent& evt);$/;" p class:AIHTestFrame access:private signature:(wxCommandEvent& evt) +AIHTestFrame::ShowMenu AIHTest.cpp /^void AIHTestFrame::ShowMenu(wxMouseEvent& evt)$/;" f class:AIHTestFrame signature:(wxMouseEvent& evt) +AIHTestFrame::ShowMenu AIHTest.h /^ void ShowMenu(wxMouseEvent& evt);$/;" p class:AIHTestFrame access:private signature:(wxMouseEvent& evt) +AIHTestFrame::m_indicator AIHTest.h /^ AppIndicatorHelper * m_indicator;$/;" m class:AIHTestFrame access:private +AIHTestFrame::m_itemID AIHTest.h /^ long m_itemID;$/;" m class:AIHTestFrame access:private +AIHTestFrame::m_mainMenu AIHTest.h /^ wxMenu * m_mainMenu;$/;" m class:AIHTestFrame access:private +AIHTestFrame::m_removedMenu AIHTest.h /^ wxMenu * m_removedMenu;$/;" m class:AIHTestFrame access:private +AIHTestFrame::m_subID AIHTest.h /^ long m_subID;$/;" m class:AIHTestFrame access:private +AIHTestFrame::~AIHTestFrame AIHTest.cpp /^AIHTestFrame::~AIHTestFrame()$/;" f class:AIHTestFrame signature:() +AIHTestFrame::~AIHTestFrame AIHTest.h /^ virtual ~AIHTestFrame();$/;" p class:AIHTestFrame access:public signature:() +APPINDICATORHELPER_H appindic.h 12;" d +AppIndicatorHelper appindic.cpp /^AppIndicatorHelper::AppIndicatorHelper()$/;" f class:AppIndicatorHelper signature:() +AppIndicatorHelper appindic.cpp /^AppIndicatorHelper::AppIndicatorHelper(const wxString& id, const wxString& iconFullFilePath, AppIndicatorCategory category)$/;" f class:AppIndicatorHelper signature:(const wxString& id, const wxString& iconFullFilePath, AppIndicatorCategory category) +AppIndicatorHelper appindic.cpp /^AppIndicatorHelper::AppIndicatorHelper(const wxString& id,$/;" f class:AppIndicatorHelper signature:(const wxString& id, const wxString& iconFileName, const wxString& iconDirPath, AppIndicatorCategory category) +AppIndicatorHelper appindic.h /^ AppIndicatorHelper();$/;" p class:AppIndicatorHelper access:public signature:() +AppIndicatorHelper appindic.h /^ AppIndicatorHelper(const wxString& id,$/;" p class:AppIndicatorHelper access:public signature:(const wxString& id, const wxString& iconFileName, const wxString& iconDirPath, AppIndicatorCategory category) +AppIndicatorHelper appindic.h /^ AppIndicatorHelper(const wxString& id,$/;" p class:AppIndicatorHelper access:public signature:(const wxString& id, const wxString& iconFullFilePath, AppIndicatorCategory category) +AppIndicatorHelper appindic.h /^class AppIndicatorHelper : public wxObject {$/;" c inherits:wxObject +AppIndicatorHelper::AppIndicatorHelper appindic.cpp /^AppIndicatorHelper::AppIndicatorHelper()$/;" f class:AppIndicatorHelper signature:() +AppIndicatorHelper::AppIndicatorHelper appindic.cpp /^AppIndicatorHelper::AppIndicatorHelper(const wxString& id, const wxString& iconFullFilePath, AppIndicatorCategory category)$/;" f class:AppIndicatorHelper signature:(const wxString& id, const wxString& iconFullFilePath, AppIndicatorCategory category) +AppIndicatorHelper::AppIndicatorHelper appindic.cpp /^AppIndicatorHelper::AppIndicatorHelper(const wxString& id,$/;" f class:AppIndicatorHelper signature:(const wxString& id, const wxString& iconFileName, const wxString& iconDirPath, AppIndicatorCategory category) +AppIndicatorHelper::AppIndicatorHelper appindic.h /^ AppIndicatorHelper();$/;" p class:AppIndicatorHelper access:public signature:() +AppIndicatorHelper::AppIndicatorHelper appindic.h /^ AppIndicatorHelper(const wxString& id,$/;" p class:AppIndicatorHelper access:public signature:(const wxString& id, const wxString& iconFileName, const wxString& iconDirPath, AppIndicatorCategory category) +AppIndicatorHelper::AppIndicatorHelper appindic.h /^ AppIndicatorHelper(const wxString& id,$/;" p class:AppIndicatorHelper access:public signature:(const wxString& id, const wxString& iconFullFilePath, AppIndicatorCategory category) +AppIndicatorHelper::DECLARE_DYNAMIC_CLASS appindic.h /^ DECLARE_DYNAMIC_CLASS(AppIndicatorHelper);$/;" p class:AppIndicatorHelper access:private signature:(AppIndicatorHelper) +AppIndicatorHelper::GetAttentionIcon appindic.cpp /^const wxString AppIndicatorHelper::GetAttentionIcon() const$/;" f class:AppIndicatorHelper signature:() const +AppIndicatorHelper::GetAttentionIcon appindic.h /^ const wxString GetAttentionIcon() const;$/;" p class:AppIndicatorHelper access:public signature:() const +AppIndicatorHelper::GetAttentionIconDesc appindic.cpp /^const wxString AppIndicatorHelper::GetAttentionIconDesc() const$/;" f class:AppIndicatorHelper signature:() const +AppIndicatorHelper::GetAttentionIconDesc appindic.h /^ const wxString GetAttentionIconDesc() const;$/;" p class:AppIndicatorHelper access:public signature:() const +AppIndicatorHelper::GetCategory appindic.cpp /^const AppIndicatorCategory AppIndicatorHelper::GetCategory() const$/;" f class:AppIndicatorHelper signature:() const +AppIndicatorHelper::GetCategory appindic.h /^ const AppIndicatorCategory GetCategory() const;$/;" p class:AppIndicatorHelper access:public signature:() const +AppIndicatorHelper::GetIcon appindic.cpp /^const wxString AppIndicatorHelper::GetIcon() const$/;" f class:AppIndicatorHelper signature:() const +AppIndicatorHelper::GetIcon appindic.h /^ const wxString GetIcon() const;$/;" p class:AppIndicatorHelper access:public signature:() const +AppIndicatorHelper::GetIconDesc appindic.cpp /^const wxString AppIndicatorHelper::GetIconDesc() const$/;" f class:AppIndicatorHelper signature:() const +AppIndicatorHelper::GetIconDesc appindic.h /^ const wxString GetIconDesc() const;$/;" p class:AppIndicatorHelper access:public signature:() const +AppIndicatorHelper::GetIconDir appindic.cpp /^const wxString AppIndicatorHelper::GetIconDir() const$/;" f class:AppIndicatorHelper signature:() const +AppIndicatorHelper::GetIconDir appindic.h /^ const wxString GetIconDir() const;$/;" p class:AppIndicatorHelper access:public signature:() const +AppIndicatorHelper::GetId appindic.cpp /^const wxString AppIndicatorHelper::GetId() const$/;" f class:AppIndicatorHelper signature:() const +AppIndicatorHelper::GetId appindic.h /^ const wxString GetId() const;$/;" p class:AppIndicatorHelper access:public signature:() const +AppIndicatorHelper::GetLabel appindic.cpp /^const wxString AppIndicatorHelper::GetLabel() const$/;" f class:AppIndicatorHelper signature:() const +AppIndicatorHelper::GetLabel appindic.h /^ const wxString GetLabel() const;$/;" p class:AppIndicatorHelper access:public signature:() const +AppIndicatorHelper::GetLabelGuide appindic.cpp /^const wxString AppIndicatorHelper::GetLabelGuide() const$/;" f class:AppIndicatorHelper signature:() const +AppIndicatorHelper::GetLabelGuide appindic.h /^ const wxString GetLabelGuide()const;$/;" p class:AppIndicatorHelper access:public signature:() const +AppIndicatorHelper::GetOrderingIndex appindic.cpp /^const uint AppIndicatorHelper::GetOrderingIndex() const$/;" f class:AppIndicatorHelper signature:() const +AppIndicatorHelper::GetOrderingIndex appindic.h /^ const uint GetOrderingIndex() const;$/;" p class:AppIndicatorHelper access:public signature:() const +AppIndicatorHelper::GetStatus appindic.cpp /^const AppIndicatorStatus AppIndicatorHelper::GetStatus() const$/;" f class:AppIndicatorHelper signature:() const +AppIndicatorHelper::GetStatus appindic.h /^ const AppIndicatorStatus GetStatus() const;$/;" p class:AppIndicatorHelper access:public signature:() const +AppIndicatorHelper::GetTitle appindic.cpp /^const wxString AppIndicatorHelper::GetTitle() const$/;" f class:AppIndicatorHelper signature:() const +AppIndicatorHelper::GetTitle appindic.h /^ const wxString GetTitle() const;$/;" p class:AppIndicatorHelper access:public signature:() const +AppIndicatorHelper::SetAttentionIcon appindic.cpp /^void AppIndicatorHelper::SetAttentionIcon(const wxString& iconFileName)$/;" f class:AppIndicatorHelper signature:(const wxString& iconFileName) +AppIndicatorHelper::SetAttentionIcon appindic.h /^ void SetAttentionIcon(const wxString& iconFileName);$/;" p class:AppIndicatorHelper access:public signature:(const wxString& iconFileName) +AppIndicatorHelper::SetAttentionIconFull appindic.cpp /^void AppIndicatorHelper::SetAttentionIconFull(const wxString& iconFileName, const wxString& iconDesc)$/;" f class:AppIndicatorHelper signature:(const wxString& iconFileName, const wxString& iconDesc) +AppIndicatorHelper::SetAttentionIconFull appindic.h /^ void SetAttentionIconFull(const wxString& iconFileName, const wxString& iconDesc);$/;" p class:AppIndicatorHelper access:public signature:(const wxString& iconFileName, const wxString& iconDesc) +AppIndicatorHelper::SetIcon appindic.cpp /^void AppIndicatorHelper::SetIcon(const wxString& iconFileName)$/;" f class:AppIndicatorHelper signature:(const wxString& iconFileName) +AppIndicatorHelper::SetIcon appindic.h /^ void SetIcon(const wxString& iconFileName);$/;" p class:AppIndicatorHelper access:public signature:(const wxString& iconFileName) +AppIndicatorHelper::SetIconDir appindic.cpp /^void AppIndicatorHelper::SetIconDir(const wxString& iconDir)$/;" f class:AppIndicatorHelper signature:(const wxString& iconDir) +AppIndicatorHelper::SetIconDir appindic.h /^ void SetIconDir(const wxString& iconDir);$/;" p class:AppIndicatorHelper access:public signature:(const wxString& iconDir) +AppIndicatorHelper::SetIconFull appindic.cpp /^void AppIndicatorHelper::SetIconFull(const wxString& iconFileName, const wxString& iconDesc)$/;" f class:AppIndicatorHelper signature:(const wxString& iconFileName, const wxString& iconDesc) +AppIndicatorHelper::SetIconFull appindic.h /^ void SetIconFull(const wxString& iconFileName, const wxString& iconDesc);$/;" p class:AppIndicatorHelper access:public signature:(const wxString& iconFileName, const wxString& iconDesc) +AppIndicatorHelper::SetLabel appindic.cpp /^void AppIndicatorHelper::SetLabel(const wxString& label, const wxString& guide)$/;" f class:AppIndicatorHelper signature:(const wxString& label, const wxString& guide) +AppIndicatorHelper::SetLabel appindic.h /^ void SetLabel(const wxString& label, const wxString& guide);$/;" p class:AppIndicatorHelper access:public signature:(const wxString& label, const wxString& guide) +AppIndicatorHelper::SetMenu appindic.cpp /^void AppIndicatorHelper::SetMenu(wxMenu * appMenu)$/;" f class:AppIndicatorHelper signature:(wxMenu * appMenu) +AppIndicatorHelper::SetMenu appindic.h /^ void SetMenu(wxMenu * appMenu);$/;" p class:AppIndicatorHelper access:public signature:(wxMenu * appMenu) +AppIndicatorHelper::SetOrderingIndex appindic.cpp /^void AppIndicatorHelper::SetOrderingIndex(uint orderingIndex)$/;" f class:AppIndicatorHelper signature:(uint orderingIndex) +AppIndicatorHelper::SetOrderingIndex appindic.h /^ void SetOrderingIndex(uint orderingIndex);$/;" p class:AppIndicatorHelper access:public signature:(uint orderingIndex) +AppIndicatorHelper::SetStatus appindic.cpp /^void AppIndicatorHelper::SetStatus(AppIndicatorStatus status)$/;" f class:AppIndicatorHelper signature:(AppIndicatorStatus status) +AppIndicatorHelper::SetStatus appindic.h /^ void SetStatus(AppIndicatorStatus status);$/;" p class:AppIndicatorHelper access:public signature:(AppIndicatorStatus status) +AppIndicatorHelper::SetTitle appindic.cpp /^void AppIndicatorHelper::SetTitle(const wxString& title)$/;" f class:AppIndicatorHelper signature:(const wxString& title) +AppIndicatorHelper::SetTitle appindic.h /^ void SetTitle(const wxString& title);$/;" p class:AppIndicatorHelper access:public signature:(const wxString& title) +AppIndicatorHelper::m_appMenu appindic.h /^ wxWeakRef m_appMenu;$/;" m class:AppIndicatorHelper access:private +AppIndicatorHelper::m_indicator appindic.h /^ AppIndicator * m_indicator;$/;" m class:AppIndicatorHelper access:private +AppIndicatorHelper::~AppIndicatorHelper appindic.cpp /^AppIndicatorHelper::~AppIndicatorHelper()$/;" f class:AppIndicatorHelper signature:() +AppIndicatorHelper::~AppIndicatorHelper appindic.h /^ virtual ~AppIndicatorHelper();$/;" p class:AppIndicatorHelper access:public signature:() +CreateMenu AIHTest.cpp /^wxMenu* AIHTestFrame::CreateMenu()$/;" f class:AIHTestFrame signature:() +CreateMenu AIHTest.h /^ wxMenu * CreateMenu();$/;" p class:AIHTestFrame access:private signature:() +DECLARE_DYNAMIC_CLASS appindic.h /^ DECLARE_DYNAMIC_CLASS(AppIndicatorHelper);$/;" p class:AppIndicatorHelper access:private signature:(AppIndicatorHelper) +DeleteMenu AIHTest.cpp /^void AIHTestFrame::DeleteMenu(wxMouseEvent& evt)$/;" f class:AIHTestFrame signature:(wxMouseEvent& evt) +DeleteMenu AIHTest.h /^ void DeleteMenu(wxMouseEvent& evt);$/;" p class:AIHTestFrame access:private signature:(wxMouseEvent& evt) +GetAttentionIcon appindic.cpp /^const wxString AppIndicatorHelper::GetAttentionIcon() const$/;" f class:AppIndicatorHelper signature:() const +GetAttentionIcon appindic.h /^ const wxString GetAttentionIcon() const;$/;" p class:AppIndicatorHelper access:public signature:() const +GetAttentionIconDesc appindic.cpp /^const wxString AppIndicatorHelper::GetAttentionIconDesc() const$/;" f class:AppIndicatorHelper signature:() const +GetAttentionIconDesc appindic.h /^ const wxString GetAttentionIconDesc() const;$/;" p class:AppIndicatorHelper access:public signature:() const +GetCategory appindic.cpp /^const AppIndicatorCategory AppIndicatorHelper::GetCategory() const$/;" f class:AppIndicatorHelper signature:() const +GetCategory appindic.h /^ const AppIndicatorCategory GetCategory() const;$/;" p class:AppIndicatorHelper access:public signature:() const +GetIcon appindic.cpp /^const wxString AppIndicatorHelper::GetIcon() const$/;" f class:AppIndicatorHelper signature:() const +GetIcon appindic.h /^ const wxString GetIcon() const;$/;" p class:AppIndicatorHelper access:public signature:() const +GetIconDesc appindic.cpp /^const wxString AppIndicatorHelper::GetIconDesc() const$/;" f class:AppIndicatorHelper signature:() const +GetIconDesc appindic.h /^ const wxString GetIconDesc() const;$/;" p class:AppIndicatorHelper access:public signature:() const +GetIconDir appindic.cpp /^const wxString AppIndicatorHelper::GetIconDir() const$/;" f class:AppIndicatorHelper signature:() const +GetIconDir appindic.h /^ const wxString GetIconDir() const;$/;" p class:AppIndicatorHelper access:public signature:() const +GetId appindic.cpp /^const wxString AppIndicatorHelper::GetId() const$/;" f class:AppIndicatorHelper signature:() const +GetId appindic.h /^ const wxString GetId() const;$/;" p class:AppIndicatorHelper access:public signature:() const +GetLabel appindic.cpp /^const wxString AppIndicatorHelper::GetLabel() const$/;" f class:AppIndicatorHelper signature:() const +GetLabel appindic.h /^ const wxString GetLabel() const;$/;" p class:AppIndicatorHelper access:public signature:() const +GetLabelGuide appindic.cpp /^const wxString AppIndicatorHelper::GetLabelGuide() const$/;" f class:AppIndicatorHelper signature:() const +GetLabelGuide appindic.h /^ const wxString GetLabelGuide()const;$/;" p class:AppIndicatorHelper access:public signature:() const +GetOrderingIndex appindic.cpp /^const uint AppIndicatorHelper::GetOrderingIndex() const$/;" f class:AppIndicatorHelper signature:() const +GetOrderingIndex appindic.h /^ const uint GetOrderingIndex() const;$/;" p class:AppIndicatorHelper access:public signature:() const +GetStatus appindic.cpp /^const AppIndicatorStatus AppIndicatorHelper::GetStatus() const$/;" f class:AppIndicatorHelper signature:() const +GetStatus appindic.h /^ const AppIndicatorStatus GetStatus() const;$/;" p class:AppIndicatorHelper access:public signature:() const +GetTitle appindic.cpp /^const wxString AppIndicatorHelper::GetTitle() const$/;" f class:AppIndicatorHelper signature:() const +GetTitle appindic.h /^ const wxString GetTitle() const;$/;" p class:AppIndicatorHelper access:public signature:() const +OnExit AIHTest.cpp /^int AIHTest::OnExit()$/;" f class:AIHTest signature:() +OnExit AIHTest.h /^ int OnExit();$/;" p class:AIHTest access:public signature:() +OnIdle AIHTest.cpp /^void AIHTestFrame::OnIdle(wxIdleEvent& evt)$/;" f class:AIHTestFrame signature:(wxIdleEvent& evt) +OnIdle AIHTest.h /^ void OnIdle(wxIdleEvent& evt);$/;" p class:AIHTestFrame access:private signature:(wxIdleEvent& evt) +OnInit AIHTest.cpp /^bool AIHTest::OnInit()$/;" f class:AIHTest signature:() +OnInit AIHTest.h /^ bool OnInit();$/;" p class:AIHTest access:public signature:() +OnMenuItemClick AIHTest.cpp /^void AIHTestFrame::OnMenuItemClick(wxCommandEvent& evt)$/;" f class:AIHTestFrame signature:(wxCommandEvent& evt) +OnMenuItemClick AIHTest.h /^ void OnMenuItemClick(wxCommandEvent& evt);$/;" p class:AIHTestFrame access:private signature:(wxCommandEvent& evt) +SetAttentionIcon appindic.cpp /^void AppIndicatorHelper::SetAttentionIcon(const wxString& iconFileName)$/;" f class:AppIndicatorHelper signature:(const wxString& iconFileName) +SetAttentionIcon appindic.h /^ void SetAttentionIcon(const wxString& iconFileName);$/;" p class:AppIndicatorHelper access:public signature:(const wxString& iconFileName) +SetAttentionIconFull appindic.cpp /^void AppIndicatorHelper::SetAttentionIconFull(const wxString& iconFileName, const wxString& iconDesc)$/;" f class:AppIndicatorHelper signature:(const wxString& iconFileName, const wxString& iconDesc) +SetAttentionIconFull appindic.h /^ void SetAttentionIconFull(const wxString& iconFileName, const wxString& iconDesc);$/;" p class:AppIndicatorHelper access:public signature:(const wxString& iconFileName, const wxString& iconDesc) +SetIcon appindic.cpp /^void AppIndicatorHelper::SetIcon(const wxString& iconFileName)$/;" f class:AppIndicatorHelper signature:(const wxString& iconFileName) +SetIcon appindic.h /^ void SetIcon(const wxString& iconFileName);$/;" p class:AppIndicatorHelper access:public signature:(const wxString& iconFileName) +SetIconDir appindic.cpp /^void AppIndicatorHelper::SetIconDir(const wxString& iconDir)$/;" f class:AppIndicatorHelper signature:(const wxString& iconDir) +SetIconDir appindic.h /^ void SetIconDir(const wxString& iconDir);$/;" p class:AppIndicatorHelper access:public signature:(const wxString& iconDir) +SetIconFull appindic.cpp /^void AppIndicatorHelper::SetIconFull(const wxString& iconFileName, const wxString& iconDesc)$/;" f class:AppIndicatorHelper signature:(const wxString& iconFileName, const wxString& iconDesc) +SetIconFull appindic.h /^ void SetIconFull(const wxString& iconFileName, const wxString& iconDesc);$/;" p class:AppIndicatorHelper access:public signature:(const wxString& iconFileName, const wxString& iconDesc) +SetLabel appindic.cpp /^void AppIndicatorHelper::SetLabel(const wxString& label, const wxString& guide)$/;" f class:AppIndicatorHelper signature:(const wxString& label, const wxString& guide) +SetLabel appindic.h /^ void SetLabel(const wxString& label, const wxString& guide);$/;" p class:AppIndicatorHelper access:public signature:(const wxString& label, const wxString& guide) +SetMenu appindic.cpp /^void AppIndicatorHelper::SetMenu(wxMenu * appMenu)$/;" f class:AppIndicatorHelper signature:(wxMenu * appMenu) +SetMenu appindic.h /^ void SetMenu(wxMenu * appMenu);$/;" p class:AppIndicatorHelper access:public signature:(wxMenu * appMenu) +SetOrderingIndex appindic.cpp /^void AppIndicatorHelper::SetOrderingIndex(uint orderingIndex)$/;" f class:AppIndicatorHelper signature:(uint orderingIndex) +SetOrderingIndex appindic.h /^ void SetOrderingIndex(uint orderingIndex);$/;" p class:AppIndicatorHelper access:public signature:(uint orderingIndex) +SetStatus appindic.cpp /^void AppIndicatorHelper::SetStatus(AppIndicatorStatus status)$/;" f class:AppIndicatorHelper signature:(AppIndicatorStatus status) +SetStatus appindic.h /^ void SetStatus(AppIndicatorStatus status);$/;" p class:AppIndicatorHelper access:public signature:(AppIndicatorStatus status) +SetTitle appindic.cpp /^void AppIndicatorHelper::SetTitle(const wxString& title)$/;" f class:AppIndicatorHelper signature:(const wxString& title) +SetTitle appindic.h /^ void SetTitle(const wxString& title);$/;" p class:AppIndicatorHelper access:public signature:(const wxString& title) +ShowMenu AIHTest.cpp /^void AIHTestFrame::ShowMenu(wxMouseEvent& evt)$/;" f class:AIHTestFrame signature:(wxMouseEvent& evt) +ShowMenu AIHTest.h /^ void ShowMenu(wxMouseEvent& evt);$/;" p class:AIHTestFrame access:private signature:(wxMouseEvent& evt) +m_appMenu appindic.h /^ wxWeakRef m_appMenu;$/;" m class:AppIndicatorHelper access:private +m_indicator AIHTest.h /^ AppIndicatorHelper * m_indicator;$/;" m class:AIHTestFrame access:private +m_indicator appindic.h /^ AppIndicator * m_indicator;$/;" m class:AppIndicatorHelper access:private +m_itemID AIHTest.h /^ long m_itemID;$/;" m class:AIHTestFrame access:private +m_mainMenu AIHTest.h /^ wxMenu * m_mainMenu;$/;" m class:AIHTestFrame access:private +m_removedMenu AIHTest.h /^ wxMenu * m_removedMenu;$/;" m class:AIHTestFrame access:private +m_subID AIHTest.h /^ long m_subID;$/;" m class:AIHTestFrame access:private +~AIHTest AIHTest.cpp /^AIHTest::~AIHTest()$/;" f class:AIHTest signature:() +~AIHTest AIHTest.h /^ virtual ~AIHTest();$/;" p class:AIHTest access:public signature:() +~AIHTestFrame AIHTest.cpp /^AIHTestFrame::~AIHTestFrame()$/;" f class:AIHTestFrame signature:() +~AIHTestFrame AIHTest.h /^ virtual ~AIHTestFrame();$/;" p class:AIHTestFrame access:public signature:() +~AppIndicatorHelper appindic.cpp /^AppIndicatorHelper::~AppIndicatorHelper()$/;" f class:AppIndicatorHelper signature:() +~AppIndicatorHelper appindic.h /^ virtual ~AppIndicatorHelper();$/;" p class:AppIndicatorHelper access:public signature:() diff --git a/ThirdParty/C++RedistributableBinaries/arm/api-ms-win-appmodel-runtime-l1-1-0.dll b/ThirdParty/C++RedistributableBinaries/arm/api-ms-win-appmodel-runtime-l1-1-0.dll new file mode 100644 index 0000000..e69de29 diff --git a/ThirdParty/C++RedistributableBinaries/arm/api-ms-win-core-winrt-error-l1-1-0.dll b/ThirdParty/C++RedistributableBinaries/arm/api-ms-win-core-winrt-error-l1-1-0.dll new file mode 100644 index 0000000..e69de29 diff --git a/ThirdParty/C++RedistributableBinaries/arm/api-ms-win-core-winrt-l1-1-0.dll b/ThirdParty/C++RedistributableBinaries/arm/api-ms-win-core-winrt-l1-1-0.dll new file mode 100644 index 0000000..e69de29 diff --git a/ThirdParty/C++RedistributableBinaries/arm/api-ms-win-core-winrt-robuffer-l1-1-0.dll b/ThirdParty/C++RedistributableBinaries/arm/api-ms-win-core-winrt-robuffer-l1-1-0.dll new file mode 100644 index 0000000..e69de29 diff --git a/ThirdParty/C++RedistributableBinaries/arm/api-ms-win-core-winrt-string-l1-1-0.dll b/ThirdParty/C++RedistributableBinaries/arm/api-ms-win-core-winrt-string-l1-1-0.dll new file mode 100644 index 0000000..e69de29 diff --git a/ThirdParty/C++RedistributableBinaries/arm/api-ms-win-shcore-scaling-l1-1-1.dll b/ThirdParty/C++RedistributableBinaries/arm/api-ms-win-shcore-scaling-l1-1-1.dll new file mode 100644 index 0000000..e69de29 diff --git a/ThirdParty/DatabaseLayer/CMakeLists.txt b/ThirdParty/DatabaseLayer/CMakeLists.txt new file mode 100644 index 0000000..2ee8aa7 --- /dev/null +++ b/ThirdParty/DatabaseLayer/CMakeLists.txt @@ -0,0 +1,54 @@ +# +# Stuff the average programmer needs to change +# +set(SRCS src/DatabaseErrorReporter.cpp + src/DatabaseLayer.cpp + src/DatabaseQueryParser.cpp + src/DatabaseResultSet.cpp + src/DatabaseStringConverter.cpp + src/PreparedStatement.cpp + src/SqliteDatabaseLayer.cpp + src/SqlitePreparedStatement.cpp + src/SqliteResultSet.cpp + src/SqliteResultSetMetaData.cpp + sqlite3/sqlite3.c +) + +#set(SRCS ${SRCS} sqlite3/sqlite3.c) + + +set(HFILES include/DatabaseErrorCodes.h + include/DatabaseErrorReporter.h + include/DatabaseLayer.h + include/DatabaseLayerDef.h + include/DatabaseLayerException.h + include/DatabaseQueryParser.h + include/DatabaseResultSet.h + include/DatabaseStringConverter.h + include/PreparedStatement.h + include/ResultSetMetaData.h + include/SqliteDatabaseLayer.h + include/SqlitePreparedStatement.h + include/SqliteResultSet.h + include/SqliteResultSetMetaData.h) +set(INCLUDE_DIRECTORIES ${BASE_INCLUDE_DIRECTORIES} include sqlite3) +set(LIBRARY_NAME DatabaseLayer) +if(WIN32) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};${wxWidgets_DEFINITIONS};/D_LIB) +endif(WIN32) +set(SRCS ${SRCS} ${HFILES}) + +add_library(${LIBRARY_NAME} STATIC ${SRCS}) + + +target_compile_definitions(${LIBRARY_NAME} PRIVATE ${PREPROCESSOR_DEFINITIONS}) + +target_include_directories(${LIBRARY_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/sqlite3 + ${BASE_INCLUDE_DIRECTORIES} + ${wxWidgets_INCLUDE_DIRS} +) + + +target_link_libraries(${LIBRARY_NAME} PUBLIC ${wxWidgets_LIBRARIES}) \ No newline at end of file diff --git a/ThirdParty/DatabaseLayer/Win/DatabaseLayer.vcxproj b/ThirdParty/DatabaseLayer/Win/DatabaseLayer.vcxproj new file mode 100644 index 0000000..975b288 --- /dev/null +++ b/ThirdParty/DatabaseLayer/Win/DatabaseLayer.vcxproj @@ -0,0 +1,155 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {05A3B61F-EB04-36AA-BEB7-F3837774E597} + 10.0.16299.0 + Win32Proj + x64 + DatabaseLayer + NoUpgrade + + + + StaticLibrary + Unicode + v141 + + + StaticLibrary + Unicode + v141 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + F:\IT-Dim\trunk\ThirdParty\DatabaseLayer\Win\Debug\ + DatabaseLayer.dir\Debug\ + DatabaseLayer + .lib + F:\IT-Dim\trunk\ThirdParty\DatabaseLayer\Win\Release\ + DatabaseLayer.dir\Release\ + DatabaseLayer + .lib + + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;F:\IT-Dim\trunk\ThirdParty\DatabaseLayer\include;F:\IT-Dim\trunk\ThirdParty\DatabaseLayer\sqlite3;%(AdditionalIncludeDirectories) + Debug/ + EnableFastChecks + CompileAsCpp + ProgramDatabase + 4996 + Sync + Disabled + true + Disabled + NotUsing + MultiThreadedDebugDLL + true + Level3 + WIN32;_WINDOWS;__WXDEBUG__=1;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_LIB;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_LIB;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;F:\IT-Dim\trunk\ThirdParty\DatabaseLayer\include;F:\IT-Dim\trunk\ThirdParty\DatabaseLayer\sqlite3;%(AdditionalIncludeDirectories) + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;F:\IT-Dim\trunk\ThirdParty\DatabaseLayer\include;F:\IT-Dim\trunk\ThirdParty\DatabaseLayer\sqlite3;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + %(AdditionalOptions) /machine:x64 + + + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;F:\IT-Dim\trunk\ThirdParty\DatabaseLayer\include;F:\IT-Dim\trunk\ThirdParty\DatabaseLayer\sqlite3;%(AdditionalIncludeDirectories) + Release/ + CompileAsCpp + 4996 + Sync + AnySuitable + true + MaxSpeed + NotUsing + MultiThreadedDLL + true + Level3 + WIN32;_WINDOWS;NDEBUG;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;__WXDEBUG__=1;_LIB;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + + + WIN32;_WINDOWS;NDEBUG;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;__WXDEBUG__=1;_LIB;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;F:\IT-Dim\trunk\ThirdParty\DatabaseLayer\include;F:\IT-Dim\trunk\ThirdParty\DatabaseLayer\sqlite3;%(AdditionalIncludeDirectories) + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;F:\IT-Dim\trunk\ThirdParty\DatabaseLayer\include;F:\IT-Dim\trunk\ThirdParty\DatabaseLayer\sqlite3;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + %(AdditionalOptions) /machine:x64 + + + + + + + + + + + + + + + CompileAsC + CompileAsC + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ThirdParty/DatabaseLayer/Win/DatabaseLayer.vcxproj.filters b/ThirdParty/DatabaseLayer/Win/DatabaseLayer.vcxproj.filters new file mode 100644 index 0000000..003a1f6 --- /dev/null +++ b/ThirdParty/DatabaseLayer/Win/DatabaseLayer.vcxproj.filters @@ -0,0 +1,90 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + {51D244FA-C21C-3174-8217-FDB3769212C0} + + + {A07A887B-0B8A-3ED7-BD7F-43C26975F88D} + + + diff --git a/ThirdParty/DatabaseLayer/include/DatabaseErrorCodes.h b/ThirdParty/DatabaseLayer/include/DatabaseErrorCodes.h new file mode 100644 index 0000000..97c1dc2 --- /dev/null +++ b/ThirdParty/DatabaseLayer/include/DatabaseErrorCodes.h @@ -0,0 +1,23 @@ +#ifndef __DATABASE_ERROR_CODES_H__ +#define __DATABASE_ERROR_CODES_H__ + +#define DATABASE_LAYER_OK 0 +#define DATABASE_LAYER_ERROR 1 +#define DATABASE_LAYER_INVALID_USER 2 +#define DATABASE_LAYER_BAD_PASSWORD 3 +#define DATABASE_LAYER_CONSTRAINT_VIOLATION 4 +#define DATABASE_LAYER_SQL_SYNTAX_ERROR 5 +#define DATABASE_LAYER_ALLOCATION_ERROR 6 +#define DATABASE_LAYER_INCOMPATIBLE_FIELD_TYPE 7 +#define DATABASE_LAYER_FIELD_NOT_IN_RESULTSET 8 +#define DATABASE_LAYER_NO_ROWS_FOUND 9 +#define DATABASE_LAYER_NON_UNIQUE_RESULTSET 10 +#define DATABASE_LAYER_UNSUPPORTED_OPERATION 11 +#define DATABASE_LAYER_ERROR_LOADING_LIBRARY 12 + +// Using 0 for now since this is replacing a +// boolean for the return code and we don't want +// to break existing code +#define DATABASE_LAYER_QUERY_RESULT_ERROR 0 + +#endif // __DATABASE_ERROR_CODES_H__ diff --git a/ThirdParty/DatabaseLayer/include/DatabaseErrorReporter.h b/ThirdParty/DatabaseLayer/include/DatabaseErrorReporter.h new file mode 100644 index 0000000..93b2ddd --- /dev/null +++ b/ThirdParty/DatabaseLayer/include/DatabaseErrorReporter.h @@ -0,0 +1,43 @@ +#ifndef __DATABASE_ERROR_REPORTER_H__ +#define __DATABASE_ERROR_REPORTER_H__ + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +#include "DatabaseLayerDef.h" + +class WXDLLIMPEXP_DATABASELAYER DatabaseErrorReporter +{ +public: + // ctor + DatabaseErrorReporter(); + + // dtor + virtual ~DatabaseErrorReporter(); + + const wxString& GetErrorMessage(); + int GetErrorCode(); + + void ResetErrorCodes(); + +protected: + void SetErrorMessage(const wxString& strErrorMessage); + void SetErrorCode(int nErrorCode); + + void ThrowDatabaseException(); + +private: + wxString m_strErrorMessage; + int m_nErrorCode; +}; + +#endif // __DATABASE_ERROR_REPORTER_H__ + diff --git a/ThirdParty/DatabaseLayer/include/DatabaseLayer.h b/ThirdParty/DatabaseLayer/include/DatabaseLayer.h new file mode 100644 index 0000000..a6eed1d --- /dev/null +++ b/ThirdParty/DatabaseLayer/include/DatabaseLayer.h @@ -0,0 +1,182 @@ +#ifndef __DATABASE_LAYER_H__ +#define __DATABASE_LAYER_H__ + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +#include "wx/hashset.h" +#include "wx/arrstr.h" +#include "wx/variant.h" + +#include "DatabaseLayerDef.h" +#include "DatabaseErrorReporter.h" +#include "DatabaseStringConverter.h" +#include "DatabaseResultSet.h" +#include "PreparedStatement.h" + +WX_DECLARE_HASH_SET( DatabaseResultSet*, wxPointerHash, wxPointerEqual, DatabaseResultSetHashSet ); +WX_DECLARE_HASH_SET( PreparedStatement*, wxPointerHash, wxPointerEqual, DatabaseStatementHashSet ); + +class WXDLLIMPEXP_DATABASELAYER DatabaseLayer : public DatabaseErrorReporter, public DatabaseStringConverter +{ +public: + /// Constructor + DatabaseLayer(); + + /// Destructor + virtual ~DatabaseLayer(); + + // Open database + virtual bool Open(const wxString& strDatabase) = 0; + + /// close database + virtual bool Close() = 0; + + /// Is the connection to the database open? + virtual bool IsOpen() = 0; + + // transaction support + /// Begin a transaction + virtual void BeginTransaction() = 0; + /// Commit the current transaction + virtual void Commit() = 0; + /// Rollback the current transaction + virtual void RollBack() = 0; + + // query database + /// Run an insert, update, or delete query on the database + virtual int RunQuery(const wxString& strQuery); + /// Run an insert, update, or delete query on the database + virtual int RunQuery(const wxString& strQuery, bool bParseQueries) = 0; + /// Run a select query on the database + virtual DatabaseResultSet* RunQueryWithResults(const wxString& strQuery) = 0; + + /// Close a result set returned by the database or a prepared statement previously + virtual bool CloseResultSet(DatabaseResultSet* pResultSet); + + // PreparedStatement support + /// Prepare a SQL statement which can be reused with different parameters + virtual PreparedStatement* PrepareStatement(const wxString& strQuery) = 0; + /// Close a prepared statement previously prepared by the database + virtual bool CloseStatement(PreparedStatement* pStatement); + + // function names more consistent with JDBC and wxSQLite3 + // these just provide wrappers for existing functions + /// See RunQuery + int ExecuteUpdate(const wxString& strQuery) { return RunQuery(strQuery); } + /// See RunQueryWithResults + DatabaseResultSet* ExecuteQuery(const wxString& strQuery) { return RunQueryWithResults(strQuery); } + + // Database schema API contributed by M. Szeftel (author of wxActiveRecordGenerator) + /// Check for the existence of a table by name + virtual bool TableExists(const wxString& table) = 0; + /// Check for the existence of a view by name + virtual bool ViewExists(const wxString& view) = 0; + /// Retrieve all table names + virtual wxArrayString GetTables() = 0; + /// Retrieve all view names + virtual wxArrayString GetViews() = 0; + /// Retrieve all column names for a table + virtual wxArrayString GetColumns(const wxString& table) = 0; + + // Database single result retrieval API contributed by Guru Kathiresan + /// With the GetSingleResultX API, two additional exception types are thrown: + /// DATABASE_LAYER_NO_ROWS_FOUND - No database rows were returned + /// DATABASE_LAYER_NON_UNIQUE_RESULTSET - More than one database row was returned + + /// Retrieve a single integer value from a query + /// If multiple records are returned from the query, a DATABASE_LAYER_NON_UNIQUE_RESULTSET exception + /// is thrown unless bRequireUniqueResult is false + virtual int GetSingleResultInt(const wxString& strSQL, int nField, bool bRequireUniqueResult = true); + virtual int GetSingleResultInt(const wxString& strSQL, const wxString& strField, bool bRequireUniqueResult = true); + + /// Retrieve a single string value from a query + /// If multiple records are returned from the query, a DATABASE_LAYER_NON_UNIQUE_RESULTSET exception + /// is thrown unless bRequireUniqueResult is false + virtual wxString GetSingleResultString(const wxString& strSQL, int nField, bool bRequireUniqueResult = true); + virtual wxString GetSingleResultString(const wxString& strSQL, const wxString& strField, bool bRequireUniqueResult = true); + + /// Retrieve a single long value from a query + /// If multiple records are returned from the query, a DATABASE_LAYER_NON_UNIQUE_RESULTSET exception + /// is thrown unless bRequireUniqueResult is false + virtual long GetSingleResultLong(const wxString& strSQL, int nField, bool bRequireUniqueResult = true); + virtual long GetSingleResultLong(const wxString& strSQL, const wxString& strField, bool bRequireUniqueResult = true); + + /// Retrieve a single bool value from a query + /// If multiple records are returned from the query, a DATABASE_LAYER_NON_UNIQUE_RESULTSET exception + /// is thrown unless bRequireUniqueResult is false + virtual bool GetSingleResultBool(const wxString& strSQL, int nField, bool bRequireUniqueResult = true); + virtual bool GetSingleResultBool(const wxString& strSQL, const wxString& strField, bool bRequireUniqueResult = true); + + /// Retrieve a single date/time value from a query + /// If multiple records are returned from the query, a DATABASE_LAYER_NON_UNIQUE_RESULTSET exception + /// is thrown unless bRequireUniqueResult is false + virtual wxDateTime GetSingleResultDate(const wxString& strSQL, int nField, bool bRequireUniqueResult = true); + virtual wxDateTime GetSingleResultDate(const wxString& strSQL, const wxString& strField, bool bRequireUniqueResult = true); + + /// Retrieve a single Blob value from a query + /// If multiple records are returned from the query, a DATABASE_LAYER_NON_UNIQUE_RESULTSET exception + /// is thrown unless bRequireUniqueResult is false + virtual void* GetSingleResultBlob(const wxString& strSQL, int nField, wxMemoryBuffer& Buffer, bool bRequireUniqueResult = true); + virtual void* GetSingleResultBlob(const wxString& strSQL, const wxString& strField, wxMemoryBuffer& Buffer, bool bRequireUniqueResult = true); + + /// Retrieve a single double value from a query + /// If multiple records are returned from the query, a DATABASE_LAYER_NON_UNIQUE_RESULTSET exception + /// is thrown unless bRequireUniqueResult is false + virtual double GetSingleResultDouble(const wxString& strSQL, int nField, bool bRequireUniqueResult = true); + virtual double GetSingleResultDouble(const wxString& strSQL, const wxString& strField, bool bRequireUniqueResult = true); + + /// Retrieve all the values of one field in a result set + virtual wxArrayInt GetResultsArrayInt(const wxString& strSQL, int nField); + virtual wxArrayInt GetResultsArrayInt(const wxString& strSQL, const wxString& Field); + + virtual wxArrayString GetResultsArrayString(const wxString& strSQL, int nField); + virtual wxArrayString GetResultsArrayString(const wxString& strSQL, const wxString& Field); + + virtual wxArrayLong GetResultsArrayLong(const wxString& strSQL, int nField); + virtual wxArrayLong GetResultsArrayLong(const wxString& strSQL, const wxString& Field); +#if wxCHECK_VERSION(2, 7, 0) + virtual wxArrayDouble GetResultsArrayDouble(const wxString& strSQL, int nField); + virtual wxArrayDouble GetResultsArrayDouble(const wxString& strSQL, const wxString& Field); +#endif + + /// Close all result set objects that have been generated but not yet closed + void CloseResultSets(); + /// Close all prepared statement objects that have been generated but not yet closed + void CloseStatements(); + +protected: + /// Add result set object pointer to the list for "garbage collection" + void LogResultSetForCleanup(DatabaseResultSet* pResultSet) { m_ResultSets.insert(pResultSet); } + /// Add prepared statement object pointer to the list for "garbage collection" + void LogStatementForCleanup(PreparedStatement* pStatement) { m_Statements.insert(pStatement); } + +private: + int GetSingleResultInt(const wxString& strSQL, const wxVariant* field, bool bRequireUniqueResult = true); + wxString GetSingleResultString(const wxString& strSQL, const wxVariant* field, bool bRequireUniqueResult = true); + long GetSingleResultLong(const wxString& strSQL, const wxVariant* field, bool bRequireUniqueResult = true); + bool GetSingleResultBool(const wxString& strSQL, const wxVariant* field, bool bRequireUniqueResult = true); + wxDateTime GetSingleResultDate(const wxString& strSQL, const wxVariant* field, bool bRequireUniqueResult = true); + void* GetSingleResultBlob(const wxString& strSQL, const wxVariant* field, wxMemoryBuffer& Buffer, bool bRequireUniqueResult = true); + double GetSingleResultDouble(const wxString& strSQL, const wxVariant* field, bool bRequireUniqueResult = true); + wxArrayInt GetResultsArrayInt(const wxString& strSQL, const wxVariant* field); + wxArrayString GetResultsArrayString(const wxString& strSQL, const wxVariant* field); + wxArrayLong GetResultsArrayLong(const wxString& strSQL, const wxVariant* field); +#if wxCHECK_VERSION(2, 7, 0) + wxArrayDouble GetResultsArrayDouble(const wxString& strSQL, const wxVariant* field); +#endif + + DatabaseResultSetHashSet m_ResultSets; + DatabaseStatementHashSet m_Statements; +}; + +#endif // __DATABASE_LAYER_H__ + diff --git a/ThirdParty/DatabaseLayer/include/DatabaseLayerDef.h b/ThirdParty/DatabaseLayer/include/DatabaseLayerDef.h new file mode 100644 index 0000000..6043097 --- /dev/null +++ b/ThirdParty/DatabaseLayer/include/DatabaseLayerDef.h @@ -0,0 +1,14 @@ +#ifndef __DATABASELAYER_DEF_H__ +#define __DATABASELAYER_DEF_H__ + +#if defined(WXMAKINGLIB_DATABASELAYER) + #define WXDLLIMPEXP_DATABASELAYER +#elif defined(WXMAKINGDLL_DATABASELAYER) + #define WXDLLIMPEXP_DATABASELAYER WXEXPORT +#elif defined(WXUSINGDLL_DATABASELAYER) + #define WXDLLIMPEXP_DATABASELAYER WXIMPORT +#else // not making nor using DLL + #define WXDLLIMPEXP_DATABASELAYER +#endif + +#endif // __DATABASELAYER_DEF_H__ diff --git a/ThirdParty/DatabaseLayer/include/DatabaseLayerException.h b/ThirdParty/DatabaseLayer/include/DatabaseLayerException.h new file mode 100644 index 0000000..9576100 --- /dev/null +++ b/ThirdParty/DatabaseLayer/include/DatabaseLayerException.h @@ -0,0 +1,26 @@ +#ifndef __DATABASE_LAYER_EXCEPTION_H__ +#define __DATABASE_LAYER_EXCEPTION_H__ + +#ifndef DONT_USE_DATABASE_LAYER_EXCEPTIONS + +class DatabaseLayerException +{ +public: + DatabaseLayerException(int nCode, const wxString& strError) + { + m_nErrorCode = nCode; + m_strErrorMessage = strError; + } + + const wxString& GetErrorMessage() const { return m_strErrorMessage; } + const int GetErrorCode() const { return m_nErrorCode; } + + // Add functions for stack traces ?? +private: + wxString m_strErrorMessage; + int m_nErrorCode; +}; + +#endif // DONT_USE_DATABASE_LAYER_EXCEPTIONS + +#endif // __DATABASE_LAYER_EXCEPTION_H__ diff --git a/ThirdParty/DatabaseLayer/include/DatabaseQueryParser.h b/ThirdParty/DatabaseLayer/include/DatabaseQueryParser.h new file mode 100644 index 0000000..39d6ad2 --- /dev/null +++ b/ThirdParty/DatabaseLayer/include/DatabaseQueryParser.h @@ -0,0 +1,17 @@ +#ifndef _DATABASEQUERYPARSER_H_ +#define _DATABASEQUERYPARSER_H_ + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +wxArrayString ParseQueries(const wxString& strQuery); + +#endif // _DATABASEQUERYPARSER_H_ diff --git a/ThirdParty/DatabaseLayer/include/DatabaseResultSet.h b/ThirdParty/DatabaseLayer/include/DatabaseResultSet.h new file mode 100644 index 0000000..c22b181 --- /dev/null +++ b/ThirdParty/DatabaseLayer/include/DatabaseResultSet.h @@ -0,0 +1,95 @@ +#ifndef __DATABASE_RESULT_SET_H__ +#define __DATABASE_RESULT_SET_H__ + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +#include "wx/hashmap.h" +#include "wx/hashset.h" +#include "wx/datetime.h" + +#include "DatabaseLayerDef.h" +#include "DatabaseErrorReporter.h" +#include "DatabaseStringConverter.h" +#include "ResultSetMetaData.h" + +WX_DECLARE_STRING_HASH_MAP(int, StringToIntMap); +WX_DECLARE_HASH_SET( ResultSetMetaData*, wxPointerHash, wxPointerEqual, MetaDataHashSet ); + +class WXDLLIMPEXP_DATABASELAYER DatabaseResultSet : public DatabaseErrorReporter, public DatabaseStringConverter +{ +public: + /// Constructor + DatabaseResultSet(); + + /// Destructor + virtual ~DatabaseResultSet(); + + /// Move to the next record in the result set + virtual bool Next() = 0; + /// Close the result set (call DatabaseLayer::CloseResultSet() instead on the result set) + virtual void Close() = 0; + + virtual int LookupField(const wxString& strField) = 0; + + // get field + /// Retrieve an integer from the result set by the 1-based field index + virtual int GetResultInt(int nField) = 0; + /// Retrieve a wxString from the result set by the 1-based field index + virtual wxString GetResultString(int nField) = 0; + /// Retrieve a long from the result set by the 1-based field index + virtual long GetResultLong(int nField) = 0; + /// Retrieve a boolean from the result set by the 1-based field index + virtual bool GetResultBool(int nField) = 0; + /// Retrieve a wxDateTime from the result set by the 1-based field index + virtual wxDateTime GetResultDate(int nField) = 0; + /// Retrieve a BLOB from the result set by the 1-based field index + virtual void* GetResultBlob(int nField, wxMemoryBuffer& Buffer) = 0; + /// Retrieve a double from the result set by the 1-based field index + virtual double GetResultDouble(int nField) = 0; + /// Check if a field in the current result set record is NULL + virtual bool IsFieldNull(int nField) = 0; + + /// Retrieve an integer from the result set by the result set column name + virtual int GetResultInt(const wxString& strField); + /// Retrieve a wxString from the result set by the result set column name + virtual wxString GetResultString(const wxString& strField); + /// Retrieve a long from the result set by the result set column name + virtual long GetResultLong(const wxString& strField); + /// Retrieve a boolean from the result set by the result set column name + virtual bool GetResultBool(const wxString& strField); + /// Retrieve a wxDateTime from the result set by the result set column name + virtual wxDateTime GetResultDate(const wxString& strField); + /// Retrieve a BLOB from the result set by the result set column name + virtual void* GetResultBlob(const wxString& strField, wxMemoryBuffer& Buffer); + /// Retrieve a double from the result set by the result set column name + virtual double GetResultDouble(const wxString& strField); + /// Check if a field in the current result set record is NULL + virtual bool IsFieldNull(const wxString& strField); + + // get MetaData + /// Retrieve the MetaData associated with this result set + virtual ResultSetMetaData* GetMetaData() = 0; + /// Close MetaData previously returned by the result set + virtual bool CloseMetaData(ResultSetMetaData* pMetaData); + +protected: + /// Close all meta data objects that have been generated but not yet closed + void CloseMetaData(); + /// Add meta data object pointer to the list for "garbage collection" + void LogMetaDataForCleanup(ResultSetMetaData* pMetaData) { m_MetaData.insert(pMetaData); } + +private: + MetaDataHashSet m_MetaData; +}; + +#endif // __DATABASE_RESULT_SET_H__ + diff --git a/ThirdParty/DatabaseLayer/include/DatabaseStringConverter.h b/ThirdParty/DatabaseLayer/include/DatabaseStringConverter.h new file mode 100644 index 0000000..bf7b217 --- /dev/null +++ b/ThirdParty/DatabaseLayer/include/DatabaseStringConverter.h @@ -0,0 +1,43 @@ +#ifndef __DATABASE_STRING_CONVERTER_H__ +#define __DATABASE_STRING_CONVERTER_H__ + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +#include "DatabaseLayerDef.h" + +class WXDLLIMPEXP_DATABASELAYER DatabaseStringConverter +{ +public: + // ctor + DatabaseStringConverter(); + DatabaseStringConverter(const wxChar* charset); + + // dtor + virtual ~DatabaseStringConverter() { } + + void SetEncoding(wxFontEncoding encoding); + void SetEncoding(const wxCSConv* conv); + const wxCSConv* GetEncoding() { return &m_Encoding; } + + virtual const wxCharBuffer ConvertToUnicodeStream(const wxString& inputString); + virtual size_t GetEncodedStreamLength(const wxString& inputString); + virtual wxString ConvertFromUnicodeStream(const char* inputBuffer); + + static const wxCharBuffer ConvertToUnicodeStream(const wxString& inputString, const char* encoding); + static wxString ConvertFromUnicodeStream(const char* inputBuffer, const char* encoding); + static size_t GetEncodedStreamLength(const wxString& inputString, const char* encoding); + +private: + wxCSConv m_Encoding; +}; + +#endif // __DATABASE_STRING_CONVERTER_H__ diff --git a/ThirdParty/DatabaseLayer/include/PreparedStatement.h b/ThirdParty/DatabaseLayer/include/PreparedStatement.h new file mode 100644 index 0000000..4b971a9 --- /dev/null +++ b/ThirdParty/DatabaseLayer/include/PreparedStatement.h @@ -0,0 +1,82 @@ +#ifndef __PREPARED_STATEMENT_H__ +#define __PREPARED_STATEMENT_H__ + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +#include "wx/hashset.h" + +#include "DatabaseLayerDef.h" +#include "DatabaseErrorReporter.h" +#include "DatabaseStringConverter.h" +#include "DatabaseResultSet.h" +#include "DatabaseQueryParser.h" + +WX_DECLARE_HASH_SET( DatabaseResultSet*, wxPointerHash, wxPointerEqual, StatementResultSetHashSet ); + +class WXDLLIMPEXP_DATABASELAYER PreparedStatement : public DatabaseErrorReporter, public DatabaseStringConverter +{ +public: + /// Constructor + PreparedStatement(); + + /// Destructor + virtual ~PreparedStatement(); + + /// Close the result set (call DatabaseLayer::ClosePreparedStatement() instead on the statement) + virtual void Close() = 0; + + // set parameters + /// Set the parameter at the 1-based position to an int value + virtual void SetParamInt(int nPosition, int nValue) = 0; + /// Set the parameter at the 1-based position to a double value + virtual void SetParamDouble(int nPosition, double dblValue) = 0; + /// Set the parameter at the 1-based position to a wxString value + virtual void SetParamString(int nPosition, const wxString& strValue) = 0; + /// Set the parameter at the 1-based position to a NULL value + virtual void SetParamNull(int nPosition) = 0; + /// Set the parameter at the 1-based position to a Blob value + virtual void SetParamBlob(int nPosition, const wxMemoryBuffer& buffer); + /// Set the parameter at the 1-based position to a Blob value + virtual void SetParamBlob(int nPosition, const void* pData, long nDataLength) = 0; + /// Set the parameter at the 1-based position to a wxDateTime value + virtual void SetParamDate(int nPosition, const wxDateTime& dateValue) = 0; + /// Set the parameter at the 1-based position to a boolean value + virtual void SetParamBool(int nPosition, bool bValue) = 0; + virtual int GetParameterCount() = 0; + + /// Run an insert, update, or delete query on the database + virtual int RunQuery() = 0; + /// Run an insert, update, or delete query on the database + virtual DatabaseResultSet* RunQueryWithResults() = 0; + + // function names more consistent with JDBC and wxSQLite3 + // these just provide wrappers for existing functions + /// See RunQuery + int ExecuteUpdate() { return RunQuery(); } + /// See RunQueryWithResults + DatabaseResultSet* ExecuteQuery() { return RunQueryWithResults(); } + + /// Close a result set returned by the database or a prepared statement previously + virtual bool CloseResultSet(DatabaseResultSet* pResultSet); + +protected: + /// Close all result set objects that have been generated but not yet closed + void CloseResultSets(); + /// Add result set object pointer to the list for "garbage collection" + void LogResultSetForCleanup(DatabaseResultSet* pResultSet) { m_ResultSets.insert(pResultSet); } + +private: + StatementResultSetHashSet m_ResultSets; +}; + +#endif // __PREPARED_STATEMENT_H__ + diff --git a/ThirdParty/DatabaseLayer/include/ResultSetMetaData.h b/ThirdParty/DatabaseLayer/include/ResultSetMetaData.h new file mode 100644 index 0000000..d8073be --- /dev/null +++ b/ThirdParty/DatabaseLayer/include/ResultSetMetaData.h @@ -0,0 +1,43 @@ +#ifndef __RESULT_SET_METADATA_H__ +#define __RESULT_SET_METADATA_H__ + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +#include "DatabaseLayerDef.h" +#include "DatabaseStringConverter.h" + +class WXDLLIMPEXP_DATABASELAYER ResultSetMetaData : public DatabaseStringConverter +{ +public: + /// Retrieve a column's type + virtual int GetColumnType(int i) = 0; + /// Retrieve a column's size + virtual int GetColumnSize(int i) = 0; + /// Retrieve a column's name + virtual wxString GetColumnName(int i) = 0; + /// Retrieve the number of columns in the result set + virtual int GetColumnCount() = 0; + + enum { + COLUMN_UNKNOWN = 0, + COLUMN_NULL, + COLUMN_INTEGER, + COLUMN_STRING, + COLUMN_DOUBLE, + COLUMN_BOOL, + COLUMN_BLOB, + COLUMN_DATE, + }; +}; + +#endif // __RESULT_SET_METADATA_H__ + diff --git a/ThirdParty/DatabaseLayer/include/SqliteDatabaseLayer.h b/ThirdParty/DatabaseLayer/include/SqliteDatabaseLayer.h new file mode 100644 index 0000000..ebe27a5 --- /dev/null +++ b/ThirdParty/DatabaseLayer/include/SqliteDatabaseLayer.h @@ -0,0 +1,73 @@ +#ifndef __SQLITE_DATABASE_LAYER_H__ +#define __SQLITE_DATABASE_LAYER_H__ + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +#include "wx/arrstr.h" + +#include "DatabaseLayerDef.h" +#include "DatabaseLayer.h" + + +class PreparedStatement; + +class WXDLLIMPEXP_DATABASELAYER SqliteDatabaseLayer : public DatabaseLayer +{ +public: + // ctor() + SqliteDatabaseLayer(); + SqliteDatabaseLayer(const wxString& strDatabase, bool mustExist = false); + SqliteDatabaseLayer(void* pDatabase) { m_pDatabase = pDatabase; } + + // dtor() + virtual ~SqliteDatabaseLayer(); + + // open database + virtual bool Open(const wxString& strDatabase); + virtual bool Open(const wxString& strDatabase, bool mustExist); + + // close database + virtual bool Close(); + + // Is the connection to the database open? + virtual bool IsOpen(); + + // transaction support + virtual void BeginTransaction(); + virtual void Commit(); + virtual void RollBack(); + + // query database + virtual int RunQuery(const wxString& strQuery, bool bParseQuery); + virtual DatabaseResultSet* RunQueryWithResults(const wxString& strQuery); + + // PreparedStatement support + virtual PreparedStatement* PrepareStatement(const wxString& strQuery); + PreparedStatement* PrepareStatement(const wxString& strQuery, bool bLogForCleanup); + + // Database schema API contributed by M. Szeftel (author of wxActiveRecordGenerator) + virtual bool TableExists(const wxString& table); + virtual bool ViewExists(const wxString& view); + virtual wxArrayString GetTables(); + virtual wxArrayString GetViews(); + virtual wxArrayString GetColumns(const wxString& table); + + static int TranslateErrorCode(int nCode); + +private: + + //sqlite3* m_pDatabase; + void* m_pDatabase; +}; + +#endif // __SQLITE_DATABASE_LAYER_H__ + diff --git a/ThirdParty/DatabaseLayer/include/SqlitePreparedStatement.h b/ThirdParty/DatabaseLayer/include/SqlitePreparedStatement.h new file mode 100644 index 0000000..e545e6f --- /dev/null +++ b/ThirdParty/DatabaseLayer/include/SqlitePreparedStatement.h @@ -0,0 +1,63 @@ +#ifndef __SQLITE_PREPARED_STATEMENT_H__ +#define __SQLITE_PREPARED_STATEMENT_H__ + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +#include "wx/dynarray.h" + +#include "PreparedStatement.h" + +#include "sqlite3.h" + +WX_DEFINE_ARRAY_PTR(sqlite3_stmt*, StatementVector); + +class DatabaseResultSet; + +class SqlitePreparedStatement : public PreparedStatement +{ +public: + // ctor + SqlitePreparedStatement(sqlite3* pDatabase); + SqlitePreparedStatement(sqlite3* pDatabase, sqlite3_stmt* pStatement); + SqlitePreparedStatement(sqlite3* pDatabase, StatementVector statements); + + // dtor + virtual ~SqlitePreparedStatement(); + + virtual void Close(); + + void AddPreparedStatement(sqlite3_stmt* pStatement); + + // get field + virtual void SetParamInt(int nPosition, int nValue); + virtual void SetParamDouble(int nPosition, double dblValue); + virtual void SetParamString(int nPosition, const wxString& strValue); + virtual void SetParamNull(int nPosition); + virtual void SetParamBlob(int nPosition, const void* pData, long nDataLength); + virtual void SetParamDate(int nPosition, const wxDateTime& dateValue); + virtual void SetParamBool(int nPosition, bool bValue); + virtual int GetParameterCount(); + + virtual int RunQuery(); + virtual DatabaseResultSet* RunQueryWithResults(); + + sqlite3_stmt* GetLastStatement() { return (m_Statements.size() > 0) ? m_Statements[m_Statements.size()-1] : NULL; } + +private: + int FindStatementAndAdjustPositionIndex(int* pPosition); + + sqlite3* m_pDatabase; // Database pointer needed for error messages + StatementVector m_Statements; +}; + +#endif // __SQLITE_PREPARED_STATEMENT_H__ + diff --git a/ThirdParty/DatabaseLayer/include/SqliteResultSet.h b/ThirdParty/DatabaseLayer/include/SqliteResultSet.h new file mode 100644 index 0000000..d60cbac --- /dev/null +++ b/ThirdParty/DatabaseLayer/include/SqliteResultSet.h @@ -0,0 +1,50 @@ +#ifndef __SQLITE_RESULT_SET_H__ +#define __SQLITE_RESULT_SET_H__ + +#include "DatabaseResultSet.h" + +#include "sqlite3.h" + +class SqlitePreparedStatement; +class ResultSetMetaData; + +class SqliteResultSet : public DatabaseResultSet +{ +public: + // ctor + SqliteResultSet(); + SqliteResultSet(SqlitePreparedStatement* pStatement, bool bManageStatement = false); + + // dtor + virtual ~SqliteResultSet(); + + virtual bool Next(); + virtual void Close(); + + virtual int LookupField(const wxString& strField); + + // get field + virtual int GetResultInt(int nField); + virtual wxString GetResultString(int nField); + virtual long GetResultLong(int nField); + virtual bool GetResultBool(int nField); + virtual wxDateTime GetResultDate(int nField); + virtual void* GetResultBlob(int nField, wxMemoryBuffer& Buffer); + virtual double GetResultDouble(int nField); + virtual bool IsFieldNull(int nField); + + // get MetaData + virtual ResultSetMetaData* GetMetaData(); + +private: + + SqlitePreparedStatement* m_pStatement; + sqlite3_stmt* m_pSqliteStatement; + + StringToIntMap m_FieldLookupMap; + + bool m_bManageStatement; +}; + +#endif // __SQLITE_RESULT_SET_H__ + diff --git a/ThirdParty/DatabaseLayer/include/SqliteResultSetMetaData.h b/ThirdParty/DatabaseLayer/include/SqliteResultSetMetaData.h new file mode 100644 index 0000000..e9add7c --- /dev/null +++ b/ThirdParty/DatabaseLayer/include/SqliteResultSetMetaData.h @@ -0,0 +1,34 @@ +#ifndef __SQLITE_RESULT_SET_METADATA_H__ +#define __SQLITE_RESULT_SET_METADATA_H__ + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +#include "ResultSetMetaData.h" + +#include "sqlite3.h" + +class SqliteResultSetMetaData : public ResultSetMetaData +{ +public: + // ctor + SqliteResultSetMetaData(sqlite3_stmt* pStmt); + + virtual int GetColumnType(int i); + virtual int GetColumnSize(int i); + virtual wxString GetColumnName(int i); + virtual int GetColumnCount(); + +private: + sqlite3_stmt* m_pSqliteStatement; +}; + +#endif // __SQLITE_RESULT_SET_METADATA_H__ diff --git a/ThirdParty/DatabaseLayer/sqlite3/sqlite3.c b/ThirdParty/DatabaseLayer/sqlite3/sqlite3.c new file mode 100644 index 0000000..a7b24a2 --- /dev/null +++ b/ThirdParty/DatabaseLayer/sqlite3/sqlite3.c @@ -0,0 +1,104497 @@ +/****************************************************************************** +** This file is an amalgamation of many separate C source files from SQLite +** version 3.6.12. By combining all the individual C code files into this +** single large file, the entire code can be compiled as a one translation +** unit. This allows many compilers to do optimizations that would not be +** possible if the files were compiled separately. Performance improvements +** of 5% are more are commonly seen when SQLite is compiled as a single +** translation unit. +** +** This file is all you need to compile SQLite. To use SQLite in other +** programs, you need this file and the "sqlite3.h" header file that defines +** the programming interface to the SQLite library. (If you do not have +** the "sqlite3.h" header file at hand, you will find a copy in the first +** 5487 lines past this header comment.) Additional code files may be +** needed if you want a wrapper to interface SQLite with your choice of +** programming language. The code for the "sqlite3" command-line shell +** is also in a separate file. This file contains only code for the core +** SQLite library. +** +** This amalgamation was generated on 2009-03-31 12:19:59 UTC. +*/ +#define SQLITE_CORE 1 +#define SQLITE_AMALGAMATION 1 +#ifndef SQLITE_PRIVATE +# define SQLITE_PRIVATE static +#endif +#ifndef SQLITE_API +# define SQLITE_API +#endif +/************** Begin file sqliteInt.h ***************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Internal interface definitions for SQLite. +** +** @(#) $Id: sqliteInt.h,v 1.848 2009/03/25 16:51:43 drh Exp $ +*/ +#ifndef _SQLITEINT_H_ +#define _SQLITEINT_H_ + +/* +** Include the configuration header output by 'configure' if we're using the +** autoconf-based build +*/ +#ifdef _HAVE_SQLITE_CONFIG_H +#include "config.h" +#endif + +/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/ +/************** Begin file sqliteLimit.h *************************************/ +/* +** 2007 May 7 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file defines various limits of what SQLite can process. +** +** @(#) $Id: sqliteLimit.h,v 1.10 2009/01/10 16:15:09 danielk1977 Exp $ +*/ + +/* +** The maximum length of a TEXT or BLOB in bytes. This also +** limits the size of a row in a table or index. +** +** The hard limit is the ability of a 32-bit signed integer +** to count the size: 2^31-1 or 2147483647. +*/ +#ifndef SQLITE_MAX_LENGTH +# define SQLITE_MAX_LENGTH 1000000000 +#endif + +/* +** This is the maximum number of +** +** * Columns in a table +** * Columns in an index +** * Columns in a view +** * Terms in the SET clause of an UPDATE statement +** * Terms in the result set of a SELECT statement +** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement. +** * Terms in the VALUES clause of an INSERT statement +** +** The hard upper limit here is 32676. Most database people will +** tell you that in a well-normalized database, you usually should +** not have more than a dozen or so columns in any table. And if +** that is the case, there is no point in having more than a few +** dozen values in any of the other situations described above. +*/ +#ifndef SQLITE_MAX_COLUMN +# define SQLITE_MAX_COLUMN 2000 +#endif + +/* +** The maximum length of a single SQL statement in bytes. +** +** It used to be the case that setting this value to zero would +** turn the limit off. That is no longer true. It is not possible +** to turn this limit off. +*/ +#ifndef SQLITE_MAX_SQL_LENGTH +# define SQLITE_MAX_SQL_LENGTH 1000000000 +#endif + +/* +** The maximum depth of an expression tree. This is limited to +** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might +** want to place more severe limits on the complexity of an +** expression. +** +** A value of 0 used to mean that the limit was not enforced. +** But that is no longer true. The limit is now strictly enforced +** at all times. +*/ +#ifndef SQLITE_MAX_EXPR_DEPTH +# define SQLITE_MAX_EXPR_DEPTH 1000 +#endif + +/* +** The maximum number of terms in a compound SELECT statement. +** The code generator for compound SELECT statements does one +** level of recursion for each term. A stack overflow can result +** if the number of terms is too large. In practice, most SQL +** never has more than 3 or 4 terms. Use a value of 0 to disable +** any limit on the number of terms in a compount SELECT. +*/ +#ifndef SQLITE_MAX_COMPOUND_SELECT +# define SQLITE_MAX_COMPOUND_SELECT 500 +#endif + +/* +** The maximum number of opcodes in a VDBE program. +** Not currently enforced. +*/ +#ifndef SQLITE_MAX_VDBE_OP +# define SQLITE_MAX_VDBE_OP 25000 +#endif + +/* +** The maximum number of arguments to an SQL function. +*/ +#ifndef SQLITE_MAX_FUNCTION_ARG +# define SQLITE_MAX_FUNCTION_ARG 127 +#endif + +/* +** The maximum number of in-memory pages to use for the main database +** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE +*/ +#ifndef SQLITE_DEFAULT_CACHE_SIZE +# define SQLITE_DEFAULT_CACHE_SIZE 2000 +#endif +#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE +# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500 +#endif + +/* +** The maximum number of attached databases. This must be between 0 +** and 30. The upper bound on 30 is because a 32-bit integer bitmap +** is used internally to track attached databases. +*/ +#ifndef SQLITE_MAX_ATTACHED +# define SQLITE_MAX_ATTACHED 10 +#endif + + +/* +** The maximum value of a ?nnn wildcard that the parser will accept. +*/ +#ifndef SQLITE_MAX_VARIABLE_NUMBER +# define SQLITE_MAX_VARIABLE_NUMBER 999 +#endif + +/* Maximum page size. The upper bound on this value is 32768. This a limit +** imposed by the necessity of storing the value in a 2-byte unsigned integer +** and the fact that the page size must be a power of 2. +** +** If this limit is changed, then the compiled library is technically +** incompatible with an SQLite library compiled with a different limit. If +** a process operating on a database with a page-size of 65536 bytes +** crashes, then an instance of SQLite compiled with the default page-size +** limit will not be able to rollback the aborted transaction. This could +** lead to database corruption. +*/ +#ifndef SQLITE_MAX_PAGE_SIZE +# define SQLITE_MAX_PAGE_SIZE 32768 +#endif + + +/* +** The default size of a database page. +*/ +#ifndef SQLITE_DEFAULT_PAGE_SIZE +# define SQLITE_DEFAULT_PAGE_SIZE 1024 +#endif +#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE +# undef SQLITE_DEFAULT_PAGE_SIZE +# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE +#endif + +/* +** Ordinarily, if no value is explicitly provided, SQLite creates databases +** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain +** device characteristics (sector-size and atomic write() support), +** SQLite may choose a larger value. This constant is the maximum value +** SQLite will choose on its own. +*/ +#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE +# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192 +#endif +#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE +# undef SQLITE_MAX_DEFAULT_PAGE_SIZE +# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE +#endif + + +/* +** Maximum number of pages in one database file. +** +** This is really just the default value for the max_page_count pragma. +** This value can be lowered (or raised) at run-time using that the +** max_page_count macro. +*/ +#ifndef SQLITE_MAX_PAGE_COUNT +# define SQLITE_MAX_PAGE_COUNT 1073741823 +#endif + +/* +** Maximum length (in bytes) of the pattern in a LIKE or GLOB +** operator. +*/ +#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH +# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 +#endif + +/************** End of sqliteLimit.h *****************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + +/* Disable nuisance warnings on Borland compilers */ +#if defined(__BORLANDC__) +#pragma warn -rch /* unreachable code */ +#pragma warn -ccc /* Condition is always true or false */ +#pragma warn -aus /* Assigned value is never used */ +#pragma warn -csu /* Comparing signed and unsigned */ +#pragma warn -spa /* Suspicious pointer arithmetic */ +#endif + +/* Needed for various definitions... */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +/* +** Include standard header files as necessary +*/ +#ifdef HAVE_STDINT_H +#include +#endif +#ifdef HAVE_INTTYPES_H +#include +#endif + +/* + * This macro is used to "hide" some ugliness in casting an int + * value to a ptr value under the MSVC 64-bit compiler. Casting + * non 64-bit values to ptr types results in a "hard" error with + * the MSVC 64-bit compiler which this attempts to avoid. + * + * A simple compiler pragma or casting sequence could not be found + * to correct this in all situations, so this macro was introduced. + * + * It could be argued that the intptr_t type could be used in this + * case, but that type is not available on all compilers, or + * requires the #include of specific headers which differs between + * platforms. + */ +#define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) +#define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) + +/* +** These #defines should enable >2GB file support on POSIX if the +** underlying operating system supports it. If the OS lacks +** large file support, or if the OS is windows, these should be no-ops. +** +** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any +** system #includes. Hence, this block of code must be the very first +** code in all source files. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: Red Hat 7.2) but you want your code to work +** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in Red Hat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +** +** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif + + +/* +** The SQLITE_THREADSAFE macro must be defined as either 0 or 1. +** Older versions of SQLite used an optional THREADSAFE macro. +** We support that for legacy +*/ +#if !defined(SQLITE_THREADSAFE) +#if defined(THREADSAFE) +# define SQLITE_THREADSAFE THREADSAFE +#else +# define SQLITE_THREADSAFE 1 +#endif +#endif + +/* +** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1. +** It determines whether or not the features related to +** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can +** be overridden at runtime using the sqlite3_config() API. +*/ +#if !defined(SQLITE_DEFAULT_MEMSTATUS) +# define SQLITE_DEFAULT_MEMSTATUS 1 +#endif + +/* +** Exactly one of the following macros must be defined in order to +** specify which memory allocation subsystem to use. +** +** SQLITE_SYSTEM_MALLOC // Use normal system malloc() +** SQLITE_MEMDEBUG // Debugging version of system malloc() +** SQLITE_MEMORY_SIZE // internal allocator #1 +** SQLITE_MMAP_HEAP_SIZE // internal mmap() allocator +** SQLITE_POW2_MEMORY_SIZE // internal power-of-two allocator +** +** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as +** the default. +*/ +#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\ + defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\ + defined(SQLITE_POW2_MEMORY_SIZE)>1 +# error "At most one of the following compile-time configuration options\ + is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG, SQLITE_MEMORY_SIZE,\ + SQLITE_MMAP_HEAP_SIZE, SQLITE_POW2_MEMORY_SIZE" +#endif +#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\ + defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\ + defined(SQLITE_POW2_MEMORY_SIZE)==0 +# define SQLITE_SYSTEM_MALLOC 1 +#endif + +/* +** If SQLITE_MALLOC_SOFT_LIMIT is defined, then try to keep the +** sizes of memory allocations below this value where possible. +*/ +#if defined(SQLITE_POW2_MEMORY_SIZE) && !defined(SQLITE_MALLOC_SOFT_LIMIT) +# define SQLITE_MALLOC_SOFT_LIMIT 1024 +#endif + +/* +** We need to define _XOPEN_SOURCE as follows in order to enable +** recursive mutexes on most Unix systems. But Mac OS X is different. +** The _XOPEN_SOURCE define causes problems for Mac OS X we are told, +** so it is omitted there. See ticket #2673. +** +** Later we learn that _XOPEN_SOURCE is poorly or incorrectly +** implemented on some systems. So we avoid defining it at all +** if it is already defined or if it is unneeded because we are +** not doing a threadsafe build. Ticket #2681. +** +** See also ticket #2741. +*/ +#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__) && SQLITE_THREADSAFE +# define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */ +#endif + +/* +** The TCL headers are only needed when compiling the TCL bindings. +*/ +#if defined(SQLITE_TCL) || defined(TCLSH) +# include +#endif + +/* +** Many people are failing to set -DNDEBUG=1 when compiling SQLite. +** Setting NDEBUG makes the code smaller and run faster. So the following +** lines are added to automatically set NDEBUG unless the -DSQLITE_DEBUG=1 +** option is set. Thus NDEBUG becomes an opt-in rather than an opt-out +** feature. +*/ +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +# define NDEBUG 1 +#endif + +/* +** The testcase() macro is used to aid in coverage testing. When +** doing coverage testing, the condition inside the argument to +** testcase() must be evaluated both true and false in order to +** get full branch coverage. The testcase() macro is inserted +** to help ensure adequate test coverage in places where simple +** condition/decision coverage is inadequate. For example, testcase() +** can be used to make sure boundary values are tested. For +** bitmask tests, testcase() can be used to make sure each bit +** is significant and used at least once. On switch statements +** where multiple cases go to the same block of code, testcase() +** can insure that all cases are evaluated. +** +*/ +#ifdef SQLITE_COVERAGE_TEST +SQLITE_PRIVATE void sqlite3Coverage(int); +# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); } +#else +# define testcase(X) +#endif + +/* +** The TESTONLY macro is used to enclose variable declarations or +** other bits of code that are needed to support the arguments +** within testcase() and assert() macros. +*/ +#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST) +# define TESTONLY(X) X +#else +# define TESTONLY(X) +#endif + +/* +** The ALWAYS and NEVER macros surround boolean expressions which +** are intended to always be true or false, respectively. Such +** expressions could be omitted from the code completely. But they +** are included in a few cases in order to enhance the resilience +** of SQLite to unexpected behavior - to make the code "self-healing" +** or "ductile" rather than being "brittle" and crashing at the first +** hint of unplanned behavior. +** +** In other words, ALWAYS and NEVER are added for defensive code. +** +** When doing coverage testing ALWAYS and NEVER are hard-coded to +** be true and false so that the unreachable code then specify will +** not be counted as untested code. +*/ +#if defined(SQLITE_COVERAGE_TEST) +# define ALWAYS(X) (1) +# define NEVER(X) (0) +#elif !defined(NDEBUG) +SQLITE_PRIVATE int sqlite3Assert(void); +# define ALWAYS(X) ((X)?1:sqlite3Assert()) +# define NEVER(X) ((X)?sqlite3Assert():0) +#else +# define ALWAYS(X) (X) +# define NEVER(X) (X) +#endif + +/* +** The macro unlikely() is a hint that surrounds a boolean +** expression that is usually false. Macro likely() surrounds +** a boolean expression that is usually true. GCC is able to +** use these hints to generate better code, sometimes. +*/ +#if defined(__GNUC__) && 0 +# define likely(X) __builtin_expect((X),1) +# define unlikely(X) __builtin_expect((X),0) +#else +# define likely(X) !!(X) +# define unlikely(X) !!(X) +#endif + +/* +** Sometimes we need a small amount of code such as a variable initialization +** to setup for a later assert() statement. We do not want this code to +** appear when assert() is disabled. The following macro is therefore +** used to contain that setup code. The "VVA" acronym stands for +** "Verification, Validation, and Accreditation". In other words, the +** code within VVA_ONLY() will only run during verification processes. +*/ +#ifndef NDEBUG +# define VVA_ONLY(X) X +#else +# define VVA_ONLY(X) +#endif + +/************** Include sqlite3.h in the middle of sqliteInt.h ***************/ +/************** Begin file sqlite3.h *****************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the SQLite library +** presents to client programs. If a C-function, structure, datatype, +** or constant definition does not appear in this file, then it is +** not a published API of SQLite, is subject to change without +** notice, and should not be referenced by programs that use SQLite. +** +** Some of the definitions that are in this file are marked as +** "experimental". Experimental interfaces are normally new +** features recently added to SQLite. We do not anticipate changes +** to experimental interfaces but reserve to make minor changes if +** experience from use "in the wild" suggest such changes are prudent. +** +** The official C-language API documentation for SQLite is derived +** from comments in this file. This file is the authoritative source +** on how SQLite interfaces are suppose to operate. +** +** The name of this file under configuration management is "sqlite.h.in". +** The makefile makes some minor changes to this file (such as inserting +** the version number) and changes its name to "sqlite3.h" as +** part of the build process. +** +** @(#) $Id: sqlite.h.in,v 1.436 2009/03/20 13:15:30 drh Exp $ +*/ +#ifndef _SQLITE3_H_ +#define _SQLITE3_H_ +#include /* Needed for the definition of va_list */ + +/* +** Make sure we can call this stuff from C++. +*/ +#if 0 +extern "C" { +#endif + + +/* +** Add the ability to override 'extern' +*/ +#ifndef SQLITE_EXTERN +# define SQLITE_EXTERN extern +#endif + +/* +** These no-op macros are used in front of interfaces to mark those +** interfaces as either deprecated or experimental. New applications +** should not use deprecated intrfaces - they are support for backwards +** compatibility only. Application writers should be aware that +** experimental interfaces are subject to change in point releases. +** +** These macros used to resolve to various kinds of compiler magic that +** would generate warning messages when they were used. But that +** compiler magic ended up generating such a flurry of bug reports +** that we have taken it all out and gone back to using simple +** noop macros. +*/ +#define SQLITE_DEPRECATED +#define SQLITE_EXPERIMENTAL + +/* +** Ensure these symbols were not defined by some previous header file. +*/ +#ifdef SQLITE_VERSION +# undef SQLITE_VERSION +#endif +#ifdef SQLITE_VERSION_NUMBER +# undef SQLITE_VERSION_NUMBER +#endif + +/* +** CAPI3REF: Compile-Time Library Version Numbers {H10010} +** +** The SQLITE_VERSION and SQLITE_VERSION_NUMBER #defines in +** the sqlite3.h file specify the version of SQLite with which +** that header file is associated. +** +** The "version" of SQLite is a string of the form "X.Y.Z". +** The phrase "alpha" or "beta" might be appended after the Z. +** The X value is major version number always 3 in SQLite3. +** The X value only changes when backwards compatibility is +** broken and we intend to never break backwards compatibility. +** The Y value is the minor version number and only changes when +** there are major feature enhancements that are forwards compatible +** but not backwards compatible. +** The Z value is the release number and is incremented with +** each release but resets back to 0 whenever Y is incremented. +** +** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. +** +** Requirements: [H10011] [H10014] +*/ +#define SQLITE_VERSION "3.6.12" +#define SQLITE_VERSION_NUMBER 3006012 + +/* +** CAPI3REF: Run-Time Library Version Numbers {H10020} +** KEYWORDS: sqlite3_version +** +** These features provide the same information as the [SQLITE_VERSION] +** and [SQLITE_VERSION_NUMBER] #defines in the header, but are associated +** with the library instead of the header file. Cautious programmers might +** include a check in their application to verify that +** sqlite3_libversion_number() always returns the value +** [SQLITE_VERSION_NUMBER]. +** +** The sqlite3_libversion() function returns the same information as is +** in the sqlite3_version[] string constant. The function is provided +** for use in DLLs since DLL users usually do not have direct access to string +** constants within the DLL. +** +** Requirements: [H10021] [H10022] [H10023] +*/ +SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; +SQLITE_API const char *sqlite3_libversion(void); +SQLITE_API int sqlite3_libversion_number(void); + +/* +** CAPI3REF: Test To See If The Library Is Threadsafe {H10100} +** +** SQLite can be compiled with or without mutexes. When +** the [SQLITE_THREADSAFE] C preprocessor macro 1 or 2, mutexes +** are enabled and SQLite is threadsafe. When the +** [SQLITE_THREADSAFE] macro is 0, +** the mutexes are omitted. Without the mutexes, it is not safe +** to use SQLite concurrently from more than one thread. +** +** Enabling mutexes incurs a measurable performance penalty. +** So if speed is of utmost importance, it makes sense to disable +** the mutexes. But for maximum safety, mutexes should be enabled. +** The default behavior is for mutexes to be enabled. +** +** This interface can be used by a program to make sure that the +** version of SQLite that it is linking against was compiled with +** the desired setting of the [SQLITE_THREADSAFE] macro. +** +** This interface only reports on the compile-time mutex setting +** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with +** SQLITE_THREADSAFE=1 then mutexes are enabled by default but +** can be fully or partially disabled using a call to [sqlite3_config()] +** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], +** or [SQLITE_CONFIG_MUTEX]. The return value of this function shows +** only the default compile-time setting, not any run-time changes +** to that setting. +** +** See the [threading mode] documentation for additional information. +** +** Requirements: [H10101] [H10102] +*/ +SQLITE_API int sqlite3_threadsafe(void); + +/* +** CAPI3REF: Database Connection Handle {H12000} +** KEYWORDS: {database connection} {database connections} +** +** Each open SQLite database is represented by a pointer to an instance of +** the opaque structure named "sqlite3". It is useful to think of an sqlite3 +** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and +** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()] +** is its destructor. There are many other interfaces (such as +** [sqlite3_prepare_v2()], [sqlite3_create_function()], and +** [sqlite3_busy_timeout()] to name but three) that are methods on an +** sqlite3 object. +*/ +typedef struct sqlite3 sqlite3; + +/* +** CAPI3REF: 64-Bit Integer Types {H10200} +** KEYWORDS: sqlite_int64 sqlite_uint64 +** +** Because there is no cross-platform way to specify 64-bit integer types +** SQLite includes typedefs for 64-bit signed and unsigned integers. +** +** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions. +** The sqlite_int64 and sqlite_uint64 types are supported for backwards +** compatibility only. +** +** Requirements: [H10201] [H10202] +*/ +#ifdef SQLITE_INT64_TYPE + typedef SQLITE_INT64_TYPE sqlite_int64; + typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; +#elif defined(_MSC_VER) || defined(__BORLANDC__) + typedef __int64 sqlite_int64; + typedef unsigned __int64 sqlite_uint64; +#else + typedef long long int sqlite_int64; + typedef unsigned long long int sqlite_uint64; +#endif +typedef sqlite_int64 sqlite3_int64; +typedef sqlite_uint64 sqlite3_uint64; + +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point. +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite3_int64 +#endif + +/* +** CAPI3REF: Closing A Database Connection {H12010} +** +** This routine is the destructor for the [sqlite3] object. +** +** Applications should [sqlite3_finalize | finalize] all [prepared statements] +** and [sqlite3_blob_close | close] all [BLOB handles] associated with +** the [sqlite3] object prior to attempting to close the object. +** The [sqlite3_next_stmt()] interface can be used to locate all +** [prepared statements] associated with a [database connection] if desired. +** Typical code might look like this: +** +**
+** sqlite3_stmt *pStmt;
+** while( (pStmt = sqlite3_next_stmt(db, 0))!=0 ){
+**     sqlite3_finalize(pStmt);
+** }
+** 
+** +** If [sqlite3_close()] is invoked while a transaction is open, +** the transaction is automatically rolled back. +** +** The C parameter to [sqlite3_close(C)] must be either a NULL +** pointer or an [sqlite3] object pointer obtained +** from [sqlite3_open()], [sqlite3_open16()], or +** [sqlite3_open_v2()], and not previously closed. +** +** Requirements: +** [H12011] [H12012] [H12013] [H12014] [H12015] [H12019] +*/ +SQLITE_API int sqlite3_close(sqlite3 *); + +/* +** The type for a callback function. +** This is legacy and deprecated. It is included for historical +** compatibility and is not documented. +*/ +typedef int (*sqlite3_callback)(void*,int,char**, char**); + +/* +** CAPI3REF: One-Step Query Execution Interface {H12100} +** +** The sqlite3_exec() interface is a convenient way of running one or more +** SQL statements without having to write a lot of C code. The UTF-8 encoded +** SQL statements are passed in as the second parameter to sqlite3_exec(). +** The statements are evaluated one by one until either an error or +** an interrupt is encountered, or until they are all done. The 3rd parameter +** is an optional callback that is invoked once for each row of any query +** results produced by the SQL statements. The 5th parameter tells where +** to write any error messages. +** +** The error message passed back through the 5th parameter is held +** in memory obtained from [sqlite3_malloc()]. To avoid a memory leak, +** the calling application should call [sqlite3_free()] on any error +** message returned through the 5th parameter when it has finished using +** the error message. +** +** If the SQL statement in the 2nd parameter is NULL or an empty string +** or a string containing only whitespace and comments, then no SQL +** statements are evaluated and the database is not changed. +** +** The sqlite3_exec() interface is implemented in terms of +** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()]. +** The sqlite3_exec() routine does nothing to the database that cannot be done +** by [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()]. +** +** The first parameter to [sqlite3_exec()] must be an valid and open +** [database connection]. +** +** The database connection must not be closed while +** [sqlite3_exec()] is running. +** +** The calling function should use [sqlite3_free()] to free +** the memory that *errmsg is left pointing at once the error +** message is no longer needed. +** +** The SQL statement text in the 2nd parameter to [sqlite3_exec()] +** must remain unchanged while [sqlite3_exec()] is running. +** +** Requirements: +** [H12101] [H12102] [H12104] [H12105] [H12107] [H12110] [H12113] [H12116] +** [H12119] [H12122] [H12125] [H12131] [H12134] [H12137] [H12138] +*/ +SQLITE_API int sqlite3_exec( + sqlite3*, /* An open database */ + const char *sql, /* SQL to be evaluated */ + int (*callback)(void*,int,char**,char**), /* Callback function */ + void *, /* 1st argument to callback */ + char **errmsg /* Error msg written here */ +); + +/* +** CAPI3REF: Result Codes {H10210} +** KEYWORDS: SQLITE_OK {error code} {error codes} +** KEYWORDS: {result code} {result codes} +** +** Many SQLite functions return an integer result code from the set shown +** here in order to indicates success or failure. +** +** New error codes may be added in future versions of SQLite. +** +** See also: [SQLITE_IOERR_READ | extended result codes] +*/ +#define SQLITE_OK 0 /* Successful result */ +/* beginning-of-error-codes */ +#define SQLITE_ERROR 1 /* SQL error or missing database */ +#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ +#define SQLITE_PERM 3 /* Access permission denied */ +#define SQLITE_ABORT 4 /* Callback routine requested an abort */ +#define SQLITE_BUSY 5 /* The database file is locked */ +#define SQLITE_LOCKED 6 /* A table in the database is locked */ +#define SQLITE_NOMEM 7 /* A malloc() failed */ +#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ +#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ +#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ +#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ +#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ +#define SQLITE_FULL 13 /* Insertion failed because database is full */ +#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ +#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ +#define SQLITE_EMPTY 16 /* Database is empty */ +#define SQLITE_SCHEMA 17 /* The database schema changed */ +#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ +#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ +#define SQLITE_MISMATCH 20 /* Data type mismatch */ +#define SQLITE_MISUSE 21 /* Library used incorrectly */ +#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ +#define SQLITE_AUTH 23 /* Authorization denied */ +#define SQLITE_FORMAT 24 /* Auxiliary database format error */ +#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ +#define SQLITE_NOTADB 26 /* File opened that is not a database file */ +#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ +#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ +/* end-of-error-codes */ + +/* +** CAPI3REF: Extended Result Codes {H10220} +** KEYWORDS: {extended error code} {extended error codes} +** KEYWORDS: {extended result code} {extended result codes} +** +** In its default configuration, SQLite API routines return one of 26 integer +** [SQLITE_OK | result codes]. However, experience has shown that many of +** these result codes are too coarse-grained. They do not provide as +** much information about problems as programmers might like. In an effort to +** address this, newer versions of SQLite (version 3.3.8 and later) include +** support for additional result codes that provide more detailed information +** about errors. The extended result codes are enabled or disabled +** on a per database connection basis using the +** [sqlite3_extended_result_codes()] API. +** +** Some of the available extended result codes are listed here. +** One may expect the number of extended result codes will be expand +** over time. Software that uses extended result codes should expect +** to see new result codes in future releases of SQLite. +** +** The SQLITE_OK result code will never be extended. It will always +** be exactly zero. +*/ +#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) +#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) +#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) +#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) +#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) +#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) +#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) +#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) +#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) +#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) +#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) +#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) +#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8)) +#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8)) +#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8)) +#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) +#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) + +#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8) ) + +/* +** CAPI3REF: Flags For File Open Operations {H10230} +** +** These bit values are intended for use in the +** 3rd parameter to the [sqlite3_open_v2()] interface and +** in the 4th parameter to the xOpen method of the +** [sqlite3_vfs] object. +*/ +#define SQLITE_OPEN_READONLY 0x00000001 +#define SQLITE_OPEN_READWRITE 0x00000002 +#define SQLITE_OPEN_CREATE 0x00000004 +#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 +#define SQLITE_OPEN_EXCLUSIVE 0x00000010 +#define SQLITE_OPEN_MAIN_DB 0x00000100 +#define SQLITE_OPEN_TEMP_DB 0x00000200 +#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 +#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 +#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 +#define SQLITE_OPEN_SUBJOURNAL 0x00002000 +#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 +#define SQLITE_OPEN_NOMUTEX 0x00008000 +#define SQLITE_OPEN_FULLMUTEX 0x00010000 + +/* +** CAPI3REF: Device Characteristics {H10240} +** +** The xDeviceCapabilities method of the [sqlite3_io_methods] +** object returns an integer which is a vector of the these +** bit values expressing I/O characteristics of the mass storage +** device that holds the file that the [sqlite3_io_methods] +** refers to. +** +** The SQLITE_IOCAP_ATOMIC property means that all writes of +** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values +** mean that writes of blocks that are nnn bytes in size and +** are aligned to an address which is an integer multiple of +** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means +** that when data is appended to a file, the data is appended +** first then the size of the file is extended, never the other +** way around. The SQLITE_IOCAP_SEQUENTIAL property means that +** information is written to disk in the same order as calls +** to xWrite(). +*/ +#define SQLITE_IOCAP_ATOMIC 0x00000001 +#define SQLITE_IOCAP_ATOMIC512 0x00000002 +#define SQLITE_IOCAP_ATOMIC1K 0x00000004 +#define SQLITE_IOCAP_ATOMIC2K 0x00000008 +#define SQLITE_IOCAP_ATOMIC4K 0x00000010 +#define SQLITE_IOCAP_ATOMIC8K 0x00000020 +#define SQLITE_IOCAP_ATOMIC16K 0x00000040 +#define SQLITE_IOCAP_ATOMIC32K 0x00000080 +#define SQLITE_IOCAP_ATOMIC64K 0x00000100 +#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 +#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 + +/* +** CAPI3REF: File Locking Levels {H10250} +** +** SQLite uses one of these integer values as the second +** argument to calls it makes to the xLock() and xUnlock() methods +** of an [sqlite3_io_methods] object. +*/ +#define SQLITE_LOCK_NONE 0 +#define SQLITE_LOCK_SHARED 1 +#define SQLITE_LOCK_RESERVED 2 +#define SQLITE_LOCK_PENDING 3 +#define SQLITE_LOCK_EXCLUSIVE 4 + +/* +** CAPI3REF: Synchronization Type Flags {H10260} +** +** When SQLite invokes the xSync() method of an +** [sqlite3_io_methods] object it uses a combination of +** these integer values as the second argument. +** +** When the SQLITE_SYNC_DATAONLY flag is used, it means that the +** sync operation only needs to flush data to mass storage. Inode +** information need not be flushed. The SQLITE_SYNC_NORMAL flag means +** to use normal fsync() semantics. The SQLITE_SYNC_FULL flag means +** to use Mac OS X style fullsync instead of fsync(). +*/ +#define SQLITE_SYNC_NORMAL 0x00002 +#define SQLITE_SYNC_FULL 0x00003 +#define SQLITE_SYNC_DATAONLY 0x00010 + +/* +** CAPI3REF: OS Interface Open File Handle {H11110} +** +** An [sqlite3_file] object represents an open file in the OS +** interface layer. Individual OS interface implementations will +** want to subclass this object by appending additional fields +** for their own use. The pMethods entry is a pointer to an +** [sqlite3_io_methods] object that defines methods for performing +** I/O operations on the open file. +*/ +typedef struct sqlite3_file sqlite3_file; +struct sqlite3_file { + const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ +}; + +/* +** CAPI3REF: OS Interface File Virtual Methods Object {H11120} +** +** Every file opened by the [sqlite3_vfs] xOpen method populates an +** [sqlite3_file] object (or, more commonly, a subclass of the +** [sqlite3_file] object) with a pointer to an instance of this object. +** This object defines the methods used to perform various operations +** against the open file represented by the [sqlite3_file] object. +** +** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or +** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). +** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY] +** flag may be ORed in to indicate that only the data of the file +** and not its inode needs to be synced. +** +** The integer values to xLock() and xUnlock() are one of +**
    +**
  • [SQLITE_LOCK_NONE], +**
  • [SQLITE_LOCK_SHARED], +**
  • [SQLITE_LOCK_RESERVED], +**
  • [SQLITE_LOCK_PENDING], or +**
  • [SQLITE_LOCK_EXCLUSIVE]. +**
+** xLock() increases the lock. xUnlock() decreases the lock. +** The xCheckReservedLock() method checks whether any database connection, +** either in this process or in some other process, is holding a RESERVED, +** PENDING, or EXCLUSIVE lock on the file. It returns true +** if such a lock exists and false otherwise. +** +** The xFileControl() method is a generic interface that allows custom +** VFS implementations to directly control an open file using the +** [sqlite3_file_control()] interface. The second "op" argument is an +** integer opcode. The third argument is a generic pointer intended to +** point to a structure that may contain arguments or space in which to +** write return values. Potential uses for xFileControl() might be +** functions to enable blocking locks with timeouts, to change the +** locking strategy (for example to use dot-file locks), to inquire +** about the status of a lock, or to break stale locks. The SQLite +** core reserves all opcodes less than 100 for its own use. +** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. +** Applications that define a custom xFileControl method should use opcodes +** greater than 100 to avoid conflicts. +** +** The xSectorSize() method returns the sector size of the +** device that underlies the file. The sector size is the +** minimum write that can be performed without disturbing +** other bytes in the file. The xDeviceCharacteristics() +** method returns a bit vector describing behaviors of the +** underlying device: +** +**
    +**
  • [SQLITE_IOCAP_ATOMIC] +**
  • [SQLITE_IOCAP_ATOMIC512] +**
  • [SQLITE_IOCAP_ATOMIC1K] +**
  • [SQLITE_IOCAP_ATOMIC2K] +**
  • [SQLITE_IOCAP_ATOMIC4K] +**
  • [SQLITE_IOCAP_ATOMIC8K] +**
  • [SQLITE_IOCAP_ATOMIC16K] +**
  • [SQLITE_IOCAP_ATOMIC32K] +**
  • [SQLITE_IOCAP_ATOMIC64K] +**
  • [SQLITE_IOCAP_SAFE_APPEND] +**
  • [SQLITE_IOCAP_SEQUENTIAL] +**
+** +** The SQLITE_IOCAP_ATOMIC property means that all writes of +** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values +** mean that writes of blocks that are nnn bytes in size and +** are aligned to an address which is an integer multiple of +** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means +** that when data is appended to a file, the data is appended +** first then the size of the file is extended, never the other +** way around. The SQLITE_IOCAP_SEQUENTIAL property means that +** information is written to disk in the same order as calls +** to xWrite(). +** +** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill +** in the unread portions of the buffer with zeros. A VFS that +** fails to zero-fill short reads might seem to work. However, +** failure to zero-fill short reads will eventually lead to +** database corruption. +*/ +typedef struct sqlite3_io_methods sqlite3_io_methods; +struct sqlite3_io_methods { + int iVersion; + int (*xClose)(sqlite3_file*); + int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); + int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); + int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); + int (*xSync)(sqlite3_file*, int flags); + int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); + int (*xLock)(sqlite3_file*, int); + int (*xUnlock)(sqlite3_file*, int); + int (*xCheckReservedLock)(sqlite3_file*, int *pResOut); + int (*xFileControl)(sqlite3_file*, int op, void *pArg); + int (*xSectorSize)(sqlite3_file*); + int (*xDeviceCharacteristics)(sqlite3_file*); + /* Additional methods may be added in future releases */ +}; + +/* +** CAPI3REF: Standard File Control Opcodes {H11310} +** +** These integer constants are opcodes for the xFileControl method +** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()] +** interface. +** +** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This +** opcode causes the xFileControl method to write the current state of +** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], +** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) +** into an integer that the pArg argument points to. This capability +** is used during testing and only needs to be supported when SQLITE_TEST +** is defined. +*/ +#define SQLITE_FCNTL_LOCKSTATE 1 +#define SQLITE_GET_LOCKPROXYFILE 2 +#define SQLITE_SET_LOCKPROXYFILE 3 +#define SQLITE_LAST_ERRNO 4 + +/* +** CAPI3REF: Mutex Handle {H17110} +** +** The mutex module within SQLite defines [sqlite3_mutex] to be an +** abstract type for a mutex object. The SQLite core never looks +** at the internal representation of an [sqlite3_mutex]. It only +** deals with pointers to the [sqlite3_mutex] object. +** +** Mutexes are created using [sqlite3_mutex_alloc()]. +*/ +typedef struct sqlite3_mutex sqlite3_mutex; + +/* +** CAPI3REF: OS Interface Object {H11140} +** +** An instance of the sqlite3_vfs object defines the interface between +** the SQLite core and the underlying operating system. The "vfs" +** in the name of the object stands for "virtual file system". +** +** The value of the iVersion field is initially 1 but may be larger in +** future versions of SQLite. Additional fields may be appended to this +** object when the iVersion value is increased. Note that the structure +** of the sqlite3_vfs object changes in the transaction between +** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not +** modified. +** +** The szOsFile field is the size of the subclassed [sqlite3_file] +** structure used by this VFS. mxPathname is the maximum length of +** a pathname in this VFS. +** +** Registered sqlite3_vfs objects are kept on a linked list formed by +** the pNext pointer. The [sqlite3_vfs_register()] +** and [sqlite3_vfs_unregister()] interfaces manage this list +** in a thread-safe way. The [sqlite3_vfs_find()] interface +** searches the list. Neither the application code nor the VFS +** implementation should use the pNext pointer. +** +** The pNext field is the only field in the sqlite3_vfs +** structure that SQLite will ever modify. SQLite will only access +** or modify this field while holding a particular static mutex. +** The application should never modify anything within the sqlite3_vfs +** object once the object has been registered. +** +** The zName field holds the name of the VFS module. The name must +** be unique across all VFS modules. +** +** SQLite will guarantee that the zFilename parameter to xOpen +** is either a NULL pointer or string obtained +** from xFullPathname(). SQLite further guarantees that +** the string will be valid and unchanged until xClose() is +** called. Because of the previous sentense, +** the [sqlite3_file] can safely store a pointer to the +** filename if it needs to remember the filename for some reason. +** If the zFilename parameter is xOpen is a NULL pointer then xOpen +** must invite its own temporary name for the file. Whenever the +** xFilename parameter is NULL it will also be the case that the +** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. +** +** The flags argument to xOpen() includes all bits set in +** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] +** or [sqlite3_open16()] is used, then flags includes at least +** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. +** If xOpen() opens a file read-only then it sets *pOutFlags to +** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set. +** +** SQLite will also add one of the following flags to the xOpen() +** call, depending on the object being opened: +** +**
    +**
  • [SQLITE_OPEN_MAIN_DB] +**
  • [SQLITE_OPEN_MAIN_JOURNAL] +**
  • [SQLITE_OPEN_TEMP_DB] +**
  • [SQLITE_OPEN_TEMP_JOURNAL] +**
  • [SQLITE_OPEN_TRANSIENT_DB] +**
  • [SQLITE_OPEN_SUBJOURNAL] +**
  • [SQLITE_OPEN_MASTER_JOURNAL] +**
+** +** The file I/O implementation can use the object type flags to +** change the way it deals with files. For example, an application +** that does not care about crash recovery or rollback might make +** the open of a journal file a no-op. Writes to this journal would +** also be no-ops, and any attempt to read the journal would return +** SQLITE_IOERR. Or the implementation might recognize that a database +** file will be doing page-aligned sector reads and writes in a random +** order and set up its I/O subsystem accordingly. +** +** SQLite might also add one of the following flags to the xOpen method: +** +**
    +**
  • [SQLITE_OPEN_DELETEONCLOSE] +**
  • [SQLITE_OPEN_EXCLUSIVE] +**
+** +** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be +** deleted when it is closed. The [SQLITE_OPEN_DELETEONCLOSE] +** will be set for TEMP databases, journals and for subjournals. +** +** The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened +** for exclusive access. This flag is set for all files except +** for the main database file. +** +** At least szOsFile bytes of memory are allocated by SQLite +** to hold the [sqlite3_file] structure passed as the third +** argument to xOpen. The xOpen method does not have to +** allocate the structure; it should just fill it in. +** +** The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] +** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to +** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] +** to test whether a file is at least readable. The file can be a +** directory. +** +** SQLite will always allocate at least mxPathname+1 bytes for the +** output buffer xFullPathname. The exact size of the output buffer +** is also passed as a parameter to both methods. If the output buffer +** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is +** handled as a fatal error by SQLite, vfs implementations should endeavor +** to prevent this by setting mxPathname to a sufficiently large value. +** +** The xRandomness(), xSleep(), and xCurrentTime() interfaces +** are not strictly a part of the filesystem, but they are +** included in the VFS structure for completeness. +** The xRandomness() function attempts to return nBytes bytes +** of good-quality randomness into zOut. The return value is +** the actual number of bytes of randomness obtained. +** The xSleep() method causes the calling thread to sleep for at +** least the number of microseconds given. The xCurrentTime() +** method returns a Julian Day Number for the current date and time. +** +*/ +typedef struct sqlite3_vfs sqlite3_vfs; +struct sqlite3_vfs { + int iVersion; /* Structure version number */ + int szOsFile; /* Size of subclassed sqlite3_file */ + int mxPathname; /* Maximum file pathname length */ + sqlite3_vfs *pNext; /* Next registered VFS */ + const char *zName; /* Name of this virtual file system */ + void *pAppData; /* Pointer to application-specific data */ + int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, + int flags, int *pOutFlags); + int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); + int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); + int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); + void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); + void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); + void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); + void (*xDlClose)(sqlite3_vfs*, void*); + int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); + int (*xSleep)(sqlite3_vfs*, int microseconds); + int (*xCurrentTime)(sqlite3_vfs*, double*); + int (*xGetLastError)(sqlite3_vfs*, int, char *); + /* New fields may be appended in figure versions. The iVersion + ** value will increment whenever this happens. */ +}; + +/* +** CAPI3REF: Flags for the xAccess VFS method {H11190} +** +** These integer constants can be used as the third parameter to +** the xAccess method of an [sqlite3_vfs] object. {END} They determine +** what kind of permissions the xAccess method is looking for. +** With SQLITE_ACCESS_EXISTS, the xAccess method +** simply checks whether the file exists. +** With SQLITE_ACCESS_READWRITE, the xAccess method +** checks whether the file is both readable and writable. +** With SQLITE_ACCESS_READ, the xAccess method +** checks whether the file is readable. +*/ +#define SQLITE_ACCESS_EXISTS 0 +#define SQLITE_ACCESS_READWRITE 1 +#define SQLITE_ACCESS_READ 2 + +/* +** CAPI3REF: Initialize The SQLite Library {H10130} +** +** The sqlite3_initialize() routine initializes the +** SQLite library. The sqlite3_shutdown() routine +** deallocates any resources that were allocated by sqlite3_initialize(). +** +** A call to sqlite3_initialize() is an "effective" call if it is +** the first time sqlite3_initialize() is invoked during the lifetime of +** the process, or if it is the first time sqlite3_initialize() is invoked +** following a call to sqlite3_shutdown(). Only an effective call +** of sqlite3_initialize() does any initialization. All other calls +** are harmless no-ops. +** +** Among other things, sqlite3_initialize() shall invoke +** sqlite3_os_init(). Similarly, sqlite3_shutdown() +** shall invoke sqlite3_os_end(). +** +** The sqlite3_initialize() routine returns [SQLITE_OK] on success. +** If for some reason, sqlite3_initialize() is unable to initialize +** the library (perhaps it is unable to allocate a needed resource such +** as a mutex) it returns an [error code] other than [SQLITE_OK]. +** +** The sqlite3_initialize() routine is called internally by many other +** SQLite interfaces so that an application usually does not need to +** invoke sqlite3_initialize() directly. For example, [sqlite3_open()] +** calls sqlite3_initialize() so the SQLite library will be automatically +** initialized when [sqlite3_open()] is called if it has not be initialized +** already. However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT] +** compile-time option, then the automatic calls to sqlite3_initialize() +** are omitted and the application must call sqlite3_initialize() directly +** prior to using any other SQLite interface. For maximum portability, +** it is recommended that applications always invoke sqlite3_initialize() +** directly prior to using any other SQLite interface. Future releases +** of SQLite may require this. In other words, the behavior exhibited +** when SQLite is compiled with [SQLITE_OMIT_AUTOINIT] might become the +** default behavior in some future release of SQLite. +** +** The sqlite3_os_init() routine does operating-system specific +** initialization of the SQLite library. The sqlite3_os_end() +** routine undoes the effect of sqlite3_os_init(). Typical tasks +** performed by these routines include allocation or deallocation +** of static resources, initialization of global variables, +** setting up a default [sqlite3_vfs] module, or setting up +** a default configuration using [sqlite3_config()]. +** +** The application should never invoke either sqlite3_os_init() +** or sqlite3_os_end() directly. The application should only invoke +** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init() +** interface is called automatically by sqlite3_initialize() and +** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate +** implementations for sqlite3_os_init() and sqlite3_os_end() +** are built into SQLite when it is compiled for unix, windows, or os/2. +** When built for other platforms (using the [SQLITE_OS_OTHER=1] compile-time +** option) the application must supply a suitable implementation for +** sqlite3_os_init() and sqlite3_os_end(). An application-supplied +** implementation of sqlite3_os_init() or sqlite3_os_end() +** must return [SQLITE_OK] on success and some other [error code] upon +** failure. +*/ +SQLITE_API int sqlite3_initialize(void); +SQLITE_API int sqlite3_shutdown(void); +SQLITE_API int sqlite3_os_init(void); +SQLITE_API int sqlite3_os_end(void); + +/* +** CAPI3REF: Configuring The SQLite Library {H14100} +** EXPERIMENTAL +** +** The sqlite3_config() interface is used to make global configuration +** changes to SQLite in order to tune SQLite to the specific needs of +** the application. The default configuration is recommended for most +** applications and so this routine is usually not necessary. It is +** provided to support rare applications with unusual needs. +** +** The sqlite3_config() interface is not threadsafe. The application +** must insure that no other SQLite interfaces are invoked by other +** threads while sqlite3_config() is running. Furthermore, sqlite3_config() +** may only be invoked prior to library initialization using +** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. +** Note, however, that sqlite3_config() can be called as part of the +** implementation of an application-defined [sqlite3_os_init()]. +** +** The first argument to sqlite3_config() is an integer +** [SQLITE_CONFIG_SINGLETHREAD | configuration option] that determines +** what property of SQLite is to be configured. Subsequent arguments +** vary depending on the [SQLITE_CONFIG_SINGLETHREAD | configuration option] +** in the first argument. +** +** When a configuration option is set, sqlite3_config() returns [SQLITE_OK]. +** If the option is unknown or SQLite is unable to set the option +** then this routine returns a non-zero [error code]. +** +** Requirements: +** [H14103] [H14106] [H14120] [H14123] [H14126] [H14129] [H14132] [H14135] +** [H14138] [H14141] [H14144] [H14147] [H14150] [H14153] [H14156] [H14159] +** [H14162] [H14165] [H14168] +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_config(int, ...); + +/* +** CAPI3REF: Configure database connections {H14200} +** EXPERIMENTAL +** +** The sqlite3_db_config() interface is used to make configuration +** changes to a [database connection]. The interface is similar to +** [sqlite3_config()] except that the changes apply to a single +** [database connection] (specified in the first argument). The +** sqlite3_db_config() interface can only be used immediately after +** the database connection is created using [sqlite3_open()], +** [sqlite3_open16()], or [sqlite3_open_v2()]. +** +** The second argument to sqlite3_db_config(D,V,...) is the +** configuration verb - an integer code that indicates what +** aspect of the [database connection] is being configured. +** The only choice for this value is [SQLITE_DBCONFIG_LOOKASIDE]. +** New verbs are likely to be added in future releases of SQLite. +** Additional arguments depend on the verb. +** +** Requirements: +** [H14203] [H14206] [H14209] [H14212] [H14215] +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_config(sqlite3*, int op, ...); + +/* +** CAPI3REF: Memory Allocation Routines {H10155} +** EXPERIMENTAL +** +** An instance of this object defines the interface between SQLite +** and low-level memory allocation routines. +** +** This object is used in only one place in the SQLite interface. +** A pointer to an instance of this object is the argument to +** [sqlite3_config()] when the configuration option is +** [SQLITE_CONFIG_MALLOC]. By creating an instance of this object +** and passing it to [sqlite3_config()] during configuration, an +** application can specify an alternative memory allocation subsystem +** for SQLite to use for all of its dynamic memory needs. +** +** Note that SQLite comes with a built-in memory allocator that is +** perfectly adequate for the overwhelming majority of applications +** and that this object is only useful to a tiny minority of applications +** with specialized memory allocation requirements. This object is +** also used during testing of SQLite in order to specify an alternative +** memory allocator that simulates memory out-of-memory conditions in +** order to verify that SQLite recovers gracefully from such +** conditions. +** +** The xMalloc, xFree, and xRealloc methods must work like the +** malloc(), free(), and realloc() functions from the standard library. +** +** xSize should return the allocated size of a memory allocation +** previously obtained from xMalloc or xRealloc. The allocated size +** is always at least as big as the requested size but may be larger. +** +** The xRoundup method returns what would be the allocated size of +** a memory allocation given a particular requested size. Most memory +** allocators round up memory allocations at least to the next multiple +** of 8. Some allocators round up to a larger multiple or to a power of 2. +** +** The xInit method initializes the memory allocator. (For example, +** it might allocate any require mutexes or initialize internal data +** structures. The xShutdown method is invoked (indirectly) by +** [sqlite3_shutdown()] and should deallocate any resources acquired +** by xInit. The pAppData pointer is used as the only parameter to +** xInit and xShutdown. +*/ +typedef struct sqlite3_mem_methods sqlite3_mem_methods; +struct sqlite3_mem_methods { + void *(*xMalloc)(int); /* Memory allocation function */ + void (*xFree)(void*); /* Free a prior allocation */ + void *(*xRealloc)(void*,int); /* Resize an allocation */ + int (*xSize)(void*); /* Return the size of an allocation */ + int (*xRoundup)(int); /* Round up request size to allocation size */ + int (*xInit)(void*); /* Initialize the memory allocator */ + void (*xShutdown)(void*); /* Deinitialize the memory allocator */ + void *pAppData; /* Argument to xInit() and xShutdown() */ +}; + +/* +** CAPI3REF: Configuration Options {H10160} +** EXPERIMENTAL +** +** These constants are the available integer configuration options that +** can be passed as the first argument to the [sqlite3_config()] interface. +** +** New configuration options may be added in future releases of SQLite. +** Existing configuration options might be discontinued. Applications +** should check the return code from [sqlite3_config()] to make sure that +** the call worked. The [sqlite3_config()] interface will return a +** non-zero [error code] if a discontinued or unsupported configuration option +** is invoked. +** +**
+**
SQLITE_CONFIG_SINGLETHREAD
+**
There are no arguments to this option. This option disables +** all mutexing and puts SQLite into a mode where it can only be used +** by a single thread.
+** +**
SQLITE_CONFIG_MULTITHREAD
+**
There are no arguments to this option. This option disables +** mutexing on [database connection] and [prepared statement] objects. +** The application is responsible for serializing access to +** [database connections] and [prepared statements]. But other mutexes +** are enabled so that SQLite will be safe to use in a multi-threaded +** environment as long as no two threads attempt to use the same +** [database connection] at the same time. See the [threading mode] +** documentation for additional information.
+** +**
SQLITE_CONFIG_SERIALIZED
+**
There are no arguments to this option. This option enables +** all mutexes including the recursive +** mutexes on [database connection] and [prepared statement] objects. +** In this mode (which is the default when SQLite is compiled with +** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access +** to [database connections] and [prepared statements] so that the +** application is free to use the same [database connection] or the +** same [prepared statement] in different threads at the same time. +** See the [threading mode] documentation for additional information.
+** +**
SQLITE_CONFIG_MALLOC
+**
This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mem_methods] structure. The argument specifies +** alternative low-level memory allocation routines to be used in place of +** the memory allocation routines built into SQLite.
+** +**
SQLITE_CONFIG_GETMALLOC
+**
This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods] +** structure is filled with the currently defined memory allocation routines. +** This option can be used to overload the default memory allocation +** routines with a wrapper that simulations memory allocation failure or +** tracks memory usage, for example.
+** +**
SQLITE_CONFIG_MEMSTATUS
+**
This option takes single argument of type int, interpreted as a +** boolean, which enables or disables the collection of memory allocation +** statistics. When disabled, the following SQLite interfaces become +** non-operational: +**
    +**
  • [sqlite3_memory_used()] +**
  • [sqlite3_memory_highwater()] +**
  • [sqlite3_soft_heap_limit()] +**
  • [sqlite3_status()] +**
+**
+** +**
SQLITE_CONFIG_SCRATCH
+**
This option specifies a static memory buffer that SQLite can use for +** scratch memory. There are three arguments: A pointer to the memory, the +** size of each scratch buffer (sz), and the number of buffers (N). The sz +** argument must be a multiple of 16. The sz parameter should be a few bytes +** larger than the actual scratch space required due internal overhead. +** The first +** argument should point to an allocation of at least sz*N bytes of memory. +** SQLite will use no more than one scratch buffer at once per thread, so +** N should be set to the expected maximum number of threads. The sz +** parameter should be 6 times the size of the largest database page size. +** Scratch buffers are used as part of the btree balance operation. If +** The btree balancer needs additional memory beyond what is provided by +** scratch buffers or if no scratch buffer space is specified, then SQLite +** goes to [sqlite3_malloc()] to obtain the memory it needs.
+** +**
SQLITE_CONFIG_PAGECACHE
+**
This option specifies a static memory buffer that SQLite can use for +** the database page cache with the default page cache implemenation. +** This configuration should not be used if an application-define page +** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option. +** There are three arguments to this option: A pointer to the +** memory, the size of each page buffer (sz), and the number of pages (N). +** The sz argument must be a power of two between 512 and 32768. The first +** argument should point to an allocation of at least sz*N bytes of memory. +** SQLite will use the memory provided by the first argument to satisfy its +** memory needs for the first N pages that it adds to cache. If additional +** page cache memory is needed beyond what is provided by this option, then +** SQLite goes to [sqlite3_malloc()] for the additional storage space. +** The implementation might use one or more of the N buffers to hold +** memory accounting information.
+** +**
SQLITE_CONFIG_HEAP
+**
This option specifies a static memory buffer that SQLite will use +** for all of its dynamic memory allocation needs beyond those provided +** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. +** There are three arguments: A pointer to the memory, the number of +** bytes in the memory buffer, and the minimum allocation size. If +** the first pointer (the memory pointer) is NULL, then SQLite reverts +** to using its default memory allocator (the system malloc() implementation), +** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. If the +** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or +** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory +** allocator is engaged to handle all of SQLites memory allocation needs.
+** +**
SQLITE_CONFIG_MUTEX
+**
This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mutex_methods] structure. The argument specifies +** alternative low-level mutex routines to be used in place +** the mutex routines built into SQLite.
+** +**
SQLITE_CONFIG_GETMUTEX
+**
This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mutex_methods] structure. The +** [sqlite3_mutex_methods] +** structure is filled with the currently defined mutex routines. +** This option can be used to overload the default mutex allocation +** routines with a wrapper used to track mutex usage for performance +** profiling or testing, for example.
+** +**
SQLITE_CONFIG_LOOKASIDE
+**
This option takes two arguments that determine the default +** memory allcation lookaside optimization. The first argument is the +** size of each lookaside buffer slot and the second is the number of +** slots allocated to each database connection.
+** +**
SQLITE_CONFIG_PCACHE
+**
This option takes a single argument which is a pointer to +** an [sqlite3_pcache_methods] object. This object specifies the interface +** to a custom page cache implementation. SQLite makes a copy of the +** object and uses it for page cache memory allocations.
+** +**
SQLITE_CONFIG_GETPCACHE
+**
This option takes a single argument which is a pointer to an +** [sqlite3_pcache_methods] object. SQLite copies of the current +** page cache implementation into that object.
+** +**
+*/ +#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ +#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ +#define SQLITE_CONFIG_SERIALIZED 3 /* nil */ +#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ +#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ +#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ +#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */ +#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ +#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ +#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ +#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ +/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ +#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ +#define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */ +#define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */ + +/* +** CAPI3REF: Configuration Options {H10170} +** EXPERIMENTAL +** +** These constants are the available integer configuration options that +** can be passed as the second argument to the [sqlite3_db_config()] interface. +** +** New configuration options may be added in future releases of SQLite. +** Existing configuration options might be discontinued. Applications +** should check the return code from [sqlite3_db_config()] to make sure that +** the call worked. The [sqlite3_db_config()] interface will return a +** non-zero [error code] if a discontinued or unsupported configuration option +** is invoked. +** +**
+**
SQLITE_DBCONFIG_LOOKASIDE
+**
This option takes three additional arguments that determine the +** [lookaside memory allocator] configuration for the [database connection]. +** The first argument (the third parameter to [sqlite3_db_config()] is a +** pointer to a memory buffer to use for lookaside memory. The first +** argument may be NULL in which case SQLite will allocate the lookaside +** buffer itself using [sqlite3_malloc()]. The second argument is the +** size of each lookaside buffer slot and the third argument is the number of +** slots. The size of the buffer in the first argument must be greater than +** or equal to the product of the second and third arguments.
+** +**
+*/ +#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ + + +/* +** CAPI3REF: Enable Or Disable Extended Result Codes {H12200} +** +** The sqlite3_extended_result_codes() routine enables or disables the +** [extended result codes] feature of SQLite. The extended result +** codes are disabled by default for historical compatibility considerations. +** +** Requirements: +** [H12201] [H12202] +*/ +SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); + +/* +** CAPI3REF: Last Insert Rowid {H12220} +** +** Each entry in an SQLite table has a unique 64-bit signed +** integer key called the [ROWID | "rowid"]. The rowid is always available +** as an undeclared column named ROWID, OID, or _ROWID_ as long as those +** names are not also used by explicitly declared columns. If +** the table has a column of type [INTEGER PRIMARY KEY] then that column +** is another alias for the rowid. +** +** This routine returns the [rowid] of the most recent +** successful [INSERT] into the database from the [database connection] +** in the first argument. If no successful [INSERT]s +** have ever occurred on that database connection, zero is returned. +** +** If an [INSERT] occurs within a trigger, then the [rowid] of the inserted +** row is returned by this routine as long as the trigger is running. +** But once the trigger terminates, the value returned by this routine +** reverts to the last value inserted before the trigger fired. +** +** An [INSERT] that fails due to a constraint violation is not a +** successful [INSERT] and does not change the value returned by this +** routine. Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, +** and INSERT OR ABORT make no changes to the return value of this +** routine when their insertion fails. When INSERT OR REPLACE +** encounters a constraint violation, it does not fail. The +** INSERT continues to completion after deleting rows that caused +** the constraint problem so INSERT OR REPLACE will always change +** the return value of this interface. +** +** For the purposes of this routine, an [INSERT] is considered to +** be successful even if it is subsequently rolled back. +** +** Requirements: +** [H12221] [H12223] +** +** If a separate thread performs a new [INSERT] on the same +** database connection while the [sqlite3_last_insert_rowid()] +** function is running and thus changes the last insert [rowid], +** then the value returned by [sqlite3_last_insert_rowid()] is +** unpredictable and might not equal either the old or the new +** last insert [rowid]. +*/ +SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); + +/* +** CAPI3REF: Count The Number Of Rows Modified {H12240} +** +** This function returns the number of database rows that were changed +** or inserted or deleted by the most recently completed SQL statement +** on the [database connection] specified by the first parameter. +** Only changes that are directly specified by the [INSERT], [UPDATE], +** or [DELETE] statement are counted. Auxiliary changes caused by +** triggers are not counted. Use the [sqlite3_total_changes()] function +** to find the total number of changes including changes caused by triggers. +** +** A "row change" is a change to a single row of a single table +** caused by an INSERT, DELETE, or UPDATE statement. Rows that +** are changed as side effects of REPLACE constraint resolution, +** rollback, ABORT processing, DROP TABLE, or by any other +** mechanisms do not count as direct row changes. +** +** A "trigger context" is a scope of execution that begins and +** ends with the script of a trigger. Most SQL statements are +** evaluated outside of any trigger. This is the "top level" +** trigger context. If a trigger fires from the top level, a +** new trigger context is entered for the duration of that one +** trigger. Subtriggers create subcontexts for their duration. +** +** Calling [sqlite3_exec()] or [sqlite3_step()] recursively does +** not create a new trigger context. +** +** This function returns the number of direct row changes in the +** most recent INSERT, UPDATE, or DELETE statement within the same +** trigger context. +** +** Thus, when called from the top level, this function returns the +** number of changes in the most recent INSERT, UPDATE, or DELETE +** that also occurred at the top level. Within the body of a trigger, +** the sqlite3_changes() interface can be called to find the number of +** changes in the most recently completed INSERT, UPDATE, or DELETE +** statement within the body of the same trigger. +** However, the number returned does not include changes +** caused by subtriggers since those have their own context. +** +** SQLite implements the command "DELETE FROM table" without a WHERE clause +** by dropping and recreating the table. Doing so is much faster than going +** through and deleting individual elements from the table. Because of this +** optimization, the deletions in "DELETE FROM table" are not row changes and +** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()] +** functions, regardless of the number of elements that were originally +** in the table. To get an accurate count of the number of rows deleted, use +** "DELETE FROM table WHERE 1" instead. Or recompile using the +** [SQLITE_OMIT_TRUNCATE_OPTIMIZATION] compile-time option to disable the +** optimization on all queries. +** +** Requirements: +** [H12241] [H12243] +** +** If a separate thread makes changes on the same database connection +** while [sqlite3_changes()] is running then the value returned +** is unpredictable and not meaningful. +*/ +SQLITE_API int sqlite3_changes(sqlite3*); + +/* +** CAPI3REF: Total Number Of Rows Modified {H12260} +** +** This function returns the number of row changes caused by INSERT, +** UPDATE or DELETE statements since the [database connection] was opened. +** The count includes all changes from all trigger contexts. However, +** the count does not include changes used to implement REPLACE constraints, +** do rollbacks or ABORT processing, or DROP table processing. +** The changes are counted as soon as the statement that makes them is +** completed (when the statement handle is passed to [sqlite3_reset()] or +** [sqlite3_finalize()]). +** +** SQLite implements the command "DELETE FROM table" without a WHERE clause +** by dropping and recreating the table. (This is much faster than going +** through and deleting individual elements from the table.) Because of this +** optimization, the deletions in "DELETE FROM table" are not row changes and +** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()] +** functions, regardless of the number of elements that were originally +** in the table. To get an accurate count of the number of rows deleted, use +** "DELETE FROM table WHERE 1" instead. Or recompile using the +** [SQLITE_OMIT_TRUNCATE_OPTIMIZATION] compile-time option to disable the +** optimization on all queries. +** +** See also the [sqlite3_changes()] interface. +** +** Requirements: +** [H12261] [H12263] +** +** If a separate thread makes changes on the same database connection +** while [sqlite3_total_changes()] is running then the value +** returned is unpredictable and not meaningful. +*/ +SQLITE_API int sqlite3_total_changes(sqlite3*); + +/* +** CAPI3REF: Interrupt A Long-Running Query {H12270} +** +** This function causes any pending database operation to abort and +** return at its earliest opportunity. This routine is typically +** called in response to a user action such as pressing "Cancel" +** or Ctrl-C where the user wants a long query operation to halt +** immediately. +** +** It is safe to call this routine from a thread different from the +** thread that is currently running the database operation. But it +** is not safe to call this routine with a [database connection] that +** is closed or might close before sqlite3_interrupt() returns. +** +** If an SQL operation is very nearly finished at the time when +** sqlite3_interrupt() is called, then it might not have an opportunity +** to be interrupted and might continue to completion. +** +** An SQL operation that is interrupted will return [SQLITE_INTERRUPT]. +** If the interrupted SQL operation is an INSERT, UPDATE, or DELETE +** that is inside an explicit transaction, then the entire transaction +** will be rolled back automatically. +** +** A call to sqlite3_interrupt() has no effect on SQL statements +** that are started after sqlite3_interrupt() returns. +** +** Requirements: +** [H12271] [H12272] +** +** If the database connection closes while [sqlite3_interrupt()] +** is running then bad things will likely happen. +*/ +SQLITE_API void sqlite3_interrupt(sqlite3*); + +/* +** CAPI3REF: Determine If An SQL Statement Is Complete {H10510} +** +** These routines are useful for command-line input to determine if the +** currently entered text seems to form complete a SQL statement or +** if additional input is needed before sending the text into +** SQLite for parsing. These routines return true if the input string +** appears to be a complete SQL statement. A statement is judged to be +** complete if it ends with a semicolon token and is not a fragment of a +** CREATE TRIGGER statement. Semicolons that are embedded within +** string literals or quoted identifier names or comments are not +** independent tokens (they are part of the token in which they are +** embedded) and thus do not count as a statement terminator. +** +** These routines do not parse the SQL statements thus +** will not detect syntactically incorrect SQL. +** +** Requirements: [H10511] [H10512] +** +** The input to [sqlite3_complete()] must be a zero-terminated +** UTF-8 string. +** +** The input to [sqlite3_complete16()] must be a zero-terminated +** UTF-16 string in native byte order. +*/ +SQLITE_API int sqlite3_complete(const char *sql); +SQLITE_API int sqlite3_complete16(const void *sql); + +/* +** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {H12310} +** +** This routine sets a callback function that might be invoked whenever +** an attempt is made to open a database table that another thread +** or process has locked. +** +** If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] +** is returned immediately upon encountering the lock. If the busy callback +** is not NULL, then the callback will be invoked with two arguments. +** +** The first argument to the handler is a copy of the void* pointer which +** is the third argument to sqlite3_busy_handler(). The second argument to +** the handler callback is the number of times that the busy handler has +** been invoked for this locking event. If the +** busy callback returns 0, then no additional attempts are made to +** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. +** If the callback returns non-zero, then another attempt +** is made to open the database for reading and the cycle repeats. +** +** The presence of a busy handler does not guarantee that it will be invoked +** when there is lock contention. If SQLite determines that invoking the busy +** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY] +** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler. +** Consider a scenario where one process is holding a read lock that +** it is trying to promote to a reserved lock and +** a second process is holding a reserved lock that it is trying +** to promote to an exclusive lock. The first process cannot proceed +** because it is blocked by the second and the second process cannot +** proceed because it is blocked by the first. If both processes +** invoke the busy handlers, neither will make any progress. Therefore, +** SQLite returns [SQLITE_BUSY] for the first process, hoping that this +** will induce the first process to release its read lock and allow +** the second process to proceed. +** +** The default busy callback is NULL. +** +** The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] +** when SQLite is in the middle of a large transaction where all the +** changes will not fit into the in-memory cache. SQLite will +** already hold a RESERVED lock on the database file, but it needs +** to promote this lock to EXCLUSIVE so that it can spill cache +** pages into the database file without harm to concurrent +** readers. If it is unable to promote the lock, then the in-memory +** cache will be left in an inconsistent state and so the error +** code is promoted from the relatively benign [SQLITE_BUSY] to +** the more severe [SQLITE_IOERR_BLOCKED]. This error code promotion +** forces an automatic rollback of the changes. See the +** +** CorruptionFollowingBusyError wiki page for a discussion of why +** this is important. +** +** There can only be a single busy handler defined for each +** [database connection]. Setting a new busy handler clears any +** previously set handler. Note that calling [sqlite3_busy_timeout()] +** will also set or clear the busy handler. +** +** The busy callback should not take any actions which modify the +** database connection that invoked the busy handler. Any such actions +** result in undefined behavior. +** +** Requirements: +** [H12311] [H12312] [H12314] [H12316] [H12318] +** +** A busy handler must not close the database connection +** or [prepared statement] that invoked the busy handler. +*/ +SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); + +/* +** CAPI3REF: Set A Busy Timeout {H12340} +** +** This routine sets a [sqlite3_busy_handler | busy handler] that sleeps +** for a specified amount of time when a table is locked. The handler +** will sleep multiple times until at least "ms" milliseconds of sleeping +** have accumulated. {H12343} After "ms" milliseconds of sleeping, +** the handler returns 0 which causes [sqlite3_step()] to return +** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. +** +** Calling this routine with an argument less than or equal to zero +** turns off all busy handlers. +** +** There can only be a single busy handler for a particular +** [database connection] any any given moment. If another busy handler +** was defined (using [sqlite3_busy_handler()]) prior to calling +** this routine, that other busy handler is cleared. +** +** Requirements: +** [H12341] [H12343] [H12344] +*/ +SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); + +/* +** CAPI3REF: Convenience Routines For Running Queries {H12370} +** +** Definition: A result table is memory data structure created by the +** [sqlite3_get_table()] interface. A result table records the +** complete query results from one or more queries. +** +** The table conceptually has a number of rows and columns. But +** these numbers are not part of the result table itself. These +** numbers are obtained separately. Let N be the number of rows +** and M be the number of columns. +** +** A result table is an array of pointers to zero-terminated UTF-8 strings. +** There are (N+1)*M elements in the array. The first M pointers point +** to zero-terminated strings that contain the names of the columns. +** The remaining entries all point to query results. NULL values result +** in NULL pointers. All other values are in their UTF-8 zero-terminated +** string representation as returned by [sqlite3_column_text()]. +** +** A result table might consist of one or more memory allocations. +** It is not safe to pass a result table directly to [sqlite3_free()]. +** A result table should be deallocated using [sqlite3_free_table()]. +** +** As an example of the result table format, suppose a query result +** is as follows: +** +**
+**        Name        | Age
+**        -----------------------
+**        Alice       | 43
+**        Bob         | 28
+**        Cindy       | 21
+** 
+** +** There are two column (M==2) and three rows (N==3). Thus the +** result table has 8 entries. Suppose the result table is stored +** in an array names azResult. Then azResult holds this content: +** +**
+**        azResult[0] = "Name";
+**        azResult[1] = "Age";
+**        azResult[2] = "Alice";
+**        azResult[3] = "43";
+**        azResult[4] = "Bob";
+**        azResult[5] = "28";
+**        azResult[6] = "Cindy";
+**        azResult[7] = "21";
+** 
+** +** The sqlite3_get_table() function evaluates one or more +** semicolon-separated SQL statements in the zero-terminated UTF-8 +** string of its 2nd parameter. It returns a result table to the +** pointer given in its 3rd parameter. +** +** After the calling function has finished using the result, it should +** pass the pointer to the result table to sqlite3_free_table() in order to +** release the memory that was malloced. Because of the way the +** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling +** function must not try to call [sqlite3_free()] directly. Only +** [sqlite3_free_table()] is able to release the memory properly and safely. +** +** The sqlite3_get_table() interface is implemented as a wrapper around +** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access +** to any internal data structures of SQLite. It uses only the public +** interface defined here. As a consequence, errors that occur in the +** wrapper layer outside of the internal [sqlite3_exec()] call are not +** reflected in subsequent calls to [sqlite3_errcode()] or [sqlite3_errmsg()]. +** +** Requirements: +** [H12371] [H12373] [H12374] [H12376] [H12379] [H12382] +*/ +SQLITE_API int sqlite3_get_table( + sqlite3 *db, /* An open database */ + const char *zSql, /* SQL to be evaluated */ + char ***pazResult, /* Results of the query */ + int *pnRow, /* Number of result rows written here */ + int *pnColumn, /* Number of result columns written here */ + char **pzErrmsg /* Error msg written here */ +); +SQLITE_API void sqlite3_free_table(char **result); + +/* +** CAPI3REF: Formatted String Printing Functions {H17400} +** +** These routines are workalikes of the "printf()" family of functions +** from the standard C library. +** +** The sqlite3_mprintf() and sqlite3_vmprintf() routines write their +** results into memory obtained from [sqlite3_malloc()]. +** The strings returned by these two routines should be +** released by [sqlite3_free()]. Both routines return a +** NULL pointer if [sqlite3_malloc()] is unable to allocate enough +** memory to hold the resulting string. +** +** In sqlite3_snprintf() routine is similar to "snprintf()" from +** the standard C library. The result is written into the +** buffer supplied as the second parameter whose size is given by +** the first parameter. Note that the order of the +** first two parameters is reversed from snprintf(). This is an +** historical accident that cannot be fixed without breaking +** backwards compatibility. Note also that sqlite3_snprintf() +** returns a pointer to its buffer instead of the number of +** characters actually written into the buffer. We admit that +** the number of characters written would be a more useful return +** value but we cannot change the implementation of sqlite3_snprintf() +** now without breaking compatibility. +** +** As long as the buffer size is greater than zero, sqlite3_snprintf() +** guarantees that the buffer is always zero-terminated. The first +** parameter "n" is the total size of the buffer, including space for +** the zero terminator. So the longest string that can be completely +** written will be n-1 characters. +** +** These routines all implement some additional formatting +** options that are useful for constructing SQL statements. +** All of the usual printf() formatting options apply. In addition, there +** is are "%q", "%Q", and "%z" options. +** +** The %q option works like %s in that it substitutes a null-terminated +** string from the argument list. But %q also doubles every '\'' character. +** %q is designed for use inside a string literal. By doubling each '\'' +** character it escapes that character and allows it to be inserted into +** the string. +** +** For example, assume the string variable zText contains text as follows: +** +**
+**  char *zText = "It's a happy day!";
+** 
+** +** One can use this text in an SQL statement as follows: +** +**
+**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
+**  sqlite3_exec(db, zSQL, 0, 0, 0);
+**  sqlite3_free(zSQL);
+** 
+** +** Because the %q format string is used, the '\'' character in zText +** is escaped and the SQL generated is as follows: +** +**
+**  INSERT INTO table1 VALUES('It''s a happy day!')
+** 
+** +** This is correct. Had we used %s instead of %q, the generated SQL +** would have looked like this: +** +**
+**  INSERT INTO table1 VALUES('It's a happy day!');
+** 
+** +** This second example is an SQL syntax error. As a general rule you should +** always use %q instead of %s when inserting text into a string literal. +** +** The %Q option works like %q except it also adds single quotes around +** the outside of the total string. Additionally, if the parameter in the +** argument list is a NULL pointer, %Q substitutes the text "NULL" (without +** single quotes) in place of the %Q option. So, for example, one could say: +** +**
+**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
+**  sqlite3_exec(db, zSQL, 0, 0, 0);
+**  sqlite3_free(zSQL);
+** 
+** +** The code above will render a correct SQL statement in the zSQL +** variable even if the zText variable is a NULL pointer. +** +** The "%z" formatting option works exactly like "%s" with the +** addition that after the string has been read and copied into +** the result, [sqlite3_free()] is called on the input string. {END} +** +** Requirements: +** [H17403] [H17406] [H17407] +*/ +SQLITE_API char *sqlite3_mprintf(const char*,...); +SQLITE_API char *sqlite3_vmprintf(const char*, va_list); +SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); + +/* +** CAPI3REF: Memory Allocation Subsystem {H17300} +** +** The SQLite core uses these three routines for all of its own +** internal memory allocation needs. "Core" in the previous sentence +** does not include operating-system specific VFS implementation. The +** Windows VFS uses native malloc() and free() for some operations. +** +** The sqlite3_malloc() routine returns a pointer to a block +** of memory at least N bytes in length, where N is the parameter. +** If sqlite3_malloc() is unable to obtain sufficient free +** memory, it returns a NULL pointer. If the parameter N to +** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns +** a NULL pointer. +** +** Calling sqlite3_free() with a pointer previously returned +** by sqlite3_malloc() or sqlite3_realloc() releases that memory so +** that it might be reused. The sqlite3_free() routine is +** a no-op if is called with a NULL pointer. Passing a NULL pointer +** to sqlite3_free() is harmless. After being freed, memory +** should neither be read nor written. Even reading previously freed +** memory might result in a segmentation fault or other severe error. +** Memory corruption, a segmentation fault, or other severe error +** might result if sqlite3_free() is called with a non-NULL pointer that +** was not obtained from sqlite3_malloc() or sqlite3_realloc(). +** +** The sqlite3_realloc() interface attempts to resize a +** prior memory allocation to be at least N bytes, where N is the +** second parameter. The memory allocation to be resized is the first +** parameter. If the first parameter to sqlite3_realloc() +** is a NULL pointer then its behavior is identical to calling +** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). +** If the second parameter to sqlite3_realloc() is zero or +** negative then the behavior is exactly the same as calling +** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). +** sqlite3_realloc() returns a pointer to a memory allocation +** of at least N bytes in size or NULL if sufficient memory is unavailable. +** If M is the size of the prior allocation, then min(N,M) bytes +** of the prior allocation are copied into the beginning of buffer returned +** by sqlite3_realloc() and the prior allocation is freed. +** If sqlite3_realloc() returns NULL, then the prior allocation +** is not freed. +** +** The memory returned by sqlite3_malloc() and sqlite3_realloc() +** is always aligned to at least an 8 byte boundary. {END} +** +** The default implementation of the memory allocation subsystem uses +** the malloc(), realloc() and free() provided by the standard C library. +** {H17382} However, if SQLite is compiled with the +** SQLITE_MEMORY_SIZE=NNN C preprocessor macro (where NNN +** is an integer), then SQLite create a static array of at least +** NNN bytes in size and uses that array for all of its dynamic +** memory allocation needs. {END} Additional memory allocator options +** may be added in future releases. +** +** In SQLite version 3.5.0 and 3.5.1, it was possible to define +** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in +** implementation of these routines to be omitted. That capability +** is no longer provided. Only built-in memory allocators can be used. +** +** The Windows OS interface layer calls +** the system malloc() and free() directly when converting +** filenames between the UTF-8 encoding used by SQLite +** and whatever filename encoding is used by the particular Windows +** installation. Memory allocation errors are detected, but +** they are reported back as [SQLITE_CANTOPEN] or +** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. +** +** Requirements: +** [H17303] [H17304] [H17305] [H17306] [H17310] [H17312] [H17315] [H17318] +** [H17321] [H17322] [H17323] +** +** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] +** must be either NULL or else pointers obtained from a prior +** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have +** not yet been released. +** +** The application must not read or write any part of +** a block of memory after it has been released using +** [sqlite3_free()] or [sqlite3_realloc()]. +*/ +SQLITE_API void *sqlite3_malloc(int); +SQLITE_API void *sqlite3_realloc(void*, int); +SQLITE_API void sqlite3_free(void*); + +/* +** CAPI3REF: Memory Allocator Statistics {H17370} +** +** SQLite provides these two interfaces for reporting on the status +** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()] +** routines, which form the built-in memory allocation subsystem. +** +** Requirements: +** [H17371] [H17373] [H17374] [H17375] +*/ +SQLITE_API sqlite3_int64 sqlite3_memory_used(void); +SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); + +/* +** CAPI3REF: Pseudo-Random Number Generator {H17390} +** +** SQLite contains a high-quality pseudo-random number generator (PRNG) used to +** select random [ROWID | ROWIDs] when inserting new records into a table that +** already uses the largest possible [ROWID]. The PRNG is also used for +** the build-in random() and randomblob() SQL functions. This interface allows +** applications to access the same PRNG for other purposes. +** +** A call to this routine stores N bytes of randomness into buffer P. +** +** The first time this routine is invoked (either internally or by +** the application) the PRNG is seeded using randomness obtained +** from the xRandomness method of the default [sqlite3_vfs] object. +** On all subsequent invocations, the pseudo-randomness is generated +** internally and without recourse to the [sqlite3_vfs] xRandomness +** method. +** +** Requirements: +** [H17392] +*/ +SQLITE_API void sqlite3_randomness(int N, void *P); + +/* +** CAPI3REF: Compile-Time Authorization Callbacks {H12500} +** +** This routine registers a authorizer callback with a particular +** [database connection], supplied in the first argument. +** The authorizer callback is invoked as SQL statements are being compiled +** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], +** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. At various +** points during the compilation process, as logic is being created +** to perform various actions, the authorizer callback is invoked to +** see if those actions are allowed. The authorizer callback should +** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the +** specific action but allow the SQL statement to continue to be +** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be +** rejected with an error. If the authorizer callback returns +** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] +** then the [sqlite3_prepare_v2()] or equivalent call that triggered +** the authorizer will fail with an error message. +** +** When the callback returns [SQLITE_OK], that means the operation +** requested is ok. When the callback returns [SQLITE_DENY], the +** [sqlite3_prepare_v2()] or equivalent call that triggered the +** authorizer will fail with an error message explaining that +** access is denied. If the authorizer code is [SQLITE_READ] +** and the callback returns [SQLITE_IGNORE] then the +** [prepared statement] statement is constructed to substitute +** a NULL value in place of the table column that would have +** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] +** return can be used to deny an untrusted user access to individual +** columns of a table. +** +** The first parameter to the authorizer callback is a copy of the third +** parameter to the sqlite3_set_authorizer() interface. The second parameter +** to the callback is an integer [SQLITE_COPY | action code] that specifies +** the particular action to be authorized. The third through sixth parameters +** to the callback are zero-terminated strings that contain additional +** details about the action to be authorized. +** +** An authorizer is used when [sqlite3_prepare | preparing] +** SQL statements from an untrusted source, to ensure that the SQL statements +** do not try to access data they are not allowed to see, or that they do not +** try to execute malicious statements that damage the database. For +** example, an application may allow a user to enter arbitrary +** SQL queries for evaluation by a database. But the application does +** not want the user to be able to make arbitrary changes to the +** database. An authorizer could then be put in place while the +** user-entered SQL is being [sqlite3_prepare | prepared] that +** disallows everything except [SELECT] statements. +** +** Applications that need to process SQL from untrusted sources +** might also consider lowering resource limits using [sqlite3_limit()] +** and limiting database size using the [max_page_count] [PRAGMA] +** in addition to using an authorizer. +** +** Only a single authorizer can be in place on a database connection +** at a time. Each call to sqlite3_set_authorizer overrides the +** previous call. Disable the authorizer by installing a NULL callback. +** The authorizer is disabled by default. +** +** The authorizer callback must not do anything that will modify +** the database connection that invoked the authorizer callback. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +** When [sqlite3_prepare_v2()] is used to prepare a statement, the +** statement might be reprepared during [sqlite3_step()] due to a +** schema change. Hence, the application should ensure that the +** correct authorizer callback remains in place during the [sqlite3_step()]. +** +** Note that the authorizer callback is invoked only during +** [sqlite3_prepare()] or its variants. Authorization is not +** performed during statement evaluation in [sqlite3_step()]. +** +** Requirements: +** [H12501] [H12502] [H12503] [H12504] [H12505] [H12506] [H12507] [H12510] +** [H12511] [H12512] [H12520] [H12521] [H12522] +*/ +SQLITE_API int sqlite3_set_authorizer( + sqlite3*, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pUserData +); + +/* +** CAPI3REF: Authorizer Return Codes {H12590} +** +** The [sqlite3_set_authorizer | authorizer callback function] must +** return either [SQLITE_OK] or one of these two constants in order +** to signal SQLite whether or not the action is permitted. See the +** [sqlite3_set_authorizer | authorizer documentation] for additional +** information. +*/ +#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ +#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ + +/* +** CAPI3REF: Authorizer Action Codes {H12550} +** +** The [sqlite3_set_authorizer()] interface registers a callback function +** that is invoked to authorize certain SQL statement actions. The +** second parameter to the callback is an integer code that specifies +** what action is being authorized. These are the integer action codes that +** the authorizer callback may be passed. +** +** These action code values signify what kind of operation is to be +** authorized. The 3rd and 4th parameters to the authorization +** callback function will be parameters or NULL depending on which of these +** codes is used as the second parameter. The 5th parameter to the +** authorizer callback is the name of the database ("main", "temp", +** etc.) if applicable. The 6th parameter to the authorizer callback +** is the name of the inner-most trigger or view that is responsible for +** the access attempt or NULL if this access attempt is directly from +** top-level SQL code. +** +** Requirements: +** [H12551] [H12552] [H12553] [H12554] +*/ +/******************************************* 3rd ************ 4th ***********/ +#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ +#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ +#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ +#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ +#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ +#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ +#define SQLITE_DELETE 9 /* Table Name NULL */ +#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ +#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ +#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ +#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ +#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ +#define SQLITE_DROP_VIEW 17 /* View Name NULL */ +#define SQLITE_INSERT 18 /* Table Name NULL */ +#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ +#define SQLITE_READ 20 /* Table Name Column Name */ +#define SQLITE_SELECT 21 /* NULL NULL */ +#define SQLITE_TRANSACTION 22 /* Operation NULL */ +#define SQLITE_UPDATE 23 /* Table Name Column Name */ +#define SQLITE_ATTACH 24 /* Filename NULL */ +#define SQLITE_DETACH 25 /* Database Name NULL */ +#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ +#define SQLITE_REINDEX 27 /* Index Name NULL */ +#define SQLITE_ANALYZE 28 /* Table Name NULL */ +#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ +#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ +#define SQLITE_FUNCTION 31 /* NULL Function Name */ +#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ +#define SQLITE_COPY 0 /* No longer used */ + +/* +** CAPI3REF: Tracing And Profiling Functions {H12280} +** EXPERIMENTAL +** +** These routines register callback functions that can be used for +** tracing and profiling the execution of SQL statements. +** +** The callback function registered by sqlite3_trace() is invoked at +** various times when an SQL statement is being run by [sqlite3_step()]. +** The callback returns a UTF-8 rendering of the SQL statement text +** as the statement first begins executing. Additional callbacks occur +** as each triggered subprogram is entered. The callbacks for triggers +** contain a UTF-8 SQL comment that identifies the trigger. +** +** The callback function registered by sqlite3_profile() is invoked +** as each SQL statement finishes. The profile callback contains +** the original statement text and an estimate of wall-clock time +** of how long that statement took to run. +** +** Requirements: +** [H12281] [H12282] [H12283] [H12284] [H12285] [H12287] [H12288] [H12289] +** [H12290] +*/ +SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); +SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, + void(*xProfile)(void*,const char*,sqlite3_uint64), void*); + +/* +** CAPI3REF: Query Progress Callbacks {H12910} +** +** This routine configures a callback function - the +** progress callback - that is invoked periodically during long +** running calls to [sqlite3_exec()], [sqlite3_step()] and +** [sqlite3_get_table()]. An example use for this +** interface is to keep a GUI updated during a large query. +** +** If the progress callback returns non-zero, the operation is +** interrupted. This feature can be used to implement a +** "Cancel" button on a GUI progress dialog box. +** +** The progress handler must not do anything that will modify +** the database connection that invoked the progress handler. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +** Requirements: +** [H12911] [H12912] [H12913] [H12914] [H12915] [H12916] [H12917] [H12918] +** +*/ +SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); + +/* +** CAPI3REF: Opening A New Database Connection {H12700} +** +** These routines open an SQLite database file whose name is given by the +** filename argument. The filename argument is interpreted as UTF-8 for +** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte +** order for sqlite3_open16(). A [database connection] handle is usually +** returned in *ppDb, even if an error occurs. The only exception is that +** if SQLite is unable to allocate memory to hold the [sqlite3] object, +** a NULL will be written into *ppDb instead of a pointer to the [sqlite3] +** object. If the database is opened (and/or created) successfully, then +** [SQLITE_OK] is returned. Otherwise an [error code] is returned. The +** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain +** an English language description of the error. +** +** The default encoding for the database will be UTF-8 if +** sqlite3_open() or sqlite3_open_v2() is called and +** UTF-16 in the native byte order if sqlite3_open16() is used. +** +** Whether or not an error occurs when it is opened, resources +** associated with the [database connection] handle should be released by +** passing it to [sqlite3_close()] when it is no longer required. +** +** The sqlite3_open_v2() interface works like sqlite3_open() +** except that it accepts two additional parameters for additional control +** over the new database connection. The flags parameter can take one of +** the following three values, optionally combined with the +** [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags: +** +**
+**
[SQLITE_OPEN_READONLY]
+**
The database is opened in read-only mode. If the database does not +** already exist, an error is returned.
+** +**
[SQLITE_OPEN_READWRITE]
+**
The database is opened for reading and writing if possible, or reading +** only if the file is write protected by the operating system. In either +** case the database must already exist, otherwise an error is returned.
+** +**
[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]
+**
The database is opened for reading and writing, and is creates it if +** it does not already exist. This is the behavior that is always used for +** sqlite3_open() and sqlite3_open16().
+**
+** +** If the 3rd parameter to sqlite3_open_v2() is not one of the +** combinations shown above or one of the combinations shown above combined +** with the [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags, +** then the behavior is undefined. +** +** If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection +** opens in the multi-thread [threading mode] as long as the single-thread +** mode has not been set at compile-time or start-time. If the +** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens +** in the serialized [threading mode] unless single-thread was +** previously selected at compile-time or start-time. +** +** If the filename is ":memory:", then a private, temporary in-memory database +** is created for the connection. This in-memory database will vanish when +** the database connection is closed. Future versions of SQLite might +** make use of additional special filenames that begin with the ":" character. +** It is recommended that when a database filename actually does begin with +** a ":" character you should prefix the filename with a pathname such as +** "./" to avoid ambiguity. +** +** If the filename is an empty string, then a private, temporary +** on-disk database will be created. This private database will be +** automatically deleted as soon as the database connection is closed. +** +** The fourth parameter to sqlite3_open_v2() is the name of the +** [sqlite3_vfs] object that defines the operating system interface that +** the new database connection should use. If the fourth parameter is +** a NULL pointer then the default [sqlite3_vfs] object is used. +** +** Note to Windows users: The encoding used for the filename argument +** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever +** codepage is currently defined. Filenames containing international +** characters must be converted to UTF-8 prior to passing them into +** sqlite3_open() or sqlite3_open_v2(). +** +** Requirements: +** [H12701] [H12702] [H12703] [H12704] [H12706] [H12707] [H12709] [H12711] +** [H12712] [H12713] [H12714] [H12717] [H12719] [H12721] [H12723] +*/ +SQLITE_API int sqlite3_open( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +SQLITE_API int sqlite3_open16( + const void *filename, /* Database filename (UTF-16) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +SQLITE_API int sqlite3_open_v2( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs /* Name of VFS module to use */ +); + +/* +** CAPI3REF: Error Codes And Messages {H12800} +** +** The sqlite3_errcode() interface returns the numeric [result code] or +** [extended result code] for the most recent failed sqlite3_* API call +** associated with a [database connection]. If a prior API call failed +** but the most recent API call succeeded, the return value from +** sqlite3_errcode() is undefined. The sqlite3_extended_errcode() +** interface is the same except that it always returns the +** [extended result code] even when extended result codes are +** disabled. +** +** The sqlite3_errmsg() and sqlite3_errmsg16() return English-language +** text that describes the error, as either UTF-8 or UTF-16 respectively. +** Memory to hold the error message string is managed internally. +** The application does not need to worry about freeing the result. +** However, the error string might be overwritten or deallocated by +** subsequent calls to other SQLite interface functions. +** +** When the serialized [threading mode] is in use, it might be the +** case that a second error occurs on a separate thread in between +** the time of the first error and the call to these interfaces. +** When that happens, the second error will be reported since these +** interfaces always report the most recent result. To avoid +** this, each thread can obtain exclusive use of the [database connection] D +** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning +** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after +** all calls to the interfaces listed here are completed. +** +** If an interface fails with SQLITE_MISUSE, that means the interface +** was invoked incorrectly by the application. In that case, the +** error code and message may or may not be set. +** +** Requirements: +** [H12801] [H12802] [H12803] [H12807] [H12808] [H12809] +*/ +SQLITE_API int sqlite3_errcode(sqlite3 *db); +SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); +SQLITE_API const char *sqlite3_errmsg(sqlite3*); +SQLITE_API const void *sqlite3_errmsg16(sqlite3*); + +/* +** CAPI3REF: SQL Statement Object {H13000} +** KEYWORDS: {prepared statement} {prepared statements} +** +** An instance of this object represents a single SQL statement. +** This object is variously known as a "prepared statement" or a +** "compiled SQL statement" or simply as a "statement". +** +** The life of a statement object goes something like this: +** +**
    +**
  1. Create the object using [sqlite3_prepare_v2()] or a related +** function. +**
  2. Bind values to [host parameters] using the sqlite3_bind_*() +** interfaces. +**
  3. Run the SQL by calling [sqlite3_step()] one or more times. +**
  4. Reset the statement using [sqlite3_reset()] then go back +** to step 2. Do this zero or more times. +**
  5. Destroy the object using [sqlite3_finalize()]. +**
+** +** Refer to documentation on individual methods above for additional +** information. +*/ +typedef struct sqlite3_stmt sqlite3_stmt; + +/* +** CAPI3REF: Run-time Limits {H12760} +** +** This interface allows the size of various constructs to be limited +** on a connection by connection basis. The first parameter is the +** [database connection] whose limit is to be set or queried. The +** second parameter is one of the [limit categories] that define a +** class of constructs to be size limited. The third parameter is the +** new limit for that construct. The function returns the old limit. +** +** If the new limit is a negative number, the limit is unchanged. +** For the limit category of SQLITE_LIMIT_XYZ there is a +** [limits | hard upper bound] +** set by a compile-time C preprocessor macro named +** [limits | SQLITE_MAX_XYZ]. +** (The "_LIMIT_" in the name is changed to "_MAX_".) +** Attempts to increase a limit above its hard upper bound are +** silently truncated to the hard upper limit. +** +** Run time limits are intended for use in applications that manage +** both their own internal database and also databases that are controlled +** by untrusted external sources. An example application might be a +** web browser that has its own databases for storing history and +** separate databases controlled by JavaScript applications downloaded +** off the Internet. The internal databases can be given the +** large, default limits. Databases managed by external sources can +** be given much smaller limits designed to prevent a denial of service +** attack. Developers might also want to use the [sqlite3_set_authorizer()] +** interface to further control untrusted SQL. The size of the database +** created by an untrusted script can be contained using the +** [max_page_count] [PRAGMA]. +** +** New run-time limit categories may be added in future releases. +** +** Requirements: +** [H12762] [H12766] [H12769] +*/ +SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); + +/* +** CAPI3REF: Run-Time Limit Categories {H12790} +** KEYWORDS: {limit category} {limit categories} +** +** These constants define various performance limits +** that can be lowered at run-time using [sqlite3_limit()]. +** The synopsis of the meanings of the various limits is shown below. +** Additional information is available at [limits | Limits in SQLite]. +** +**
+**
SQLITE_LIMIT_LENGTH
+**
The maximum size of any string or BLOB or table row.
+** +**
SQLITE_LIMIT_SQL_LENGTH
+**
The maximum length of an SQL statement.
+** +**
SQLITE_LIMIT_COLUMN
+**
The maximum number of columns in a table definition or in the +** result set of a [SELECT] or the maximum number of columns in an index +** or in an ORDER BY or GROUP BY clause.
+** +**
SQLITE_LIMIT_EXPR_DEPTH
+**
The maximum depth of the parse tree on any expression.
+** +**
SQLITE_LIMIT_COMPOUND_SELECT
+**
The maximum number of terms in a compound SELECT statement.
+** +**
SQLITE_LIMIT_VDBE_OP
+**
The maximum number of instructions in a virtual machine program +** used to implement an SQL statement.
+** +**
SQLITE_LIMIT_FUNCTION_ARG
+**
The maximum number of arguments on a function.
+** +**
SQLITE_LIMIT_ATTACHED
+**
The maximum number of [ATTACH | attached databases].
+** +**
SQLITE_LIMIT_LIKE_PATTERN_LENGTH
+**
The maximum length of the pattern argument to the [LIKE] or +** [GLOB] operators.
+** +**
SQLITE_LIMIT_VARIABLE_NUMBER
+**
The maximum number of variables in an SQL statement that can +** be bound.
+**
+*/ +#define SQLITE_LIMIT_LENGTH 0 +#define SQLITE_LIMIT_SQL_LENGTH 1 +#define SQLITE_LIMIT_COLUMN 2 +#define SQLITE_LIMIT_EXPR_DEPTH 3 +#define SQLITE_LIMIT_COMPOUND_SELECT 4 +#define SQLITE_LIMIT_VDBE_OP 5 +#define SQLITE_LIMIT_FUNCTION_ARG 6 +#define SQLITE_LIMIT_ATTACHED 7 +#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 +#define SQLITE_LIMIT_VARIABLE_NUMBER 9 + +/* +** CAPI3REF: Compiling An SQL Statement {H13010} +** KEYWORDS: {SQL statement compiler} +** +** To execute an SQL query, it must first be compiled into a byte-code +** program using one of these routines. +** +** The first argument, "db", is a [database connection] obtained from a +** prior call to [sqlite3_open()], [sqlite3_open_v2()] or [sqlite3_open16()]. +** +** The second argument, "zSql", is the statement to be compiled, encoded +** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() +** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2() +** use UTF-16. +** +** If the nByte argument is less than zero, then zSql is read up to the +** first zero terminator. If nByte is non-negative, then it is the maximum +** number of bytes read from zSql. When nByte is non-negative, the +** zSql string ends at either the first '\000' or '\u0000' character or +** the nByte-th byte, whichever comes first. If the caller knows +** that the supplied string is nul-terminated, then there is a small +** performance advantage to be gained by passing an nByte parameter that +** is equal to the number of bytes in the input string including +** the nul-terminator bytes. +** +** *pzTail is made to point to the first byte past the end of the +** first SQL statement in zSql. These routines only compile the first +** statement in zSql, so *pzTail is left pointing to what remains +** uncompiled. +** +** *ppStmt is left pointing to a compiled [prepared statement] that can be +** executed using [sqlite3_step()]. If there is an error, *ppStmt is set +** to NULL. If the input text contains no SQL (if the input is an empty +** string or a comment) then *ppStmt is set to NULL. +** {A13018} The calling procedure is responsible for deleting the compiled +** SQL statement using [sqlite3_finalize()] after it has finished with it. +** +** On success, [SQLITE_OK] is returned, otherwise an [error code] is returned. +** +** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are +** recommended for all new programs. The two older interfaces are retained +** for backwards compatibility, but their use is discouraged. +** In the "v2" interfaces, the prepared statement +** that is returned (the [sqlite3_stmt] object) contains a copy of the +** original SQL text. This causes the [sqlite3_step()] interface to +** behave a differently in two ways: +** +**
    +**
  1. +** If the database schema changes, instead of returning [SQLITE_SCHEMA] as it +** always used to do, [sqlite3_step()] will automatically recompile the SQL +** statement and try to run it again. If the schema has changed in +** a way that makes the statement no longer valid, [sqlite3_step()] will still +** return [SQLITE_SCHEMA]. But unlike the legacy behavior, [SQLITE_SCHEMA] is +** now a fatal error. Calling [sqlite3_prepare_v2()] again will not make the +** error go away. Note: use [sqlite3_errmsg()] to find the text +** of the parsing error that results in an [SQLITE_SCHEMA] return. +**
  2. +** +**
  3. +** When an error occurs, [sqlite3_step()] will return one of the detailed +** [error codes] or [extended error codes]. The legacy behavior was that +** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code +** and you would have to make a second call to [sqlite3_reset()] in order +** to find the underlying cause of the problem. With the "v2" prepare +** interfaces, the underlying reason for the error is returned immediately. +**
  4. +**
+** +** Requirements: +** [H13011] [H13012] [H13013] [H13014] [H13015] [H13016] [H13019] [H13021] +** +*/ +SQLITE_API int sqlite3_prepare( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int sqlite3_prepare_v2( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int sqlite3_prepare16( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int sqlite3_prepare16_v2( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); + +/* +** CAPI3REF: Retrieving Statement SQL {H13100} +** +** This interface can be used to retrieve a saved copy of the original +** SQL text used to create a [prepared statement] if that statement was +** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()]. +** +** Requirements: +** [H13101] [H13102] [H13103] +*/ +SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Dynamically Typed Value Object {H15000} +** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value} +** +** SQLite uses the sqlite3_value object to represent all values +** that can be stored in a database table. SQLite uses dynamic typing +** for the values it stores. Values stored in sqlite3_value objects +** can be integers, floating point values, strings, BLOBs, or NULL. +** +** An sqlite3_value object may be either "protected" or "unprotected". +** Some interfaces require a protected sqlite3_value. Other interfaces +** will accept either a protected or an unprotected sqlite3_value. +** Every interface that accepts sqlite3_value arguments specifies +** whether or not it requires a protected sqlite3_value. +** +** The terms "protected" and "unprotected" refer to whether or not +** a mutex is held. A internal mutex is held for a protected +** sqlite3_value object but no mutex is held for an unprotected +** sqlite3_value object. If SQLite is compiled to be single-threaded +** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0) +** or if SQLite is run in one of reduced mutex modes +** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD] +** then there is no distinction between protected and unprotected +** sqlite3_value objects and they can be used interchangeably. However, +** for maximum code portability it is recommended that applications +** still make the distinction between between protected and unprotected +** sqlite3_value objects even when not strictly required. +** +** The sqlite3_value objects that are passed as parameters into the +** implementation of [application-defined SQL functions] are protected. +** The sqlite3_value object returned by +** [sqlite3_column_value()] is unprotected. +** Unprotected sqlite3_value objects may only be used with +** [sqlite3_result_value()] and [sqlite3_bind_value()]. +** The [sqlite3_value_blob | sqlite3_value_type()] family of +** interfaces require protected sqlite3_value objects. +*/ +typedef struct Mem sqlite3_value; + +/* +** CAPI3REF: SQL Function Context Object {H16001} +** +** The context in which an SQL function executes is stored in an +** sqlite3_context object. A pointer to an sqlite3_context object +** is always first parameter to [application-defined SQL functions]. +** The application-defined SQL function implementation will pass this +** pointer through into calls to [sqlite3_result_int | sqlite3_result()], +** [sqlite3_aggregate_context()], [sqlite3_user_data()], +** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()], +** and/or [sqlite3_set_auxdata()]. +*/ +typedef struct sqlite3_context sqlite3_context; + +/* +** CAPI3REF: Binding Values To Prepared Statements {H13500} +** KEYWORDS: {host parameter} {host parameters} {host parameter name} +** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} +** +** In the SQL strings input to [sqlite3_prepare_v2()] and its variants, +** literals may be replaced by a [parameter] in one of these forms: +** +**
    +**
  • ? +**
  • ?NNN +**
  • :VVV +**
  • @VVV +**
  • $VVV +**
+** +** In the parameter forms shown above NNN is an integer literal, +** and VVV is an alpha-numeric parameter name. The values of these +** parameters (also called "host parameter names" or "SQL parameters") +** can be set using the sqlite3_bind_*() routines defined here. +** +** The first argument to the sqlite3_bind_*() routines is always +** a pointer to the [sqlite3_stmt] object returned from +** [sqlite3_prepare_v2()] or its variants. +** +** The second argument is the index of the SQL parameter to be set. +** The leftmost SQL parameter has an index of 1. When the same named +** SQL parameter is used more than once, second and subsequent +** occurrences have the same index as the first occurrence. +** The index for named parameters can be looked up using the +** [sqlite3_bind_parameter_index()] API if desired. The index +** for "?NNN" parameters is the value of NNN. +** The NNN value must be between 1 and the [sqlite3_limit()] +** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999). +** +** The third argument is the value to bind to the parameter. +** +** In those routines that have a fourth argument, its value is the +** number of bytes in the parameter. To be clear: the value is the +** number of bytes in the value, not the number of characters. +** If the fourth parameter is negative, the length of the string is +** the number of bytes up to the first zero terminator. +** +** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and +** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or +** string after SQLite has finished with it. If the fifth argument is +** the special value [SQLITE_STATIC], then SQLite assumes that the +** information is in static, unmanaged space and does not need to be freed. +** If the fifth argument has the value [SQLITE_TRANSIENT], then +** SQLite makes its own private copy of the data immediately, before +** the sqlite3_bind_*() routine returns. +** +** The sqlite3_bind_zeroblob() routine binds a BLOB of length N that +** is filled with zeroes. A zeroblob uses a fixed amount of memory +** (just an integer to hold its size) while it is being processed. +** Zeroblobs are intended to serve as placeholders for BLOBs whose +** content is later written using +** [sqlite3_blob_open | incremental BLOB I/O] routines. +** A negative value for the zeroblob results in a zero-length BLOB. +** +** The sqlite3_bind_*() routines must be called after +** [sqlite3_prepare_v2()] (and its variants) or [sqlite3_reset()] and +** before [sqlite3_step()]. +** Bindings are not cleared by the [sqlite3_reset()] routine. +** Unbound parameters are interpreted as NULL. +** +** These routines return [SQLITE_OK] on success or an error code if +** anything goes wrong. [SQLITE_RANGE] is returned if the parameter +** index is out of range. [SQLITE_NOMEM] is returned if malloc() fails. +** [SQLITE_MISUSE] might be returned if these routines are called on a +** virtual machine that is the wrong state or which has already been finalized. +** Detection of misuse is unreliable. Applications should not depend +** on SQLITE_MISUSE returns. SQLITE_MISUSE is intended to indicate a +** a logic error in the application. Future versions of SQLite might +** panic rather than return SQLITE_MISUSE. +** +** See also: [sqlite3_bind_parameter_count()], +** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. +** +** Requirements: +** [H13506] [H13509] [H13512] [H13515] [H13518] [H13521] [H13524] [H13527] +** [H13530] [H13533] [H13536] [H13539] [H13542] [H13545] [H13548] [H13551] +** +*/ +SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); +SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); +SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); +SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); + +/* +** CAPI3REF: Number Of SQL Parameters {H13600} +** +** This routine can be used to find the number of [SQL parameters] +** in a [prepared statement]. SQL parameters are tokens of the +** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as +** placeholders for values that are [sqlite3_bind_blob | bound] +** to the parameters at a later time. +** +** This routine actually returns the index of the largest (rightmost) +** parameter. For all forms except ?NNN, this will correspond to the +** number of unique parameters. If parameters of the ?NNN are used, +** there may be gaps in the list. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_name()], and +** [sqlite3_bind_parameter_index()]. +** +** Requirements: +** [H13601] +*/ +SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); + +/* +** CAPI3REF: Name Of A Host Parameter {H13620} +** +** This routine returns a pointer to the name of the n-th +** [SQL parameter] in a [prepared statement]. +** SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA" +** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA" +** respectively. +** In other words, the initial ":" or "$" or "@" or "?" +** is included as part of the name. +** Parameters of the form "?" without a following integer have no name +** and are also referred to as "anonymous parameters". +** +** The first host parameter has an index of 1, not 0. +** +** If the value n is out of range or if the n-th parameter is +** nameless, then NULL is returned. The returned string is +** always in UTF-8 encoding even if the named parameter was +** originally specified as UTF-16 in [sqlite3_prepare16()] or +** [sqlite3_prepare16_v2()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +** +** Requirements: +** [H13621] +*/ +SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); + +/* +** CAPI3REF: Index Of A Parameter With A Given Name {H13640} +** +** Return the index of an SQL parameter given its name. The +** index value returned is suitable for use as the second +** parameter to [sqlite3_bind_blob|sqlite3_bind()]. A zero +** is returned if no matching parameter is found. The parameter +** name must be given in UTF-8 even if the original statement +** was prepared from UTF-16 text using [sqlite3_prepare16_v2()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +** +** Requirements: +** [H13641] +*/ +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); + +/* +** CAPI3REF: Reset All Bindings On A Prepared Statement {H13660} +** +** Contrary to the intuition of many, [sqlite3_reset()] does not reset +** the [sqlite3_bind_blob | bindings] on a [prepared statement]. +** Use this routine to reset all host parameters to NULL. +** +** Requirements: +** [H13661] +*/ +SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); + +/* +** CAPI3REF: Number Of Columns In A Result Set {H13710} +** +** Return the number of columns in the result set returned by the +** [prepared statement]. This routine returns 0 if pStmt is an SQL +** statement that does not return data (for example an [UPDATE]). +** +** Requirements: +** [H13711] +*/ +SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Column Names In A Result Set {H13720} +** +** These routines return the name assigned to a particular column +** in the result set of a [SELECT] statement. The sqlite3_column_name() +** interface returns a pointer to a zero-terminated UTF-8 string +** and sqlite3_column_name16() returns a pointer to a zero-terminated +** UTF-16 string. The first parameter is the [prepared statement] +** that implements the [SELECT] statement. The second parameter is the +** column number. The leftmost column is number 0. +** +** The returned string pointer is valid until either the [prepared statement] +** is destroyed by [sqlite3_finalize()] or until the next call to +** sqlite3_column_name() or sqlite3_column_name16() on the same column. +** +** If sqlite3_malloc() fails during the processing of either routine +** (for example during a conversion from UTF-8 to UTF-16) then a +** NULL pointer is returned. +** +** The name of a result column is the value of the "AS" clause for +** that column, if there is an AS clause. If there is no AS clause +** then the name of the column is unspecified and may change from +** one release of SQLite to the next. +** +** Requirements: +** [H13721] [H13723] [H13724] [H13725] [H13726] [H13727] +*/ +SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); +SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); + +/* +** CAPI3REF: Source Of Data In A Query Result {H13740} +** +** These routines provide a means to determine what column of what +** table in which database a result of a [SELECT] statement comes from. +** The name of the database or table or column can be returned as +** either a UTF-8 or UTF-16 string. The _database_ routines return +** the database name, the _table_ routines return the table name, and +** the origin_ routines return the column name. +** The returned string is valid until the [prepared statement] is destroyed +** using [sqlite3_finalize()] or until the same information is requested +** again in a different encoding. +** +** The names returned are the original un-aliased names of the +** database, table, and column. +** +** The first argument to the following calls is a [prepared statement]. +** These functions return information about the Nth column returned by +** the statement, where N is the second function argument. +** +** If the Nth column returned by the statement is an expression or +** subquery and is not a column value, then all of these functions return +** NULL. These routine might also return NULL if a memory allocation error +** occurs. Otherwise, they return the name of the attached database, table +** and column that query result column was extracted from. +** +** As with all other SQLite APIs, those postfixed with "16" return +** UTF-16 encoded strings, the other functions return UTF-8. {END} +** +** These APIs are only available if the library was compiled with the +** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. +** +** {A13751} +** If two or more threads call one or more of these routines against the same +** prepared statement and column at the same time then the results are +** undefined. +** +** Requirements: +** [H13741] [H13742] [H13743] [H13744] [H13745] [H13746] [H13748] +** +** If two or more threads call one or more +** [sqlite3_column_database_name | column metadata interfaces] +** for the same [prepared statement] and result column +** at the same time then the results are undefined. +*/ +SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Declared Datatype Of A Query Result {H13760} +** +** The first parameter is a [prepared statement]. +** If this statement is a [SELECT] statement and the Nth column of the +** returned result set of that [SELECT] is a table column (not an +** expression or subquery) then the declared type of the table +** column is returned. If the Nth column of the result set is an +** expression or subquery, then a NULL pointer is returned. +** The returned string is always UTF-8 encoded. {END} +** +** For example, given the database schema: +** +** CREATE TABLE t1(c1 VARIANT); +** +** and the following statement to be compiled: +** +** SELECT c1 + 1, c1 FROM t1; +** +** this routine would return the string "VARIANT" for the second result +** column (i==1), and a NULL pointer for the first result column (i==0). +** +** SQLite uses dynamic run-time typing. So just because a column +** is declared to contain a particular type does not mean that the +** data stored in that column is of the declared type. SQLite is +** strongly typed, but the typing is dynamic not static. Type +** is associated with individual values, not with the containers +** used to hold those values. +** +** Requirements: +** [H13761] [H13762] [H13763] +*/ +SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Evaluate An SQL Statement {H13200} +** +** After a [prepared statement] has been prepared using either +** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy +** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function +** must be called one or more times to evaluate the statement. +** +** The details of the behavior of the sqlite3_step() interface depend +** on whether the statement was prepared using the newer "v2" interface +** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy +** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the +** new "v2" interface is recommended for new applications but the legacy +** interface will continue to be supported. +** +** In the legacy interface, the return value will be either [SQLITE_BUSY], +** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. +** With the "v2" interface, any of the other [result codes] or +** [extended result codes] might be returned as well. +** +** [SQLITE_BUSY] means that the database engine was unable to acquire the +** database locks it needs to do its job. If the statement is a [COMMIT] +** or occurs outside of an explicit transaction, then you can retry the +** statement. If the statement is not a [COMMIT] and occurs within a +** explicit transaction then you should rollback the transaction before +** continuing. +** +** [SQLITE_DONE] means that the statement has finished executing +** successfully. sqlite3_step() should not be called again on this virtual +** machine without first calling [sqlite3_reset()] to reset the virtual +** machine back to its initial state. +** +** If the SQL statement being executed returns any data, then [SQLITE_ROW] +** is returned each time a new row of data is ready for processing by the +** caller. The values may be accessed using the [column access functions]. +** sqlite3_step() is called again to retrieve the next row of data. +** +** [SQLITE_ERROR] means that a run-time error (such as a constraint +** violation) has occurred. sqlite3_step() should not be called again on +** the VM. More information may be found by calling [sqlite3_errmsg()]. +** With the legacy interface, a more specific error code (for example, +** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) +** can be obtained by calling [sqlite3_reset()] on the +** [prepared statement]. In the "v2" interface, +** the more specific error code is returned directly by sqlite3_step(). +** +** [SQLITE_MISUSE] means that the this routine was called inappropriately. +** Perhaps it was called on a [prepared statement] that has +** already been [sqlite3_finalize | finalized] or on one that had +** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could +** be the case that the same database connection is being used by two or +** more threads at the same moment in time. +** +** Goofy Interface Alert: In the legacy interface, the sqlite3_step() +** API always returns a generic error code, [SQLITE_ERROR], following any +** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call +** [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the +** specific [error codes] that better describes the error. +** We admit that this is a goofy design. The problem has been fixed +** with the "v2" interface. If you prepare all of your SQL statements +** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead +** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces, +** then the more specific [error codes] are returned directly +** by sqlite3_step(). The use of the "v2" interface is recommended. +** +** Requirements: +** [H13202] [H15304] [H15306] [H15308] [H15310] +*/ +SQLITE_API int sqlite3_step(sqlite3_stmt*); + +/* +** CAPI3REF: Number of columns in a result set {H13770} +** +** Returns the number of values in the current row of the result set. +** +** Requirements: +** [H13771] [H13772] +*/ +SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Fundamental Datatypes {H10265} +** KEYWORDS: SQLITE_TEXT +** +** {H10266} Every value in SQLite has one of five fundamental datatypes: +** +**
    +**
  • 64-bit signed integer +**
  • 64-bit IEEE floating point number +**
  • string +**
  • BLOB +**
  • NULL +**
{END} +** +** These constants are codes for each of those types. +** +** Note that the SQLITE_TEXT constant was also used in SQLite version 2 +** for a completely different meaning. Software that links against both +** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, not +** SQLITE_TEXT. +*/ +#define SQLITE_INTEGER 1 +#define SQLITE_FLOAT 2 +#define SQLITE_BLOB 4 +#define SQLITE_NULL 5 +#ifdef SQLITE_TEXT +# undef SQLITE_TEXT +#else +# define SQLITE_TEXT 3 +#endif +#define SQLITE3_TEXT 3 + +/* +** CAPI3REF: Result Values From A Query {H13800} +** KEYWORDS: {column access functions} +** +** These routines form the "result set query" interface. +** +** These routines return information about a single column of the current +** result row of a query. In every case the first argument is a pointer +** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*] +** that was returned from [sqlite3_prepare_v2()] or one of its variants) +** and the second argument is the index of the column for which information +** should be returned. The leftmost column of the result set has the index 0. +** +** If the SQL statement does not currently point to a valid row, or if the +** column index is out of range, the result is undefined. +** These routines may only be called when the most recent call to +** [sqlite3_step()] has returned [SQLITE_ROW] and neither +** [sqlite3_reset()] nor [sqlite3_finalize()] have been called subsequently. +** If any of these routines are called after [sqlite3_reset()] or +** [sqlite3_finalize()] or after [sqlite3_step()] has returned +** something other than [SQLITE_ROW], the results are undefined. +** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] +** are called from a different thread while any of these routines +** are pending, then the results are undefined. +** +** The sqlite3_column_type() routine returns the +** [SQLITE_INTEGER | datatype code] for the initial data type +** of the result column. The returned value is one of [SQLITE_INTEGER], +** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value +** returned by sqlite3_column_type() is only meaningful if no type +** conversions have occurred as described below. After a type conversion, +** the value returned by sqlite3_column_type() is undefined. Future +** versions of SQLite may change the behavior of sqlite3_column_type() +** following a type conversion. +** +** If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() +** routine returns the number of bytes in that BLOB or string. +** If the result is a UTF-16 string, then sqlite3_column_bytes() converts +** the string to UTF-8 and then returns the number of bytes. +** If the result is a numeric value then sqlite3_column_bytes() uses +** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns +** the number of bytes in that string. +** The value returned does not include the zero terminator at the end +** of the string. For clarity: the value returned is the number of +** bytes in the string, not the number of characters. +** +** Strings returned by sqlite3_column_text() and sqlite3_column_text16(), +** even empty strings, are always zero terminated. The return +** value from sqlite3_column_blob() for a zero-length BLOB is an arbitrary +** pointer, possibly even a NULL pointer. +** +** The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes() +** but leaves the result in UTF-16 in native byte order instead of UTF-8. +** The zero terminator is not included in this count. +** +** The object returned by [sqlite3_column_value()] is an +** [unprotected sqlite3_value] object. An unprotected sqlite3_value object +** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()]. +** If the [unprotected sqlite3_value] object returned by +** [sqlite3_column_value()] is used in any other way, including calls +** to routines like [sqlite3_value_int()], [sqlite3_value_text()], +** or [sqlite3_value_bytes()], then the behavior is undefined. +** +** These routines attempt to convert the value where appropriate. For +** example, if the internal representation is FLOAT and a text result +** is requested, [sqlite3_snprintf()] is used internally to perform the +** conversion automatically. The following table details the conversions +** that are applied: +** +**
+** +**
Internal
Type
Requested
Type
Conversion +** +**
NULL INTEGER Result is 0 +**
NULL FLOAT Result is 0.0 +**
NULL TEXT Result is NULL pointer +**
NULL BLOB Result is NULL pointer +**
INTEGER FLOAT Convert from integer to float +**
INTEGER TEXT ASCII rendering of the integer +**
INTEGER BLOB Same as INTEGER->TEXT +**
FLOAT INTEGER Convert from float to integer +**
FLOAT TEXT ASCII rendering of the float +**
FLOAT BLOB Same as FLOAT->TEXT +**
TEXT INTEGER Use atoi() +**
TEXT FLOAT Use atof() +**
TEXT BLOB No change +**
BLOB INTEGER Convert to TEXT then use atoi() +**
BLOB FLOAT Convert to TEXT then use atof() +**
BLOB TEXT Add a zero terminator if needed +**
+**
+** +** The table above makes reference to standard C library functions atoi() +** and atof(). SQLite does not really use these functions. It has its +** own equivalent internal routines. The atoi() and atof() names are +** used in the table for brevity and because they are familiar to most +** C programmers. +** +** Note that when type conversions occur, pointers returned by prior +** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or +** sqlite3_column_text16() may be invalidated. +** Type conversions and pointer invalidations might occur +** in the following cases: +** +**
    +**
  • The initial content is a BLOB and sqlite3_column_text() or +** sqlite3_column_text16() is called. A zero-terminator might +** need to be added to the string.
  • +**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or +** sqlite3_column_text16() is called. The content must be converted +** to UTF-16.
  • +**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or +** sqlite3_column_text() is called. The content must be converted +** to UTF-8.
  • +**
+** +** Conversions between UTF-16be and UTF-16le are always done in place and do +** not invalidate a prior pointer, though of course the content of the buffer +** that the prior pointer points to will have been modified. Other kinds +** of conversion are done in place when it is possible, but sometimes they +** are not possible and in those cases prior pointers are invalidated. +** +** The safest and easiest to remember policy is to invoke these routines +** in one of the following ways: +** +**
    +**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • +**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • +**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • +**
+** +** In other words, you should call sqlite3_column_text(), +** sqlite3_column_blob(), or sqlite3_column_text16() first to force the result +** into the desired format, then invoke sqlite3_column_bytes() or +** sqlite3_column_bytes16() to find the size of the result. Do not mix calls +** to sqlite3_column_text() or sqlite3_column_blob() with calls to +** sqlite3_column_bytes16(), and do not mix calls to sqlite3_column_text16() +** with calls to sqlite3_column_bytes(). +** +** The pointers returned are valid until a type conversion occurs as +** described above, or until [sqlite3_step()] or [sqlite3_reset()] or +** [sqlite3_finalize()] is called. The memory space used to hold strings +** and BLOBs is freed automatically. Do not pass the pointers returned +** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into +** [sqlite3_free()]. +** +** If a memory allocation error occurs during the evaluation of any +** of these routines, a default value is returned. The default value +** is either the integer 0, the floating point number 0.0, or a NULL +** pointer. Subsequent calls to [sqlite3_errcode()] will return +** [SQLITE_NOMEM]. +** +** Requirements: +** [H13803] [H13806] [H13809] [H13812] [H13815] [H13818] [H13821] [H13824] +** [H13827] [H13830] +*/ +SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); +SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); +SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); + +/* +** CAPI3REF: Destroy A Prepared Statement Object {H13300} +** +** The sqlite3_finalize() function is called to delete a [prepared statement]. +** If the statement was executed successfully or not executed at all, then +** SQLITE_OK is returned. If execution of the statement failed then an +** [error code] or [extended error code] is returned. +** +** This routine can be called at any point during the execution of the +** [prepared statement]. If the virtual machine has not +** completed execution when this routine is called, that is like +** encountering an error or an [sqlite3_interrupt | interrupt]. +** Incomplete updates may be rolled back and transactions canceled, +** depending on the circumstances, and the +** [error code] returned will be [SQLITE_ABORT]. +** +** Requirements: +** [H11302] [H11304] +*/ +SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Reset A Prepared Statement Object {H13330} +** +** The sqlite3_reset() function is called to reset a [prepared statement] +** object back to its initial state, ready to be re-executed. +** Any SQL statement variables that had values bound to them using +** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. +** Use [sqlite3_clear_bindings()] to reset the bindings. +** +** {H11332} The [sqlite3_reset(S)] interface resets the [prepared statement] S +** back to the beginning of its program. +** +** {H11334} If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], +** or if [sqlite3_step(S)] has never before been called on S, +** then [sqlite3_reset(S)] returns [SQLITE_OK]. +** +** {H11336} If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S indicated an error, then +** [sqlite3_reset(S)] returns an appropriate [error code]. +** +** {H11338} The [sqlite3_reset(S)] interface does not change the values +** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. +*/ +SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Create Or Redefine SQL Functions {H16100} +** KEYWORDS: {function creation routines} +** KEYWORDS: {application-defined SQL function} +** KEYWORDS: {application-defined SQL functions} +** +** These two functions (collectively known as "function creation routines") +** are used to add SQL functions or aggregates or to redefine the behavior +** of existing SQL functions or aggregates. The only difference between the +** two is that the second parameter, the name of the (scalar) function or +** aggregate, is encoded in UTF-8 for sqlite3_create_function() and UTF-16 +** for sqlite3_create_function16(). +** +** The first parameter is the [database connection] to which the SQL +** function is to be added. If a single program uses more than one database +** connection internally, then SQL functions must be added individually to +** each database connection. +** +** The second parameter is the name of the SQL function to be created or +** redefined. The length of the name is limited to 255 bytes, exclusive of +** the zero-terminator. Note that the name length limit is in bytes, not +** characters. Any attempt to create a function with a longer name +** will result in [SQLITE_ERROR] being returned. +** +** The third parameter (nArg) +** is the number of arguments that the SQL function or +** aggregate takes. If this parameter is negative, then the SQL function or +** aggregate may take any number of arguments. +** +** The fourth parameter, eTextRep, specifies what +** [SQLITE_UTF8 | text encoding] this SQL function prefers for +** its parameters. Any SQL function implementation should be able to work +** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be +** more efficient with one encoding than another. It is allowed to +** invoke sqlite3_create_function() or sqlite3_create_function16() multiple +** times with the same function but with different values of eTextRep. +** When multiple implementations of the same function are available, SQLite +** will pick the one that involves the least amount of data conversion. +** If there is only a single implementation which does not care what text +** encoding is used, then the fourth argument should be [SQLITE_ANY]. +** +** The fifth parameter is an arbitrary pointer. The implementation of the +** function can gain access to this pointer using [sqlite3_user_data()]. +** +** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are +** pointers to C-language functions that implement the SQL function or +** aggregate. A scalar SQL function requires an implementation of the xFunc +** callback only, NULL pointers should be passed as the xStep and xFinal +** parameters. An aggregate SQL function requires an implementation of xStep +** and xFinal and NULL should be passed for xFunc. To delete an existing +** SQL function or aggregate, pass NULL for all three function callbacks. +** +** It is permitted to register multiple implementations of the same +** functions with the same name but with either differing numbers of +** arguments or differing preferred text encodings. SQLite will use +** the implementation most closely matches the way in which the +** SQL function is used. A function implementation with a non-negative +** nArg parameter is a better match than a function implementation with +** a negative nArg. A function where the preferred text encoding +** matches the database encoding is a better +** match than a function where the encoding is different. +** A function where the encoding difference is between UTF16le and UTF16be +** is a closer match than a function where the encoding difference is +** between UTF8 and UTF16. +** +** Built-in functions may be overloaded by new application-defined functions. +** The first application-defined function with a given name overrides all +** built-in functions in the same [database connection] with the same name. +** Subsequent application-defined functions of the same name only override +** prior application-defined functions that are an exact match for the +** number of parameters and preferred encoding. +** +** An application-defined function is permitted to call other +** SQLite interfaces. However, such calls must not +** close the database connection nor finalize or reset the prepared +** statement in which the function is running. +** +** Requirements: +** [H16103] [H16106] [H16109] [H16112] [H16118] [H16121] [H16124] [H16127] +** [H16130] [H16133] [H16136] [H16139] [H16142] +*/ +SQLITE_API int sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +SQLITE_API int sqlite3_create_function16( + sqlite3 *db, + const void *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); + +/* +** CAPI3REF: Text Encodings {H10267} +** +** These constant define integer codes that represent the various +** text encodings supported by SQLite. +*/ +#define SQLITE_UTF8 1 +#define SQLITE_UTF16LE 2 +#define SQLITE_UTF16BE 3 +#define SQLITE_UTF16 4 /* Use native byte order */ +#define SQLITE_ANY 5 /* sqlite3_create_function only */ +#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ + +/* +** CAPI3REF: Deprecated Functions +** DEPRECATED +** +** These functions are [deprecated]. In order to maintain +** backwards compatibility with older code, these functions continue +** to be supported. However, new applications should avoid +** the use of these functions. To help encourage people to avoid +** using these functions, we are not going to tell you what they do. +*/ +#ifndef SQLITE_OMIT_DEPRECATED +SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); +SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); +SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); +#endif + +/* +** CAPI3REF: Obtaining SQL Function Parameter Values {H15100} +** +** The C-language implementation of SQL functions and aggregates uses +** this set of interface routines to access the parameter values on +** the function or aggregate. +** +** The xFunc (for scalar functions) or xStep (for aggregates) parameters +** to [sqlite3_create_function()] and [sqlite3_create_function16()] +** define callbacks that implement the SQL functions and aggregates. +** The 4th parameter to these callbacks is an array of pointers to +** [protected sqlite3_value] objects. There is one [sqlite3_value] object for +** each parameter to the SQL function. These routines are used to +** extract values from the [sqlite3_value] objects. +** +** These routines work only with [protected sqlite3_value] objects. +** Any attempt to use these routines on an [unprotected sqlite3_value] +** object results in undefined behavior. +** +** These routines work just like the corresponding [column access functions] +** except that these routines take a single [protected sqlite3_value] object +** pointer instead of a [sqlite3_stmt*] pointer and an integer column number. +** +** The sqlite3_value_text16() interface extracts a UTF-16 string +** in the native byte-order of the host machine. The +** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces +** extract UTF-16 strings as big-endian and little-endian respectively. +** +** The sqlite3_value_numeric_type() interface attempts to apply +** numeric affinity to the value. This means that an attempt is +** made to convert the value to an integer or floating point. If +** such a conversion is possible without loss of information (in other +** words, if the value is a string that looks like a number) +** then the conversion is performed. Otherwise no conversion occurs. +** The [SQLITE_INTEGER | datatype] after conversion is returned. +** +** Please pay particular attention to the fact that the pointer returned +** from [sqlite3_value_blob()], [sqlite3_value_text()], or +** [sqlite3_value_text16()] can be invalidated by a subsequent call to +** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], +** or [sqlite3_value_text16()]. +** +** These routines must be called from the same thread as +** the SQL function that supplied the [sqlite3_value*] parameters. +** +** Requirements: +** [H15103] [H15106] [H15109] [H15112] [H15115] [H15118] [H15121] [H15124] +** [H15127] [H15130] [H15133] [H15136] +*/ +SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); +SQLITE_API double sqlite3_value_double(sqlite3_value*); +SQLITE_API int sqlite3_value_int(sqlite3_value*); +SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); +SQLITE_API int sqlite3_value_type(sqlite3_value*); +SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); + +/* +** CAPI3REF: Obtain Aggregate Function Context {H16210} +** +** The implementation of aggregate SQL functions use this routine to allocate +** a structure for storing their state. +** +** The first time the sqlite3_aggregate_context() routine is called for a +** particular aggregate, SQLite allocates nBytes of memory, zeroes out that +** memory, and returns a pointer to it. On second and subsequent calls to +** sqlite3_aggregate_context() for the same aggregate function index, +** the same buffer is returned. The implementation of the aggregate can use +** the returned buffer to accumulate data. +** +** SQLite automatically frees the allocated buffer when the aggregate +** query concludes. +** +** The first parameter should be a copy of the +** [sqlite3_context | SQL function context] that is the first parameter +** to the callback routine that implements the aggregate function. +** +** This routine must be called from the same thread in which +** the aggregate SQL function is running. +** +** Requirements: +** [H16211] [H16213] [H16215] [H16217] +*/ +SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); + +/* +** CAPI3REF: User Data For Functions {H16240} +** +** The sqlite3_user_data() interface returns a copy of +** the pointer that was the pUserData parameter (the 5th parameter) +** of the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. {END} +** +** This routine must be called from the same thread in which +** the application-defined function is running. +** +** Requirements: +** [H16243] +*/ +SQLITE_API void *sqlite3_user_data(sqlite3_context*); + +/* +** CAPI3REF: Database Connection For Functions {H16250} +** +** The sqlite3_context_db_handle() interface returns a copy of +** the pointer to the [database connection] (the 1st parameter) +** of the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. +** +** Requirements: +** [H16253] +*/ +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); + +/* +** CAPI3REF: Function Auxiliary Data {H16270} +** +** The following two functions may be used by scalar SQL functions to +** associate metadata with argument values. If the same value is passed to +** multiple invocations of the same SQL function during query execution, under +** some circumstances the associated metadata may be preserved. This may +** be used, for example, to add a regular-expression matching scalar +** function. The compiled version of the regular expression is stored as +** metadata associated with the SQL value passed as the regular expression +** pattern. The compiled regular expression can be reused on multiple +** invocations of the same function so that the original pattern string +** does not need to be recompiled on each invocation. +** +** The sqlite3_get_auxdata() interface returns a pointer to the metadata +** associated by the sqlite3_set_auxdata() function with the Nth argument +** value to the application-defined function. If no metadata has been ever +** been set for the Nth argument of the function, or if the corresponding +** function parameter has changed since the meta-data was set, +** then sqlite3_get_auxdata() returns a NULL pointer. +** +** The sqlite3_set_auxdata() interface saves the metadata +** pointed to by its 3rd parameter as the metadata for the N-th +** argument of the application-defined function. Subsequent +** calls to sqlite3_get_auxdata() might return this data, if it has +** not been destroyed. +** If it is not NULL, SQLite will invoke the destructor +** function given by the 4th parameter to sqlite3_set_auxdata() on +** the metadata when the corresponding function parameter changes +** or when the SQL statement completes, whichever comes first. +** +** SQLite is free to call the destructor and drop metadata on any +** parameter of any function at any time. The only guarantee is that +** the destructor will be called before the metadata is dropped. +** +** In practice, metadata is preserved between function calls for +** expressions that are constant at compile time. This includes literal +** values and SQL variables. +** +** These routines must be called from the same thread in which +** the SQL function is running. +** +** Requirements: +** [H16272] [H16274] [H16276] [H16277] [H16278] [H16279] +*/ +SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); +SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); + + +/* +** CAPI3REF: Constants Defining Special Destructor Behavior {H10280} +** +** These are special values for the destructor that is passed in as the +** final argument to routines like [sqlite3_result_blob()]. If the destructor +** argument is SQLITE_STATIC, it means that the content pointer is constant +** and will never change. It does not need to be destroyed. The +** SQLITE_TRANSIENT value means that the content will likely change in +** the near future and that SQLite should make its own private copy of +** the content before returning. +** +** The typedef is necessary to work around problems in certain +** C++ compilers. See ticket #2191. +*/ +typedef void (*sqlite3_destructor_type)(void*); +#define SQLITE_STATIC ((sqlite3_destructor_type)0) +#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) + +/* +** CAPI3REF: Setting The Result Of An SQL Function {H16400} +** +** These routines are used by the xFunc or xFinal callbacks that +** implement SQL functions and aggregates. See +** [sqlite3_create_function()] and [sqlite3_create_function16()] +** for additional information. +** +** These functions work very much like the [parameter binding] family of +** functions used to bind values to host parameters in prepared statements. +** Refer to the [SQL parameter] documentation for additional information. +** +** The sqlite3_result_blob() interface sets the result from +** an application-defined function to be the BLOB whose content is pointed +** to by the second parameter and which is N bytes long where N is the +** third parameter. +** +** The sqlite3_result_zeroblob() interfaces set the result of +** the application-defined function to be a BLOB containing all zero +** bytes and N bytes in size, where N is the value of the 2nd parameter. +** +** The sqlite3_result_double() interface sets the result from +** an application-defined function to be a floating point value specified +** by its 2nd argument. +** +** The sqlite3_result_error() and sqlite3_result_error16() functions +** cause the implemented SQL function to throw an exception. +** SQLite uses the string pointed to by the +** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() +** as the text of an error message. SQLite interprets the error +** message string from sqlite3_result_error() as UTF-8. SQLite +** interprets the string from sqlite3_result_error16() as UTF-16 in native +** byte order. If the third parameter to sqlite3_result_error() +** or sqlite3_result_error16() is negative then SQLite takes as the error +** message all text up through the first zero character. +** If the third parameter to sqlite3_result_error() or +** sqlite3_result_error16() is non-negative then SQLite takes that many +** bytes (not characters) from the 2nd parameter as the error message. +** The sqlite3_result_error() and sqlite3_result_error16() +** routines make a private copy of the error message text before +** they return. Hence, the calling function can deallocate or +** modify the text after they return without harm. +** The sqlite3_result_error_code() function changes the error code +** returned by SQLite as a result of an error in a function. By default, +** the error code is SQLITE_ERROR. A subsequent call to sqlite3_result_error() +** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. +** +** The sqlite3_result_toobig() interface causes SQLite to throw an error +** indicating that a string or BLOB is to long to represent. +** +** The sqlite3_result_nomem() interface causes SQLite to throw an error +** indicating that a memory allocation failed. +** +** The sqlite3_result_int() interface sets the return value +** of the application-defined function to be the 32-bit signed integer +** value given in the 2nd argument. +** The sqlite3_result_int64() interface sets the return value +** of the application-defined function to be the 64-bit signed integer +** value given in the 2nd argument. +** +** The sqlite3_result_null() interface sets the return value +** of the application-defined function to be NULL. +** +** The sqlite3_result_text(), sqlite3_result_text16(), +** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces +** set the return value of the application-defined function to be +** a text string which is represented as UTF-8, UTF-16 native byte order, +** UTF-16 little endian, or UTF-16 big endian, respectively. +** SQLite takes the text result from the application from +** the 2nd parameter of the sqlite3_result_text* interfaces. +** If the 3rd parameter to the sqlite3_result_text* interfaces +** is negative, then SQLite takes result text from the 2nd parameter +** through the first zero character. +** If the 3rd parameter to the sqlite3_result_text* interfaces +** is non-negative, then as many bytes (not characters) of the text +** pointed to by the 2nd parameter are taken as the application-defined +** function result. +** If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that +** function as the destructor on the text or BLOB result when it has +** finished using that result. +** If the 4th parameter to the sqlite3_result_text* interfaces or +** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite +** assumes that the text or BLOB result is in constant space and does not +** copy the it or call a destructor when it has finished using that result. +** If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT +** then SQLite makes a copy of the result into space obtained from +** from [sqlite3_malloc()] before it returns. +** +** The sqlite3_result_value() interface sets the result of +** the application-defined function to be a copy the +** [unprotected sqlite3_value] object specified by the 2nd parameter. The +** sqlite3_result_value() interface makes a copy of the [sqlite3_value] +** so that the [sqlite3_value] specified in the parameter may change or +** be deallocated after sqlite3_result_value() returns without harm. +** A [protected sqlite3_value] object may always be used where an +** [unprotected sqlite3_value] object is required, so either +** kind of [sqlite3_value] object can be used with this interface. +** +** If these routines are called from within the different thread +** than the one containing the application-defined function that received +** the [sqlite3_context] pointer, the results are undefined. +** +** Requirements: +** [H16403] [H16406] [H16409] [H16412] [H16415] [H16418] [H16421] [H16424] +** [H16427] [H16430] [H16433] [H16436] [H16439] [H16442] [H16445] [H16448] +** [H16451] [H16454] [H16457] [H16460] [H16463] +*/ +SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_double(sqlite3_context*, double); +SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); +SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); +SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); +SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); +SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +SQLITE_API void sqlite3_result_null(sqlite3_context*); +SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); + +/* +** CAPI3REF: Define New Collating Sequences {H16600} +** +** These functions are used to add new collation sequences to the +** [database connection] specified as the first argument. +** +** The name of the new collation sequence is specified as a UTF-8 string +** for sqlite3_create_collation() and sqlite3_create_collation_v2() +** and a UTF-16 string for sqlite3_create_collation16(). In all cases +** the name is passed as the second function argument. +** +** The third argument may be one of the constants [SQLITE_UTF8], +** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied +** routine expects to be passed pointers to strings encoded using UTF-8, +** UTF-16 little-endian, or UTF-16 big-endian, respectively. The +** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that +** the routine expects pointers to 16-bit word aligned strings +** of UTF-16 in the native byte order of the host computer. +** +** A pointer to the user supplied routine must be passed as the fifth +** argument. If it is NULL, this is the same as deleting the collation +** sequence (so that SQLite cannot call it anymore). +** Each time the application supplied function is invoked, it is passed +** as its first parameter a copy of the void* passed as the fourth argument +** to sqlite3_create_collation() or sqlite3_create_collation16(). +** +** The remaining arguments to the application-supplied routine are two strings, +** each represented by a (length, data) pair and encoded in the encoding +** that was passed as the third argument when the collation sequence was +** registered. {END} The application defined collation routine should +** return negative, zero or positive if the first string is less than, +** equal to, or greater than the second string. i.e. (STRING1 - STRING2). +** +** The sqlite3_create_collation_v2() works like sqlite3_create_collation() +** except that it takes an extra argument which is a destructor for +** the collation. The destructor is called when the collation is +** destroyed and is passed a copy of the fourth parameter void* pointer +** of the sqlite3_create_collation_v2(). +** Collations are destroyed when they are overridden by later calls to the +** collation creation functions or when the [database connection] is closed +** using [sqlite3_close()]. +** +** Requirements: +** [H16603] [H16604] [H16606] [H16609] [H16612] [H16615] [H16618] [H16621] +** [H16624] [H16627] [H16630] +*/ +SQLITE_API int sqlite3_create_collation( + sqlite3*, + const char *zName, + int eTextRep, + void*, + int(*xCompare)(void*,int,const void*,int,const void*) +); +SQLITE_API int sqlite3_create_collation_v2( + sqlite3*, + const char *zName, + int eTextRep, + void*, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDestroy)(void*) +); +SQLITE_API int sqlite3_create_collation16( + sqlite3*, + const void *zName, + int eTextRep, + void*, + int(*xCompare)(void*,int,const void*,int,const void*) +); + +/* +** CAPI3REF: Collation Needed Callbacks {H16700} +** +** To avoid having to register all collation sequences before a database +** can be used, a single callback function may be registered with the +** [database connection] to be called whenever an undefined collation +** sequence is required. +** +** If the function is registered using the sqlite3_collation_needed() API, +** then it is passed the names of undefined collation sequences as strings +** encoded in UTF-8. {H16703} If sqlite3_collation_needed16() is used, +** the names are passed as UTF-16 in machine native byte order. +** A call to either function replaces any existing callback. +** +** When the callback is invoked, the first argument passed is a copy +** of the second argument to sqlite3_collation_needed() or +** sqlite3_collation_needed16(). The second argument is the database +** connection. The third argument is one of [SQLITE_UTF8], [SQLITE_UTF16BE], +** or [SQLITE_UTF16LE], indicating the most desirable form of the collation +** sequence function required. The fourth parameter is the name of the +** required collation sequence. +** +** The callback function should register the desired collation using +** [sqlite3_create_collation()], [sqlite3_create_collation16()], or +** [sqlite3_create_collation_v2()]. +** +** Requirements: +** [H16702] [H16704] [H16706] +*/ +SQLITE_API int sqlite3_collation_needed( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const char*) +); +SQLITE_API int sqlite3_collation_needed16( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const void*) +); + +/* +** Specify the key for an encrypted database. This routine should be +** called right after sqlite3_open(). +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +SQLITE_API int sqlite3_key( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The key */ +); + +/* +** Change the key on an open database. If the current database is not +** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the +** database is decrypted. +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +SQLITE_API int sqlite3_rekey( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The new key */ +); + +/* +** CAPI3REF: Suspend Execution For A Short Time {H10530} +** +** The sqlite3_sleep() function causes the current thread to suspend execution +** for at least a number of milliseconds specified in its parameter. +** +** If the operating system does not support sleep requests with +** millisecond time resolution, then the time will be rounded up to +** the nearest second. The number of milliseconds of sleep actually +** requested from the operating system is returned. +** +** SQLite implements this interface by calling the xSleep() +** method of the default [sqlite3_vfs] object. +** +** Requirements: [H10533] [H10536] +*/ +SQLITE_API int sqlite3_sleep(int); + +/* +** CAPI3REF: Name Of The Folder Holding Temporary Files {H10310} +** +** If this global variable is made to point to a string which is +** the name of a folder (a.k.a. directory), then all temporary files +** created by SQLite will be placed in that directory. If this variable +** is a NULL pointer, then SQLite performs a search for an appropriate +** temporary file directory. +** +** It is not safe to modify this variable once a [database connection] +** has been opened. It is intended that this variable be set once +** as part of process initialization and before any SQLite interface +** routines have been call and remain unchanged thereafter. +*/ +SQLITE_API char *sqlite3_temp_directory; + +/* +** CAPI3REF: Test For Auto-Commit Mode {H12930} +** KEYWORDS: {autocommit mode} +** +** The sqlite3_get_autocommit() interface returns non-zero or +** zero if the given database connection is or is not in autocommit mode, +** respectively. Autocommit mode is on by default. +** Autocommit mode is disabled by a [BEGIN] statement. +** Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK]. +** +** If certain kinds of errors occur on a statement within a multi-statement +** transaction (errors including [SQLITE_FULL], [SQLITE_IOERR], +** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the +** transaction might be rolled back automatically. The only way to +** find out whether SQLite automatically rolled back the transaction after +** an error is to use this function. +** +** If another thread changes the autocommit status of the database +** connection while this routine is running, then the return value +** is undefined. +** +** Requirements: [H12931] [H12932] [H12933] [H12934] +*/ +SQLITE_API int sqlite3_get_autocommit(sqlite3*); + +/* +** CAPI3REF: Find The Database Handle Of A Prepared Statement {H13120} +** +** The sqlite3_db_handle interface returns the [database connection] handle +** to which a [prepared statement] belongs. The [database connection] +** returned by sqlite3_db_handle is the same [database connection] that was the first argument +** to the [sqlite3_prepare_v2()] call (or its variants) that was used to +** create the statement in the first place. +** +** Requirements: [H13123] +*/ +SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); + +/* +** CAPI3REF: Find the next prepared statement {H13140} +** +** This interface returns a pointer to the next [prepared statement] after +** pStmt associated with the [database connection] pDb. If pStmt is NULL +** then this interface returns a pointer to the first prepared statement +** associated with the database connection pDb. If no prepared statement +** satisfies the conditions of this routine, it returns NULL. +** +** The [database connection] pointer D in a call to +** [sqlite3_next_stmt(D,S)] must refer to an open database +** connection and in particular must not be a NULL pointer. +** +** Requirements: [H13143] [H13146] [H13149] [H13152] +*/ +SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Commit And Rollback Notification Callbacks {H12950} +** +** The sqlite3_commit_hook() interface registers a callback +** function to be invoked whenever a transaction is committed. +** Any callback set by a previous call to sqlite3_commit_hook() +** for the same database connection is overridden. +** The sqlite3_rollback_hook() interface registers a callback +** function to be invoked whenever a transaction is committed. +** Any callback set by a previous call to sqlite3_commit_hook() +** for the same database connection is overridden. +** The pArg argument is passed through to the callback. +** If the callback on a commit hook function returns non-zero, +** then the commit is converted into a rollback. +** +** If another function was previously registered, its +** pArg value is returned. Otherwise NULL is returned. +** +** The callback implementation must not do anything that will modify +** the database connection that invoked the callback. Any actions +** to modify the database connection must be deferred until after the +** completion of the [sqlite3_step()] call that triggered the commit +** or rollback hook in the first place. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +** Registering a NULL function disables the callback. +** +** For the purposes of this API, a transaction is said to have been +** rolled back if an explicit "ROLLBACK" statement is executed, or +** an error or constraint causes an implicit rollback to occur. +** The rollback callback is not invoked if a transaction is +** automatically rolled back because the database connection is closed. +** The rollback callback is not invoked if a transaction is +** rolled back because a commit callback returned non-zero. +** Check on this +** +** Requirements: +** [H12951] [H12952] [H12953] [H12954] [H12955] +** [H12961] [H12962] [H12963] [H12964] +*/ +SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); + +/* +** CAPI3REF: Data Change Notification Callbacks {H12970} +** +** The sqlite3_update_hook() interface registers a callback function +** with the [database connection] identified by the first argument +** to be invoked whenever a row is updated, inserted or deleted. +** Any callback set by a previous call to this function +** for the same database connection is overridden. +** +** The second argument is a pointer to the function to invoke when a +** row is updated, inserted or deleted. +** The first argument to the callback is a copy of the third argument +** to sqlite3_update_hook(). +** The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE], +** or [SQLITE_UPDATE], depending on the operation that caused the callback +** to be invoked. +** The third and fourth arguments to the callback contain pointers to the +** database and table name containing the affected row. +** The final callback parameter is the [rowid] of the row. +** In the case of an update, this is the [rowid] after the update takes place. +** +** The update hook is not invoked when internal system tables are +** modified (i.e. sqlite_master and sqlite_sequence). +** +** The update hook implementation must not do anything that will modify +** the database connection that invoked the update hook. Any actions +** to modify the database connection must be deferred until after the +** completion of the [sqlite3_step()] call that triggered the update hook. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +** If another function was previously registered, its pArg value +** is returned. Otherwise NULL is returned. +** +** Requirements: +** [H12971] [H12973] [H12975] [H12977] [H12979] [H12981] [H12983] [H12986] +*/ +SQLITE_API void *sqlite3_update_hook( + sqlite3*, + void(*)(void *,int ,char const *,char const *,sqlite3_int64), + void* +); + +/* +** CAPI3REF: Enable Or Disable Shared Pager Cache {H10330} +** KEYWORDS: {shared cache} {shared cache mode} +** +** This routine enables or disables the sharing of the database cache +** and schema data structures between [database connection | connections] +** to the same database. Sharing is enabled if the argument is true +** and disabled if the argument is false. +** +** Cache sharing is enabled and disabled for an entire process. +** This is a change as of SQLite version 3.5.0. In prior versions of SQLite, +** sharing was enabled or disabled for each thread separately. +** +** The cache sharing mode set by this interface effects all subsequent +** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. +** Existing database connections continue use the sharing mode +** that was in effect at the time they were opened. +** +** Virtual tables cannot be used with a shared cache. When shared +** cache is enabled, the [sqlite3_create_module()] API used to register +** virtual tables will always return an error. +** +** This routine returns [SQLITE_OK] if shared cache was enabled or disabled +** successfully. An [error code] is returned otherwise. +** +** Shared cache is disabled by default. But this might change in +** future releases of SQLite. Applications that care about shared +** cache setting should set it explicitly. +** +** See Also: [SQLite Shared-Cache Mode] +** +** Requirements: [H10331] [H10336] [H10337] [H10339] +*/ +SQLITE_API int sqlite3_enable_shared_cache(int); + +/* +** CAPI3REF: Attempt To Free Heap Memory {H17340} +** +** The sqlite3_release_memory() interface attempts to free N bytes +** of heap memory by deallocating non-essential memory allocations +** held by the database library. {END} Memory used to cache database +** pages to improve performance is an example of non-essential memory. +** sqlite3_release_memory() returns the number of bytes actually freed, +** which might be more or less than the amount requested. +** +** Requirements: [H17341] [H17342] +*/ +SQLITE_API int sqlite3_release_memory(int); + +/* +** CAPI3REF: Impose A Limit On Heap Size {H17350} +** +** The sqlite3_soft_heap_limit() interface places a "soft" limit +** on the amount of heap memory that may be allocated by SQLite. +** If an internal allocation is requested that would exceed the +** soft heap limit, [sqlite3_release_memory()] is invoked one or +** more times to free up some space before the allocation is performed. +** +** The limit is called "soft", because if [sqlite3_release_memory()] +** cannot free sufficient memory to prevent the limit from being exceeded, +** the memory is allocated anyway and the current operation proceeds. +** +** A negative or zero value for N means that there is no soft heap limit and +** [sqlite3_release_memory()] will only be called when memory is exhausted. +** The default value for the soft heap limit is zero. +** +** SQLite makes a best effort to honor the soft heap limit. +** But if the soft heap limit cannot be honored, execution will +** continue without error or notification. This is why the limit is +** called a "soft" limit. It is advisory only. +** +** Prior to SQLite version 3.5.0, this routine only constrained the memory +** allocated by a single thread - the same thread in which this routine +** runs. Beginning with SQLite version 3.5.0, the soft heap limit is +** applied to all threads. The value specified for the soft heap limit +** is an upper bound on the total memory allocation for all threads. In +** version 3.5.0 there is no mechanism for limiting the heap usage for +** individual threads. +** +** Requirements: +** [H16351] [H16352] [H16353] [H16354] [H16355] [H16358] +*/ +SQLITE_API void sqlite3_soft_heap_limit(int); + +/* +** CAPI3REF: Extract Metadata About A Column Of A Table {H12850} +** +** This routine returns metadata about a specific column of a specific +** database table accessible using the [database connection] handle +** passed as the first function argument. +** +** The column is identified by the second, third and fourth parameters to +** this function. The second parameter is either the name of the database +** (i.e. "main", "temp" or an attached database) containing the specified +** table or NULL. If it is NULL, then all attached databases are searched +** for the table using the same algorithm used by the database engine to +** resolve unqualified table references. +** +** The third and fourth parameters to this function are the table and column +** name of the desired column, respectively. Neither of these parameters +** may be NULL. +** +** Metadata is returned by writing to the memory locations passed as the 5th +** and subsequent parameters to this function. Any of these arguments may be +** NULL, in which case the corresponding element of metadata is omitted. +** +**
+** +**
Parameter Output
Type
Description +** +**
5th const char* Data type +**
6th const char* Name of default collation sequence +**
7th int True if column has a NOT NULL constraint +**
8th int True if column is part of the PRIMARY KEY +**
9th int True if column is [AUTOINCREMENT] +**
+**
+** +** The memory pointed to by the character pointers returned for the +** declaration type and collation sequence is valid only until the next +** call to any SQLite API function. +** +** If the specified table is actually a view, an [error code] is returned. +** +** If the specified column is "rowid", "oid" or "_rowid_" and an +** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output +** parameters are set for the explicitly declared column. If there is no +** explicitly declared [INTEGER PRIMARY KEY] column, then the output +** parameters are set as follows: +** +**
+**     data type: "INTEGER"
+**     collation sequence: "BINARY"
+**     not null: 0
+**     primary key: 1
+**     auto increment: 0
+** 
+** +** This function may load one or more schemas from database files. If an +** error occurs during this process, or if the requested table or column +** cannot be found, an [error code] is returned and an error message left +** in the [database connection] (to be retrieved using sqlite3_errmsg()). +** +** This API is only available if the library was compiled with the +** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. +*/ +SQLITE_API int sqlite3_table_column_metadata( + sqlite3 *db, /* Connection handle */ + const char *zDbName, /* Database name or NULL */ + const char *zTableName, /* Table name */ + const char *zColumnName, /* Column name */ + char const **pzDataType, /* OUTPUT: Declared data type */ + char const **pzCollSeq, /* OUTPUT: Collation sequence name */ + int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ + int *pPrimaryKey, /* OUTPUT: True if column part of PK */ + int *pAutoinc /* OUTPUT: True if column is auto-increment */ +); + +/* +** CAPI3REF: Load An Extension {H12600} +** +** This interface loads an SQLite extension library from the named file. +** +** {H12601} The sqlite3_load_extension() interface attempts to load an +** SQLite extension library contained in the file zFile. +** +** {H12602} The entry point is zProc. +** +** {H12603} zProc may be 0, in which case the name of the entry point +** defaults to "sqlite3_extension_init". +** +** {H12604} The sqlite3_load_extension() interface shall return +** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. +** +** {H12605} If an error occurs and pzErrMsg is not 0, then the +** [sqlite3_load_extension()] interface shall attempt to +** fill *pzErrMsg with error message text stored in memory +** obtained from [sqlite3_malloc()]. {END} The calling function +** should free this memory by calling [sqlite3_free()]. +** +** {H12606} Extension loading must be enabled using +** [sqlite3_enable_load_extension()] prior to calling this API, +** otherwise an error will be returned. +*/ +SQLITE_API int sqlite3_load_extension( + sqlite3 *db, /* Load the extension into this database connection */ + const char *zFile, /* Name of the shared library containing extension */ + const char *zProc, /* Entry point. Derived from zFile if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ +); + +/* +** CAPI3REF: Enable Or Disable Extension Loading {H12620} +** +** So as not to open security holes in older applications that are +** unprepared to deal with extension loading, and as a means of disabling +** extension loading while evaluating user-entered SQL, the following API +** is provided to turn the [sqlite3_load_extension()] mechanism on and off. +** +** Extension loading is off by default. See ticket #1863. +** +** {H12621} Call the sqlite3_enable_load_extension() routine with onoff==1 +** to turn extension loading on and call it with onoff==0 to turn +** it back off again. +** +** {H12622} Extension loading is off by default. +*/ +SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); + +/* +** CAPI3REF: Automatically Load An Extensions {H12640} +** +** This API can be invoked at program startup in order to register +** one or more statically linked extensions that will be available +** to all new [database connections]. {END} +** +** This routine stores a pointer to the extension in an array that is +** obtained from [sqlite3_malloc()]. If you run a memory leak checker +** on your program and it reports a leak because of this array, invoke +** [sqlite3_reset_auto_extension()] prior to shutdown to free the memory. +** +** {H12641} This function registers an extension entry point that is +** automatically invoked whenever a new [database connection] +** is opened using [sqlite3_open()], [sqlite3_open16()], +** or [sqlite3_open_v2()]. +** +** {H12642} Duplicate extensions are detected so calling this routine +** multiple times with the same extension is harmless. +** +** {H12643} This routine stores a pointer to the extension in an array +** that is obtained from [sqlite3_malloc()]. +** +** {H12644} Automatic extensions apply across all threads. +*/ +SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); + +/* +** CAPI3REF: Reset Automatic Extension Loading {H12660} +** +** This function disables all previously registered automatic +** extensions. {END} It undoes the effect of all prior +** [sqlite3_auto_extension()] calls. +** +** {H12661} This function disables all previously registered +** automatic extensions. +** +** {H12662} This function disables automatic extensions in all threads. +*/ +SQLITE_API void sqlite3_reset_auto_extension(void); + +/* +****** EXPERIMENTAL - subject to change without notice ************** +** +** The interface to the virtual-table mechanism is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ + +/* +** Structures used by the virtual table interface +*/ +typedef struct sqlite3_vtab sqlite3_vtab; +typedef struct sqlite3_index_info sqlite3_index_info; +typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; +typedef struct sqlite3_module sqlite3_module; + +/* +** CAPI3REF: Virtual Table Object {H18000} +** KEYWORDS: sqlite3_module +** EXPERIMENTAL +** +** A module is a class of virtual tables. Each module is defined +** by an instance of the following structure. This structure consists +** mostly of methods for the module. +** +** This interface is experimental and is subject to change or +** removal in future releases of SQLite. +*/ +struct sqlite3_module { + int iVersion; + int (*xCreate)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xConnect)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); + int (*xDisconnect)(sqlite3_vtab *pVTab); + int (*xDestroy)(sqlite3_vtab *pVTab); + int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); + int (*xClose)(sqlite3_vtab_cursor*); + int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, + int argc, sqlite3_value **argv); + int (*xNext)(sqlite3_vtab_cursor*); + int (*xEof)(sqlite3_vtab_cursor*); + int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); + int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); + int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); + int (*xBegin)(sqlite3_vtab *pVTab); + int (*xSync)(sqlite3_vtab *pVTab); + int (*xCommit)(sqlite3_vtab *pVTab); + int (*xRollback)(sqlite3_vtab *pVTab); + int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg); + int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); +}; + +/* +** CAPI3REF: Virtual Table Indexing Information {H18100} +** KEYWORDS: sqlite3_index_info +** EXPERIMENTAL +** +** The sqlite3_index_info structure and its substructures is used to +** pass information into and receive the reply from the xBestIndex +** method of an sqlite3_module. The fields under **Inputs** are the +** inputs to xBestIndex and are read-only. xBestIndex inserts its +** results into the **Outputs** fields. +** +** The aConstraint[] array records WHERE clause constraints of the form: +** +**
column OP expr
+** +** where OP is =, <, <=, >, or >=. The particular operator is +** stored in aConstraint[].op. The index of the column is stored in +** aConstraint[].iColumn. aConstraint[].usable is TRUE if the +** expr on the right-hand side can be evaluated (and thus the constraint +** is usable) and false if it cannot. +** +** The optimizer automatically inverts terms of the form "expr OP column" +** and makes other simplifications to the WHERE clause in an attempt to +** get as many WHERE clause terms into the form shown above as possible. +** The aConstraint[] array only reports WHERE clause terms in the correct +** form that refer to the particular virtual table being queried. +** +** Information about the ORDER BY clause is stored in aOrderBy[]. +** Each term of aOrderBy records a column of the ORDER BY clause. +** +** The xBestIndex method must fill aConstraintUsage[] with information +** about what parameters to pass to xFilter. If argvIndex>0 then +** the right-hand side of the corresponding aConstraint[] is evaluated +** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit +** is true, then the constraint is assumed to be fully handled by the +** virtual table and is not checked again by SQLite. +** +** The idxNum and idxPtr values are recorded and passed into xFilter. +** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. +** +** The orderByConsumed means that output from xFilter will occur in +** the correct order to satisfy the ORDER BY clause so that no separate +** sorting step is required. +** +** The estimatedCost value is an estimate of the cost of doing the +** particular lookup. A full scan of a table with N entries should have +** a cost of N. A binary search of a table of N entries should have a +** cost of approximately log(N). +** +** This interface is experimental and is subject to change or +** removal in future releases of SQLite. +*/ +struct sqlite3_index_info { + /* Inputs */ + int nConstraint; /* Number of entries in aConstraint */ + struct sqlite3_index_constraint { + int iColumn; /* Column on left-hand side of constraint */ + unsigned char op; /* Constraint operator */ + unsigned char usable; /* True if this constraint is usable */ + int iTermOffset; /* Used internally - xBestIndex should ignore */ + } *aConstraint; /* Table of WHERE clause constraints */ + int nOrderBy; /* Number of terms in the ORDER BY clause */ + struct sqlite3_index_orderby { + int iColumn; /* Column number */ + unsigned char desc; /* True for DESC. False for ASC. */ + } *aOrderBy; /* The ORDER BY clause */ + /* Outputs */ + struct sqlite3_index_constraint_usage { + int argvIndex; /* if >0, constraint is part of argv to xFilter */ + unsigned char omit; /* Do not code a test for this constraint */ + } *aConstraintUsage; + int idxNum; /* Number used to identify the index */ + char *idxStr; /* String, possibly obtained from sqlite3_malloc */ + int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ + int orderByConsumed; /* True if output is already ordered */ + double estimatedCost; /* Estimated cost of using this index */ +}; +#define SQLITE_INDEX_CONSTRAINT_EQ 2 +#define SQLITE_INDEX_CONSTRAINT_GT 4 +#define SQLITE_INDEX_CONSTRAINT_LE 8 +#define SQLITE_INDEX_CONSTRAINT_LT 16 +#define SQLITE_INDEX_CONSTRAINT_GE 32 +#define SQLITE_INDEX_CONSTRAINT_MATCH 64 + +/* +** CAPI3REF: Register A Virtual Table Implementation {H18200} +** EXPERIMENTAL +** +** This routine is used to register a new module name with a +** [database connection]. Module names must be registered before +** creating new virtual tables on the module, or before using +** preexisting virtual tables of the module. +** +** This interface is experimental and is subject to change or +** removal in future releases of SQLite. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *, /* Methods for the module */ + void * /* Client data for xCreate/xConnect */ +); + +/* +** CAPI3REF: Register A Virtual Table Implementation {H18210} +** EXPERIMENTAL +** +** This routine is identical to the [sqlite3_create_module()] method above, +** except that it allows a destructor function to be specified. It is +** even more experimental than the rest of the virtual tables API. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module_v2( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *, /* Methods for the module */ + void *, /* Client data for xCreate/xConnect */ + void(*xDestroy)(void*) /* Module destructor function */ +); + +/* +** CAPI3REF: Virtual Table Instance Object {H18010} +** KEYWORDS: sqlite3_vtab +** EXPERIMENTAL +** +** Every module implementation uses a subclass of the following structure +** to describe a particular instance of the module. Each subclass will +** be tailored to the specific needs of the module implementation. +** The purpose of this superclass is to define certain fields that are +** common to all module implementations. +** +** Virtual tables methods can set an error message by assigning a +** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should +** take care that any prior string is freed by a call to [sqlite3_free()] +** prior to assigning a new string to zErrMsg. After the error message +** is delivered up to the client application, the string will be automatically +** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note +** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field +** since virtual tables are commonly implemented in loadable extensions which +** do not have access to sqlite3MPrintf() or sqlite3Free(). +** +** This interface is experimental and is subject to change or +** removal in future releases of SQLite. +*/ +struct sqlite3_vtab { + const sqlite3_module *pModule; /* The module for this virtual table */ + int nRef; /* Used internally */ + char *zErrMsg; /* Error message from sqlite3_mprintf() */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* +** CAPI3REF: Virtual Table Cursor Object {H18020} +** KEYWORDS: sqlite3_vtab_cursor +** EXPERIMENTAL +** +** Every module implementation uses a subclass of the following structure +** to describe cursors that point into the virtual table and are used +** to loop through the virtual table. Cursors are created using the +** xOpen method of the module. Each module implementation will define +** the content of a cursor structure to suit its own needs. +** +** This superclass exists in order to define fields of the cursor that +** are common to all implementations. +** +** This interface is experimental and is subject to change or +** removal in future releases of SQLite. +*/ +struct sqlite3_vtab_cursor { + sqlite3_vtab *pVtab; /* Virtual table of this cursor */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* +** CAPI3REF: Declare The Schema Of A Virtual Table {H18280} +** EXPERIMENTAL +** +** The xCreate and xConnect methods of a module use the following API +** to declare the format (the names and datatypes of the columns) of +** the virtual tables they implement. +** +** This interface is experimental and is subject to change or +** removal in future releases of SQLite. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); + +/* +** CAPI3REF: Overload A Function For A Virtual Table {H18300} +** EXPERIMENTAL +** +** Virtual tables can provide alternative implementations of functions +** using the xFindFunction method. But global versions of those functions +** must exist in order to be overloaded. +** +** This API makes sure a global version of a function with a particular +** name and number of parameters exists. If no such function exists +** before this API is called, a new function is created. The implementation +** of the new function always causes an exception to be thrown. So +** the new function is not good for anything by itself. Its only +** purpose is to be a placeholder function that can be overloaded +** by virtual tables. +** +** This API should be considered part of the virtual table interface, +** which is experimental and subject to change. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); + +/* +** The interface to the virtual-table mechanism defined above (back up +** to a comment remarkably similar to this one) is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +** +****** EXPERIMENTAL - subject to change without notice ************** +*/ + +/* +** CAPI3REF: A Handle To An Open BLOB {H17800} +** KEYWORDS: {BLOB handle} {BLOB handles} +** +** An instance of this object represents an open BLOB on which +** [sqlite3_blob_open | incremental BLOB I/O] can be performed. +** Objects of this type are created by [sqlite3_blob_open()] +** and destroyed by [sqlite3_blob_close()]. +** The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces +** can be used to read or write small subsections of the BLOB. +** The [sqlite3_blob_bytes()] interface returns the size of the BLOB in bytes. +*/ +typedef struct sqlite3_blob sqlite3_blob; + +/* +** CAPI3REF: Open A BLOB For Incremental I/O {H17810} +** +** This interfaces opens a [BLOB handle | handle] to the BLOB located +** in row iRow, column zColumn, table zTable in database zDb; +** in other words, the same BLOB that would be selected by: +** +**
+**     SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
+** 
{END} +** +** If the flags parameter is non-zero, the the BLOB is opened for read +** and write access. If it is zero, the BLOB is opened for read access. +** +** Note that the database name is not the filename that contains +** the database but rather the symbolic name of the database that +** is assigned when the database is connected using [ATTACH]. +** For the main database file, the database name is "main". +** For TEMP tables, the database name is "temp". +** +** On success, [SQLITE_OK] is returned and the new [BLOB handle] is written +** to *ppBlob. Otherwise an [error code] is returned and any value written +** to *ppBlob should not be used by the caller. +** This function sets the [database connection] error code and message +** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. +** +** If the row that a BLOB handle points to is modified by an +** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects +** then the BLOB handle is marked as "expired". +** This is true if any column of the row is changed, even a column +** other than the one the BLOB handle is open on. +** Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for +** a expired BLOB handle fail with an return code of [SQLITE_ABORT]. +** Changes written into a BLOB prior to the BLOB expiring are not +** rollback by the expiration of the BLOB. Such changes will eventually +** commit if the transaction continues to completion. +** +** Requirements: +** [H17813] [H17814] [H17816] [H17819] [H17821] [H17824] +*/ +SQLITE_API int sqlite3_blob_open( + sqlite3*, + const char *zDb, + const char *zTable, + const char *zColumn, + sqlite3_int64 iRow, + int flags, + sqlite3_blob **ppBlob +); + +/* +** CAPI3REF: Close A BLOB Handle {H17830} +** +** Closes an open [BLOB handle]. +** +** Closing a BLOB shall cause the current transaction to commit +** if there are no other BLOBs, no pending prepared statements, and the +** database connection is in [autocommit mode]. +** If any writes were made to the BLOB, they might be held in cache +** until the close operation if they will fit. {END} +** +** Closing the BLOB often forces the changes +** out to disk and so if any I/O errors occur, they will likely occur +** at the time when the BLOB is closed. {H17833} Any errors that occur during +** closing are reported as a non-zero return value. +** +** The BLOB is closed unconditionally. Even if this routine returns +** an error code, the BLOB is still closed. +** +** Requirements: +** [H17833] [H17836] [H17839] +*/ +SQLITE_API int sqlite3_blob_close(sqlite3_blob *); + +/* +** CAPI3REF: Return The Size Of An Open BLOB {H17840} +** +** Returns the size in bytes of the BLOB accessible via the open +** []BLOB handle] in its only argument. +** +** Requirements: +** [H17843] +*/ +SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); + +/* +** CAPI3REF: Read Data From A BLOB Incrementally {H17850} +** +** This function is used to read data from an open [BLOB handle] into a +** caller-supplied buffer. N bytes of data are copied into buffer Z +** from the open BLOB, starting at offset iOffset. +** +** If offset iOffset is less than N bytes from the end of the BLOB, +** [SQLITE_ERROR] is returned and no data is read. If N or iOffset is +** less than zero, [SQLITE_ERROR] is returned and no data is read. +** +** An attempt to read from an expired [BLOB handle] fails with an +** error code of [SQLITE_ABORT]. +** +** On success, SQLITE_OK is returned. +** Otherwise, an [error code] or an [extended error code] is returned. +** +** Requirements: +** [H17853] [H17856] [H17859] [H17862] [H17863] [H17865] [H17868] +*/ +SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); + +/* +** CAPI3REF: Write Data Into A BLOB Incrementally {H17870} +** +** This function is used to write data into an open [BLOB handle] from a +** caller-supplied buffer. N bytes of data are copied from the buffer Z +** into the open BLOB, starting at offset iOffset. +** +** If the [BLOB handle] passed as the first argument was not opened for +** writing (the flags parameter to [sqlite3_blob_open()] was zero), +** this function returns [SQLITE_READONLY]. +** +** This function may only modify the contents of the BLOB; it is +** not possible to increase the size of a BLOB using this API. +** If offset iOffset is less than N bytes from the end of the BLOB, +** [SQLITE_ERROR] is returned and no data is written. If N is +** less than zero [SQLITE_ERROR] is returned and no data is written. +** +** An attempt to write to an expired [BLOB handle] fails with an +** error code of [SQLITE_ABORT]. Writes to the BLOB that occurred +** before the [BLOB handle] expired are not rolled back by the +** expiration of the handle, though of course those changes might +** have been overwritten by the statement that expired the BLOB handle +** or by other independent statements. +** +** On success, SQLITE_OK is returned. +** Otherwise, an [error code] or an [extended error code] is returned. +** +** Requirements: +** [H17873] [H17874] [H17875] [H17876] [H17877] [H17879] [H17882] [H17885] +** [H17888] +*/ +SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); + +/* +** CAPI3REF: Virtual File System Objects {H11200} +** +** A virtual filesystem (VFS) is an [sqlite3_vfs] object +** that SQLite uses to interact +** with the underlying operating system. Most SQLite builds come with a +** single default VFS that is appropriate for the host computer. +** New VFSes can be registered and existing VFSes can be unregistered. +** The following interfaces are provided. +** +** The sqlite3_vfs_find() interface returns a pointer to a VFS given its name. +** Names are case sensitive. +** Names are zero-terminated UTF-8 strings. +** If there is no match, a NULL pointer is returned. +** If zVfsName is NULL then the default VFS is returned. +** +** New VFSes are registered with sqlite3_vfs_register(). +** Each new VFS becomes the default VFS if the makeDflt flag is set. +** The same VFS can be registered multiple times without injury. +** To make an existing VFS into the default VFS, register it again +** with the makeDflt flag set. If two different VFSes with the +** same name are registered, the behavior is undefined. If a +** VFS is registered with a name that is NULL or an empty string, +** then the behavior is undefined. +** +** Unregister a VFS with the sqlite3_vfs_unregister() interface. +** If the default VFS is unregistered, another VFS is chosen as +** the default. The choice for the new VFS is arbitrary. +** +** Requirements: +** [H11203] [H11206] [H11209] [H11212] [H11215] [H11218] +*/ +SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); +SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); +SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); + +/* +** CAPI3REF: Mutexes {H17000} +** +** The SQLite core uses these routines for thread +** synchronization. Though they are intended for internal +** use by SQLite, code that links against SQLite is +** permitted to use any of these routines. +** +** The SQLite source code contains multiple implementations +** of these mutex routines. An appropriate implementation +** is selected automatically at compile-time. The following +** implementations are available in the SQLite core: +** +**
    +**
  • SQLITE_MUTEX_OS2 +**
  • SQLITE_MUTEX_PTHREAD +**
  • SQLITE_MUTEX_W32 +**
  • SQLITE_MUTEX_NOOP +**
+** +** The SQLITE_MUTEX_NOOP implementation is a set of routines +** that does no real locking and is appropriate for use in +** a single-threaded application. The SQLITE_MUTEX_OS2, +** SQLITE_MUTEX_PTHREAD, and SQLITE_MUTEX_W32 implementations +** are appropriate for use on OS/2, Unix, and Windows. +** +** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor +** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex +** implementation is included with the library. In this case the +** application must supply a custom mutex implementation using the +** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function +** before calling sqlite3_initialize() or any other public sqlite3_ +** function that calls sqlite3_initialize(). +** +** {H17011} The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. {H17012} If it returns NULL +** that means that a mutex could not be allocated. {H17013} SQLite +** will unwind its stack and return an error. {H17014} The argument +** to sqlite3_mutex_alloc() is one of these integer constants: +** +**
    +**
  • SQLITE_MUTEX_FAST +**
  • SQLITE_MUTEX_RECURSIVE +**
  • SQLITE_MUTEX_STATIC_MASTER +**
  • SQLITE_MUTEX_STATIC_MEM +**
  • SQLITE_MUTEX_STATIC_MEM2 +**
  • SQLITE_MUTEX_STATIC_PRNG +**
  • SQLITE_MUTEX_STATIC_LRU +**
  • SQLITE_MUTEX_STATIC_LRU2 +**
+** +** {H17015} The first two constants cause sqlite3_mutex_alloc() to create +** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. {END} +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. {H17016} But SQLite will only request a recursive mutex in +** cases where it really needs one. {END} If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** {H17017} The other allowed parameters to sqlite3_mutex_alloc() each return +** a pointer to a static preexisting mutex. {END} Four static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** {H17018} Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. {H17034} But for the static +** mutex types, the same mutex is returned on every call that has +** the same type number. +** +** {H17019} The sqlite3_mutex_free() routine deallocates a previously +** allocated dynamic mutex. {H17020} SQLite is careful to deallocate every +** dynamic mutex that it allocates. {A17021} The dynamic mutexes must not be in +** use when they are deallocated. {A17022} Attempting to deallocate a static +** mutex results in undefined behavior. {H17023} SQLite never deallocates +** a static mutex. {END} +** +** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. {H17024} If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. {H17025} The sqlite3_mutex_try() interface returns [SQLITE_OK] +** upon successful entry. {H17026} Mutexes created using +** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. +** {H17027} In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter. {A17028} If the same thread tries to enter any other +** kind of mutex more than once, the behavior is undefined. +** {H17029} SQLite will never exhibit +** such behavior in its own use of mutexes. +** +** Some systems (for example, Windows 95) do not support the operation +** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() +** will always return SQLITE_BUSY. {H17030} The SQLite core only ever uses +** sqlite3_mutex_try() as an optimization so this is acceptable behavior. +** +** {H17031} The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. {A17032} The behavior +** is undefined if the mutex is not currently entered by the +** calling thread or is not currently allocated. {H17033} SQLite will +** never do either. {END} +** +** If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or +** sqlite3_mutex_leave() is a NULL pointer, then all three routines +** behave as no-ops. +** +** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. +*/ +SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); +SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); + +/* +** CAPI3REF: Mutex Methods Object {H17120} +** EXPERIMENTAL +** +** An instance of this structure defines the low-level routines +** used to allocate and use mutexes. +** +** Usually, the default mutex implementations provided by SQLite are +** sufficient, however the user has the option of substituting a custom +** implementation for specialized deployments or systems for which SQLite +** does not provide a suitable implementation. In this case, the user +** creates and populates an instance of this structure to pass +** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option. +** Additionally, an instance of this structure can be used as an +** output variable when querying the system for the current mutex +** implementation, using the [SQLITE_CONFIG_GETMUTEX] option. +** +** The xMutexInit method defined by this structure is invoked as +** part of system initialization by the sqlite3_initialize() function. +** {H17001} The xMutexInit routine shall be called by SQLite once for each +** effective call to [sqlite3_initialize()]. +** +** The xMutexEnd method defined by this structure is invoked as +** part of system shutdown by the sqlite3_shutdown() function. The +** implementation of this method is expected to release all outstanding +** resources obtained by the mutex methods implementation, especially +** those obtained by the xMutexInit method. {H17003} The xMutexEnd() +** interface shall be invoked once for each call to [sqlite3_shutdown()]. +** +** The remaining seven methods defined by this structure (xMutexAlloc, +** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and +** xMutexNotheld) implement the following interfaces (respectively): +** +**
    +**
  • [sqlite3_mutex_alloc()]
  • +**
  • [sqlite3_mutex_free()]
  • +**
  • [sqlite3_mutex_enter()]
  • +**
  • [sqlite3_mutex_try()]
  • +**
  • [sqlite3_mutex_leave()]
  • +**
  • [sqlite3_mutex_held()]
  • +**
  • [sqlite3_mutex_notheld()]
  • +**
+** +** The only difference is that the public sqlite3_XXX functions enumerated +** above silently ignore any invocations that pass a NULL pointer instead +** of a valid mutex handle. The implementations of the methods defined +** by this structure are not required to handle this case, the results +** of passing a NULL pointer instead of a valid mutex handle are undefined +** (i.e. it is acceptable to provide an implementation that segfaults if +** it is passed a NULL pointer). +*/ +typedef struct sqlite3_mutex_methods sqlite3_mutex_methods; +struct sqlite3_mutex_methods { + int (*xMutexInit)(void); + int (*xMutexEnd)(void); + sqlite3_mutex *(*xMutexAlloc)(int); + void (*xMutexFree)(sqlite3_mutex *); + void (*xMutexEnter)(sqlite3_mutex *); + int (*xMutexTry)(sqlite3_mutex *); + void (*xMutexLeave)(sqlite3_mutex *); + int (*xMutexHeld)(sqlite3_mutex *); + int (*xMutexNotheld)(sqlite3_mutex *); +}; + +/* +** CAPI3REF: Mutex Verification Routines {H17080} +** +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines +** are intended for use inside assert() statements. {H17081} The SQLite core +** never uses these routines except inside an assert() and applications +** are advised to follow the lead of the core. {H17082} The core only +** provides implementations for these routines when it is compiled +** with the SQLITE_DEBUG flag. {A17087} External mutex implementations +** are only required to provide these routines if SQLITE_DEBUG is +** defined and if NDEBUG is not defined. +** +** {H17083} These routines should return true if the mutex in their argument +** is held or not held, respectively, by the calling thread. +** +** {X17084} The implementation is not required to provided versions of these +** routines that actually work. If the implementation does not provide working +** versions of these routines, it should at least provide stubs that always +** return true so that one does not get spurious assertion failures. +** +** {H17085} If the argument to sqlite3_mutex_held() is a NULL pointer then +** the routine should return 1. {END} This seems counter-intuitive since +** clearly the mutex cannot be held if it does not exist. But the +** the reason the mutex does not exist is because the build is not +** using mutexes. And we do not want the assert() containing the +** call to sqlite3_mutex_held() to fail, so a non-zero return is +** the appropriate thing to do. {H17086} The sqlite3_mutex_notheld() +** interface should also return 1 when given a NULL pointer. +*/ +SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); + +/* +** CAPI3REF: Mutex Types {H17001} +** +** The [sqlite3_mutex_alloc()] interface takes a single argument +** which is one of these integer constants. +** +** The set of static mutexes may change from one SQLite release to the +** next. Applications that override the built-in mutex logic must be +** prepared to accommodate additional static mutexes. +*/ +#define SQLITE_MUTEX_FAST 0 +#define SQLITE_MUTEX_RECURSIVE 1 +#define SQLITE_MUTEX_STATIC_MASTER 2 +#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ +#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */ +#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */ +#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ +#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ +#define SQLITE_MUTEX_STATIC_LRU2 7 /* lru page list */ + +/* +** CAPI3REF: Retrieve the mutex for a database connection {H17002} +** +** This interface returns a pointer the [sqlite3_mutex] object that +** serializes access to the [database connection] given in the argument +** when the [threading mode] is Serialized. +** If the [threading mode] is Single-thread or Multi-thread then this +** routine returns a NULL pointer. +*/ +SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); + +/* +** CAPI3REF: Low-Level Control Of Database Files {H11300} +** +** {H11301} The [sqlite3_file_control()] interface makes a direct call to the +** xFileControl method for the [sqlite3_io_methods] object associated +** with a particular database identified by the second argument. {H11302} The +** name of the database is the name assigned to the database by the +** ATTACH SQL command that opened the +** database. {H11303} To control the main database file, use the name "main" +** or a NULL pointer. {H11304} The third and fourth parameters to this routine +** are passed directly through to the second and third parameters of +** the xFileControl method. {H11305} The return value of the xFileControl +** method becomes the return value of this routine. +** +** {H11306} If the second parameter (zDbName) does not match the name of any +** open database file, then SQLITE_ERROR is returned. {H11307} This error +** code is not remembered and will not be recalled by [sqlite3_errcode()] +** or [sqlite3_errmsg()]. {A11308} The underlying xFileControl method might +** also return SQLITE_ERROR. {A11309} There is no way to distinguish between +** an incorrect zDbName and an SQLITE_ERROR return from the underlying +** xFileControl method. {END} +** +** See also: [SQLITE_FCNTL_LOCKSTATE] +*/ +SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); + +/* +** CAPI3REF: Testing Interface {H11400} +** +** The sqlite3_test_control() interface is used to read out internal +** state of SQLite and to inject faults into SQLite for testing +** purposes. The first parameter is an operation code that determines +** the number, meaning, and operation of all subsequent parameters. +** +** This interface is not for use by applications. It exists solely +** for verifying the correct operation of the SQLite library. Depending +** on how the SQLite library is compiled, this interface might not exist. +** +** The details of the operation codes, their meanings, the parameters +** they take, and what they do are all subject to change without notice. +** Unlike most of the SQLite API, this function is not guaranteed to +** operate consistently from one release to the next. +*/ +SQLITE_API int sqlite3_test_control(int op, ...); + +/* +** CAPI3REF: Testing Interface Operation Codes {H11410} +** +** These constants are the valid operation code parameters used +** as the first argument to [sqlite3_test_control()]. +** +** These parameters and their meanings are subject to change +** without notice. These values are for testing purposes only. +** Applications should not use any of these parameters or the +** [sqlite3_test_control()] interface. +*/ +#define SQLITE_TESTCTRL_PRNG_SAVE 5 +#define SQLITE_TESTCTRL_PRNG_RESTORE 6 +#define SQLITE_TESTCTRL_PRNG_RESET 7 +#define SQLITE_TESTCTRL_BITVEC_TEST 8 +#define SQLITE_TESTCTRL_FAULT_INSTALL 9 +#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 +#define SQLITE_TESTCTRL_PENDING_BYTE 11 + +/* +** CAPI3REF: SQLite Runtime Status {H17200} +** EXPERIMENTAL +** +** This interface is used to retrieve runtime status information +** about the preformance of SQLite, and optionally to reset various +** highwater marks. The first argument is an integer code for +** the specific parameter to measure. Recognized integer codes +** are of the form [SQLITE_STATUS_MEMORY_USED | SQLITE_STATUS_...]. +** The current value of the parameter is returned into *pCurrent. +** The highest recorded value is returned in *pHighwater. If the +** resetFlag is true, then the highest record value is reset after +** *pHighwater is written. Some parameters do not record the highest +** value. For those parameters +** nothing is written into *pHighwater and the resetFlag is ignored. +** Other parameters record only the highwater mark and not the current +** value. For these latter parameters nothing is written into *pCurrent. +** +** This routine returns SQLITE_OK on success and a non-zero +** [error code] on failure. +** +** This routine is threadsafe but is not atomic. This routine can +** called while other threads are running the same or different SQLite +** interfaces. However the values returned in *pCurrent and +** *pHighwater reflect the status of SQLite at different points in time +** and it is possible that another thread might change the parameter +** in between the times when *pCurrent and *pHighwater are written. +** +** See also: [sqlite3_db_status()] +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); + + +/* +** CAPI3REF: Status Parameters {H17250} +** EXPERIMENTAL +** +** These integer constants designate various run-time status parameters +** that can be returned by [sqlite3_status()]. +** +**
+**
SQLITE_STATUS_MEMORY_USED
+**
This parameter is the current amount of memory checked out +** using [sqlite3_malloc()], either directly or indirectly. The +** figure includes calls made to [sqlite3_malloc()] by the application +** and internal memory usage by the SQLite library. Scratch memory +** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache +** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in +** this parameter. The amount returned is the sum of the allocation +** sizes as reported by the xSize method in [sqlite3_mem_methods].
+** +**
SQLITE_STATUS_MALLOC_SIZE
+**
This parameter records the largest memory allocation request +** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their +** internal equivalents). Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
+** +**
SQLITE_STATUS_PAGECACHE_USED
+**
This parameter returns the number of pages used out of the +** [pagecache memory allocator] that was configured using +** [SQLITE_CONFIG_PAGECACHE]. The +** value returned is in pages, not in bytes.
+** +**
SQLITE_STATUS_PAGECACHE_OVERFLOW
+**
This parameter returns the number of bytes of page cache +** allocation which could not be statisfied by the [SQLITE_CONFIG_PAGECACHE] +** buffer and where forced to overflow to [sqlite3_malloc()]. The +** returned value includes allocations that overflowed because they +** where too large (they were larger than the "sz" parameter to +** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because +** no space was left in the page cache.
+** +**
SQLITE_STATUS_PAGECACHE_SIZE
+**
This parameter records the largest memory allocation request +** handed to [pagecache memory allocator]. Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
+** +**
SQLITE_STATUS_SCRATCH_USED
+**
This parameter returns the number of allocations used out of the +** [scratch memory allocator] configured using +** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not +** in bytes. Since a single thread may only have one scratch allocation +** outstanding at time, this parameter also reports the number of threads +** using scratch memory at the same time.
+** +**
SQLITE_STATUS_SCRATCH_OVERFLOW
+**
This parameter returns the number of bytes of scratch memory +** allocation which could not be statisfied by the [SQLITE_CONFIG_SCRATCH] +** buffer and where forced to overflow to [sqlite3_malloc()]. The values +** returned include overflows because the requested allocation was too +** larger (that is, because the requested allocation was larger than the +** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer +** slots were available. +**
+** +**
SQLITE_STATUS_SCRATCH_SIZE
+**
This parameter records the largest memory allocation request +** handed to [scratch memory allocator]. Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
+** +**
SQLITE_STATUS_PARSER_STACK
+**
This parameter records the deepest parser stack. It is only +** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].
+**
+** +** New status parameters may be added from time to time. +*/ +#define SQLITE_STATUS_MEMORY_USED 0 +#define SQLITE_STATUS_PAGECACHE_USED 1 +#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 +#define SQLITE_STATUS_SCRATCH_USED 3 +#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 +#define SQLITE_STATUS_MALLOC_SIZE 5 +#define SQLITE_STATUS_PARSER_STACK 6 +#define SQLITE_STATUS_PAGECACHE_SIZE 7 +#define SQLITE_STATUS_SCRATCH_SIZE 8 + +/* +** CAPI3REF: Database Connection Status {H17500} +** EXPERIMENTAL +** +** This interface is used to retrieve runtime status information +** about a single [database connection]. The first argument is the +** database connection object to be interrogated. The second argument +** is the parameter to interrogate. Currently, the only allowed value +** for the second parameter is [SQLITE_DBSTATUS_LOOKASIDE_USED]. +** Additional options will likely appear in future releases of SQLite. +** +** The current value of the requested parameter is written into *pCur +** and the highest instantaneous value is written into *pHiwtr. If +** the resetFlg is true, then the highest instantaneous value is +** reset back down to the current value. +** +** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); + +/* +** CAPI3REF: Status Parameters for database connections {H17520} +** EXPERIMENTAL +** +** Status verbs for [sqlite3_db_status()]. +** +**
+**
SQLITE_DBSTATUS_LOOKASIDE_USED
+**
This parameter returns the number of lookaside memory slots currently +** checked out.
+**
+*/ +#define SQLITE_DBSTATUS_LOOKASIDE_USED 0 + + +/* +** CAPI3REF: Prepared Statement Status {H17550} +** EXPERIMENTAL +** +** Each prepared statement maintains various +** [SQLITE_STMTSTATUS_SORT | counters] that measure the number +** of times it has performed specific operations. These counters can +** be used to monitor the performance characteristics of the prepared +** statements. For example, if the number of table steps greatly exceeds +** the number of table searches or result rows, that would tend to indicate +** that the prepared statement is using a full table scan rather than +** an index. +** +** This interface is used to retrieve and reset counter values from +** a [prepared statement]. The first argument is the prepared statement +** object to be interrogated. The second argument +** is an integer code for a specific [SQLITE_STMTSTATUS_SORT | counter] +** to be interrogated. +** The current value of the requested counter is returned. +** If the resetFlg is true, then the counter is reset to zero after this +** interface call returns. +** +** See also: [sqlite3_status()] and [sqlite3_db_status()]. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); + +/* +** CAPI3REF: Status Parameters for prepared statements {H17570} +** EXPERIMENTAL +** +** These preprocessor macros define integer codes that name counter +** values associated with the [sqlite3_stmt_status()] interface. +** The meanings of the various counters are as follows: +** +**
+**
SQLITE_STMTSTATUS_FULLSCAN_STEP
+**
This is the number of times that SQLite has stepped forward in +** a table as part of a full table scan. Large numbers for this counter +** may indicate opportunities for performance improvement through +** careful use of indices.
+** +**
SQLITE_STMTSTATUS_SORT
+**
This is the number of sort operations that have occurred. +** A non-zero value in this counter may indicate an opportunity to +** improvement performance through careful use of indices.
+** +**
+*/ +#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 +#define SQLITE_STMTSTATUS_SORT 2 + +/* +** CAPI3REF: Custom Page Cache Object +** EXPERIMENTAL +** +** The sqlite3_pcache type is opaque. It is implemented by +** the pluggable module. The SQLite core has no knowledge of +** its size or internal structure and never deals with the +** sqlite3_pcache object except by holding and passing pointers +** to the object. +** +** See [sqlite3_pcache_methods] for additional information. +*/ +typedef struct sqlite3_pcache sqlite3_pcache; + +/* +** CAPI3REF: Application Defined Page Cache. +** EXPERIMENTAL +** +** The [sqlite3_config]([SQLITE_CONFIG_PCACHE], ...) interface can +** register an alternative page cache implementation by passing in an +** instance of the sqlite3_pcache_methods structure. The majority of the +** heap memory used by sqlite is used by the page cache to cache data read +** from, or ready to be written to, the database file. By implementing a +** custom page cache using this API, an application can control more +** precisely the amount of memory consumed by sqlite, the way in which +** said memory is allocated and released, and the policies used to +** determine exactly which parts of a database file are cached and for +** how long. +** +** The contents of the structure are copied to an internal buffer by sqlite +** within the call to [sqlite3_config]. +** +** The xInit() method is called once for each call to [sqlite3_initialize()] +** (usually only once during the lifetime of the process). It is passed +** a copy of the sqlite3_pcache_methods.pArg value. It can be used to set +** up global structures and mutexes required by the custom page cache +** implementation. The xShutdown() method is called from within +** [sqlite3_shutdown()], if the application invokes this API. It can be used +** to clean up any outstanding resources before process shutdown, if required. +** +** The xCreate() method is used to construct a new cache instance. The +** first parameter, szPage, is the size in bytes of the pages that must +** be allocated by the cache. szPage will not be a power of two. The +** second argument, bPurgeable, is true if the cache being created will +** be used to cache database pages read from a file stored on disk, or +** false if it is used for an in-memory database. The cache implementation +** does not have to do anything special based on the value of bPurgeable, +** it is purely advisory. +** +** The xCachesize() method may be called at any time by SQLite to set the +** suggested maximum cache-size (number of pages stored by) the cache +** instance passed as the first argument. This is the value configured using +** the SQLite "[PRAGMA cache_size]" command. As with the bPurgeable parameter, +** the implementation is not required to do anything special with this +** value, it is advisory only. +** +** The xPagecount() method should return the number of pages currently +** stored in the cache supplied as an argument. +** +** The xFetch() method is used to fetch a page and return a pointer to it. +** A 'page', in this context, is a buffer of szPage bytes aligned at an +** 8-byte boundary. The page to be fetched is determined by the key. The +** mimimum key value is 1. After it has been retrieved using xFetch, the page +** is considered to be pinned. +** +** If the requested page is already in the page cache, then a pointer to +** the cached buffer should be returned with its contents intact. If the +** page is not already in the cache, then the expected behaviour of the +** cache is determined by the value of the createFlag parameter passed +** to xFetch, according to the following table: +** +** +**
createFlagExpected Behaviour +**
0NULL should be returned. No new cache entry is created. +**
1If createFlag is set to 1, this indicates that +** SQLite is holding pinned pages that can be unpinned +** by writing their contents to the database file (a +** relatively expensive operation). In this situation the +** cache implementation has two choices: it can return NULL, +** in which case SQLite will attempt to unpin one or more +** pages before re-requesting the same page, or it can +** allocate a new page and return a pointer to it. If a new +** page is allocated, then the first sizeof(void*) bytes of +** it (at least) must be zeroed before it is returned. +**
2If createFlag is set to 2, then SQLite is not holding any +** pinned pages associated with the specific cache passed +** as the first argument to xFetch() that can be unpinned. The +** cache implementation should attempt to allocate a new +** cache entry and return a pointer to it. Again, the first +** sizeof(void*) bytes of the page should be zeroed before +** it is returned. If the xFetch() method returns NULL when +** createFlag==2, SQLite assumes that a memory allocation +** failed and returns SQLITE_NOMEM to the user. +**
+** +** xUnpin() is called by SQLite with a pointer to a currently pinned page +** as its second argument. If the third parameter, discard, is non-zero, +** then the page should be evicted from the cache. In this case SQLite +** assumes that the next time the page is retrieved from the cache using +** the xFetch() method, it will be zeroed. If the discard parameter is +** zero, then the page is considered to be unpinned. The cache implementation +** may choose to reclaim (free or recycle) unpinned pages at any time. +** SQLite assumes that next time the page is retrieved from the cache +** it will either be zeroed, or contain the same data that it did when it +** was unpinned. +** +** The cache is not required to perform any reference counting. A single +** call to xUnpin() unpins the page regardless of the number of prior calls +** to xFetch(). +** +** The xRekey() method is used to change the key value associated with the +** page passed as the second argument from oldKey to newKey. If the cache +** previously contains an entry associated with newKey, it should be +** discarded. Any prior cache entry associated with newKey is guaranteed not +** to be pinned. +** +** When SQLite calls the xTruncate() method, the cache must discard all +** existing cache entries with page numbers (keys) greater than or equal +** to the value of the iLimit parameter passed to xTruncate(). If any +** of these pages are pinned, they are implicitly unpinned, meaning that +** they can be safely discarded. +** +** The xDestroy() method is used to delete a cache allocated by xCreate(). +** All resources associated with the specified cache should be freed. After +** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*] +** handle invalid, and will not use it with any other sqlite3_pcache_methods +** functions. +*/ +typedef struct sqlite3_pcache_methods sqlite3_pcache_methods; +struct sqlite3_pcache_methods { + void *pArg; + int (*xInit)(void*); + void (*xShutdown)(void*); + sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable); + void (*xCachesize)(sqlite3_pcache*, int nCachesize); + int (*xPagecount)(sqlite3_pcache*); + void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); + void (*xUnpin)(sqlite3_pcache*, void*, int discard); + void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey); + void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); + void (*xDestroy)(sqlite3_pcache*); +}; + +/* +** CAPI3REF: Online Backup Object +** EXPERIMENTAL +** +** The sqlite3_backup object records state information about an ongoing +** online backup operation. The sqlite3_backup object is created by +** a call to [sqlite3_backup_init()] and is destroyed by a call to +** [sqlite3_backup_finish()]. +** +** See Also: [Using the SQLite Online Backup API] +*/ +typedef struct sqlite3_backup sqlite3_backup; + +/* +** CAPI3REF: Online Backup API. +** EXPERIMENTAL +** +** This API is used to overwrite the contents of one database with that +** of another. It is useful either for creating backups of databases or +** for copying in-memory databases to or from persistent files. +** +** See Also: [Using the SQLite Online Backup API] +** +** Exclusive access is required to the destination database for the +** duration of the operation. However the source database is only +** read-locked while it is actually being read, it is not locked +** continuously for the entire operation. Thus, the backup may be +** performed on a live database without preventing other users from +** writing to the database for an extended period of time. +** +** To perform a backup operation: +**
    +**
  1. sqlite3_backup_init() is called once to initialize the +** backup, +**
  2. sqlite3_backup_step() is called one or more times to transfer +** the data between the two databases, and finally +**
  3. sqlite3_backup_finish() is called to release all resources +** associated with the backup operation. +**
+** There should be exactly one call to sqlite3_backup_finish() for each +** successful call to sqlite3_backup_init(). +** +** sqlite3_backup_init() +** +** The first two arguments passed to [sqlite3_backup_init()] are the database +** handle associated with the destination database and the database name +** used to attach the destination database to the handle. The database name +** is "main" for the main database, "temp" for the temporary database, or +** the name specified as part of the [ATTACH] statement if the destination is +** an attached database. The third and fourth arguments passed to +** sqlite3_backup_init() identify the [database connection] +** and database name used +** to access the source database. The values passed for the source and +** destination [database connection] parameters must not be the same. +** +** If an error occurs within sqlite3_backup_init(), then NULL is returned +** and an error code and error message written into the [database connection] +** passed as the first argument. They may be retrieved using the +** [sqlite3_errcode()], [sqlite3_errmsg()], and [sqlite3_errmsg16()] functions. +** Otherwise, if successful, a pointer to an [sqlite3_backup] object is +** returned. This pointer may be used with the sqlite3_backup_step() and +** sqlite3_backup_finish() functions to perform the specified backup +** operation. +** +** sqlite3_backup_step() +** +** Function [sqlite3_backup_step()] is used to copy up to nPage pages between +** the source and destination databases, where nPage is the value of the +** second parameter passed to sqlite3_backup_step(). If nPage is a negative +** value, all remaining source pages are copied. If the required pages are +** succesfully copied, but there are still more pages to copy before the +** backup is complete, it returns [SQLITE_OK]. If no error occured and there +** are no more pages to copy, then [SQLITE_DONE] is returned. If an error +** occurs, then an SQLite error code is returned. As well as [SQLITE_OK] and +** [SQLITE_DONE], a call to sqlite3_backup_step() may return [SQLITE_READONLY], +** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an +** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code. +** +** As well as the case where the destination database file was opened for +** read-only access, sqlite3_backup_step() may return [SQLITE_READONLY] if +** the destination is an in-memory database with a different page size +** from the source database. +** +** If sqlite3_backup_step() cannot obtain a required file-system lock, then +** the [sqlite3_busy_handler | busy-handler function] +** is invoked (if one is specified). If the +** busy-handler returns non-zero before the lock is available, then +** [SQLITE_BUSY] is returned to the caller. In this case the call to +** sqlite3_backup_step() can be retried later. If the source +** [database connection] +** is being used to write to the source database when sqlite3_backup_step() +** is called, then [SQLITE_LOCKED] is returned immediately. Again, in this +** case the call to sqlite3_backup_step() can be retried later on. If +** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or +** [SQLITE_READONLY] is returned, then +** there is no point in retrying the call to sqlite3_backup_step(). These +** errors are considered fatal. At this point the application must accept +** that the backup operation has failed and pass the backup operation handle +** to the sqlite3_backup_finish() to release associated resources. +** +** Following the first call to sqlite3_backup_step(), an exclusive lock is +** obtained on the destination file. It is not released until either +** sqlite3_backup_finish() is called or the backup operation is complete +** and sqlite3_backup_step() returns [SQLITE_DONE]. Additionally, each time +** a call to sqlite3_backup_step() is made a [shared lock] is obtained on +** the source database file. This lock is released before the +** sqlite3_backup_step() call returns. Because the source database is not +** locked between calls to sqlite3_backup_step(), it may be modified mid-way +** through the backup procedure. If the source database is modified by an +** external process or via a database connection other than the one being +** used by the backup operation, then the backup will be transparently +** restarted by the next call to sqlite3_backup_step(). If the source +** database is modified by the using the same database connection as is used +** by the backup operation, then the backup database is transparently +** updated at the same time. +** +** sqlite3_backup_finish() +** +** Once sqlite3_backup_step() has returned [SQLITE_DONE], or when the +** application wishes to abandon the backup operation, the [sqlite3_backup] +** object should be passed to sqlite3_backup_finish(). This releases all +** resources associated with the backup operation. If sqlite3_backup_step() +** has not yet returned [SQLITE_DONE], then any active write-transaction on the +** destination database is rolled back. The [sqlite3_backup] object is invalid +** and may not be used following a call to sqlite3_backup_finish(). +** +** The value returned by sqlite3_backup_finish is [SQLITE_OK] if no error +** occurred, regardless or whether or not sqlite3_backup_step() was called +** a sufficient number of times to complete the backup operation. Or, if +** an out-of-memory condition or IO error occured during a call to +** sqlite3_backup_step() then [SQLITE_NOMEM] or an +** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] error code +** is returned. In this case the error code and an error message are +** written to the destination [database connection]. +** +** A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step() is +** not a permanent error and does not affect the return value of +** sqlite3_backup_finish(). +** +** sqlite3_backup_remaining(), sqlite3_backup_pagecount() +** +** Each call to sqlite3_backup_step() sets two values stored internally +** by an [sqlite3_backup] object. The number of pages still to be backed +** up, which may be queried by sqlite3_backup_remaining(), and the total +** number of pages in the source database file, which may be queried by +** sqlite3_backup_pagecount(). +** +** The values returned by these functions are only updated by +** sqlite3_backup_step(). If the source database is modified during a backup +** operation, then the values are not updated to account for any extra +** pages that need to be updated or the size of the source database file +** changing. +** +** Concurrent Usage of Database Handles +** +** The source [database connection] may be used by the application for other +** purposes while a backup operation is underway or being initialized. +** If SQLite is compiled and configured to support threadsafe database +** connections, then the source database connection may be used concurrently +** from within other threads. +** +** However, the application must guarantee that the destination database +** connection handle is not passed to any other API (by any thread) after +** sqlite3_backup_init() is called and before the corresponding call to +** sqlite3_backup_finish(). Unfortunately SQLite does not currently check +** for this, if the application does use the destination [database connection] +** for some other purpose during a backup operation, things may appear to +** work correctly but in fact be subtly malfunctioning. Use of the +** destination database connection while a backup is in progress might +** also cause a mutex deadlock. +** +** Furthermore, if running in [shared cache mode], the application must +** guarantee that the shared cache used by the destination database +** is not accessed while the backup is running. In practice this means +** that the application must guarantee that the file-system file being +** backed up to is not accessed by any connection within the process, +** not just the specific connection that was passed to sqlite3_backup_init(). +** +** The [sqlite3_backup] object itself is partially threadsafe. Multiple +** threads may safely make multiple concurrent calls to sqlite3_backup_step(). +** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount() +** APIs are not strictly speaking threadsafe. If they are invoked at the +** same time as another thread is invoking sqlite3_backup_step() it is +** possible that they return invalid values. +*/ +SQLITE_API sqlite3_backup *sqlite3_backup_init( + sqlite3 *pDest, /* Destination database handle */ + const char *zDestName, /* Destination database name */ + sqlite3 *pSource, /* Source database handle */ + const char *zSourceName /* Source database name */ +); +SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); +SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); + +/* +** CAPI3REF: Unlock Notification +** EXPERIMENTAL +** +** When running in shared-cache mode, a database operation may fail with +** an [SQLITE_LOCKED] error if the required locks on the shared-cache or +** individual tables within the shared-cache cannot be obtained. See +** [SQLite Shared-Cache Mode] for a description of shared-cache locking. +** This API may be used to register a callback that SQLite will invoke +** when the connection currently holding the required lock relinquishes it. +** This API is only available if the library was compiled with the +** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined. +** +** See Also: [Using the SQLite Unlock Notification Feature]. +** +** Shared-cache locks are released when a database connection concludes +** its current transaction, either by committing it or rolling it back. +** +** When a connection (known as the blocked connection) fails to obtain a +** shared-cache lock and SQLITE_LOCKED is returned to the caller, the +** identity of the database connection (the blocking connection) that +** has locked the required resource is stored internally. After an +** application receives an SQLITE_LOCKED error, it may call the +** sqlite3_unlock_notify() method with the blocked connection handle as +** the first argument to register for a callback that will be invoked +** when the blocking connections current transaction is concluded. The +** callback is invoked from within the [sqlite3_step] or [sqlite3_close] +** call that concludes the blocking connections transaction. +** +** If sqlite3_unlock_notify() is called in a multi-threaded application, +** there is a chance that the blocking connection will have already +** concluded its transaction by the time sqlite3_unlock_notify() is invoked. +** If this happens, then the specified callback is invoked immediately, +** from within the call to sqlite3_unlock_notify(). +** +** If the blocked connection is attempting to obtain a write-lock on a +** shared-cache table, and more than one other connection currently holds +** a read-lock on the same table, then SQLite arbitrarily selects one of +** the other connections to use as the blocking connection. +** +** There may be at most one unlock-notify callback registered by a +** blocked connection. If sqlite3_unlock_notify() is called when the +** blocked connection already has a registered unlock-notify callback, +** then the new callback replaces the old. If sqlite3_unlock_notify() is +** called with a NULL pointer as its second argument, then any existing +** unlock-notify callback is cancelled. The blocked connections +** unlock-notify callback may also be canceled by closing the blocked +** connection using [sqlite3_close()]. +** +** The unlock-notify callback is not reentrant. If an application invokes +** any sqlite3_xxx API functions from within an unlock-notify callback, a +** crash or deadlock may be the result. +** +** Unless deadlock is detected (see below), sqlite3_unlock_notify() always +** returns SQLITE_OK. +** +** Callback Invocation Details +** +** When an unlock-notify callback is registered, the application provides a +** single void* pointer that is passed to the callback when it is invoked. +** However, the signature of the callback function allows SQLite to pass +** it an array of void* context pointers. The first argument passed to +** an unlock-notify callback is a pointer to an array of void* pointers, +** and the second is the number of entries in the array. +** +** When a blocking connections transaction is concluded, there may be +** more than one blocked connection that has registered for an unlock-notify +** callback. If two or more such blocked connections have specified the +** same callback function, then instead of invoking the callback function +** multiple times, it is invoked once with the set of void* context pointers +** specified by the blocked connections bundled together into an array. +** This gives the application an opportunity to prioritize any actions +** related to the set of unblocked database connections. +** +** Deadlock Detection +** +** Assuming that after registering for an unlock-notify callback a +** database waits for the callback to be issued before taking any further +** action (a reasonable assumption), then using this API may cause the +** application to deadlock. For example, if connection X is waiting for +** connection Y's transaction to be concluded, and similarly connection +** Y is waiting on connection X's transaction, then neither connection +** will proceed and the system may remain deadlocked indefinitely. +** +** To avoid this scenario, the sqlite3_unlock_notify() performs deadlock +** detection. If a given call to sqlite3_unlock_notify() would put the +** system in a deadlocked state, then SQLITE_LOCKED is returned and no +** unlock-notify callback is registered. The system is said to be in +** a deadlocked state if connection A has registered for an unlock-notify +** callback on the conclusion of connection B's transaction, and connection +** B has itself registered for an unlock-notify callback when connection +** A's transaction is concluded. Indirect deadlock is also detected, so +** the system is also considered to be deadlocked if connection B has +** registered for an unlock-notify callback on the conclusion of connection +** C's transaction, where connection C is waiting on connection A. Any +** number of levels of indirection are allowed. +** +** The "DROP TABLE" Exception +** +** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost +** always appropriate to call sqlite3_unlock_notify(). There is however, +** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement, +** SQLite checks if there are any currently executing SELECT statements +** that belong to the same connection. If there are, SQLITE_LOCKED is +** returned. In this case there is no "blocking connection", so invoking +** sqlite3_unlock_notify() results in the unlock-notify callback being +** invoked immediately. If the application then re-attempts the "DROP TABLE" +** or "DROP INDEX" query, an infinite loop might be the result. +** +** One way around this problem is to check the extended error code returned +** by an sqlite3_step() call. If there is a blocking connection, then the +** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in +** the special "DROP TABLE/INDEX" case, the extended error code is just +** SQLITE_LOCKED. +*/ +SQLITE_API int sqlite3_unlock_notify( + sqlite3 *pBlocked, /* Waiting connection */ + void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ + void *pNotifyArg /* Argument to pass to xNotify */ +); + +/* +** Undo the hack that converts floating point types to integer for +** builds on processors without floating point support. +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# undef double +#endif + +#if 0 +} /* End of the 'extern "C"' block */ +#endif +#endif + +/************** End of sqlite3.h *********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include hash.h in the middle of sqliteInt.h ******************/ +/************** Begin file hash.h ********************************************/ +/* +** 2001 September 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This is the header file for the generic hash-table implemenation +** used in SQLite. +** +** $Id: hash.h,v 1.12 2008/10/10 17:41:29 drh Exp $ +*/ +#ifndef _SQLITE_HASH_H_ +#define _SQLITE_HASH_H_ + +/* Forward declarations of structures. */ +typedef struct Hash Hash; +typedef struct HashElem HashElem; + +/* A complete hash table is an instance of the following structure. +** The internals of this structure are intended to be opaque -- client +** code should not attempt to access or modify the fields of this structure +** directly. Change this structure only by using the routines below. +** However, many of the "procedures" and "functions" for modifying and +** accessing this structure are really macros, so we can't really make +** this structure opaque. +*/ +struct Hash { + unsigned int copyKey: 1; /* True if copy of key made on insert */ + unsigned int htsize : 31; /* Number of buckets in the hash table */ + unsigned int count; /* Number of entries in this table */ + HashElem *first; /* The first element of the array */ + struct _ht { /* the hash table */ + int count; /* Number of entries with this hash */ + HashElem *chain; /* Pointer to first entry with this hash */ + } *ht; +}; + +/* Each element in the hash table is an instance of the following +** structure. All elements are stored on a single doubly-linked list. +** +** Again, this structure is intended to be opaque, but it can't really +** be opaque because it is used by macros. +*/ +struct HashElem { + HashElem *next, *prev; /* Next and previous elements in the table */ + void *data; /* Data associated with this element */ + void *pKey; int nKey; /* Key associated with this element */ +}; + +/* +** Access routines. To delete, insert a NULL pointer. +*/ +SQLITE_PRIVATE void sqlite3HashInit(Hash*, int copyKey); +SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const void *pKey, int nKey, void *pData); +SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const void *pKey, int nKey); +SQLITE_PRIVATE HashElem *sqlite3HashFindElem(const Hash*, const void *pKey, int nKey); +SQLITE_PRIVATE void sqlite3HashClear(Hash*); + +/* +** Macros for looping over all elements of a hash table. The idiom is +** like this: +** +** Hash h; +** HashElem *p; +** ... +** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){ +** SomeStructure *pData = sqliteHashData(p); +** // do something with pData +** } +*/ +#define sqliteHashFirst(H) ((H)->first) +#define sqliteHashNext(E) ((E)->next) +#define sqliteHashData(E) ((E)->data) +#define sqliteHashKey(E) ((E)->pKey) +#define sqliteHashKeysize(E) ((E)->nKey) + +/* +** Number of entries in a hash table +*/ +#define sqliteHashCount(H) ((H)->count) + +#endif /* _SQLITE_HASH_H_ */ + +/************** End of hash.h ************************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include parse.h in the middle of sqliteInt.h *****************/ +/************** Begin file parse.h *******************************************/ +#define TK_SEMI 1 +#define TK_EXPLAIN 2 +#define TK_QUERY 3 +#define TK_PLAN 4 +#define TK_BEGIN 5 +#define TK_TRANSACTION 6 +#define TK_DEFERRED 7 +#define TK_IMMEDIATE 8 +#define TK_EXCLUSIVE 9 +#define TK_COMMIT 10 +#define TK_END 11 +#define TK_ROLLBACK 12 +#define TK_SAVEPOINT 13 +#define TK_RELEASE 14 +#define TK_TO 15 +#define TK_TABLE 16 +#define TK_CREATE 17 +#define TK_IF 18 +#define TK_NOT 19 +#define TK_EXISTS 20 +#define TK_TEMP 21 +#define TK_LP 22 +#define TK_RP 23 +#define TK_AS 24 +#define TK_COMMA 25 +#define TK_ID 26 +#define TK_INDEXED 27 +#define TK_ABORT 28 +#define TK_AFTER 29 +#define TK_ANALYZE 30 +#define TK_ASC 31 +#define TK_ATTACH 32 +#define TK_BEFORE 33 +#define TK_BY 34 +#define TK_CASCADE 35 +#define TK_CAST 36 +#define TK_COLUMNKW 37 +#define TK_CONFLICT 38 +#define TK_DATABASE 39 +#define TK_DESC 40 +#define TK_DETACH 41 +#define TK_EACH 42 +#define TK_FAIL 43 +#define TK_FOR 44 +#define TK_IGNORE 45 +#define TK_INITIALLY 46 +#define TK_INSTEAD 47 +#define TK_LIKE_KW 48 +#define TK_MATCH 49 +#define TK_KEY 50 +#define TK_OF 51 +#define TK_OFFSET 52 +#define TK_PRAGMA 53 +#define TK_RAISE 54 +#define TK_REPLACE 55 +#define TK_RESTRICT 56 +#define TK_ROW 57 +#define TK_TRIGGER 58 +#define TK_VACUUM 59 +#define TK_VIEW 60 +#define TK_VIRTUAL 61 +#define TK_REINDEX 62 +#define TK_RENAME 63 +#define TK_CTIME_KW 64 +#define TK_ANY 65 +#define TK_OR 66 +#define TK_AND 67 +#define TK_IS 68 +#define TK_BETWEEN 69 +#define TK_IN 70 +#define TK_ISNULL 71 +#define TK_NOTNULL 72 +#define TK_NE 73 +#define TK_EQ 74 +#define TK_GT 75 +#define TK_LE 76 +#define TK_LT 77 +#define TK_GE 78 +#define TK_ESCAPE 79 +#define TK_BITAND 80 +#define TK_BITOR 81 +#define TK_LSHIFT 82 +#define TK_RSHIFT 83 +#define TK_PLUS 84 +#define TK_MINUS 85 +#define TK_STAR 86 +#define TK_SLASH 87 +#define TK_REM 88 +#define TK_CONCAT 89 +#define TK_COLLATE 90 +#define TK_UMINUS 91 +#define TK_UPLUS 92 +#define TK_BITNOT 93 +#define TK_STRING 94 +#define TK_JOIN_KW 95 +#define TK_CONSTRAINT 96 +#define TK_DEFAULT 97 +#define TK_NULL 98 +#define TK_PRIMARY 99 +#define TK_UNIQUE 100 +#define TK_CHECK 101 +#define TK_REFERENCES 102 +#define TK_AUTOINCR 103 +#define TK_ON 104 +#define TK_DELETE 105 +#define TK_UPDATE 106 +#define TK_INSERT 107 +#define TK_SET 108 +#define TK_DEFERRABLE 109 +#define TK_FOREIGN 110 +#define TK_DROP 111 +#define TK_UNION 112 +#define TK_ALL 113 +#define TK_EXCEPT 114 +#define TK_INTERSECT 115 +#define TK_SELECT 116 +#define TK_DISTINCT 117 +#define TK_DOT 118 +#define TK_FROM 119 +#define TK_JOIN 120 +#define TK_USING 121 +#define TK_ORDER 122 +#define TK_GROUP 123 +#define TK_HAVING 124 +#define TK_LIMIT 125 +#define TK_WHERE 126 +#define TK_INTO 127 +#define TK_VALUES 128 +#define TK_INTEGER 129 +#define TK_FLOAT 130 +#define TK_BLOB 131 +#define TK_REGISTER 132 +#define TK_VARIABLE 133 +#define TK_CASE 134 +#define TK_WHEN 135 +#define TK_THEN 136 +#define TK_ELSE 137 +#define TK_INDEX 138 +#define TK_ALTER 139 +#define TK_ADD 140 +#define TK_TO_TEXT 141 +#define TK_TO_BLOB 142 +#define TK_TO_NUMERIC 143 +#define TK_TO_INT 144 +#define TK_TO_REAL 145 +#define TK_END_OF_FILE 146 +#define TK_ILLEGAL 147 +#define TK_SPACE 148 +#define TK_UNCLOSED_STRING 149 +#define TK_FUNCTION 150 +#define TK_COLUMN 151 +#define TK_AGG_FUNCTION 152 +#define TK_AGG_COLUMN 153 +#define TK_CONST_FUNC 154 + +/************** End of parse.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +#include +#include +#include +#include +#include + +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite_int64 +# define LONGDOUBLE_TYPE sqlite_int64 +# ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (0x7fffffffffffffff) +# endif +# define SQLITE_OMIT_DATETIME_FUNCS 1 +# define SQLITE_OMIT_TRACE 1 +# undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT +#endif +#ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (1e99) +#endif + +/* +** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0 +** afterward. Having this macro allows us to cause the C compiler +** to omit code used by TEMP tables without messy #ifndef statements. +*/ +#ifdef SQLITE_OMIT_TEMPDB +#define OMIT_TEMPDB 1 +#else +#define OMIT_TEMPDB 0 +#endif + +/* +** If the following macro is set to 1, then NULL values are considered +** distinct when determining whether or not two entries are the same +** in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL, +** OCELOT, and Firebird all work. The SQL92 spec explicitly says this +** is the way things are suppose to work. +** +** If the following macro is set to 0, the NULLs are indistinct for +** a UNIQUE index. In this mode, you can only have a single NULL entry +** for a column declared UNIQUE. This is the way Informix and SQL Server +** work. +*/ +#define NULL_DISTINCT_FOR_UNIQUE 1 + +/* +** The "file format" number is an integer that is incremented whenever +** the VDBE-level file format changes. The following macros define the +** the default file format for new databases and the maximum file format +** that the library can read. +*/ +#define SQLITE_MAX_FILE_FORMAT 4 +#ifndef SQLITE_DEFAULT_FILE_FORMAT +# define SQLITE_DEFAULT_FILE_FORMAT 1 +#endif + +/* +** Provide a default value for SQLITE_TEMP_STORE in case it is not specified +** on the command-line +*/ +#ifndef SQLITE_TEMP_STORE +# define SQLITE_TEMP_STORE 1 +#endif + +/* +** GCC does not define the offsetof() macro so we'll have to do it +** ourselves. +*/ +#ifndef offsetof +#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) +#endif + +/* +** Check to see if this machine uses EBCDIC. (Yes, believe it or +** not, there are still machines out there that use EBCDIC.) +*/ +#if 'A' == '\301' +# define SQLITE_EBCDIC 1 +#else +# define SQLITE_ASCII 1 +#endif + +/* +** Integers of known sizes. These typedefs might change for architectures +** where the sizes very. Preprocessor macros are available so that the +** types can be conveniently redefined at compile-type. Like this: +** +** cc '-DUINTPTR_TYPE=long long int' ... +*/ +#ifndef UINT32_TYPE +# ifdef HAVE_UINT32_T +# define UINT32_TYPE uint32_t +# else +# define UINT32_TYPE unsigned int +# endif +#endif +#ifndef UINT16_TYPE +# ifdef HAVE_UINT16_T +# define UINT16_TYPE uint16_t +# else +# define UINT16_TYPE unsigned short int +# endif +#endif +#ifndef INT16_TYPE +# ifdef HAVE_INT16_T +# define INT16_TYPE int16_t +# else +# define INT16_TYPE short int +# endif +#endif +#ifndef UINT8_TYPE +# ifdef HAVE_UINT8_T +# define UINT8_TYPE uint8_t +# else +# define UINT8_TYPE unsigned char +# endif +#endif +#ifndef INT8_TYPE +# ifdef HAVE_INT8_T +# define INT8_TYPE int8_t +# else +# define INT8_TYPE signed char +# endif +#endif +#ifndef LONGDOUBLE_TYPE +# define LONGDOUBLE_TYPE long double +#endif +typedef sqlite_int64 i64; /* 8-byte signed integer */ +typedef sqlite_uint64 u64; /* 8-byte unsigned integer */ +typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ +typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ +typedef INT16_TYPE i16; /* 2-byte signed integer */ +typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ +typedef INT8_TYPE i8; /* 1-byte signed integer */ + +/* +** Macros to determine whether the machine is big or little endian, +** evaluated at runtime. +*/ +#ifdef SQLITE_AMALGAMATION +SQLITE_PRIVATE const int sqlite3one = 1; +#else +SQLITE_PRIVATE const int sqlite3one; +#endif +#if defined(i386) || defined(__i386__) || defined(_M_IX86)\ + || defined(__x86_64) || defined(__x86_64__) +# define SQLITE_BIGENDIAN 0 +# define SQLITE_LITTLEENDIAN 1 +# define SQLITE_UTF16NATIVE SQLITE_UTF16LE +#else +# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) +# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) +# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) +#endif + +/* +** Constants for the largest and smallest possible 64-bit signed integers. +** These macros are designed to work correctly on both 32-bit and 64-bit +** compilers. +*/ +#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) +#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) + +/* +** Round up a number to the next larger multiple of 8. This is used +** to force 8-byte alignment on 64-bit architectures. +*/ +#define ROUND8(x) (((x)+7)&~7) + +/* +** Round down to the nearest multiple of 8 +*/ +#define ROUNDDOWN8(x) ((x)&~7) + +/* +** An instance of the following structure is used to store the busy-handler +** callback for a given sqlite handle. +** +** The sqlite.busyHandler member of the sqlite struct contains the busy +** callback for the database handle. Each pager opened via the sqlite +** handle is passed a pointer to sqlite.busyHandler. The busy-handler +** callback is currently invoked only from within pager.c. +*/ +typedef struct BusyHandler BusyHandler; +struct BusyHandler { + int (*xFunc)(void *,int); /* The busy callback */ + void *pArg; /* First arg to busy callback */ + int nBusy; /* Incremented with each busy call */ +}; + +/* +** Name of the master database table. The master database table +** is a special table that holds the names and attributes of all +** user tables and indices. +*/ +#define MASTER_NAME "sqlite_master" +#define TEMP_MASTER_NAME "sqlite_temp_master" + +/* +** The root-page of the master database table. +*/ +#define MASTER_ROOT 1 + +/* +** The name of the schema table. +*/ +#define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME) + +/* +** A convenience macro that returns the number of elements in +** an array. +*/ +#define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) + +/* +** The following value as a destructor means to use sqlite3DbFree(). +** This is an internal extension to SQLITE_STATIC and SQLITE_TRANSIENT. +*/ +#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3DbFree) + +/* +** When SQLITE_OMIT_WSD is defined, it means that the target platform does +** not support Writable Static Data (WSD) such as global and static variables. +** All variables must either be on the stack or dynamically allocated from +** the heap. When WSD is unsupported, the variable declarations scattered +** throughout the SQLite code must become constants instead. The SQLITE_WSD +** macro is used for this purpose. And instead of referencing the variable +** directly, we use its constant as a key to lookup the run-time allocated +** buffer that holds real variable. The constant is also the initializer +** for the run-time allocated buffer. +** +** In the usual case where WSD is supported, the SQLITE_WSD and GLOBAL +** macros become no-ops and have zero performance impact. +*/ +#ifdef SQLITE_OMIT_WSD + #define SQLITE_WSD const + #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v))) + #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config) +SQLITE_API int sqlite3_wsd_init(int N, int J); +SQLITE_API void *sqlite3_wsd_find(void *K, int L); +#else + #define SQLITE_WSD + #define GLOBAL(t,v) v + #define sqlite3GlobalConfig sqlite3Config +#endif + +/* +** The following macros are used to suppress compiler warnings and to +** make it clear to human readers when a function parameter is deliberately +** left unused within the body of a function. This usually happens when +** a function is called via a function pointer. For example the +** implementation of an SQL aggregate step callback may not use the +** parameter indicating the number of arguments passed to the aggregate, +** if it knows that this is enforced elsewhere. +** +** When a function parameter is not used at all within the body of a function, +** it is generally named "NotUsed" or "NotUsed2" to make things even clearer. +** However, these macros may also be used to suppress warnings related to +** parameters that may or may not be used depending on compilation options. +** For example those parameters only used in assert() statements. In these +** cases the parameters are named as per the usual conventions. +*/ +#define UNUSED_PARAMETER(x) (void)(x) +#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y) + +/* +** Forward references to structures +*/ +typedef struct AggInfo AggInfo; +typedef struct AuthContext AuthContext; +typedef struct Bitvec Bitvec; +typedef struct RowSet RowSet; +typedef struct CollSeq CollSeq; +typedef struct Column Column; +typedef struct Db Db; +typedef struct Schema Schema; +typedef struct Expr Expr; +typedef struct ExprList ExprList; +typedef struct FKey FKey; +typedef struct FuncDef FuncDef; +typedef struct FuncDefHash FuncDefHash; +typedef struct IdList IdList; +typedef struct Index Index; +typedef struct KeyClass KeyClass; +typedef struct KeyInfo KeyInfo; +typedef struct Lookaside Lookaside; +typedef struct LookasideSlot LookasideSlot; +typedef struct Module Module; +typedef struct NameContext NameContext; +typedef struct Parse Parse; +typedef struct Savepoint Savepoint; +typedef struct Select Select; +typedef struct SrcList SrcList; +typedef struct StrAccum StrAccum; +typedef struct Table Table; +typedef struct TableLock TableLock; +typedef struct Token Token; +typedef struct TriggerStack TriggerStack; +typedef struct TriggerStep TriggerStep; +typedef struct Trigger Trigger; +typedef struct UnpackedRecord UnpackedRecord; +typedef struct Walker Walker; +typedef struct WherePlan WherePlan; +typedef struct WhereInfo WhereInfo; +typedef struct WhereLevel WhereLevel; + +/* +** Defer sourcing vdbe.h and btree.h until after the "u8" and +** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque +** pointer types (i.e. FuncDef) defined above. +*/ +/************** Include btree.h in the middle of sqliteInt.h *****************/ +/************** Begin file btree.h *******************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the sqlite B-Tree file +** subsystem. See comments in the source code for a detailed description +** of what each interface routine does. +** +** @(#) $Id: btree.h,v 1.111 2009/03/18 10:33:01 danielk1977 Exp $ +*/ +#ifndef _BTREE_H_ +#define _BTREE_H_ + +/* TODO: This definition is just included so other modules compile. It +** needs to be revisited. +*/ +#define SQLITE_N_BTREE_META 10 + +/* +** If defined as non-zero, auto-vacuum is enabled by default. Otherwise +** it must be turned on for each database using "PRAGMA auto_vacuum = 1". +*/ +#ifndef SQLITE_DEFAULT_AUTOVACUUM + #define SQLITE_DEFAULT_AUTOVACUUM 0 +#endif + +#define BTREE_AUTOVACUUM_NONE 0 /* Do not do auto-vacuum */ +#define BTREE_AUTOVACUUM_FULL 1 /* Do full auto-vacuum */ +#define BTREE_AUTOVACUUM_INCR 2 /* Incremental vacuum */ + +/* +** Forward declarations of structure +*/ +typedef struct Btree Btree; +typedef struct BtCursor BtCursor; +typedef struct BtShared BtShared; +typedef struct BtreeMutexArray BtreeMutexArray; + +/* +** This structure records all of the Btrees that need to hold +** a mutex before we enter sqlite3VdbeExec(). The Btrees are +** are placed in aBtree[] in order of aBtree[]->pBt. That way, +** we can always lock and unlock them all quickly. +*/ +struct BtreeMutexArray { + int nMutex; + Btree *aBtree[SQLITE_MAX_ATTACHED+1]; +}; + + +SQLITE_PRIVATE int sqlite3BtreeOpen( + const char *zFilename, /* Name of database file to open */ + sqlite3 *db, /* Associated database connection */ + Btree **, /* Return open Btree* here */ + int flags, /* Flags */ + int vfsFlags /* Flags passed through to VFS open */ +); + +/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the +** following values. +** +** NOTE: These values must match the corresponding PAGER_ values in +** pager.h. +*/ +#define BTREE_OMIT_JOURNAL 1 /* Do not use journal. No argument */ +#define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */ +#define BTREE_MEMORY 4 /* In-memory DB. No argument */ +#define BTREE_READONLY 8 /* Open the database in read-only mode */ +#define BTREE_READWRITE 16 /* Open for both reading and writing */ +#define BTREE_CREATE 32 /* Create the database if it does not exist */ + +SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); +SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int); +SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); +SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree*,int,int); +SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); +SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*); +SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); +SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); +SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); +SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*); +SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); +SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*); +SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags); +SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*); +SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*); +SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*); +SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); +SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *); +SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *, int, u8); +SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int); + +SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *); +SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *); +SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *); + +SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *); + +/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR +** of the following flags: +*/ +#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ +#define BTREE_ZERODATA 2 /* Table has keys only - no data */ +#define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */ + +SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); +SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*); +SQLITE_PRIVATE int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue); +SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); +SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int); + +SQLITE_PRIVATE int sqlite3BtreeCursor( + Btree*, /* BTree containing table to open */ + int iTable, /* Index of root page */ + int wrFlag, /* 1 for writing. 0 for read-only */ + struct KeyInfo*, /* First argument to compare function */ + BtCursor *pCursor /* Space to write cursor structure */ +); +SQLITE_PRIVATE int sqlite3BtreeCursorSize(void); + +SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreeMoveto( + BtCursor*, + const void *pKey, + i64 nKey, + int bias, + int *pRes +); +SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( + BtCursor*, + UnpackedRecord *pUnKey, + i64 intKey, + int bias, + int *pRes +); +SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*, int*); +SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, + const void *pData, int nData, + int nZero, int bias); +SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreeFlags(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor*, i64 *pSize); +SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); +SQLITE_PRIVATE sqlite3 *sqlite3BtreeCursorDb(const BtCursor*); +SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt); +SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt); +SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); +SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); +SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor*, sqlite3_int64); +SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor*); + +SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); +SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*); + +SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); +SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *); +SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *); + +#ifndef SQLITE_OMIT_BTREECOUNT +SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *); +#endif + +#ifdef SQLITE_TEST +SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int); +SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*); +#endif + +/* +** If we are not using shared cache, then there is no need to +** use mutexes to access the BtShared structures. So make the +** Enter and Leave procedures no-ops. +*/ +#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE +SQLITE_PRIVATE void sqlite3BtreeEnter(Btree*); +SQLITE_PRIVATE void sqlite3BtreeLeave(Btree*); +#ifndef NDEBUG + /* This routine is used inside assert() statements only. */ +SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree*); +#endif +SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*); +SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor*); +SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*); +SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3*); +#ifndef NDEBUG + /* This routine is used inside assert() statements only. */ +SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3*); +#endif +SQLITE_PRIVATE void sqlite3BtreeMutexArrayEnter(BtreeMutexArray*); +SQLITE_PRIVATE void sqlite3BtreeMutexArrayLeave(BtreeMutexArray*); +SQLITE_PRIVATE void sqlite3BtreeMutexArrayInsert(BtreeMutexArray*, Btree*); +#else +# define sqlite3BtreeEnter(X) +# define sqlite3BtreeLeave(X) +#ifndef NDEBUG + /* This routine is used inside assert() statements only. */ +# define sqlite3BtreeHoldsMutex(X) 1 +#endif +# define sqlite3BtreeEnterCursor(X) +# define sqlite3BtreeLeaveCursor(X) +# define sqlite3BtreeEnterAll(X) +# define sqlite3BtreeLeaveAll(X) +#ifndef NDEBUG + /* This routine is used inside assert() statements only. */ +# define sqlite3BtreeHoldsAllMutexes(X) 1 +#endif +# define sqlite3BtreeMutexArrayEnter(X) +# define sqlite3BtreeMutexArrayLeave(X) +# define sqlite3BtreeMutexArrayInsert(X,Y) +#endif + + +#endif /* _BTREE_H_ */ + +/************** End of btree.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include vdbe.h in the middle of sqliteInt.h ******************/ +/************** Begin file vdbe.h ********************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Header file for the Virtual DataBase Engine (VDBE) +** +** This header defines the interface to the virtual database engine +** or VDBE. The VDBE implements an abstract machine that runs a +** simple program to access and modify the underlying database. +** +** $Id: vdbe.h,v 1.140 2009/02/19 14:39:25 danielk1977 Exp $ +*/ +#ifndef _SQLITE_VDBE_H_ +#define _SQLITE_VDBE_H_ + +/* +** A single VDBE is an opaque structure named "Vdbe". Only routines +** in the source file sqliteVdbe.c are allowed to see the insides +** of this structure. +*/ +typedef struct Vdbe Vdbe; + +/* +** The names of the following types declared in vdbeInt.h are required +** for the VdbeOp definition. +*/ +typedef struct VdbeFunc VdbeFunc; +typedef struct Mem Mem; + +/* +** A single instruction of the virtual machine has an opcode +** and as many as three operands. The instruction is recorded +** as an instance of the following structure: +*/ +struct VdbeOp { + u8 opcode; /* What operation to perform */ + signed char p4type; /* One of the P4_xxx constants for p4 */ + u8 opflags; /* Not currently used */ + u8 p5; /* Fifth parameter is an unsigned character */ + int p1; /* First operand */ + int p2; /* Second parameter (often the jump destination) */ + int p3; /* The third parameter */ + union { /* forth parameter */ + int i; /* Integer value if p4type==P4_INT32 */ + void *p; /* Generic pointer */ + char *z; /* Pointer to data for string (char array) types */ + i64 *pI64; /* Used when p4type is P4_INT64 */ + double *pReal; /* Used when p4type is P4_REAL */ + FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */ + VdbeFunc *pVdbeFunc; /* Used when p4type is P4_VDBEFUNC */ + CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ + Mem *pMem; /* Used when p4type is P4_MEM */ + sqlite3_vtab *pVtab; /* Used when p4type is P4_VTAB */ + KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ + int *ai; /* Used when p4type is P4_INTARRAY */ + } p4; +#ifdef SQLITE_DEBUG + char *zComment; /* Comment to improve readability */ +#endif +#ifdef VDBE_PROFILE + int cnt; /* Number of times this instruction was executed */ + u64 cycles; /* Total time spent executing this instruction */ +#endif +}; +typedef struct VdbeOp VdbeOp; + +/* +** A smaller version of VdbeOp used for the VdbeAddOpList() function because +** it takes up less space. +*/ +struct VdbeOpList { + u8 opcode; /* What operation to perform */ + signed char p1; /* First operand */ + signed char p2; /* Second parameter (often the jump destination) */ + signed char p3; /* Third parameter */ +}; +typedef struct VdbeOpList VdbeOpList; + +/* +** Allowed values of VdbeOp.p3type +*/ +#define P4_NOTUSED 0 /* The P4 parameter is not used */ +#define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ +#define P4_STATIC (-2) /* Pointer to a static string */ +#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ +#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */ +#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */ +#define P4_VDBEFUNC (-7) /* P4 is a pointer to a VdbeFunc structure */ +#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */ +#define P4_TRANSIENT (-9) /* P4 is a pointer to a transient string */ +#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */ +#define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */ +#define P4_REAL (-12) /* P4 is a 64-bit floating point value */ +#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ +#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ +#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ + +/* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure +** is made. That copy is freed when the Vdbe is finalized. But if the +** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used. It still +** gets freed when the Vdbe is finalized so it still should be obtained +** from a single sqliteMalloc(). But no copy is made and the calling +** function should *not* try to free the KeyInfo. +*/ +#define P4_KEYINFO_HANDOFF (-16) +#define P4_KEYINFO_STATIC (-17) + +/* +** The Vdbe.aColName array contains 5n Mem structures, where n is the +** number of columns of data returned by the statement. +*/ +#define COLNAME_NAME 0 +#define COLNAME_DECLTYPE 1 +#define COLNAME_DATABASE 2 +#define COLNAME_TABLE 3 +#define COLNAME_COLUMN 4 +#ifdef SQLITE_ENABLE_COLUMN_METADATA +# define COLNAME_N 5 /* Number of COLNAME_xxx symbols */ +#else +# ifdef SQLITE_OMIT_DECLTYPE +# define COLNAME_N 1 /* Store only the name */ +# else +# define COLNAME_N 2 /* Store the name and decltype */ +# endif +#endif + +/* +** The following macro converts a relative address in the p2 field +** of a VdbeOp structure into a negative number so that +** sqlite3VdbeAddOpList() knows that the address is relative. Calling +** the macro again restores the address. +*/ +#define ADDR(X) (-1-(X)) + +/* +** The makefile scans the vdbe.c source file and creates the "opcodes.h" +** header file that defines a number for each opcode used by the VDBE. +*/ +/************** Include opcodes.h in the middle of vdbe.h ********************/ +/************** Begin file opcodes.h *****************************************/ +/* Automatically generated. Do not edit */ +/* See the mkopcodeh.awk script for details */ +#define OP_VNext 1 +#define OP_Affinity 2 +#define OP_Column 3 +#define OP_SetCookie 4 +#define OP_Seek 5 +#define OP_Real 130 /* same as TK_FLOAT */ +#define OP_Sequence 6 +#define OP_Savepoint 7 +#define OP_Ge 78 /* same as TK_GE */ +#define OP_RowKey 8 +#define OP_SCopy 9 +#define OP_Eq 74 /* same as TK_EQ */ +#define OP_OpenWrite 10 +#define OP_NotNull 72 /* same as TK_NOTNULL */ +#define OP_If 11 +#define OP_ToInt 144 /* same as TK_TO_INT */ +#define OP_String8 94 /* same as TK_STRING */ +#define OP_VRowid 12 +#define OP_CollSeq 13 +#define OP_OpenRead 14 +#define OP_Expire 15 +#define OP_AutoCommit 16 +#define OP_Gt 75 /* same as TK_GT */ +#define OP_Pagecount 17 +#define OP_IntegrityCk 18 +#define OP_Sort 20 +#define OP_Copy 21 +#define OP_Trace 22 +#define OP_Function 23 +#define OP_IfNeg 24 +#define OP_And 67 /* same as TK_AND */ +#define OP_Subtract 85 /* same as TK_MINUS */ +#define OP_Noop 25 +#define OP_Return 26 +#define OP_Remainder 88 /* same as TK_REM */ +#define OP_NewRowid 27 +#define OP_Multiply 86 /* same as TK_STAR */ +#define OP_Variable 28 +#define OP_String 29 +#define OP_RealAffinity 30 +#define OP_VRename 31 +#define OP_ParseSchema 32 +#define OP_VOpen 33 +#define OP_Close 34 +#define OP_CreateIndex 35 +#define OP_IsUnique 36 +#define OP_NotFound 37 +#define OP_Int64 38 +#define OP_MustBeInt 39 +#define OP_Halt 40 +#define OP_Rowid 41 +#define OP_IdxLT 42 +#define OP_AddImm 43 +#define OP_Statement 44 +#define OP_RowData 45 +#define OP_MemMax 46 +#define OP_Or 66 /* same as TK_OR */ +#define OP_NotExists 47 +#define OP_Gosub 48 +#define OP_Divide 87 /* same as TK_SLASH */ +#define OP_Integer 49 +#define OP_ToNumeric 143 /* same as TK_TO_NUMERIC*/ +#define OP_Prev 50 +#define OP_RowSetRead 51 +#define OP_Concat 89 /* same as TK_CONCAT */ +#define OP_RowSetAdd 52 +#define OP_BitAnd 80 /* same as TK_BITAND */ +#define OP_VColumn 53 +#define OP_CreateTable 54 +#define OP_Last 55 +#define OP_SeekLe 56 +#define OP_IsNull 71 /* same as TK_ISNULL */ +#define OP_IncrVacuum 57 +#define OP_IdxRowid 58 +#define OP_ShiftRight 83 /* same as TK_RSHIFT */ +#define OP_ResetCount 59 +#define OP_ContextPush 60 +#define OP_Yield 61 +#define OP_DropTrigger 62 +#define OP_DropIndex 63 +#define OP_IdxGE 64 +#define OP_IdxDelete 65 +#define OP_Vacuum 68 +#define OP_IfNot 69 +#define OP_DropTable 70 +#define OP_SeekLt 79 +#define OP_MakeRecord 90 +#define OP_ToBlob 142 /* same as TK_TO_BLOB */ +#define OP_ResultRow 91 +#define OP_Delete 92 +#define OP_AggFinal 95 +#define OP_Compare 96 +#define OP_ShiftLeft 82 /* same as TK_LSHIFT */ +#define OP_Goto 97 +#define OP_TableLock 98 +#define OP_Clear 99 +#define OP_Le 76 /* same as TK_LE */ +#define OP_VerifyCookie 100 +#define OP_AggStep 101 +#define OP_ToText 141 /* same as TK_TO_TEXT */ +#define OP_Not 19 /* same as TK_NOT */ +#define OP_ToReal 145 /* same as TK_TO_REAL */ +#define OP_SetNumColumns 102 +#define OP_Transaction 103 +#define OP_VFilter 104 +#define OP_Ne 73 /* same as TK_NE */ +#define OP_VDestroy 105 +#define OP_ContextPop 106 +#define OP_BitOr 81 /* same as TK_BITOR */ +#define OP_Next 107 +#define OP_Count 108 +#define OP_IdxInsert 109 +#define OP_Lt 77 /* same as TK_LT */ +#define OP_SeekGe 110 +#define OP_Insert 111 +#define OP_Destroy 112 +#define OP_ReadCookie 113 +#define OP_LoadAnalysis 114 +#define OP_Explain 115 +#define OP_HaltIfNull 116 +#define OP_OpenPseudo 117 +#define OP_OpenEphemeral 118 +#define OP_Null 119 +#define OP_Move 120 +#define OP_Blob 121 +#define OP_Add 84 /* same as TK_PLUS */ +#define OP_Rewind 122 +#define OP_SeekGt 123 +#define OP_VBegin 124 +#define OP_VUpdate 125 +#define OP_IfZero 126 +#define OP_BitNot 93 /* same as TK_BITNOT */ +#define OP_VCreate 127 +#define OP_Found 128 +#define OP_IfPos 129 +#define OP_NullRow 131 +#define OP_Jump 132 +#define OP_Permutation 133 + +/* The following opcode values are never used */ +#define OP_NotUsed_134 134 +#define OP_NotUsed_135 135 +#define OP_NotUsed_136 136 +#define OP_NotUsed_137 137 +#define OP_NotUsed_138 138 +#define OP_NotUsed_139 139 +#define OP_NotUsed_140 140 + + +/* Properties such as "out2" or "jump" that are specified in +** comments following the "case" for each opcode in the vdbe.c +** are encoded into bitvectors as follows: +*/ +#define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */ +#define OPFLG_OUT2_PRERELEASE 0x0002 /* out2-prerelease: */ +#define OPFLG_IN1 0x0004 /* in1: P1 is an input */ +#define OPFLG_IN2 0x0008 /* in2: P2 is an input */ +#define OPFLG_IN3 0x0010 /* in3: P3 is an input */ +#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */ +#define OPFLG_INITIALIZER {\ +/* 0 */ 0x00, 0x01, 0x00, 0x00, 0x10, 0x08, 0x02, 0x00,\ +/* 8 */ 0x00, 0x04, 0x00, 0x05, 0x02, 0x00, 0x00, 0x00,\ +/* 16 */ 0x00, 0x02, 0x00, 0x04, 0x01, 0x04, 0x00, 0x00,\ +/* 24 */ 0x05, 0x00, 0x04, 0x02, 0x00, 0x02, 0x04, 0x00,\ +/* 32 */ 0x00, 0x00, 0x00, 0x02, 0x11, 0x11, 0x02, 0x05,\ +/* 40 */ 0x00, 0x02, 0x11, 0x04, 0x00, 0x00, 0x0c, 0x11,\ +/* 48 */ 0x01, 0x02, 0x01, 0x21, 0x08, 0x00, 0x02, 0x01,\ +/* 56 */ 0x11, 0x01, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00,\ +/* 64 */ 0x11, 0x00, 0x2c, 0x2c, 0x00, 0x05, 0x00, 0x05,\ +/* 72 */ 0x05, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x11,\ +/* 80 */ 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,\ +/* 88 */ 0x2c, 0x2c, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00,\ +/* 96 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 104 */ 0x01, 0x00, 0x00, 0x01, 0x02, 0x08, 0x11, 0x00,\ +/* 112 */ 0x02, 0x02, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02,\ +/* 120 */ 0x00, 0x02, 0x01, 0x11, 0x00, 0x00, 0x05, 0x00,\ +/* 128 */ 0x11, 0x05, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,\ +/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\ +/* 144 */ 0x04, 0x04,} + +/************** End of opcodes.h *********************************************/ +/************** Continuing where we left off in vdbe.h ***********************/ + +/* +** Prototypes for the VDBE interface. See comments on the implementation +** for a description of what each of these routines does. +*/ +SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3*); +SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); +SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); +SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); +SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); +SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3); +SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5); +SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr); +SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); +SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); +SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); +SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); +SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int); +SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); +SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); +#ifdef SQLITE_DEBUG +SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe*,FILE*); +#endif +SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*); +SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int); +SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*)); +SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*); +SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int); +SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*); + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +SQLITE_PRIVATE int sqlite3VdbeReleaseMemory(int); +#endif +SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*, + UnpackedRecord*,int); +SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*); +SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); + + +#ifndef NDEBUG +SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe*, const char*, ...); +# define VdbeComment(X) sqlite3VdbeComment X +SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); +# define VdbeNoopComment(X) sqlite3VdbeNoopComment X +#else +# define VdbeComment(X) +# define VdbeNoopComment(X) +#endif + +#endif + +/************** End of vdbe.h ************************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include pager.h in the middle of sqliteInt.h *****************/ +/************** Begin file pager.h *******************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the sqlite page cache +** subsystem. The page cache subsystem reads and writes a file a page +** at a time and provides a journal for rollback. +** +** @(#) $Id: pager.h,v 1.100 2009/02/03 16:51:25 danielk1977 Exp $ +*/ + +#ifndef _PAGER_H_ +#define _PAGER_H_ + +/* +** Default maximum size for persistent journal files. A negative +** value means no limit. This value may be overridden using the +** sqlite3PagerJournalSizeLimit() API. See also "PRAGMA journal_size_limit". +*/ +#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT + #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1 +#endif + +/* +** The type used to represent a page number. The first page in a file +** is called page 1. 0 is used to represent "not a page". +*/ +typedef u32 Pgno; + +/* +** Each open file is managed by a separate instance of the "Pager" structure. +*/ +typedef struct Pager Pager; + +/* +** Handle type for pages. +*/ +typedef struct PgHdr DbPage; + +/* +** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is +** reserved for working around a windows/posix incompatibility). It is +** used in the journal to signify that the remainder of the journal file +** is devoted to storing a master journal name - there are no more pages to +** roll back. See comments for function writeMasterJournal() in pager.c +** for details. +*/ +#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1)) + +/* +** Allowed values for the flags parameter to sqlite3PagerOpen(). +** +** NOTE: These values must match the corresponding BTREE_ values in btree.h. +*/ +#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ +#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */ + +/* +** Valid values for the second argument to sqlite3PagerLockingMode(). +*/ +#define PAGER_LOCKINGMODE_QUERY -1 +#define PAGER_LOCKINGMODE_NORMAL 0 +#define PAGER_LOCKINGMODE_EXCLUSIVE 1 + +/* +** Valid values for the second argument to sqlite3PagerJournalMode(). +*/ +#define PAGER_JOURNALMODE_QUERY -1 +#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */ +#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */ +#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */ +#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */ +#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */ + +/* +** The remainder of this file contains the declarations of the functions +** that make up the Pager sub-system API. See source code comments for +** a detailed description of each routine. +*/ + +/* Open and close a Pager connection. */ +SQLITE_PRIVATE int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int); +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); + +/* Functions used to configure a Pager object. */ +SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); +SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*)); +SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u16*); +SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); +SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); +SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int); +SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); +SQLITE_PRIVATE int sqlite3PagerJournalMode(Pager *, int); +SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64); +SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*); + +/* Functions used to obtain and release page references. */ +SQLITE_PRIVATE int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); +#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) +SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); +SQLITE_PRIVATE void sqlite3PagerRef(DbPage*); +SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*); + +/* Operations on page references. */ +SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*); +SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*); +SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int); +SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*); +SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *); +SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *); + +/* Functions used to manage pager transactions and savepoints. */ +SQLITE_PRIVATE int sqlite3PagerPagecount(Pager*, int*); +SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag); +SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int); +SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*); +SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); +SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); +SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); + +/* Functions used to query pager state and configuration. */ +SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); +SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); +SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*); +SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*); +SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); +SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*); +SQLITE_PRIVATE int sqlite3PagerNosync(Pager*); +SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); +SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); + +/* Functions used to truncate the database file. */ +SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); + +/* Used by encryption extensions. */ +#ifdef SQLITE_HAS_CODEC +SQLITE_PRIVATE void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*); +#endif + +/* Functions to support testing and debugging. */ +#if !defined(NDEBUG) || defined(SQLITE_TEST) +SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*); +SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage*); +#endif +#ifdef SQLITE_TEST +SQLITE_PRIVATE int *sqlite3PagerStats(Pager*); +SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*); + void disable_simulated_io_errors(void); + void enable_simulated_io_errors(void); +#else +# define disable_simulated_io_errors() +# define enable_simulated_io_errors() +#endif + +#endif /* _PAGER_H_ */ + +/************** End of pager.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include pcache.h in the middle of sqliteInt.h ****************/ +/************** Begin file pcache.h ******************************************/ +/* +** 2008 August 05 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the sqlite page cache +** subsystem. +** +** @(#) $Id: pcache.h,v 1.19 2009/01/20 17:06:27 danielk1977 Exp $ +*/ + +#ifndef _PCACHE_H_ + +typedef struct PgHdr PgHdr; +typedef struct PCache PCache; + +/* +** Every page in the cache is controlled by an instance of the following +** structure. +*/ +struct PgHdr { + void *pData; /* Content of this page */ + void *pExtra; /* Extra content */ + PgHdr *pDirty; /* Transient list of dirty pages */ + Pgno pgno; /* Page number for this page */ + Pager *pPager; /* The pager this page is part of */ +#ifdef SQLITE_CHECK_PAGES + u32 pageHash; /* Hash of page content */ +#endif + u16 flags; /* PGHDR flags defined below */ + + /********************************************************************** + ** Elements above are public. All that follows is private to pcache.c + ** and should not be accessed by other modules. + */ + i16 nRef; /* Number of users of this page */ + PCache *pCache; /* Cache that owns this page */ + + PgHdr *pDirtyNext; /* Next element in list of dirty pages */ + PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */ +}; + +/* Bit values for PgHdr.flags */ +#define PGHDR_DIRTY 0x002 /* Page has changed */ +#define PGHDR_NEED_SYNC 0x004 /* Fsync the rollback journal before + ** writing this page to the database */ +#define PGHDR_NEED_READ 0x008 /* Content is unread */ +#define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */ +#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */ + +/* Initialize and shutdown the page cache subsystem */ +SQLITE_PRIVATE int sqlite3PcacheInitialize(void); +SQLITE_PRIVATE void sqlite3PcacheShutdown(void); + +/* Page cache buffer management: +** These routines implement SQLITE_CONFIG_PAGECACHE. +*/ +SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *, int sz, int n); + +/* Create a new pager cache. +** Under memory stress, invoke xStress to try to make pages clean. +** Only clean and unpinned pages can be reclaimed. +*/ +SQLITE_PRIVATE void sqlite3PcacheOpen( + int szPage, /* Size of every page */ + int szExtra, /* Extra space associated with each page */ + int bPurgeable, /* True if pages are on backing store */ + int (*xStress)(void*, PgHdr*), /* Call to try to make pages clean */ + void *pStress, /* Argument to xStress */ + PCache *pToInit /* Preallocated space for the PCache */ +); + +/* Modify the page-size after the cache has been created. */ +SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *, int); + +/* Return the size in bytes of a PCache object. Used to preallocate +** storage space. +*/ +SQLITE_PRIVATE int sqlite3PcacheSize(void); + +/* One release per successful fetch. Page is pinned until released. +** Reference counted. +*/ +SQLITE_PRIVATE int sqlite3PcacheFetch(PCache*, Pgno, int createFlag, PgHdr**); +SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*); + +SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */ +SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */ +SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */ +SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */ + +/* Change a page number. Used by incr-vacuum. */ +SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr*, Pgno); + +/* Remove all pages with pgno>x. Reset the cache if x==0 */ +SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache*, Pgno x); + +/* Get a list of all dirty pages in the cache, sorted by page number */ +SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*); + +/* Reset and close the cache object */ +SQLITE_PRIVATE void sqlite3PcacheClose(PCache*); + +/* Clear flags from pages of the page cache */ +SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *); + +/* Discard the contents of the cache */ +SQLITE_PRIVATE void sqlite3PcacheClear(PCache*); + +/* Return the total number of outstanding page references */ +SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache*); + +/* Increment the reference count of an existing page */ +SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*); + +SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr*); + +/* Return the total number of pages stored in the cache */ +SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*); + +#ifdef SQLITE_CHECK_PAGES +/* Iterate through all dirty pages currently stored in the cache. This +** interface is only available if SQLITE_CHECK_PAGES is defined when the +** library is built. +*/ +SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)); +#endif + +/* Set and get the suggested cache-size for the specified pager-cache. +** +** If no global maximum is configured, then the system attempts to limit +** the total number of pages cached by purgeable pager-caches to the sum +** of the suggested cache-sizes. +*/ +SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *, int); +#ifdef SQLITE_TEST +SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *); +#endif + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +/* Try to return memory used by the pcache module to the main memory heap */ +SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int); +#endif + +#ifdef SQLITE_TEST +SQLITE_PRIVATE void sqlite3PcacheStats(int*,int*,int*,int*); +#endif + +SQLITE_PRIVATE void sqlite3PCacheSetDefault(void); + +#endif /* _PCACHE_H_ */ + +/************** End of pcache.h **********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + +/************** Include os.h in the middle of sqliteInt.h ********************/ +/************** Begin file os.h **********************************************/ +/* +** 2001 September 16 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This header file (together with is companion C source-code file +** "os.c") attempt to abstract the underlying operating system so that +** the SQLite library will work on both POSIX and windows systems. +** +** This header file is #include-ed by sqliteInt.h and thus ends up +** being included by every source file. +** +** $Id: os.h,v 1.108 2009/02/05 16:31:46 drh Exp $ +*/ +#ifndef _SQLITE_OS_H_ +#define _SQLITE_OS_H_ + +/* +** Figure out if we are dealing with Unix, Windows, or some other +** operating system. After the following block of preprocess macros, +** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, SQLITE_OS_OS2, and SQLITE_OS_OTHER +** will defined to either 1 or 0. One of the four will be 1. The other +** three will be 0. +*/ +#if defined(SQLITE_OS_OTHER) +# if SQLITE_OS_OTHER==1 +# undef SQLITE_OS_UNIX +# define SQLITE_OS_UNIX 0 +# undef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +# undef SQLITE_OS_OS2 +# define SQLITE_OS_OS2 0 +# else +# undef SQLITE_OS_OTHER +# endif +#endif +#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER) +# define SQLITE_OS_OTHER 0 +# ifndef SQLITE_OS_WIN +# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) +# define SQLITE_OS_WIN 1 +# define SQLITE_OS_UNIX 0 +# define SQLITE_OS_OS2 0 +# elif defined(__EMX__) || defined(_OS2) || defined(OS2) || defined(_OS2_) || defined(__OS2__) +# define SQLITE_OS_WIN 0 +# define SQLITE_OS_UNIX 0 +# define SQLITE_OS_OS2 1 +# else +# define SQLITE_OS_WIN 0 +# define SQLITE_OS_UNIX 1 +# define SQLITE_OS_OS2 0 +# endif +# else +# define SQLITE_OS_UNIX 0 +# define SQLITE_OS_OS2 0 +# endif +#else +# ifndef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +# endif +#endif + +/* +** Determine if we are dealing with WindowsCE - which has a much +** reduced API. +*/ +#if defined(_WIN32_WCE) +# define SQLITE_OS_WINCE 1 +#else +# define SQLITE_OS_WINCE 0 +#endif + + +/* +** Define the maximum size of a temporary filename +*/ +#if SQLITE_OS_WIN +# include +# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) +#elif SQLITE_OS_OS2 +# if (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3) && defined(OS2_HIGH_MEMORY) +# include /* has to be included before os2.h for linking to work */ +# endif +# define INCL_DOSDATETIME +# define INCL_DOSFILEMGR +# define INCL_DOSERRORS +# define INCL_DOSMISC +# define INCL_DOSPROCESS +# define INCL_DOSMODULEMGR +# define INCL_DOSSEMAPHORES +# include +# include +# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP) +#else +# define SQLITE_TEMPNAME_SIZE 200 +#endif + +/* If the SET_FULLSYNC macro is not defined above, then make it +** a no-op +*/ +#ifndef SET_FULLSYNC +# define SET_FULLSYNC(x,y) +#endif + +/* +** The default size of a disk sector +*/ +#ifndef SQLITE_DEFAULT_SECTOR_SIZE +# define SQLITE_DEFAULT_SECTOR_SIZE 512 +#endif + +/* +** Temporary files are named starting with this prefix followed by 16 random +** alphanumeric characters, and no file extension. They are stored in the +** OS's standard temporary file directory, and are deleted prior to exit. +** If sqlite is being embedded in another program, you may wish to change the +** prefix to reflect your program's name, so that if your program exits +** prematurely, old temporary files can be easily identified. This can be done +** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line. +** +** 2006-10-31: The default prefix used to be "sqlite_". But then +** Mcafee started using SQLite in their anti-virus product and it +** started putting files with the "sqlite" name in the c:/temp folder. +** This annoyed many windows users. Those users would then do a +** Google search for "sqlite", find the telephone numbers of the +** developers and call to wake them up at night and complain. +** For this reason, the default name prefix is changed to be "sqlite" +** spelled backwards. So the temp files are still identified, but +** anybody smart enough to figure out the code is also likely smart +** enough to know that calling the developer will not help get rid +** of the file. +*/ +#ifndef SQLITE_TEMP_FILE_PREFIX +# define SQLITE_TEMP_FILE_PREFIX "etilqs_" +#endif + +/* +** The following values may be passed as the second argument to +** sqlite3OsLock(). The various locks exhibit the following semantics: +** +** SHARED: Any number of processes may hold a SHARED lock simultaneously. +** RESERVED: A single process may hold a RESERVED lock on a file at +** any time. Other processes may hold and obtain new SHARED locks. +** PENDING: A single process may hold a PENDING lock on a file at +** any one time. Existing SHARED locks may persist, but no new +** SHARED locks may be obtained by other processes. +** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks. +** +** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a +** process that requests an EXCLUSIVE lock may actually obtain a PENDING +** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to +** sqlite3OsLock(). +*/ +#define NO_LOCK 0 +#define SHARED_LOCK 1 +#define RESERVED_LOCK 2 +#define PENDING_LOCK 3 +#define EXCLUSIVE_LOCK 4 + +/* +** File Locking Notes: (Mostly about windows but also some info for Unix) +** +** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because +** those functions are not available. So we use only LockFile() and +** UnlockFile(). +** +** LockFile() prevents not just writing but also reading by other processes. +** A SHARED_LOCK is obtained by locking a single randomly-chosen +** byte out of a specific range of bytes. The lock byte is obtained at +** random so two separate readers can probably access the file at the +** same time, unless they are unlucky and choose the same lock byte. +** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range. +** There can only be one writer. A RESERVED_LOCK is obtained by locking +** a single byte of the file that is designated as the reserved lock byte. +** A PENDING_LOCK is obtained by locking a designated byte different from +** the RESERVED_LOCK byte. +** +** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available, +** which means we can use reader/writer locks. When reader/writer locks +** are used, the lock is placed on the same range of bytes that is used +** for probabilistic locking in Win95/98/ME. Hence, the locking scheme +** will support two or more Win95 readers or two or more WinNT readers. +** But a single Win95 reader will lock out all WinNT readers and a single +** WinNT reader will lock out all other Win95 readers. +** +** The following #defines specify the range of bytes used for locking. +** SHARED_SIZE is the number of bytes available in the pool from which +** a random byte is selected for a shared lock. The pool of bytes for +** shared locks begins at SHARED_FIRST. +** +** The same locking strategy and +** byte ranges are used for Unix. This leaves open the possiblity of having +** clients on win95, winNT, and unix all talking to the same shared file +** and all locking correctly. To do so would require that samba (or whatever +** tool is being used for file sharing) implements locks correctly between +** windows and unix. I'm guessing that isn't likely to happen, but by +** using the same locking range we are at least open to the possibility. +** +** Locking in windows is manditory. For this reason, we cannot store +** actual data in the bytes used for locking. The pager never allocates +** the pages involved in locking therefore. SHARED_SIZE is selected so +** that all locks will fit on a single page even at the minimum page size. +** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE +** is set high so that we don't have to allocate an unused page except +** for very large databases. But one should test the page skipping logic +** by setting PENDING_BYTE low and running the entire regression suite. +** +** Changing the value of PENDING_BYTE results in a subtly incompatible +** file format. Depending on how it is changed, you might not notice +** the incompatibility right away, even running a full regression test. +** The default location of PENDING_BYTE is the first byte past the +** 1GB boundary. +** +*/ +#define PENDING_BYTE sqlite3PendingByte +#define RESERVED_BYTE (PENDING_BYTE+1) +#define SHARED_FIRST (PENDING_BYTE+2) +#define SHARED_SIZE 510 + +/* +** Functions for accessing sqlite3_file methods +*/ +SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file*); +SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset); +SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset); +SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size); +SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file*, i64 *pSize); +SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut); +SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*); +#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0 +SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id); +SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id); + +/* +** Functions for accessing sqlite3_vfs methods +*/ +SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *); +SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int); +SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut); +SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *); +#ifndef SQLITE_OMIT_LOAD_EXTENSION +SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *); +SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *); +SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void); +SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *); +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ +SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *); +SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int); +SQLITE_PRIVATE int sqlite3OsCurrentTime(sqlite3_vfs *, double*); + +/* +** Convenience functions for opening and closing files using +** sqlite3_malloc() to obtain space for the file-handle structure. +*/ +SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*); +SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *); + +#endif /* _SQLITE_OS_H_ */ + +/************** End of os.h **************************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include mutex.h in the middle of sqliteInt.h *****************/ +/************** Begin file mutex.h *******************************************/ +/* +** 2007 August 28 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains the common header for all mutex implementations. +** The sqliteInt.h header #includes this file so that it is available +** to all source files. We break it out in an effort to keep the code +** better organized. +** +** NOTE: source files should *not* #include this header file directly. +** Source files should #include the sqliteInt.h file and let that file +** include this one indirectly. +** +** $Id: mutex.h,v 1.9 2008/10/07 15:25:48 drh Exp $ +*/ + + +/* +** Figure out what version of the code to use. The choices are +** +** SQLITE_MUTEX_OMIT No mutex logic. Not even stubs. The +** mutexes implemention cannot be overridden +** at start-time. +** +** SQLITE_MUTEX_NOOP For single-threaded applications. No +** mutual exclusion is provided. But this +** implementation can be overridden at +** start-time. +** +** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix. +** +** SQLITE_MUTEX_W32 For multi-threaded applications on Win32. +** +** SQLITE_MUTEX_OS2 For multi-threaded applications on OS/2. +*/ +#if !SQLITE_THREADSAFE +# define SQLITE_MUTEX_OMIT +#endif +#if SQLITE_THREADSAFE && !defined(SQLITE_MUTEX_NOOP) +# if SQLITE_OS_UNIX +# define SQLITE_MUTEX_PTHREADS +# elif SQLITE_OS_WIN +# define SQLITE_MUTEX_W32 +# elif SQLITE_OS_OS2 +# define SQLITE_MUTEX_OS2 +# else +# define SQLITE_MUTEX_NOOP +# endif +#endif + +#ifdef SQLITE_MUTEX_OMIT +/* +** If this is a no-op implementation, implement everything as macros. +*/ +#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8) +#define sqlite3_mutex_free(X) +#define sqlite3_mutex_enter(X) +#define sqlite3_mutex_try(X) SQLITE_OK +#define sqlite3_mutex_leave(X) +#define sqlite3_mutex_held(X) 1 +#define sqlite3_mutex_notheld(X) 1 +#define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8) +#define sqlite3MutexInit() SQLITE_OK +#define sqlite3MutexEnd() +#endif /* defined(SQLITE_OMIT_MUTEX) */ + +/************** End of mutex.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + + +/* +** Each database file to be accessed by the system is an instance +** of the following structure. There are normally two of these structures +** in the sqlite.aDb[] array. aDb[0] is the main database file and +** aDb[1] is the database file used to hold temporary tables. Additional +** databases may be attached. +*/ +struct Db { + char *zName; /* Name of this database */ + Btree *pBt; /* The B*Tree structure for this database file */ + u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ + u8 safety_level; /* How aggressive at syncing data to disk */ + void *pAux; /* Auxiliary data. Usually NULL */ + void (*xFreeAux)(void*); /* Routine to free pAux */ + Schema *pSchema; /* Pointer to database schema (possibly shared) */ +}; + +/* +** An instance of the following structure stores a database schema. +** +** If there are no virtual tables configured in this schema, the +** Schema.db variable is set to NULL. After the first virtual table +** has been added, it is set to point to the database connection +** used to create the connection. Once a virtual table has been +** added to the Schema structure and the Schema.db variable populated, +** only that database connection may use the Schema to prepare +** statements. +*/ +struct Schema { + int schema_cookie; /* Database schema version number for this file */ + Hash tblHash; /* All tables indexed by name */ + Hash idxHash; /* All (named) indices indexed by name */ + Hash trigHash; /* All triggers indexed by name */ + Hash aFKey; /* Foreign keys indexed by to-table */ + Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ + u8 file_format; /* Schema format version for this file */ + u8 enc; /* Text encoding used by this database */ + u16 flags; /* Flags associated with this schema */ + int cache_size; /* Number of pages to use in the cache */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3 *db; /* "Owner" connection. See comment above */ +#endif +}; + +/* +** These macros can be used to test, set, or clear bits in the +** Db.flags field. +*/ +#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P)) +#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0) +#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P) +#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P) + +/* +** Allowed values for the DB.flags field. +** +** The DB_SchemaLoaded flag is set after the database schema has been +** read into internal hash tables. +** +** DB_UnresetViews means that one or more views have column names that +** have been filled out. If the schema changes, these column names might +** changes and so the view will need to be reset. +*/ +#define DB_SchemaLoaded 0x0001 /* The schema has been loaded */ +#define DB_UnresetViews 0x0002 /* Some views have defined column names */ +#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */ + +/* +** The number of different kinds of things that can be limited +** using the sqlite3_limit() interface. +*/ +#define SQLITE_N_LIMIT (SQLITE_LIMIT_VARIABLE_NUMBER+1) + +/* +** Lookaside malloc is a set of fixed-size buffers that can be used +** to satisfy small transient memory allocation requests for objects +** associated with a particular database connection. The use of +** lookaside malloc provides a significant performance enhancement +** (approx 10%) by avoiding numerous malloc/free requests while parsing +** SQL statements. +** +** The Lookaside structure holds configuration information about the +** lookaside malloc subsystem. Each available memory allocation in +** the lookaside subsystem is stored on a linked list of LookasideSlot +** objects. +** +** Lookaside allocations are only allowed for objects that are associated +** with a particular database connection. Hence, schema information cannot +** be stored in lookaside because in shared cache mode the schema information +** is shared by multiple database connections. Therefore, while parsing +** schema information, the Lookaside.bEnabled flag is cleared so that +** lookaside allocations are not used to construct the schema objects. +*/ +struct Lookaside { + u16 sz; /* Size of each buffer in bytes */ + u8 bEnabled; /* False to disable new lookaside allocations */ + u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ + int nOut; /* Number of buffers currently checked out */ + int mxOut; /* Highwater mark for nOut */ + LookasideSlot *pFree; /* List of available buffers */ + void *pStart; /* First byte of available memory space */ + void *pEnd; /* First byte past end of available space */ +}; +struct LookasideSlot { + LookasideSlot *pNext; /* Next buffer in the list of free buffers */ +}; + +/* +** A hash table for function definitions. +** +** Hash each FuncDef structure into one of the FuncDefHash.a[] slots. +** Collisions are on the FuncDef.pHash chain. +*/ +struct FuncDefHash { + FuncDef *a[23]; /* Hash table for functions */ +}; + +/* +** Each database is an instance of the following structure. +** +** The sqlite.lastRowid records the last insert rowid generated by an +** insert statement. Inserts on views do not affect its value. Each +** trigger has its own context, so that lastRowid can be updated inside +** triggers as usual. The previous value will be restored once the trigger +** exits. Upon entering a before or instead of trigger, lastRowid is no +** longer (since after version 2.8.12) reset to -1. +** +** The sqlite.nChange does not count changes within triggers and keeps no +** context. It is reset at start of sqlite3_exec. +** The sqlite.lsChange represents the number of changes made by the last +** insert, update, or delete statement. It remains constant throughout the +** length of a statement and is then updated by OP_SetCounts. It keeps a +** context stack just like lastRowid so that the count of changes +** within a trigger is not seen outside the trigger. Changes to views do not +** affect the value of lsChange. +** The sqlite.csChange keeps track of the number of current changes (since +** the last statement) and is used to update sqlite_lsChange. +** +** The member variables sqlite.errCode, sqlite.zErrMsg and sqlite.zErrMsg16 +** store the most recent error code and, if applicable, string. The +** internal function sqlite3Error() is used to set these variables +** consistently. +*/ +struct sqlite3 { + sqlite3_vfs *pVfs; /* OS Interface */ + int nDb; /* Number of backends currently in use */ + Db *aDb; /* All backends */ + int flags; /* Miscellaneous flags. See below */ + int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ + int errCode; /* Most recent error code (SQLITE_*) */ + int errMask; /* & result codes with this before returning */ + u8 autoCommit; /* The auto-commit flag. */ + u8 temp_store; /* 1: file 2: memory 0: default */ + u8 mallocFailed; /* True if we have seen a malloc failure */ + u8 dfltLockMode; /* Default locking-mode for attached dbs */ + u8 dfltJournalMode; /* Default journal mode for attached dbs */ + signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ + int nextPagesize; /* Pagesize after VACUUM if >0 */ + int nTable; /* Number of tables in the database */ + CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ + i64 lastRowid; /* ROWID of most recent insert (see above) */ + i64 priorNewRowid; /* Last randomly generated ROWID */ + u32 magic; /* Magic number for detect library misuse */ + int nChange; /* Value returned by sqlite3_changes() */ + int nTotalChange; /* Value returned by sqlite3_total_changes() */ + sqlite3_mutex *mutex; /* Connection mutex */ + int aLimit[SQLITE_N_LIMIT]; /* Limits */ + struct sqlite3InitInfo { /* Information used during initialization */ + int iDb; /* When back is being initialized */ + int newTnum; /* Rootpage of table being initialized */ + u8 busy; /* TRUE if currently initializing */ + } init; + int nExtension; /* Number of loaded extensions */ + void **aExtension; /* Array of shared library handles */ + struct Vdbe *pVdbe; /* List of active virtual machines */ + int activeVdbeCnt; /* Number of VDBEs currently executing */ + int writeVdbeCnt; /* Number of active VDBEs that are writing */ + void (*xTrace)(void*,const char*); /* Trace function */ + void *pTraceArg; /* Argument to the trace function */ + void (*xProfile)(void*,const char*,u64); /* Profiling function */ + void *pProfileArg; /* Argument to profile function */ + void *pCommitArg; /* Argument to xCommitCallback() */ + int (*xCommitCallback)(void*); /* Invoked at every commit. */ + void *pRollbackArg; /* Argument to xRollbackCallback() */ + void (*xRollbackCallback)(void*); /* Invoked at every commit. */ + void *pUpdateArg; + void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); + void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); + void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); + void *pCollNeededArg; + sqlite3_value *pErr; /* Most recent error message */ + char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ + char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ + union { + volatile int isInterrupted; /* True if sqlite3_interrupt has been called */ + double notUsed1; /* Spacer */ + } u1; + Lookaside lookaside; /* Lookaside malloc configuration */ +#ifndef SQLITE_OMIT_AUTHORIZATION + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); + /* Access authorization function */ + void *pAuthArg; /* 1st argument to the access auth function */ +#endif +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + int (*xProgress)(void *); /* The progress callback */ + void *pProgressArg; /* Argument to the progress callback */ + int nProgressOps; /* Number of opcodes for progress callback */ +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + Hash aModule; /* populated by sqlite3_create_module() */ + Table *pVTab; /* vtab with active Connect/Create method */ + sqlite3_vtab **aVTrans; /* Virtual tables with open transactions */ + int nVTrans; /* Allocated size of aVTrans */ +#endif + FuncDefHash aFunc; /* Hash table of connection functions */ + Hash aCollSeq; /* All collating sequences */ + BusyHandler busyHandler; /* Busy callback */ + int busyTimeout; /* Busy handler timeout, in msec */ + Db aDbStatic[2]; /* Static space for the 2 default backends */ +#ifdef SQLITE_SSE + sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */ +#endif + Savepoint *pSavepoint; /* List of active savepoints */ + int nSavepoint; /* Number of non-transaction savepoints */ + int nStatement; /* Number of nested statement-transactions */ + u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ + +#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY + /* The following variables are all protected by the STATIC_MASTER + ** mutex, not by sqlite3.mutex. They are used by code in notify.c. + */ + sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */ + sqlite3 *pUnlockConnection; /* Connection to watch for unlock */ + void *pUnlockArg; /* Argument to xUnlockNotify */ + void (*xUnlockNotify)(void **, int); /* Unlock notify callback */ + sqlite3 *pNextBlocked; /* Next in list of all blocked connections */ +#endif +}; + +/* +** A macro to discover the encoding of a database. +*/ +#define ENC(db) ((db)->aDb[0].pSchema->enc) + +/* +** Possible values for the sqlite.flags and or Db.flags fields. +** +** On sqlite.flags, the SQLITE_InTrans value means that we have +** executed a BEGIN. On Db.flags, SQLITE_InTrans means a statement +** transaction is active on that particular database file. +*/ +#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ +#define SQLITE_InTrans 0x00000008 /* True if in a transaction */ +#define SQLITE_InternChanges 0x00000010 /* Uncommitted Hash table changes */ +#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */ +#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ +#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */ + /* DELETE, or UPDATE and return */ + /* the count using a callback. */ +#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ + /* result set is empty */ +#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */ +#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */ +#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */ +#define SQLITE_NoReadlock 0x00001000 /* Readlocks are omitted when + ** accessing read-only databases */ +#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */ +#define SQLITE_ReadUncommitted 0x00004000 /* For shared-cache mode */ +#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */ +#define SQLITE_FullFSync 0x00010000 /* Use full fsync on the backend */ +#define SQLITE_LoadExtension 0x00020000 /* Enable load_extension */ + +#define SQLITE_RecoveryMode 0x00040000 /* Ignore schema errors */ +#define SQLITE_SharedCache 0x00080000 /* Cache sharing is enabled */ +#define SQLITE_Vtab 0x00100000 /* There exists a virtual table */ +#define SQLITE_CommitBusy 0x00200000 /* In the process of committing */ +#define SQLITE_ReverseOrder 0x00400000 /* Reverse unordered SELECTs */ + +/* +** Possible values for the sqlite.magic field. +** The numbers are obtained at random and have no special meaning, other +** than being distinct from one another. +*/ +#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ +#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */ +#define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */ +#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */ +#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */ + +/* +** Each SQL function is defined by an instance of the following +** structure. A pointer to this structure is stored in the sqlite.aFunc +** hash table. When multiple functions have the same name, the hash table +** points to a linked list of these structures. +*/ +struct FuncDef { + i16 nArg; /* Number of arguments. -1 means unlimited */ + u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */ + u8 flags; /* Some combination of SQLITE_FUNC_* */ + void *pUserData; /* User data parameter */ + FuncDef *pNext; /* Next function with same name */ + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */ + void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */ + void (*xFinalize)(sqlite3_context*); /* Aggregate finalizer */ + char *zName; /* SQL name of the function. */ + FuncDef *pHash; /* Next with a different name but the same hash */ +}; + +/* +** Possible values for FuncDef.flags +*/ +#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */ +#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */ +#define SQLITE_FUNC_EPHEM 0x04 /* Ephemeral. Delete with VDBE */ +#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */ +#define SQLITE_FUNC_PRIVATE 0x10 /* Allowed for internal use only */ +#define SQLITE_FUNC_COUNT 0x20 /* Built-in count(*) aggregate */ + +/* +** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are +** used to create the initializers for the FuncDef structures. +** +** FUNCTION(zName, nArg, iArg, bNC, xFunc) +** Used to create a scalar function definition of a function zName +** implemented by C function xFunc that accepts nArg arguments. The +** value passed as iArg is cast to a (void*) and made available +** as the user-data (sqlite3_user_data()) for the function. If +** argument bNC is true, then the FuncDef.needCollate flag is set. +** +** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal) +** Used to create an aggregate function definition implemented by +** the C functions xStep and xFinal. The first four parameters +** are interpreted in the same way as the first 4 parameters to +** FUNCTION(). +** +** LIKEFUNC(zName, nArg, pArg, flags) +** Used to create a scalar function definition of a function zName +** that accepts nArg arguments and is implemented by a call to C +** function likeFunc. Argument pArg is cast to a (void *) and made +** available as the function user-data (sqlite3_user_data()). The +** FuncDef.flags variable is set to the value passed as the flags +** parameter. +*/ +#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ + {nArg, SQLITE_UTF8, bNC*8, SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0} +#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ + {nArg, SQLITE_UTF8, bNC*8, pArg, 0, xFunc, 0, 0, #zName, 0} +#define LIKEFUNC(zName, nArg, arg, flags) \ + {nArg, SQLITE_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0} +#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ + {nArg, SQLITE_UTF8, nc*8, SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0} + +/* +** All current savepoints are stored in a linked list starting at +** sqlite3.pSavepoint. The first element in the list is the most recently +** opened savepoint. Savepoints are added to the list by the vdbe +** OP_Savepoint instruction. +*/ +struct Savepoint { + char *zName; /* Savepoint name (nul-terminated) */ + Savepoint *pNext; /* Parent savepoint (if any) */ +}; + +/* +** The following are used as the second parameter to sqlite3Savepoint(), +** and as the P1 argument to the OP_Savepoint instruction. +*/ +#define SAVEPOINT_BEGIN 0 +#define SAVEPOINT_RELEASE 1 +#define SAVEPOINT_ROLLBACK 2 + + +/* +** Each SQLite module (virtual table definition) is defined by an +** instance of the following structure, stored in the sqlite3.aModule +** hash table. +*/ +struct Module { + const sqlite3_module *pModule; /* Callback pointers */ + const char *zName; /* Name passed to create_module() */ + void *pAux; /* pAux passed to create_module() */ + void (*xDestroy)(void *); /* Module destructor function */ +}; + +/* +** information about each column of an SQL table is held in an instance +** of this structure. +*/ +struct Column { + char *zName; /* Name of this column */ + Expr *pDflt; /* Default value of this column */ + char *zType; /* Data type for this column */ + char *zColl; /* Collating sequence. If NULL, use the default */ + u8 notNull; /* True if there is a NOT NULL constraint */ + u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */ + char affinity; /* One of the SQLITE_AFF_... values */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + u8 isHidden; /* True if this column is 'hidden' */ +#endif +}; + +/* +** A "Collating Sequence" is defined by an instance of the following +** structure. Conceptually, a collating sequence consists of a name and +** a comparison routine that defines the order of that sequence. +** +** There may two separate implementations of the collation function, one +** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that +** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine +** native byte order. When a collation sequence is invoked, SQLite selects +** the version that will require the least expensive encoding +** translations, if any. +** +** The CollSeq.pUser member variable is an extra parameter that passed in +** as the first argument to the UTF-8 comparison function, xCmp. +** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function, +** xCmp16. +** +** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the +** collating sequence is undefined. Indices built on an undefined +** collating sequence may not be read or written. +*/ +struct CollSeq { + char *zName; /* Name of the collating sequence, UTF-8 encoded */ + u8 enc; /* Text encoding handled by xCmp() */ + u8 type; /* One of the SQLITE_COLL_... values below */ + void *pUser; /* First argument to xCmp() */ + int (*xCmp)(void*,int, const void*, int, const void*); + void (*xDel)(void*); /* Destructor for pUser */ +}; + +/* +** Allowed values of CollSeq.type: +*/ +#define SQLITE_COLL_BINARY 1 /* The default memcmp() collating sequence */ +#define SQLITE_COLL_NOCASE 2 /* The built-in NOCASE collating sequence */ +#define SQLITE_COLL_REVERSE 3 /* The built-in REVERSE collating sequence */ +#define SQLITE_COLL_USER 0 /* Any other user-defined collating sequence */ + +/* +** A sort order can be either ASC or DESC. +*/ +#define SQLITE_SO_ASC 0 /* Sort in ascending order */ +#define SQLITE_SO_DESC 1 /* Sort in ascending order */ + +/* +** Column affinity types. +** +** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and +** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve +** the speed a little by numbering the values consecutively. +** +** But rather than start with 0 or 1, we begin with 'a'. That way, +** when multiple affinity types are concatenated into a string and +** used as the P4 operand, they will be more readable. +** +** Note also that the numeric types are grouped together so that testing +** for a numeric type is a single comparison. +*/ +#define SQLITE_AFF_TEXT 'a' +#define SQLITE_AFF_NONE 'b' +#define SQLITE_AFF_NUMERIC 'c' +#define SQLITE_AFF_INTEGER 'd' +#define SQLITE_AFF_REAL 'e' + +#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) + +/* +** The SQLITE_AFF_MASK values masks off the significant bits of an +** affinity value. +*/ +#define SQLITE_AFF_MASK 0x67 + +/* +** Additional bit values that can be ORed with an affinity without +** changing the affinity. +*/ +#define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */ +#define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */ + +/* +** Each SQL table is represented in memory by an instance of the +** following structure. +** +** Table.zName is the name of the table. The case of the original +** CREATE TABLE statement is stored, but case is not significant for +** comparisons. +** +** Table.nCol is the number of columns in this table. Table.aCol is a +** pointer to an array of Column structures, one for each column. +** +** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of +** the column that is that key. Otherwise Table.iPKey is negative. Note +** that the datatype of the PRIMARY KEY must be INTEGER for this field to +** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of +** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid +** is generated for each row of the table. TF_HasPrimaryKey is set if +** the table has any PRIMARY KEY, INTEGER or otherwise. +** +** Table.tnum is the page number for the root BTree page of the table in the +** database file. If Table.iDb is the index of the database table backend +** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that +** holds temporary tables and indices. If TF_Ephemeral is set +** then the table is stored in a file that is automatically deleted +** when the VDBE cursor to the table is closed. In this case Table.tnum +** refers VDBE cursor number that holds the table open, not to the root +** page number. Transient tables are used to hold the results of a +** sub-query that appears instead of a real table name in the FROM clause +** of a SELECT statement. +*/ +struct Table { + sqlite3 *dbMem; /* DB connection used for lookaside allocations. */ + char *zName; /* Name of the table or view */ + int iPKey; /* If not negative, use aCol[iPKey] as the primary key */ + int nCol; /* Number of columns in this table */ + Column *aCol; /* Information about each column */ + Index *pIndex; /* List of SQL indexes on this table. */ + int tnum; /* Root BTree node for this table (see note above) */ + Select *pSelect; /* NULL for tables. Points to definition if a view. */ + u16 nRef; /* Number of pointers to this Table */ + u8 tabFlags; /* Mask of TF_* values */ + u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ + FKey *pFKey; /* Linked list of all foreign keys in this table */ + char *zColAff; /* String defining the affinity of each column */ +#ifndef SQLITE_OMIT_CHECK + Expr *pCheck; /* The AND of all CHECK constraints */ +#endif +#ifndef SQLITE_OMIT_ALTERTABLE + int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + Module *pMod; /* Pointer to the implementation of the module */ + sqlite3_vtab *pVtab; /* Pointer to the module instance */ + int nModuleArg; /* Number of arguments to the module */ + char **azModuleArg; /* Text of all module args. [0] is module name */ +#endif + Trigger *pTrigger; /* List of triggers stored in pSchema */ + Schema *pSchema; /* Schema that contains this table */ + Table *pNextZombie; /* Next on the Parse.pZombieTab list */ +}; + +/* +** Allowed values for Tabe.tabFlags. +*/ +#define TF_Readonly 0x01 /* Read-only system table */ +#define TF_Ephemeral 0x02 /* An ephemeral table */ +#define TF_HasPrimaryKey 0x04 /* Table has a primary key */ +#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */ +#define TF_Virtual 0x10 /* Is a virtual table */ +#define TF_NeedMetadata 0x20 /* aCol[].zType and aCol[].pColl missing */ + + + +/* +** Test to see whether or not a table is a virtual table. This is +** done as a macro so that it will be optimized out when virtual +** table support is omitted from the build. +*/ +#ifndef SQLITE_OMIT_VIRTUALTABLE +# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) +# define IsHiddenColumn(X) ((X)->isHidden) +#else +# define IsVirtual(X) 0 +# define IsHiddenColumn(X) 0 +#endif + +/* +** Each foreign key constraint is an instance of the following structure. +** +** A foreign key is associated with two tables. The "from" table is +** the table that contains the REFERENCES clause that creates the foreign +** key. The "to" table is the table that is named in the REFERENCES clause. +** Consider this example: +** +** CREATE TABLE ex1( +** a INTEGER PRIMARY KEY, +** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x) +** ); +** +** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2". +** +** Each REFERENCES clause generates an instance of the following structure +** which is attached to the from-table. The to-table need not exist when +** the from-table is created. The existence of the to-table is not checked +** until an attempt is made to insert data into the from-table. +** +** The sqlite.aFKey hash table stores pointers to this structure +** given the name of a to-table. For each to-table, all foreign keys +** associated with that table are on a linked list using the FKey.pNextTo +** field. +*/ +struct FKey { + Table *pFrom; /* The table that contains the REFERENCES clause */ + FKey *pNextFrom; /* Next foreign key in pFrom */ + char *zTo; /* Name of table that the key points to */ + FKey *pNextTo; /* Next foreign key that points to zTo */ + int nCol; /* Number of columns in this key */ + struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ + int iFrom; /* Index of column in pFrom */ + char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */ + } *aCol; /* One entry for each of nCol column s */ + u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ + u8 updateConf; /* How to resolve conflicts that occur on UPDATE */ + u8 deleteConf; /* How to resolve conflicts that occur on DELETE */ + u8 insertConf; /* How to resolve conflicts that occur on INSERT */ +}; + +/* +** SQLite supports many different ways to resolve a constraint +** error. ROLLBACK processing means that a constraint violation +** causes the operation in process to fail and for the current transaction +** to be rolled back. ABORT processing means the operation in process +** fails and any prior changes from that one operation are backed out, +** but the transaction is not rolled back. FAIL processing means that +** the operation in progress stops and returns an error code. But prior +** changes due to the same operation are not backed out and no rollback +** occurs. IGNORE means that the particular row that caused the constraint +** error is not inserted or updated. Processing continues and no error +** is returned. REPLACE means that preexisting database rows that caused +** a UNIQUE constraint violation are removed so that the new insert or +** update can proceed. Processing continues and no error is reported. +** +** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys. +** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the +** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign +** key is set to NULL. CASCADE means that a DELETE or UPDATE of the +** referenced table row is propagated into the row that holds the +** foreign key. +** +** The following symbolic values are used to record which type +** of action to take. +*/ +#define OE_None 0 /* There is no constraint to check */ +#define OE_Rollback 1 /* Fail the operation and rollback the transaction */ +#define OE_Abort 2 /* Back out changes but do no rollback transaction */ +#define OE_Fail 3 /* Stop the operation but leave all prior changes */ +#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ +#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ + +#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ +#define OE_SetNull 7 /* Set the foreign key value to NULL */ +#define OE_SetDflt 8 /* Set the foreign key value to its default */ +#define OE_Cascade 9 /* Cascade the changes */ + +#define OE_Default 99 /* Do whatever the default action is */ + + +/* +** An instance of the following structure is passed as the first +** argument to sqlite3VdbeKeyCompare and is used to control the +** comparison of the two index keys. +*/ +struct KeyInfo { + sqlite3 *db; /* The database connection */ + u8 enc; /* Text encoding - one of the TEXT_Utf* values */ + u16 nField; /* Number of entries in aColl[] */ + u8 *aSortOrder; /* If defined an aSortOrder[i] is true, sort DESC */ + CollSeq *aColl[1]; /* Collating sequence for each term of the key */ +}; + +/* +** An instance of the following structure holds information about a +** single index record that has already been parsed out into individual +** values. +** +** A record is an object that contains one or more fields of data. +** Records are used to store the content of a table row and to store +** the key of an index. A blob encoding of a record is created by +** the OP_MakeRecord opcode of the VDBE and is disassembled by the +** OP_Column opcode. +** +** This structure holds a record that has already been disassembled +** into its constituent fields. +*/ +struct UnpackedRecord { + KeyInfo *pKeyInfo; /* Collation and sort-order information */ + u16 nField; /* Number of entries in apMem[] */ + u16 flags; /* Boolean settings. UNPACKED_... below */ + Mem *aMem; /* Values */ +}; + +/* +** Allowed values of UnpackedRecord.flags +*/ +#define UNPACKED_NEED_FREE 0x0001 /* Memory is from sqlite3Malloc() */ +#define UNPACKED_NEED_DESTROY 0x0002 /* apMem[]s should all be destroyed */ +#define UNPACKED_IGNORE_ROWID 0x0004 /* Ignore trailing rowid on key1 */ +#define UNPACKED_INCRKEY 0x0008 /* Make this key an epsilon larger */ +#define UNPACKED_PREFIX_MATCH 0x0010 /* A prefix match is considered OK */ + +/* +** Each SQL index is represented in memory by an +** instance of the following structure. +** +** The columns of the table that are to be indexed are described +** by the aiColumn[] field of this structure. For example, suppose +** we have the following table and index: +** +** CREATE TABLE Ex1(c1 int, c2 int, c3 text); +** CREATE INDEX Ex2 ON Ex1(c3,c1); +** +** In the Table structure describing Ex1, nCol==3 because there are +** three columns in the table. In the Index structure describing +** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed. +** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the +** first column to be indexed (c3) has an index of 2 in Ex1.aCol[]. +** The second column to be indexed (c1) has an index of 0 in +** Ex1.aCol[], hence Ex2.aiColumn[1]==0. +** +** The Index.onError field determines whether or not the indexed columns +** must be unique and what to do if they are not. When Index.onError=OE_None, +** it means this is not a unique index. Otherwise it is a unique index +** and the value of Index.onError indicate the which conflict resolution +** algorithm to employ whenever an attempt is made to insert a non-unique +** element. +*/ +struct Index { + char *zName; /* Name of this index */ + int nColumn; /* Number of columns in the table used by this index */ + int *aiColumn; /* Which columns are used by this index. 1st is 0 */ + unsigned *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */ + Table *pTable; /* The SQL table being indexed */ + int tnum; /* Page containing root of this index in database file */ + u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ + u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ + char *zColAff; /* String defining the affinity of each column */ + Index *pNext; /* The next index associated with the same table */ + Schema *pSchema; /* Schema containing this index */ + u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ + char **azColl; /* Array of collation sequence names for index */ +}; + +/* +** Each token coming out of the lexer is an instance of +** this structure. Tokens are also used as part of an expression. +** +** Note if Token.z==0 then Token.dyn and Token.n are undefined and +** may contain random values. Do not make any assumptions about Token.dyn +** and Token.n when Token.z==0. +*/ +struct Token { + const unsigned char *z; /* Text of the token. Not NULL-terminated! */ + unsigned dyn : 1; /* True for malloced memory, false for static */ + unsigned n : 31; /* Number of characters in this token */ +}; + +/* +** An instance of this structure contains information needed to generate +** code for a SELECT that contains aggregate functions. +** +** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a +** pointer to this structure. The Expr.iColumn field is the index in +** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate +** code for that node. +** +** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the +** original Select structure that describes the SELECT statement. These +** fields do not need to be freed when deallocating the AggInfo structure. +*/ +struct AggInfo { + u8 directMode; /* Direct rendering mode means take data directly + ** from source tables rather than from accumulators */ + u8 useSortingIdx; /* In direct mode, reference the sorting index rather + ** than the source table */ + int sortingIdx; /* Cursor number of the sorting index */ + ExprList *pGroupBy; /* The group by clause */ + int nSortingColumn; /* Number of columns in the sorting index */ + struct AggInfo_col { /* For each column used in source tables */ + Table *pTab; /* Source table */ + int iTable; /* Cursor number of the source table */ + int iColumn; /* Column number within the source table */ + int iSorterColumn; /* Column number in the sorting index */ + int iMem; /* Memory location that acts as accumulator */ + Expr *pExpr; /* The original expression */ + } *aCol; + int nColumn; /* Number of used entries in aCol[] */ + int nColumnAlloc; /* Number of slots allocated for aCol[] */ + int nAccumulator; /* Number of columns that show through to the output. + ** Additional columns are used only as parameters to + ** aggregate functions */ + struct AggInfo_func { /* For each aggregate function */ + Expr *pExpr; /* Expression encoding the function */ + FuncDef *pFunc; /* The aggregate function implementation */ + int iMem; /* Memory location that acts as accumulator */ + int iDistinct; /* Ephemeral table used to enforce DISTINCT */ + } *aFunc; + int nFunc; /* Number of entries in aFunc[] */ + int nFuncAlloc; /* Number of slots allocated for aFunc[] */ +}; + +/* +** Each node of an expression in the parse tree is an instance +** of this structure. +** +** Expr.op is the opcode. The integer parser token codes are reused +** as opcodes here. For example, the parser defines TK_GE to be an integer +** code representing the ">=" operator. This same integer code is reused +** to represent the greater-than-or-equal-to operator in the expression +** tree. +** +** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB, +** or TK_STRING), then Expr.token contains the text of the SQL literal. If +** the expression is a variable (TK_VARIABLE), then Expr.token contains the +** variable name. Finally, if the expression is an SQL function (TK_FUNCTION), +** then Expr.token contains the name of the function. +** +** Expr.pRight and Expr.pLeft are the left and right subexpressions of a +** binary operator. Either or both may be NULL. +** +** Expr.x.pList is a list of arguments if the expression is an SQL function, +** a CASE expression or an IN expression of the form " IN (, ...)". +** Expr.x.pSelect is used if the expression is a sub-select or an expression of +** the form " IN (SELECT ...)". If the EP_xIsSelect bit is set in the +** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is +** valid. +** +** An expression of the form ID or ID.ID refers to a column in a table. +** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is +** the integer cursor number of a VDBE cursor pointing to that table and +** Expr.iColumn is the column number for the specific column. If the +** expression is used as a result in an aggregate SELECT, then the +** value is also stored in the Expr.iAgg column in the aggregate so that +** it can be accessed after all aggregates are computed. +** +** If the expression is an unbound variable marker (a question mark +** character '?' in the original SQL) then the Expr.iTable holds the index +** number for that variable. +** +** If the expression is a subquery then Expr.iColumn holds an integer +** register number containing the result of the subquery. If the +** subquery gives a constant result, then iTable is -1. If the subquery +** gives a different answer at different times during statement processing +** then iTable is the address of a subroutine that computes the subquery. +** +** If the Expr is of type OP_Column, and the table it is selecting from +** is a disk table or the "old.*" pseudo-table, then pTab points to the +** corresponding table definition. +** +** ALLOCATION NOTES: +** +** Expr structures may be stored as part of the in-memory database schema, +** for example as part of trigger, view or table definitions. In this case, +** the amount of memory consumed by complex expressions may be significant. +** For this reason, less than sizeof(Expr) bytes may be allocated for some +** Expr structs stored as part of the in-memory database schema. +** +** If the EP_Reduced flag is set in Expr.flags, then only EXPR_REDUCEDSIZE +** bytes of space are allocated for the expression structure. This is enough +** space to store all fields up to and including the "Token span;" field. +** +** If the EP_TokenOnly flag is set in Expr.flags, then only EXPR_TOKENONLYSIZE +** bytes of space are allocated for the expression structure. This is enough +** space to store all fields up to and including the "Token token;" field. +*/ +struct Expr { + u8 op; /* Operation performed by this node */ + char affinity; /* The affinity of the column or 0 if not a column */ + VVA_ONLY(u8 vvaFlags;) /* Flags used for VV&A only. EVVA_* below. */ + u16 flags; /* Various flags. EP_* See below */ + Token token; /* An operand token */ + + /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no + ** space is allocated for the fields below this point. An attempt to + ** access them will result in a segfault or malfunction. + *********************************************************************/ + + Token span; /* Complete text of the expression */ + + /* If the EP_SpanOnly flag is set in the Expr.flags mask, then no + ** space is allocated for the fields below this point. An attempt to + ** access them will result in a segfault or malfunction. + *********************************************************************/ + + Expr *pLeft; /* Left subnode */ + Expr *pRight; /* Right subnode */ + union { + ExprList *pList; /* Function arguments or in " IN ( IN ( +// +// 00 means an unconnected pin. +// <- means using a R/W allocator from the upstream filter +// <= means using a R-O allocator from an upstream filter +// || means using our own (R/W) allocator. +// -> means using a R/W allocator from a downstream filter +// (a R-O allocator from downstream is nonsense, it can't ever work). +// +// +// That makes 25 possible states. Some states are nonsense (two different +// allocators from the same place). These are just an artifact of the notation. +// <= <- Nonsense. +// <- <= Nonsense +// Some states are illegal (the output pin never accepts a R-O allocator): +// 00 <= !! Error !! +// <= <= !! Error !! +// || <= !! Error !! +// -> <= !! Error !! +// Three states appears to be inaccessible: +// -> || Inaccessible +// || -> Inaccessible +// || <- Inaccessible +// Some states only ever occur as intermediates with a pending reconnect which +// is guaranteed to finish in another state. +// -> 00 ?? unstable goes to || 00 +// 00 <- ?? unstable goes to 00 || +// -> <- ?? unstable goes to -> -> +// <- || ?? unstable goes to <- <- +// <- -> ?? unstable goes to <- <- +// And that leaves 11 possible resting states: +// 1 00 00 Nothing connected. +// 2 <- 00 Input pin connected. +// 3 <= 00 Input pin connected using R-O allocator. +// 4 || 00 Needs several state changes to get here. +// 5 00 || Output pin connected using our allocator +// 6 00 -> Downstream only connected +// 7 || || Undesirable but can be forced upon us. +// 8 <= || Copy forced. <= -> is preferable +// 9 <= -> OK - forced to copy. +// 10 <- <- Transform in place (ideal) +// 11 -> -> Transform in place (ideal) +// +// The object of the exercise is to ensure that we finish up in states +// 10 or 11 whenever possible. State 10 is only possible if the upstream +// filter has a R/W allocator (the AVI splitter notoriously +// doesn't) and state 11 is only possible if the downstream filter does +// offer an allocator. +// +// The transition table (entries marked * go via a reconnect) +// +// There are 8 possible transitions: +// A: Connect upstream to filter with R-O allocator that insists on using it. +// B: Connect upstream to filter with R-O allocator but chooses not to use it. +// C: Connect upstream to filter with R/W allocator and insists on using it. +// D: Connect upstream to filter with R/W allocator but chooses not to use it. +// E: Connect downstream to a filter that offers an allocator +// F: Connect downstream to a filter that does not offer an allocator +// G: disconnect upstream +// H: Disconnect downstream +// +// A B C D E F G H +// --------------------------------------------------------- +// 00 00 1 | 3 3 2 2 6 5 . . |1 00 00 +// <- 00 2 | . . . . *10/11 10 1 . |2 <- 00 +// <= 00 3 | . . . . *9/11 *7/8 1 . |3 <= 00 +// || 00 4 | . . . . *8 *7 1 . |4 || 00 +// 00 || 5 | 8 7 *10 7 . . . 1 |5 00 || +// 00 -> 6 | 9 11 *10 11 . . . 1 |6 00 -> +// || || 7 | . . . . . . 5 4 |7 || || +// <= || 8 | . . . . . . 5 3 |8 <= || +// <= -> 9 | . . . . . . 6 3 |9 <= -> +// <- <- 10| . . . . . . *5/6 2 |10 <- <- +// -> -> 11| . . . . . . 6 *2/3 |11 -> -> +// --------------------------------------------------------- +// A B C D E F G H +// +// All these states are accessible without requiring any filter to +// change its behaviour but not all transitions are accessible, for +// instance a transition from state 4 to anywhere other than +// state 8 requires that the upstream filter first offer a R-O allocator +// and then changes its mind and offer R/W. This is NOT allowable - it +// leads to things like the output pin getting a R/W allocator from +// upstream and then the input pin being told it can only have a R-O one. +// Note that you CAN change (say) the upstream filter for a different one, but +// only as a disconnect / connect, not as a Reconnect. (Exercise for +// the reader is to see how you get into state 4). +// +// The reconnection stuff goes as follows (some of the cases shown here as +// "no reconnect" may get one to finalise media type - an old story). +// If there is a reconnect where it says "no reconnect" here then the +// reconnection must not change the allocator choice. +// +// state 2: <- 00 transition E <- <- case C <- <- (no change) +// case D -> <- and then to -> -> +// +// state 2: <- 00 transition F <- <- (no reconnect) +// +// state 3: <= 00 transition E <= -> case A <= -> (no change) +// case B -> -> +// transition F <= || case A <= || (no change) +// case B || || +// +// state 4: || 00 transition E || || case B -> || and then all cases to -> -> +// F || || case B || || (no change) +// +// state 5: 00 || transition A <= || (no reconnect) +// B || || (no reconnect) +// C <- || all cases <- <- +// D || || (unfortunate, but upstream's choice) +// +// state 6: 00 -> transition A <= -> (no reconnect) +// B -> -> (no reconnect) +// C <- -> all cases <- <- +// D -> -> (no reconnect) +// +// state 10:<- <- transition G 00 <- case E 00 -> +// case F 00 || +// +// state 11:-> -> transition H -> 00 case A <= 00 (schizo) +// case B <= 00 +// case C <- 00 (schizo) +// case D <- 00 +// +// The Rules: +// To sort out media types: +// The input is reconnected +// if the input pin is connected and the output pin connects +// The output is reconnected +// If the output pin is connected +// and the input pin connects to a different media type +// +// To sort out allocators: +// The input is reconnected +// if the output disconnects and the input was using a downstream allocator +// The output pin calls SetAllocator to pass on a new allocator +// if the output is connected and +// if the input disconnects and the output was using an upstream allocator +// if the input acquires an allocator different from the output one +// and that new allocator is not R-O +// +// Data is copied (i.e. call getbuffer and copy the data before transforming it) +// if the two allocators are different. + + + +// CHAINS of filters: +// +// We sit between two filters (call them A and Z). We should finish up +// with the same allocator on both of our pins and that should be the +// same one that A and Z would have agreed on if we hadn't been in the +// way. Furthermore, it should not matter how many in-place transforms +// are in the way. Let B, C, D... be in-place transforms ("us"). +// Here's how it goes: +// +// 1. +// A connects to B. They agree on A's allocator. +// A-a->B +// +// 2. +// B connects to C. Same story. There is no point in a reconnect, but +// B will request an input reconnect anyway. +// A-a->B-a->C +// +// 3. +// C connects to Z. +// C insists on using A's allocator, but compromises by requesting a reconnect. +// of C's input. +// A-a->B-?->C-a->Z +// +// We now have pending reconnects on both A--->B and B--->C +// +// 4. +// The A--->B link is reconnected. +// A asks B for an allocator. B sees that it has a downstream connection so +// asks its downstream input pin i.e. C's input pin for an allocator. C sees +// that it too has a downstream connection so asks Z for an allocator. +// +// Even though Z's input pin is connected, it is being asked for an allocator. +// It could refuse, in which case the chain is done and will use A's allocator +// Alternatively, Z may supply one. A chooses either Z's or A's own one. +// B's input pin gets NotifyAllocator called to tell it the decision and it +// propagates this downstream by calling ReceiveAllocator on its output pin +// which calls NotifyAllocator on the next input pin downstream etc. +// If the choice is Z then it goes: +// A-z->B-a->C-a->Z +// A-z->B-z->C-a->Z +// A-z->B-z->C-z->Z +// +// And that's IT!! Any further (essentially spurious) reconnects peter out +// with no change in the chain. + +#include +#include +#include + + +// ================================================================= +// Implements the CTransInPlaceFilter class +// ================================================================= + +CTransInPlaceFilter::CTransInPlaceFilter + ( TCHAR *pName, + LPUNKNOWN pUnk, + REFCLSID clsid, + HRESULT *phr, + bool bModifiesData + ) + : CTransformFilter(pName, pUnk, clsid), + m_bModifiesData(bModifiesData) +{ +#ifdef PERF + RegisterPerfId(); +#endif // PERF + +} // constructor + +#ifdef UNICODE +CTransInPlaceFilter::CTransInPlaceFilter + ( CHAR *pName, + LPUNKNOWN pUnk, + REFCLSID clsid, + HRESULT *phr, + bool bModifiesData + ) + : CTransformFilter(pName, pUnk, clsid), + m_bModifiesData(bModifiesData) +{ +#ifdef PERF + RegisterPerfId(); +#endif // PERF + +} // constructor +#endif + +// return a non-addrefed CBasePin * for the user to addref if he holds onto it +// for longer than his pointer to us. We create the pins dynamically when they +// are asked for rather than in the constructor. This is because we want to +// give the derived class an oppportunity to return different pin objects + +// As soon as any pin is needed we create both (this is different from the +// usual transform filter) because enumerators, allocators etc are passed +// through from one pin to another and it becomes very painful if the other +// pin isn't there. If we fail to create either pin we ensure we fail both. + +CBasePin * +CTransInPlaceFilter::GetPin(int n) +{ + HRESULT hr = S_OK; + + // Create an input pin if not already done + + if (m_pInput == NULL) { + + m_pInput = new CTransInPlaceInputPin( NAME("TransInPlace input pin") + , this // Owner filter + , &hr // Result code + , L"Input" // Pin name + ); + + // Constructor for CTransInPlaceInputPin can't fail + ASSERT(SUCCEEDED(hr)); + } + + // Create an output pin if not already done + + if (m_pInput!=NULL && m_pOutput == NULL) { + + m_pOutput = new CTransInPlaceOutputPin( NAME("TransInPlace output pin") + , this // Owner filter + , &hr // Result code + , L"Output" // Pin name + ); + + // a failed return code should delete the object + + ASSERT(SUCCEEDED(hr)); + if (m_pOutput == NULL) { + delete m_pInput; + m_pInput = NULL; + } + } + + // Return the appropriate pin + + ASSERT (n>=0 && n<=1); + if (n == 0) { + return m_pInput; + } else if (n==1) { + return m_pOutput; + } else { + return NULL; + } + +} // GetPin + + + +// dir is the direction of our pin. +// pReceivePin is the pin we are connecting to. +HRESULT CTransInPlaceFilter::CompleteConnect(PIN_DIRECTION dir,IPin *pReceivePin) +{ + UNREFERENCED_PARAMETER(pReceivePin); + ASSERT(m_pInput); + ASSERT(m_pOutput); + + // if we are not part of a graph, then don't indirect the pointer + // this probably prevents use of the filter without a filtergraph + if (!m_pGraph) { + return VFW_E_NOT_IN_GRAPH; + } + + // Always reconnect the input to account for buffering changes + // + // Because we don't get to suggest a type on ReceiveConnection + // we need another way of making sure the right type gets used. + // + // One way would be to have our EnumMediaTypes return our output + // connection type first but more deterministic and simple is to + // call ReconnectEx passing the type we want to reconnect with + // via the base class ReconeectPin method. + + if (dir == PINDIR_OUTPUT) { + if( m_pInput->IsConnected() ) { + return ReconnectPin( m_pInput, &m_pOutput->CurrentMediaType() ); + } + return NOERROR; + } + + ASSERT(dir == PINDIR_INPUT); + + // Reconnect output if necessary + + if( m_pOutput->IsConnected() ) { + + if ( m_pInput->CurrentMediaType() + != m_pOutput->CurrentMediaType() + ) { + return ReconnectPin( m_pOutput, &m_pInput->CurrentMediaType() ); + } + } + return NOERROR; + +} // ComnpleteConnect + + +// +// DecideBufferSize +// +// Tell the output pin's allocator what size buffers we require. +// *pAlloc will be the allocator our output pin is using. +// + +HRESULT CTransInPlaceFilter::DecideBufferSize + ( IMemAllocator *pAlloc + , ALLOCATOR_PROPERTIES *pProperties + ) +{ + ALLOCATOR_PROPERTIES Request, Actual; + HRESULT hr; + + // If we are connected upstream, get his views + if (m_pInput->IsConnected()) { + // Get the input pin allocator, and get its size and count. + // we don't care about his alignment and prefix. + + hr = InputPin()->PeekAllocator()->GetProperties(&Request); + if (FAILED(hr)) { + // Input connected but with a secretive allocator - enough! + return hr; + } + } else { + // We're reduced to blind guessing. Let's guess one byte and if + // this isn't enough then when the other pin does get connected + // we can revise it. + ZeroMemory(&Request, sizeof(Request)); + Request.cBuffers = 1; + Request.cbBuffer = 1; + } + + + DbgLog((LOG_MEMORY,1,TEXT("Setting Allocator Requirements"))); + DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d"), + Request.cBuffers, Request.cbBuffer)); + + // Pass the allocator requirements to our output side + // but do a little sanity checking first or we'll just hit + // asserts in the allocator. + + pProperties->cBuffers = Request.cBuffers; + pProperties->cbBuffer = Request.cbBuffer; + pProperties->cbAlign = Request.cbAlign; + if (pProperties->cBuffers<=0) {pProperties->cBuffers = 1; } + if (pProperties->cbBuffer<=0) {pProperties->cbBuffer = 1; } + hr = pAlloc->SetProperties(pProperties, &Actual); + + if (FAILED(hr)) { + return hr; + } + + DbgLog((LOG_MEMORY,1,TEXT("Obtained Allocator Requirements"))); + DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d, Alignment %d"), + Actual.cBuffers, Actual.cbBuffer, Actual.cbAlign)); + + // Make sure we got the right alignment and at least the minimum required + + if ( (Request.cBuffers > Actual.cBuffers) + || (Request.cbBuffer > Actual.cbBuffer) + || (Request.cbAlign > Actual.cbAlign) + ) { + return E_FAIL; + } + return NOERROR; + +} // DecideBufferSize + +// +// Copy +// +// return a pointer to an identical copy of pSample +IMediaSample * CTransInPlaceFilter::Copy(IMediaSample *pSource) +{ + IMediaSample * pDest; + + HRESULT hr; + REFERENCE_TIME tStart, tStop; + const BOOL bTime = S_OK == pSource->GetTime( &tStart, &tStop); + + // this may block for an indeterminate amount of time + hr = OutputPin()->PeekAllocator()->GetBuffer( + &pDest + , bTime ? &tStart : NULL + , bTime ? &tStop : NULL + , m_bSampleSkipped ? AM_GBF_PREVFRAMESKIPPED : 0 + ); + + if (FAILED(hr)) { + return NULL; + } + + ASSERT(pDest); + IMediaSample2 *pSample2; + if (SUCCEEDED(pDest->QueryInterface(IID_IMediaSample2, (void **)&pSample2))) { + HRESULT hr = pSample2->SetProperties( + FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, pbBuffer), + (PBYTE)m_pInput->SampleProps()); + pSample2->Release(); + if (FAILED(hr)) { + pDest->Release(); + return NULL; + } + } else { + if (bTime) { + pDest->SetTime(&tStart, &tStop); + } + + if (S_OK == pSource->IsSyncPoint()) { + pDest->SetSyncPoint(TRUE); + } + if (S_OK == pSource->IsDiscontinuity() || m_bSampleSkipped) { + pDest->SetDiscontinuity(TRUE); + } + if (S_OK == pSource->IsPreroll()) { + pDest->SetPreroll(TRUE); + } + + // Copy the media type + AM_MEDIA_TYPE *pMediaType; + if (S_OK == pSource->GetMediaType(&pMediaType)) { + pDest->SetMediaType(pMediaType); + DeleteMediaType( pMediaType ); + } + + } + + m_bSampleSkipped = FALSE; + + // Copy the sample media times + REFERENCE_TIME TimeStart, TimeEnd; + if (pSource->GetMediaTime(&TimeStart,&TimeEnd) == NOERROR) { + pDest->SetMediaTime(&TimeStart,&TimeEnd); + } + + // Copy the actual data length and the actual data. + { + const long lDataLength = pSource->GetActualDataLength(); + pDest->SetActualDataLength(lDataLength); + + // Copy the sample data + { + BYTE *pSourceBuffer, *pDestBuffer; + long lSourceSize = pSource->GetSize(); + long lDestSize = pDest->GetSize(); + + ASSERT(lDestSize >= lSourceSize && lDestSize >= lDataLength); + + pSource->GetPointer(&pSourceBuffer); + pDest->GetPointer(&pDestBuffer); + ASSERT(lDestSize == 0 || pSourceBuffer != NULL && pDestBuffer != NULL); + + CopyMemory( (PVOID) pDestBuffer, (PVOID) pSourceBuffer, lDataLength ); + } + } + + return pDest; + +} // Copy + + +// override this to customize the transform process + +HRESULT +CTransInPlaceFilter::Receive(IMediaSample *pSample) +{ + /* Check for other streams and pass them on */ + AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps(); + if (pProps->dwStreamId != AM_STREAM_MEDIA) { + return m_pOutput->Deliver(pSample); + } + HRESULT hr; + + // Start timing the TransInPlace (if PERF is defined) + MSR_START(m_idTransInPlace); + + if (UsingDifferentAllocators()) { + + // We have to copy the data. + + pSample = Copy(pSample); + + if (pSample==NULL) { + MSR_STOP(m_idTransInPlace); + return E_UNEXPECTED; + } + } + + // have the derived class transform the data + hr = Transform(pSample); + + // Stop the clock and log it (if PERF is defined) + MSR_STOP(m_idTransInPlace); + + if (FAILED(hr)) { + DbgLog((LOG_TRACE, 1, TEXT("Error from TransInPlace"))); + if (UsingDifferentAllocators()) { + pSample->Release(); + } + return hr; + } + + // the Transform() function can return S_FALSE to indicate that the + // sample should not be delivered; we only deliver the sample if it's + // really S_OK (same as NOERROR, of course.) + if (hr == NOERROR) { + hr = m_pOutput->Deliver(pSample); + } else { + // But it would be an error to return this private workaround + // to the caller ... + if (S_FALSE == hr) { + // S_FALSE returned from Transform is a PRIVATE agreement + // We should return NOERROR from Receive() in this cause because + // returning S_FALSE from Receive() means that this is the end + // of the stream and no more data should be sent. + m_bSampleSkipped = TRUE; + if (!m_bQualityChanged) { + NotifyEvent(EC_QUALITY_CHANGE,0,0); + m_bQualityChanged = TRUE; + } + hr = NOERROR; + } + } + + // release the output buffer. If the connected pin still needs it, + // it will have addrefed it itself. + if (UsingDifferentAllocators()) { + pSample->Release(); + } + + return hr; + +} // Receive + + + +// ================================================================= +// Implements the CTransInPlaceInputPin class +// ================================================================= + + +// constructor + +CTransInPlaceInputPin::CTransInPlaceInputPin + ( TCHAR *pObjectName + , CTransInPlaceFilter *pFilter + , HRESULT *phr + , LPCWSTR pName + ) + : CTransformInputPin(pObjectName, + pFilter, + phr, + pName) + , m_bReadOnly(FALSE) + , m_pTIPFilter(pFilter) +{ + DbgLog((LOG_TRACE, 2 + , TEXT("CTransInPlaceInputPin::CTransInPlaceInputPin"))); + +} // constructor + + +// ================================================================= +// Implements IMemInputPin interface +// ================================================================= + + +// If the downstream filter has one then offer that (even if our own output +// pin is not using it yet. If the upstream filter chooses it then we will +// tell our output pin to ReceiveAllocator). +// Else if our output pin is using an allocator then offer that. +// ( This could mean offering the upstream filter his own allocator, +// it could mean offerring our own +// ) or it could mean offering the one from downstream +// Else fail to offer any allocator at all. + +STDMETHODIMP CTransInPlaceInputPin::GetAllocator(IMemAllocator ** ppAllocator) +{ + CheckPointer(ppAllocator,E_POINTER); + ValidateReadWritePtr(ppAllocator,sizeof(IMemAllocator *)); + CAutoLock cObjectLock(m_pLock); + + HRESULT hr; + + if ( m_pTIPFilter->m_pOutput->IsConnected() ) { + // Store the allocator we got + hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin() + ->GetAllocator( ppAllocator ); + if (SUCCEEDED(hr)) { + m_pTIPFilter->OutputPin()->SetAllocator( *ppAllocator ); + } + } + else { + // Help upstream filter (eg TIP filter which is having to do a copy) + // by providing a temp allocator here - we'll never use + // this allocator because when our output is connected we'll + // reconnect this pin + hr = CTransformInputPin::GetAllocator( ppAllocator ); + } + return hr; + +} // GetAllocator + + + +/* Get told which allocator the upstream output pin is actually going to use */ + + +STDMETHODIMP +CTransInPlaceInputPin::NotifyAllocator( + IMemAllocator * pAllocator, + BOOL bReadOnly) +{ + HRESULT hr = S_OK; + CheckPointer(pAllocator,E_POINTER); + ValidateReadPtr(pAllocator,sizeof(IMemAllocator)); + + CAutoLock cObjectLock(m_pLock); + + m_bReadOnly = bReadOnly; + // If we modify data then don't accept the allocator if it's + // the same as the output pin's allocator + + // If our output is not connected just accept the allocator + // We're never going to use this allocator because when our + // output pin is connected we'll reconnect this pin + if (!m_pTIPFilter->OutputPin()->IsConnected()) { + return CTransformInputPin::NotifyAllocator(pAllocator, bReadOnly); + } + + // If the allocator is read-only and we're modifying data + // and the allocator is the same as the output pin's + // then reject + if (bReadOnly && m_pTIPFilter->m_bModifiesData) { + IMemAllocator *pOutputAllocator = + m_pTIPFilter->OutputPin()->PeekAllocator(); + + // Make sure we have an output allocator + if (pOutputAllocator == NULL) { + hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()-> + GetAllocator(&pOutputAllocator); + if(FAILED(hr)) { + hr = CreateMemoryAllocator(&pOutputAllocator); + } + if (SUCCEEDED(hr)) { + m_pTIPFilter->OutputPin()->SetAllocator(pOutputAllocator); + pOutputAllocator->Release(); + } + } + if (pAllocator == pOutputAllocator) { + hr = E_FAIL; + } else if(SUCCEEDED(hr)) { + // Must copy so set the allocator properties on the output + ALLOCATOR_PROPERTIES Props, Actual; + hr = pAllocator->GetProperties(&Props); + if (SUCCEEDED(hr)) { + hr = pOutputAllocator->SetProperties(&Props, &Actual); + } + if (SUCCEEDED(hr)) { + if ( (Props.cBuffers > Actual.cBuffers) + || (Props.cbBuffer > Actual.cbBuffer) + || (Props.cbAlign > Actual.cbAlign) + ) { + hr = E_FAIL; + } + } + + // Set the allocator on the output pin + if (SUCCEEDED(hr)) { + hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin() + ->NotifyAllocator( pOutputAllocator, FALSE ); + } + } + } else { + hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin() + ->NotifyAllocator( pAllocator, bReadOnly ); + if (SUCCEEDED(hr)) { + m_pTIPFilter->OutputPin()->SetAllocator( pAllocator ); + } + } + + if (SUCCEEDED(hr)) { + + // It's possible that the old and the new are the same thing. + // AddRef before release ensures that we don't unload it. + pAllocator->AddRef(); + + if( m_pAllocator != NULL ) + m_pAllocator->Release(); + + m_pAllocator = pAllocator; // We have an allocator for the input pin + } + + return hr; + +} // NotifyAllocator + + +// EnumMediaTypes +// - pass through to our downstream filter +STDMETHODIMP CTransInPlaceInputPin::EnumMediaTypes( IEnumMediaTypes **ppEnum ) +{ + // Can only pass through if connected + if( !m_pTIPFilter->m_pOutput->IsConnected() ) + return VFW_E_NOT_CONNECTED; + + return m_pTIPFilter->m_pOutput->GetConnected()->EnumMediaTypes( ppEnum ); + +} // EnumMediaTypes + + +// CheckMediaType +// - agree to anything if not connected, +// otherwise pass through to the downstream filter. +// This assumes that the filter does not change the media type. + +HRESULT CTransInPlaceInputPin::CheckMediaType(const CMediaType *pmt ) +{ + HRESULT hr = m_pTIPFilter->CheckInputType(pmt); + if (hr!=S_OK) return hr; + + if( m_pTIPFilter->m_pOutput->IsConnected() ) + return m_pTIPFilter->m_pOutput->GetConnected()->QueryAccept( pmt ); + else + return S_OK; + +} // CheckMediaType + + +// If upstream asks us what our requirements are, we will try to ask downstream +// if that doesn't work, we'll just take the defaults. +STDMETHODIMP +CTransInPlaceInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps) +{ + + if( m_pTIPFilter->m_pOutput->IsConnected() ) + return m_pTIPFilter->OutputPin() + ->ConnectedIMemInputPin()->GetAllocatorRequirements( pProps ); + else + return E_NOTIMPL; + +} // GetAllocatorRequirements + + +// CTransInPlaceInputPin::CompleteConnect() calls CBaseInputPin::CompleteConnect() +// and then calls CTransInPlaceFilter::CompleteConnect(). It does this because +// CTransInPlaceFilter::CompleteConnect() can reconnect a pin and we do not +// want to reconnect a pin if CBaseInputPin::CompleteConnect() fails. +HRESULT +CTransInPlaceInputPin::CompleteConnect(IPin *pReceivePin) +{ + HRESULT hr = CBaseInputPin::CompleteConnect(pReceivePin); + if (FAILED(hr)) { + return hr; + } + + return m_pTransformFilter->CompleteConnect(PINDIR_INPUT,pReceivePin); +} // CompleteConnect + + +// ================================================================= +// Implements the CTransInPlaceOutputPin class +// ================================================================= + + +// constructor + +CTransInPlaceOutputPin::CTransInPlaceOutputPin( + TCHAR *pObjectName, + CTransInPlaceFilter *pFilter, + HRESULT * phr, + LPCWSTR pPinName) + : CTransformOutputPin( pObjectName + , pFilter + , phr + , pPinName), + m_pTIPFilter(pFilter) +{ + DbgLog(( LOG_TRACE, 2 + , TEXT("CTransInPlaceOutputPin::CTransInPlaceOutputPin"))); + +} // constructor + + +// EnumMediaTypes +// - pass through to our upstream filter +STDMETHODIMP CTransInPlaceOutputPin::EnumMediaTypes( IEnumMediaTypes **ppEnum ) +{ + // Can only pass through if connected. + if( ! m_pTIPFilter->m_pInput->IsConnected() ) + return VFW_E_NOT_CONNECTED; + + return m_pTIPFilter->m_pInput->GetConnected()->EnumMediaTypes( ppEnum ); + +} // EnumMediaTypes + + + +// CheckMediaType +// - agree to anything if not connected, +// otherwise pass through to the upstream filter. + +HRESULT CTransInPlaceOutputPin::CheckMediaType(const CMediaType *pmt ) +{ + // Don't accept any output pin type changes if we're copying + // between allocators - it's too late to change the input + // allocator size. + if (m_pTIPFilter->UsingDifferentAllocators() && !m_pFilter->IsStopped()) { + if (*pmt == m_mt) { + return S_OK; + } else { + return VFW_E_TYPE_NOT_ACCEPTED; + } + } + + // Assumes the type does not change. That's why we're calling + // CheckINPUTType here on the OUTPUT pin. + HRESULT hr = m_pTIPFilter->CheckInputType(pmt); + if (hr!=S_OK) return hr; + + if( m_pTIPFilter->m_pInput->IsConnected() ) + return m_pTIPFilter->m_pInput->GetConnected()->QueryAccept( pmt ); + else + return S_OK; + +} // CheckMediaType + + +/* Save the allocator pointer in the output pin +*/ +void +CTransInPlaceOutputPin::SetAllocator(IMemAllocator * pAllocator) +{ + pAllocator->AddRef(); + if (m_pAllocator) { + m_pAllocator->Release(); + } + m_pAllocator = pAllocator; +} // SetAllocator + + +// CTransInPlaceOutputPin::CompleteConnect() calls CBaseOutputPin::CompleteConnect() +// and then calls CTransInPlaceFilter::CompleteConnect(). It does this because +// CTransInPlaceFilter::CompleteConnect() can reconnect a pin and we do not want to +// reconnect a pin if CBaseOutputPin::CompleteConnect() fails. +// CBaseOutputPin::CompleteConnect() often fails when our output pin is being connected +// to the Video Mixing Renderer. +HRESULT +CTransInPlaceOutputPin::CompleteConnect(IPin *pReceivePin) +{ + HRESULT hr = CBaseOutputPin::CompleteConnect(pReceivePin); + if (FAILED(hr)) { + return hr; + } + + return m_pTransformFilter->CompleteConnect(PINDIR_OUTPUT,pReceivePin); +} // CompleteConnect diff --git a/ThirdParty/strmbas/transip.h b/ThirdParty/strmbas/transip.h new file mode 100644 index 0000000..4945f62 --- /dev/null +++ b/ThirdParty/strmbas/transip.h @@ -0,0 +1,250 @@ +//------------------------------------------------------------------------------ +// File: TransIP.h +// +// Desc: DirectShow base classes - defines classes from which simple +// Transform-In-Place filters may be derived. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +// +// The difference between this and Transfrm.h is that Transfrm copies the data. +// +// It assumes the filter has one input and one output stream, and has no +// interest in memory management, interface negotiation or anything else. +// +// Derive your class from this, and supply Transform and the media type/format +// negotiation functions. Implement that class, compile and link and +// you're done. + + +#ifndef __TRANSIP__ +#define __TRANSIP__ + +// ====================================================================== +// This is the com object that represents a simple transform filter. It +// supports IBaseFilter, IMediaFilter and two pins through nested interfaces +// ====================================================================== + +class CTransInPlaceFilter; + +// Several of the pin functions call filter functions to do the work, +// so you can often use the pin classes unaltered, just overriding the +// functions in CTransInPlaceFilter. If that's not enough and you want +// to derive your own pin class, override GetPin in the filter to supply +// your own pin classes to the filter. + +// ================================================== +// Implements the input pin +// ================================================== + +class CTransInPlaceInputPin : public CTransformInputPin +{ + +protected: + CTransInPlaceFilter * const m_pTIPFilter; // our filter + BOOL m_bReadOnly; // incoming stream is read only + +public: + + CTransInPlaceInputPin( + TCHAR *pObjectName, + CTransInPlaceFilter *pFilter, + HRESULT *phr, + LPCWSTR pName); + + // --- IMemInputPin ----- + + // Provide an enumerator for media types by getting one from downstream + STDMETHODIMP EnumMediaTypes( IEnumMediaTypes **ppEnum ); + + // Say whether media type is acceptable. + HRESULT CheckMediaType(const CMediaType* pmt); + + // Return our upstream allocator + STDMETHODIMP GetAllocator(IMemAllocator ** ppAllocator); + + // get told which allocator the upstream output pin is actually + // going to use. + STDMETHODIMP NotifyAllocator(IMemAllocator * pAllocator, + BOOL bReadOnly); + + // Allow the filter to see what allocator we have + // N.B. This does NOT AddRef + IMemAllocator * PeekAllocator() const + { return m_pAllocator; } + + // Pass this on downstream if it ever gets called. + STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps); + + HRESULT CompleteConnect(IPin *pReceivePin); + + inline const BOOL ReadOnly() { return m_bReadOnly ; } + +}; // CTransInPlaceInputPin + +// ================================================== +// Implements the output pin +// ================================================== + +class CTransInPlaceOutputPin : public CTransformOutputPin +{ + +protected: + // m_pFilter points to our CBaseFilter + CTransInPlaceFilter * const m_pTIPFilter; + +public: + + CTransInPlaceOutputPin( + TCHAR *pObjectName, + CTransInPlaceFilter *pFilter, + HRESULT *phr, + LPCWSTR pName); + + + // --- CBaseOutputPin ------------ + + // negotiate the allocator and its buffer size/count + // Insists on using our own allocator. (Actually the one upstream of us). + // We don't override this - instead we just agree the default + // then let the upstream filter decide for itself on reconnect + // virtual HRESULT DecideAllocator(IMemInputPin * pPin, IMemAllocator ** pAlloc); + + // Provide a media type enumerator. Get it from upstream. + STDMETHODIMP EnumMediaTypes( IEnumMediaTypes **ppEnum ); + + // Say whether media type is acceptable. + HRESULT CheckMediaType(const CMediaType* pmt); + + // This just saves the allocator being used on the output pin + // Also called by input pin's GetAllocator() + void SetAllocator(IMemAllocator * pAllocator); + + IMemInputPin * ConnectedIMemInputPin() + { return m_pInputPin; } + + // Allow the filter to see what allocator we have + // N.B. This does NOT AddRef + IMemAllocator * PeekAllocator() const + { return m_pAllocator; } + + HRESULT CompleteConnect(IPin *pReceivePin); + +}; // CTransInPlaceOutputPin + + +class AM_NOVTABLE CTransInPlaceFilter : public CTransformFilter +{ + +public: + + // map getpin/getpincount for base enum of pins to owner + // override this to return more specialised pin objects + + virtual CBasePin *GetPin(int n); + +public: + + // Set bModifiesData == false if your derived filter does + // not modify the data samples (for instance it's just copying + // them somewhere else or looking at the timestamps). + + CTransInPlaceFilter(TCHAR *, LPUNKNOWN, REFCLSID clsid, HRESULT *, + bool bModifiesData = true); +#ifdef UNICODE + CTransInPlaceFilter(CHAR *, LPUNKNOWN, REFCLSID clsid, HRESULT *, + bool bModifiesData = true); +#endif + // The following are defined to avoid undefined pure virtuals. + // Even if they are never called, they will give linkage warnings/errors + + // We override EnumMediaTypes to bypass the transform class enumerator + // which would otherwise call this. + HRESULT GetMediaType(int iPosition, CMediaType *pMediaType) + { DbgBreak("CTransInPlaceFilter::GetMediaType should never be called"); + return E_UNEXPECTED; + } + + // This is called when we actually have to provide out own allocator. + HRESULT DecideBufferSize(IMemAllocator*, ALLOCATOR_PROPERTIES *); + + // The functions which call this in CTransform are overridden in this + // class to call CheckInputType with the assumption that the type + // does not change. In Debug builds some calls will be made and + // we just ensure that they do not assert. + HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut) + { + return S_OK; + }; + + + // ================================================================= + // ----- You may want to override this ----------------------------- + // ================================================================= + + HRESULT CompleteConnect(PIN_DIRECTION dir,IPin *pReceivePin); + + // chance to customize the transform process + virtual HRESULT Receive(IMediaSample *pSample); + + // ================================================================= + // ----- You MUST override these ----------------------------------- + // ================================================================= + + virtual HRESULT Transform(IMediaSample *pSample) PURE; + + // this goes in the factory template table to create new instances + // static CCOMObject * CreateInstance(LPUNKNOWN, HRESULT *); + + +#ifdef PERF + // Override to register performance measurement with a less generic string + // You should do this to avoid confusion with other filters + virtual void RegisterPerfId() + {m_idTransInPlace = MSR_REGISTER(TEXT("TransInPlace"));} +#endif // PERF + + +// implementation details + +protected: + + IMediaSample * CTransInPlaceFilter::Copy(IMediaSample *pSource); + +#ifdef PERF + int m_idTransInPlace; // performance measuring id +#endif // PERF + bool m_bModifiesData; // Does this filter change the data? + + // these hold our input and output pins + + friend class CTransInPlaceInputPin; + friend class CTransInPlaceOutputPin; + + CTransInPlaceInputPin *InputPin() const + { + return (CTransInPlaceInputPin *)m_pInput; + }; + CTransInPlaceOutputPin *OutputPin() const + { + return (CTransInPlaceOutputPin *)m_pOutput; + }; + + // Helper to see if the input and output types match + BOOL TypesMatch() + { + return InputPin()->CurrentMediaType() == + OutputPin()->CurrentMediaType(); + } + + // Are the input and output allocators different? + BOOL UsingDifferentAllocators() const + { + return InputPin()->PeekAllocator() != OutputPin()->PeekAllocator(); + } +}; // CTransInPlaceFilter + +#endif /* __TRANSIP__ */ + diff --git a/ThirdParty/strmbas/videoctl.cpp b/ThirdParty/strmbas/videoctl.cpp new file mode 100644 index 0000000..c60c94f --- /dev/null +++ b/ThirdParty/strmbas/videoctl.cpp @@ -0,0 +1,715 @@ +//------------------------------------------------------------------------------ +// File: VideoCtl.cpp +// +// Desc: DirectShow base classes. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +#include +#include "ddmm.h" + +// Load a string from the resource file string table. The buffer must be at +// least STR_MAX_LENGTH bytes. The easiest way to use this is to declare a +// buffer in the property page class and use it for all string loading. It +// cannot be static as multiple property pages may be active simultaneously + +TCHAR *WINAPI StringFromResource(TCHAR *pBuffer, int iResourceID) +{ + if (LoadString(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) { + return TEXT(""); + } + return pBuffer; +} + +#ifdef UNICODE +char *WINAPI StringFromResource(char *pBuffer, int iResourceID) +{ + if (LoadStringA(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) { + return ""; + } + return pBuffer; +} +#endif + + + +// Property pages typically are called through their OLE interfaces. These +// use UNICODE strings regardless of how the binary is built. So when we +// load strings from the resource file we sometimes want to convert them +// to UNICODE. This method is passed the target UNICODE buffer and does a +// convert after loading the string (if built UNICODE this is not needed) +// On WinNT we can explicitly call LoadStringW which saves two conversions + +#ifndef UNICODE + +WCHAR * WINAPI WideStringFromResource(WCHAR *pBuffer, int iResourceID) +{ + *pBuffer = 0; + + if (g_amPlatform == VER_PLATFORM_WIN32_NT) { + LoadStringW(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH); + } else { + + CHAR szBuffer[STR_MAX_LENGTH]; + DWORD dwStringLength = LoadString(g_hInst,iResourceID,szBuffer,STR_MAX_LENGTH); + // if we loaded a string convert it to wide characters, ensuring + // that we also null terminate the result. + if (dwStringLength++) { + MultiByteToWideChar(CP_ACP,0,szBuffer,dwStringLength,pBuffer,STR_MAX_LENGTH); + } + } + return pBuffer; +} + +#endif + + +// Helper function to calculate the size of the dialog + +BOOL WINAPI GetDialogSize(int iResourceID, + DLGPROC pDlgProc, + LPARAM lParam, + SIZE *pResult) +{ + RECT rc; + HWND hwnd; + + // Create a temporary property page + + hwnd = CreateDialogParam(g_hInst, + MAKEINTRESOURCE(iResourceID), + GetDesktopWindow(), + pDlgProc, + lParam); + if (hwnd == NULL) { + return FALSE; + } + + GetWindowRect(hwnd, &rc); + pResult->cx = rc.right - rc.left; + pResult->cy = rc.bottom - rc.top; + + DestroyWindow(hwnd); + return TRUE; +} + + +// Class that aggregates on the IDirectDraw interface. Although DirectDraw +// has the ability in its interfaces to be aggregated they're not currently +// implemented. This makes it difficult for various parts of Quartz that want +// to aggregate these interfaces. In particular the video renderer passes out +// media samples that expose IDirectDraw and IDirectDrawSurface. The filter +// graph manager also exposes IDirectDraw as a plug in distributor. For these +// objects we provide these aggregation classes that republish the interfaces + +STDMETHODIMP CAggDirectDraw::NonDelegatingQueryInterface(REFIID riid, void **ppv) +{ + ASSERT(m_pDirectDraw); + + // Do we have this interface + + if (riid == IID_IDirectDraw) { + return GetInterface((IDirectDraw *)this,ppv); + } else { + return CUnknown::NonDelegatingQueryInterface(riid,ppv); + } +} + + +STDMETHODIMP CAggDirectDraw::Compact() +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->Compact(); +} + + +STDMETHODIMP CAggDirectDraw::CreateClipper(DWORD dwFlags,LPDIRECTDRAWCLIPPER *lplpDDClipper,IUnknown *pUnkOuter) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->CreateClipper(dwFlags,lplpDDClipper,pUnkOuter); +} + + +STDMETHODIMP CAggDirectDraw::CreatePalette(DWORD dwFlags,LPPALETTEENTRY lpColorTable,LPDIRECTDRAWPALETTE *lplpDDPalette,IUnknown *pUnkOuter) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->CreatePalette(dwFlags,lpColorTable,lplpDDPalette,pUnkOuter); +} + + +STDMETHODIMP CAggDirectDraw::CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc,LPDIRECTDRAWSURFACE *lplpDDSurface,IUnknown *pUnkOuter) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->CreateSurface(lpDDSurfaceDesc,lplpDDSurface,pUnkOuter); +} + + +STDMETHODIMP CAggDirectDraw::DuplicateSurface(LPDIRECTDRAWSURFACE lpDDSurface,LPDIRECTDRAWSURFACE *lplpDupDDSurface) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->DuplicateSurface(lpDDSurface,lplpDupDDSurface); +} + + +STDMETHODIMP CAggDirectDraw::EnumDisplayModes(DWORD dwSurfaceDescCount,LPDDSURFACEDESC lplpDDSurfaceDescList,LPVOID lpContext,LPDDENUMMODESCALLBACK lpEnumCallback) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->EnumDisplayModes(dwSurfaceDescCount,lplpDDSurfaceDescList,lpContext,lpEnumCallback); +} + + +STDMETHODIMP CAggDirectDraw::EnumSurfaces(DWORD dwFlags,LPDDSURFACEDESC lpDDSD,LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpEnumCallback) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->EnumSurfaces(dwFlags,lpDDSD,lpContext,lpEnumCallback); +} + + +STDMETHODIMP CAggDirectDraw::FlipToGDISurface() +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->FlipToGDISurface(); +} + + +STDMETHODIMP CAggDirectDraw::GetCaps(LPDDCAPS lpDDDriverCaps,LPDDCAPS lpDDHELCaps) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->GetCaps(lpDDDriverCaps,lpDDHELCaps); +} + + +STDMETHODIMP CAggDirectDraw::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->GetDisplayMode(lpDDSurfaceDesc); +} + + +STDMETHODIMP CAggDirectDraw::GetFourCCCodes(LPDWORD lpNumCodes,LPDWORD lpCodes) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->GetFourCCCodes(lpNumCodes,lpCodes); +} + + +STDMETHODIMP CAggDirectDraw::GetGDISurface(LPDIRECTDRAWSURFACE *lplpGDIDDSurface) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->GetGDISurface(lplpGDIDDSurface); +} + + +STDMETHODIMP CAggDirectDraw::GetMonitorFrequency(LPDWORD lpdwFrequency) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->GetMonitorFrequency(lpdwFrequency); +} + + +STDMETHODIMP CAggDirectDraw::GetScanLine(LPDWORD lpdwScanLine) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->GetScanLine(lpdwScanLine); +} + + +STDMETHODIMP CAggDirectDraw::GetVerticalBlankStatus(LPBOOL lpblsInVB) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->GetVerticalBlankStatus(lpblsInVB); +} + + +STDMETHODIMP CAggDirectDraw::Initialize(GUID *lpGUID) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->Initialize(lpGUID); +} + + +STDMETHODIMP CAggDirectDraw::RestoreDisplayMode() +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->RestoreDisplayMode(); +} + + +STDMETHODIMP CAggDirectDraw::SetCooperativeLevel(HWND hWnd,DWORD dwFlags) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->SetCooperativeLevel(hWnd,dwFlags); +} + + +STDMETHODIMP CAggDirectDraw::SetDisplayMode(DWORD dwWidth,DWORD dwHeight,DWORD dwBpp) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->SetDisplayMode(dwWidth,dwHeight,dwBpp); +} + + +STDMETHODIMP CAggDirectDraw::WaitForVerticalBlank(DWORD dwFlags,HANDLE hEvent) +{ + ASSERT(m_pDirectDraw); + return m_pDirectDraw->WaitForVerticalBlank(dwFlags,hEvent); +} + + +// Class that aggregates an IDirectDrawSurface interface. Although DirectDraw +// has the ability in its interfaces to be aggregated they're not currently +// implemented. This makes it difficult for various parts of Quartz that want +// to aggregate these interfaces. In particular the video renderer passes out +// media samples that expose IDirectDraw and IDirectDrawSurface. The filter +// graph manager also exposes IDirectDraw as a plug in distributor. For these +// objects we provide these aggregation classes that republish the interfaces + +STDMETHODIMP CAggDrawSurface::NonDelegatingQueryInterface(REFIID riid, void **ppv) +{ + ASSERT(m_pDirectDrawSurface); + + // Do we have this interface + + if (riid == IID_IDirectDrawSurface) { + return GetInterface((IDirectDrawSurface *)this,ppv); + } else { + return CUnknown::NonDelegatingQueryInterface(riid,ppv); + } +} + + +STDMETHODIMP CAggDrawSurface::AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->AddAttachedSurface(lpDDSAttachedSurface); +} + + +STDMETHODIMP CAggDrawSurface::AddOverlayDirtyRect(LPRECT lpRect) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->AddOverlayDirtyRect(lpRect); +} + + +STDMETHODIMP CAggDrawSurface::Blt(LPRECT lpDestRect,LPDIRECTDRAWSURFACE lpDDSrcSurface,LPRECT lpSrcRect,DWORD dwFlags,LPDDBLTFX lpDDBltFx) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->Blt(lpDestRect,lpDDSrcSurface,lpSrcRect,dwFlags,lpDDBltFx); +} + + +STDMETHODIMP CAggDrawSurface::BltBatch(LPDDBLTBATCH lpDDBltBatch,DWORD dwCount,DWORD dwFlags) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->BltBatch(lpDDBltBatch,dwCount,dwFlags); +} + + +STDMETHODIMP CAggDrawSurface::BltFast(DWORD dwX,DWORD dwY,LPDIRECTDRAWSURFACE lpDDSrcSurface,LPRECT lpSrcRect,DWORD dwTrans) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->BltFast(dwX,dwY,lpDDSrcSurface,lpSrcRect,dwTrans); +} + + +STDMETHODIMP CAggDrawSurface::DeleteAttachedSurface(DWORD dwFlags,LPDIRECTDRAWSURFACE lpDDSAttachedSurface) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->DeleteAttachedSurface(dwFlags,lpDDSAttachedSurface); +} + + +STDMETHODIMP CAggDrawSurface::EnumAttachedSurfaces(LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->EnumAttachedSurfaces(lpContext,lpEnumSurfacesCallback); +} + + +STDMETHODIMP CAggDrawSurface::EnumOverlayZOrders(DWORD dwFlags,LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpfnCallback) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->EnumOverlayZOrders(dwFlags,lpContext,lpfnCallback); +} + + +STDMETHODIMP CAggDrawSurface::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride,DWORD dwFlags) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->Flip(lpDDSurfaceTargetOverride,dwFlags); +} + + +STDMETHODIMP CAggDrawSurface::GetAttachedSurface(LPDDSCAPS lpDDSCaps,LPDIRECTDRAWSURFACE *lplpDDAttachedSurface) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->GetAttachedSurface(lpDDSCaps,lplpDDAttachedSurface); +} + + +STDMETHODIMP CAggDrawSurface::GetBltStatus(DWORD dwFlags) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->GetBltStatus(dwFlags); +} + + +STDMETHODIMP CAggDrawSurface::GetCaps(LPDDSCAPS lpDDSCaps) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->GetCaps(lpDDSCaps); +} + + +STDMETHODIMP CAggDrawSurface::GetClipper(LPDIRECTDRAWCLIPPER *lplpDDClipper) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->GetClipper(lplpDDClipper); +} + + +STDMETHODIMP CAggDrawSurface::GetColorKey(DWORD dwFlags,LPDDCOLORKEY lpDDColorKey) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->GetColorKey(dwFlags,lpDDColorKey); +} + + +STDMETHODIMP CAggDrawSurface::GetDC(HDC *lphDC) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->GetDC(lphDC); +} + + +STDMETHODIMP CAggDrawSurface::GetFlipStatus(DWORD dwFlags) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->GetFlipStatus(dwFlags); +} + + +STDMETHODIMP CAggDrawSurface::GetOverlayPosition(LPLONG lpdwX,LPLONG lpdwY) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->GetOverlayPosition(lpdwX,lpdwY); +} + + +STDMETHODIMP CAggDrawSurface::GetPalette(LPDIRECTDRAWPALETTE *lplpDDPalette) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->GetPalette(lplpDDPalette); +} + + +STDMETHODIMP CAggDrawSurface::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->GetPixelFormat(lpDDPixelFormat); +} + + +// A bit of a warning here: Our media samples in DirectShow aggregate on +// IDirectDraw and IDirectDrawSurface (ie are available through IMediaSample +// by QueryInterface). Unfortunately the underlying DirectDraw code cannot +// be aggregated so we have to use these classes. The snag is that when we +// call a different surface and pass in this interface as perhaps the source +// surface the call will fail because DirectDraw dereferences the pointer to +// get at its private data structures. Therefore we supply this workaround to give +// access to the real IDirectDraw surface. A filter can call GetSurfaceDesc +// and we will fill in the lpSurface pointer with the real underlying surface + +STDMETHODIMP CAggDrawSurface::GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc) +{ + ASSERT(m_pDirectDrawSurface); + + // First call down to the underlying DirectDraw + + HRESULT hr = m_pDirectDrawSurface->GetSurfaceDesc(lpDDSurfaceDesc); + if (FAILED(hr)) { + return hr; + } + + // Store the real DirectDrawSurface interface + lpDDSurfaceDesc->lpSurface = m_pDirectDrawSurface; + return hr; +} + + +STDMETHODIMP CAggDrawSurface::Initialize(LPDIRECTDRAW lpDD,LPDDSURFACEDESC lpDDSurfaceDesc) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->Initialize(lpDD,lpDDSurfaceDesc); +} + + +STDMETHODIMP CAggDrawSurface::IsLost() +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->IsLost(); +} + + +STDMETHODIMP CAggDrawSurface::Lock(LPRECT lpDestRect,LPDDSURFACEDESC lpDDSurfaceDesc,DWORD dwFlags,HANDLE hEvent) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->Lock(lpDestRect,lpDDSurfaceDesc,dwFlags,hEvent); +} + + +STDMETHODIMP CAggDrawSurface::ReleaseDC(HDC hDC) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->ReleaseDC(hDC); +} + + +STDMETHODIMP CAggDrawSurface::Restore() +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->Restore(); +} + + +STDMETHODIMP CAggDrawSurface::SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->SetClipper(lpDDClipper); +} + + +STDMETHODIMP CAggDrawSurface::SetColorKey(DWORD dwFlags,LPDDCOLORKEY lpDDColorKey) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->SetColorKey(dwFlags,lpDDColorKey); +} + + +STDMETHODIMP CAggDrawSurface::SetOverlayPosition(LONG dwX,LONG dwY) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->SetOverlayPosition(dwX,dwY); +} + + +STDMETHODIMP CAggDrawSurface::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->SetPalette(lpDDPalette); +} + + +STDMETHODIMP CAggDrawSurface::Unlock(LPVOID lpSurfaceData) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->Unlock(lpSurfaceData); +} + + +STDMETHODIMP CAggDrawSurface::UpdateOverlay(LPRECT lpSrcRect,LPDIRECTDRAWSURFACE lpDDDestSurface,LPRECT lpDestRect,DWORD dwFlags,LPDDOVERLAYFX lpDDOverlayFX) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->UpdateOverlay(lpSrcRect,lpDDDestSurface,lpDestRect,dwFlags,lpDDOverlayFX); +} + + +STDMETHODIMP CAggDrawSurface::UpdateOverlayDisplay(DWORD dwFlags) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->UpdateOverlayDisplay(dwFlags); +} + + +STDMETHODIMP CAggDrawSurface::UpdateOverlayZOrder(DWORD dwFlags,LPDIRECTDRAWSURFACE lpDDSReference) +{ + ASSERT(m_pDirectDrawSurface); + return m_pDirectDrawSurface->UpdateOverlayZOrder(dwFlags,lpDDSReference); +} + + +// DirectShow must work on multiple platforms. In particular, it also runs on +// Windows NT 3.51 which does not have DirectDraw capabilities. The filters +// cannot therefore link statically to the DirectDraw library. To make their +// lives that little bit easier we provide this class that manages loading +// and unloading the library and creating the initial IDirectDraw interface + +CLoadDirectDraw::CLoadDirectDraw() : + m_pDirectDraw(NULL), + m_hDirectDraw(NULL) +{ +} + + +// Destructor forces unload + +CLoadDirectDraw::~CLoadDirectDraw() +{ + ReleaseDirectDraw(); + + if (m_hDirectDraw) { + NOTE("Unloading library"); + FreeLibrary(m_hDirectDraw); + } +} + + +// We can't be sure that DirectDraw is always available so we can't statically +// link to the library. Therefore we load the library, get the function entry +// point addresses and call them to create the driver objects. We return S_OK +// if we manage to load DirectDraw correctly otherwise we return E_NOINTERFACE +// We initialise a DirectDraw instance by explicitely loading the library and +// calling GetProcAddress on the DirectDrawCreate entry point that it exports + +// On a multi monitor system, we can get the DirectDraw object for any +// monitor (device) with the optional szDevice parameter + +HRESULT CLoadDirectDraw::LoadDirectDraw(LPSTR szDevice) +{ + PDRAWCREATE pDrawCreate; + PDRAWENUM pDrawEnum; + LPDIRECTDRAWENUMERATEEXA pDrawEnumEx; + HRESULT hr = NOERROR; + + NOTE("Entering DoLoadDirectDraw"); + + // Is DirectDraw already loaded + + if (m_pDirectDraw) { + NOTE("Already loaded"); + ASSERT(m_hDirectDraw); + return NOERROR; + } + + // Make sure the library is available + + if(!m_hDirectDraw) + { + UINT ErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX); + m_hDirectDraw = LoadLibrary(TEXT("DDRAW.DLL")); + SetErrorMode(ErrorMode); + + if (m_hDirectDraw == NULL) { + DbgLog((LOG_ERROR,1,TEXT("Can't load DDRAW.DLL"))); + NOTE("No library"); + return E_NOINTERFACE; + } + } + + // Get the DLL address for the creator function + + pDrawCreate = (PDRAWCREATE)GetProcAddress(m_hDirectDraw,"DirectDrawCreate"); + // force ANSI, we assume it + pDrawEnum = (PDRAWENUM)GetProcAddress(m_hDirectDraw,"DirectDrawEnumerateA"); + pDrawEnumEx = (LPDIRECTDRAWENUMERATEEXA)GetProcAddress(m_hDirectDraw, + "DirectDrawEnumerateExA"); + + // We don't NEED DirectDrawEnumerateEx, that's just for multimon stuff + if (pDrawCreate == NULL || pDrawEnum == NULL) { + DbgLog((LOG_ERROR,1,TEXT("Can't get functions: Create=%x Enum=%x"), + pDrawCreate, pDrawEnum)); + NOTE("No entry point"); + ReleaseDirectDraw(); + return E_NOINTERFACE; + } + + DbgLog((LOG_TRACE,3,TEXT("Creating DDraw for device %s"), + szDevice ? szDevice : "")); + + // Create a DirectDraw display provider for this device, using the fancy + // multimon-aware version, if it exists + if (pDrawEnumEx) + m_pDirectDraw = DirectDrawCreateFromDeviceEx(szDevice, pDrawCreate, + pDrawEnumEx); + else + m_pDirectDraw = DirectDrawCreateFromDevice(szDevice, pDrawCreate, + pDrawEnum); + + if (m_pDirectDraw == NULL) { + DbgLog((LOG_ERROR,1,TEXT("Can't create DDraw"))); + NOTE("No instance"); + ReleaseDirectDraw(); + return E_NOINTERFACE; + } + return NOERROR; +} + + +// Called to release any DirectDraw provider we previously loaded. We may be +// called at any time especially when something goes horribly wrong and when +// we need to clean up before returning so we can't guarantee that all state +// variables are consistent so free only those really allocated allocated +// This should only be called once all reference counts have been released + +void CLoadDirectDraw::ReleaseDirectDraw() +{ + NOTE("Releasing DirectDraw driver"); + + // Release any DirectDraw provider interface + + if (m_pDirectDraw) { + NOTE("Releasing instance"); + m_pDirectDraw->Release(); + m_pDirectDraw = NULL; + } + +} + + +// Return NOERROR (S_OK) if DirectDraw has been loaded by this object + +HRESULT CLoadDirectDraw::IsDirectDrawLoaded() +{ + NOTE("Entering IsDirectDrawLoaded"); + + if (m_pDirectDraw == NULL) { + NOTE("DirectDraw not loaded"); + return S_FALSE; + } + return NOERROR; +} + + +// Return the IDirectDraw interface we look after + +LPDIRECTDRAW CLoadDirectDraw::GetDirectDraw() +{ + NOTE("Entering GetDirectDraw"); + + if (m_pDirectDraw == NULL) { + NOTE("No DirectDraw"); + return NULL; + } + + NOTE("Returning DirectDraw"); + m_pDirectDraw->AddRef(); + return m_pDirectDraw; +} + + +// Are we running on Direct Draw version 1? We need to find out as +// we rely on specific bug fixes in DirectDraw 2 for fullscreen playback. To +// find out, we simply see if it supports IDirectDraw2. Only version 2 and +// higher support this. + +BOOL CLoadDirectDraw::IsDirectDrawVersion1() +{ + + if (m_pDirectDraw == NULL) + return FALSE; + + IDirectDraw2 *p = NULL; + HRESULT hr = m_pDirectDraw->QueryInterface(IID_IDirectDraw2, (void **)&p); + if (p) + p->Release(); + if (hr == NOERROR) { + DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 2 or greater"))); + return FALSE; + } else { + DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 1"))); + return TRUE; + } +} diff --git a/ThirdParty/strmbas/videoctl.h b/ThirdParty/strmbas/videoctl.h new file mode 100644 index 0000000..9e05357 --- /dev/null +++ b/ThirdParty/strmbas/videoctl.h @@ -0,0 +1,178 @@ +//------------------------------------------------------------------------------ +// File: VideoCtl.h +// +// Desc: DirectShow base classes. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +#ifndef __VIDEOCTL__ +#define __VIDEOCTL__ + +// These help with property page implementations. The first can be used to +// load any string from a resource file. The buffer to load into is passed +// as an input parameter. The same buffer is the return value if the string +// was found otherwise it returns TEXT(""). The GetDialogSize is passed the +// resource ID of a dialog box and returns the size of it in screen pixels + +#define STR_MAX_LENGTH 256 +TCHAR * WINAPI StringFromResource(TCHAR *pBuffer, int iResourceID); + +#ifdef UNICODE +#define WideStringFromResource StringFromResource +char* WINAPI StringFromResource(char*pBuffer, int iResourceID); +#else +WCHAR * WINAPI WideStringFromResource(WCHAR *pBuffer, int iResourceID); +#endif + + +BOOL WINAPI GetDialogSize(int iResourceID, // Dialog box resource identifier + DLGPROC pDlgProc, // Pointer to dialog procedure + LPARAM lParam, // Any user data wanted in pDlgProc + SIZE *pResult); // Returns the size of dialog box + +// Class that aggregates an IDirectDraw interface + +class CAggDirectDraw : public IDirectDraw, public CUnknown +{ +protected: + + LPDIRECTDRAW m_pDirectDraw; + +public: + + DECLARE_IUNKNOWN + STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,void **ppv); + + // Constructor and destructor + + CAggDirectDraw(TCHAR *pName,LPUNKNOWN pUnk) : + CUnknown(pName,pUnk), + m_pDirectDraw(NULL) { }; + + virtual CAggDirectDraw::~CAggDirectDraw() { }; + + // Set the object we should be aggregating + void SetDirectDraw(LPDIRECTDRAW pDirectDraw) { + m_pDirectDraw = pDirectDraw; + } + + // IDirectDraw methods + + STDMETHODIMP Compact(); + STDMETHODIMP CreateClipper(DWORD dwFlags,LPDIRECTDRAWCLIPPER *lplpDDClipper,IUnknown *pUnkOuter); + STDMETHODIMP CreatePalette(DWORD dwFlags,LPPALETTEENTRY lpColorTable,LPDIRECTDRAWPALETTE *lplpDDPalette,IUnknown *pUnkOuter); + STDMETHODIMP CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc,LPDIRECTDRAWSURFACE *lplpDDSurface,IUnknown *pUnkOuter); + STDMETHODIMP DuplicateSurface(LPDIRECTDRAWSURFACE lpDDSurface,LPDIRECTDRAWSURFACE *lplpDupDDSurface); + STDMETHODIMP EnumDisplayModes(DWORD dwSurfaceDescCount,LPDDSURFACEDESC lplpDDSurfaceDescList,LPVOID lpContext,LPDDENUMMODESCALLBACK lpEnumCallback); + STDMETHODIMP EnumSurfaces(DWORD dwFlags,LPDDSURFACEDESC lpDDSD,LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpEnumCallback); + STDMETHODIMP FlipToGDISurface(); + STDMETHODIMP GetCaps(LPDDCAPS lpDDDriverCaps,LPDDCAPS lpDDHELCaps); + STDMETHODIMP GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc); + STDMETHODIMP GetFourCCCodes(LPDWORD lpNumCodes,LPDWORD lpCodes); + STDMETHODIMP GetGDISurface(LPDIRECTDRAWSURFACE *lplpGDIDDSurface); + STDMETHODIMP GetMonitorFrequency(LPDWORD lpdwFrequency); + STDMETHODIMP GetScanLine(LPDWORD lpdwScanLine); + STDMETHODIMP GetVerticalBlankStatus(LPBOOL lpblsInVB); + STDMETHODIMP Initialize(GUID *lpGUID); + STDMETHODIMP RestoreDisplayMode(); + STDMETHODIMP SetCooperativeLevel(HWND hWnd,DWORD dwFlags); + STDMETHODIMP SetDisplayMode(DWORD dwWidth,DWORD dwHeight,DWORD dwBpp); + STDMETHODIMP WaitForVerticalBlank(DWORD dwFlags,HANDLE hEvent); +}; + + +// Class that aggregates an IDirectDrawSurface interface + +class CAggDrawSurface : public IDirectDrawSurface, public CUnknown +{ +protected: + + LPDIRECTDRAWSURFACE m_pDirectDrawSurface; + +public: + + DECLARE_IUNKNOWN + STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,void **ppv); + + // Constructor and destructor + + CAggDrawSurface(TCHAR *pName,LPUNKNOWN pUnk) : + CUnknown(pName,pUnk), + m_pDirectDrawSurface(NULL) { }; + + virtual ~CAggDrawSurface() { }; + + // Set the object we should be aggregating + void SetDirectDrawSurface(LPDIRECTDRAWSURFACE pDirectDrawSurface) { + m_pDirectDrawSurface = pDirectDrawSurface; + } + + // IDirectDrawSurface methods + + STDMETHODIMP AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface); + STDMETHODIMP AddOverlayDirtyRect(LPRECT lpRect); + STDMETHODIMP Blt(LPRECT lpDestRect,LPDIRECTDRAWSURFACE lpDDSrcSurface,LPRECT lpSrcRect,DWORD dwFlags,LPDDBLTFX lpDDBltFx); + STDMETHODIMP BltBatch(LPDDBLTBATCH lpDDBltBatch,DWORD dwCount,DWORD dwFlags); + STDMETHODIMP BltFast(DWORD dwX,DWORD dwY,LPDIRECTDRAWSURFACE lpDDSrcSurface,LPRECT lpSrcRect,DWORD dwTrans); + STDMETHODIMP DeleteAttachedSurface(DWORD dwFlags,LPDIRECTDRAWSURFACE lpDDSAttachedSurface); + STDMETHODIMP EnumAttachedSurfaces(LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback); + STDMETHODIMP EnumOverlayZOrders(DWORD dwFlags,LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpfnCallback); + STDMETHODIMP Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride,DWORD dwFlags); + STDMETHODIMP GetAttachedSurface(LPDDSCAPS lpDDSCaps,LPDIRECTDRAWSURFACE *lplpDDAttachedSurface); + STDMETHODIMP GetBltStatus(DWORD dwFlags); + STDMETHODIMP GetCaps(LPDDSCAPS lpDDSCaps); + STDMETHODIMP GetClipper(LPDIRECTDRAWCLIPPER *lplpDDClipper); + STDMETHODIMP GetColorKey(DWORD dwFlags,LPDDCOLORKEY lpDDColorKey); + STDMETHODIMP GetDC(HDC *lphDC); + STDMETHODIMP GetFlipStatus(DWORD dwFlags); + STDMETHODIMP GetOverlayPosition(LPLONG lpdwX,LPLONG lpdwY); + STDMETHODIMP GetPalette(LPDIRECTDRAWPALETTE *lplpDDPalette); + STDMETHODIMP GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat); + STDMETHODIMP GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc); + STDMETHODIMP Initialize(LPDIRECTDRAW lpDD,LPDDSURFACEDESC lpDDSurfaceDesc); + STDMETHODIMP IsLost(); + STDMETHODIMP Lock(LPRECT lpDestRect,LPDDSURFACEDESC lpDDSurfaceDesc,DWORD dwFlags,HANDLE hEvent); + STDMETHODIMP ReleaseDC(HDC hDC); + STDMETHODIMP Restore(); + STDMETHODIMP SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper); + STDMETHODIMP SetColorKey(DWORD dwFlags,LPDDCOLORKEY lpDDColorKey); + STDMETHODIMP SetOverlayPosition(LONG dwX,LONG dwY); + STDMETHODIMP SetPalette(LPDIRECTDRAWPALETTE lpDDPalette); + STDMETHODIMP Unlock(LPVOID lpSurfaceData); + STDMETHODIMP UpdateOverlay(LPRECT lpSrcRect,LPDIRECTDRAWSURFACE lpDDDestSurface,LPRECT lpDestRect,DWORD dwFlags,LPDDOVERLAYFX lpDDOverlayFX); + STDMETHODIMP UpdateOverlayDisplay(DWORD dwFlags); + STDMETHODIMP UpdateOverlayZOrder(DWORD dwFlags,LPDIRECTDRAWSURFACE lpDDSReference); +}; + + +// DirectShow must work on multiple platforms. In particular, it also runs on +// Windows NT 3.51 which does not have DirectDraw capabilities. The filters +// cannot therefore link statically to the DirectDraw library. To make their +// lives that little bit easier we provide this class that manages loading +// and unloading the library and creating the initial IDirectDraw interface + +typedef DWORD (WINAPI *PGETFILEVERSIONINFOSIZE)(LPTSTR,LPDWORD); +typedef BOOL (WINAPI *PGETFILEVERSIONINFO)(LPTSTR,DWORD,DWORD,LPVOID); +typedef BOOL (WINAPI *PVERQUERYVALUE)(LPVOID,LPTSTR,LPVOID,PUINT); + +class CLoadDirectDraw +{ + LPDIRECTDRAW m_pDirectDraw; // The DirectDraw driver instance + HINSTANCE m_hDirectDraw; // Handle to the loaded library + +public: + + CLoadDirectDraw(); + ~CLoadDirectDraw(); + + HRESULT LoadDirectDraw(LPSTR szDevice); + void ReleaseDirectDraw(); + HRESULT IsDirectDrawLoaded(); + LPDIRECTDRAW GetDirectDraw(); + BOOL IsDirectDrawVersion1(); +}; + +#endif // __VIDEOCTL__ + diff --git a/ThirdParty/strmbas/vtrans.cpp b/ThirdParty/strmbas/vtrans.cpp new file mode 100644 index 0000000..bc4f2cd --- /dev/null +++ b/ThirdParty/strmbas/vtrans.cpp @@ -0,0 +1,468 @@ +//------------------------------------------------------------------------------ +// File: Vtrans.cpp +// +// Desc: DirectShow base classes. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +#include +#include +// #include // now in precomp file streams.h + +CVideoTransformFilter::CVideoTransformFilter + ( TCHAR *pName, LPUNKNOWN pUnk, REFCLSID clsid) + : CTransformFilter(pName, pUnk, clsid) + , m_itrLate(0) + , m_nKeyFramePeriod(0) // No QM until we see at least 2 key frames + , m_nFramesSinceKeyFrame(0) + , m_bSkipping(FALSE) + , m_tDecodeStart(0) + , m_itrAvgDecode(300000) // 30mSec - probably allows skipping + , m_bQualityChanged(FALSE) +{ +#ifdef PERF + RegisterPerfId(); +#endif // PERF +} + + +CVideoTransformFilter::~CVideoTransformFilter() +{ + // nothing to do +} + + +// Reset our quality management state + +HRESULT CVideoTransformFilter::StartStreaming() +{ + m_itrLate = 0; + m_nKeyFramePeriod = 0; // No QM until we see at least 2 key frames + m_nFramesSinceKeyFrame = 0; + m_bSkipping = FALSE; + m_tDecodeStart = 0; + m_itrAvgDecode = 300000; // 30mSec - probably allows skipping + m_bQualityChanged = FALSE; + m_bSampleSkipped = FALSE; + return NOERROR; +} + + +// Overriden to reset quality management information + +HRESULT CVideoTransformFilter::EndFlush() +{ + { + // Synchronize + CAutoLock lck(&m_csReceive); + + // Reset our stats + // + // Note - we don't want to call derived classes here, + // we only want to reset our internal variables and this + // is a convenient way to do it + CVideoTransformFilter::StartStreaming(); + } + return CTransformFilter::EndFlush(); +} + + +HRESULT CVideoTransformFilter::AbortPlayback(HRESULT hr) +{ + NotifyEvent(EC_ERRORABORT, hr, 0); + m_pOutput->DeliverEndOfStream(); + return hr; +} + + +// Receive() +// +// Accept a sample from upstream, decide whether to process it +// or drop it. If we process it then get a buffer from the +// allocator of the downstream connection, transform it into the +// new buffer and deliver it to the downstream filter. +// If we decide not to process it then we do not get a buffer. + +// Remember that although this code will notice format changes coming into +// the input pin, it will NOT change its output format if that results +// in the filter needing to make a corresponding output format change. Your +// derived filter will have to take care of that. (eg. a palette change if +// the input and output is an 8 bit format). If the input sample is discarded +// and nothing is sent out for this Receive, please remember to put the format +// change on the first output sample that you actually do send. +// If your filter will produce the same output type even when the input type +// changes, then this base class code will do everything you need. + +HRESULT CVideoTransformFilter::Receive(IMediaSample *pSample) +{ + // If the next filter downstream is the video renderer, then it may + // be able to operate in DirectDraw mode which saves copying the data + // and gives higher performance. In that case the buffer which we + // get from GetDeliveryBuffer will be a DirectDraw buffer, and + // drawing into this buffer draws directly onto the display surface. + // This means that any waiting for the correct time to draw occurs + // during GetDeliveryBuffer, and that once the buffer is given to us + // the video renderer will count it in its statistics as a frame drawn. + // This means that any decision to drop the frame must be taken before + // calling GetDeliveryBuffer. + + ASSERT(CritCheckIn(&m_csReceive)); + AM_MEDIA_TYPE *pmtOut, *pmt; +#ifdef DEBUG + FOURCCMap fccOut; +#endif + HRESULT hr; + ASSERT(pSample); + IMediaSample * pOutSample; + + // If no output pin to deliver to then no point sending us data + ASSERT (m_pOutput != NULL) ; + + // The source filter may dynamically ask us to start transforming from a + // different media type than the one we're using now. If we don't, we'll + // draw garbage. (typically, this is a palette change in the movie, + // but could be something more sinister like the compression type changing, + // or even the video size changing) + +#define rcS1 ((VIDEOINFOHEADER *)(pmt->pbFormat))->rcSource +#define rcT1 ((VIDEOINFOHEADER *)(pmt->pbFormat))->rcTarget + + pSample->GetMediaType(&pmt); + if (pmt != NULL && pmt->pbFormat != NULL) { + + // spew some debug output + ASSERT(!IsEqualGUID(pmt->majortype, GUID_NULL)); +#ifdef DEBUG + fccOut.SetFOURCC(&pmt->subtype); + LONG lCompression = HEADER(pmt->pbFormat)->biCompression; + LONG lBitCount = HEADER(pmt->pbFormat)->biBitCount; + LONG lStride = (HEADER(pmt->pbFormat)->biWidth * lBitCount + 7) / 8; + lStride = (lStride + 3) & ~3; + DbgLog((LOG_TRACE,3,TEXT("*Changing input type on the fly to"))); + DbgLog((LOG_TRACE,3,TEXT("FourCC: %lx Compression: %lx BitCount: %ld"), + fccOut.GetFOURCC(), lCompression, lBitCount)); + DbgLog((LOG_TRACE,3,TEXT("biHeight: %ld rcDst: (%ld, %ld, %ld, %ld)"), + HEADER(pmt->pbFormat)->biHeight, + rcT1.left, rcT1.top, rcT1.right, rcT1.bottom)); + DbgLog((LOG_TRACE,3,TEXT("rcSrc: (%ld, %ld, %ld, %ld) Stride: %ld"), + rcS1.left, rcS1.top, rcS1.right, rcS1.bottom, + lStride)); +#endif + + // now switch to using the new format. I am assuming that the + // derived filter will do the right thing when its media type is + // switched and streaming is restarted. + + StopStreaming(); + m_pInput->CurrentMediaType() = *pmt; + DeleteMediaType(pmt); + // if this fails, playback will stop, so signal an error + hr = StartStreaming(); + if (FAILED(hr)) { + return AbortPlayback(hr); + } + } + + // Now that we have noticed any format changes on the input sample, it's + // OK to discard it. + + if (ShouldSkipFrame(pSample)) { + MSR_NOTE(m_idSkip); + m_bSampleSkipped = TRUE; + return NOERROR; + } + + // Set up the output sample + hr = InitializeOutputSample(pSample, &pOutSample); + + if (FAILED(hr)) { + return hr; + } + + m_bSampleSkipped = FALSE; + + // The renderer may ask us to on-the-fly to start transforming to a + // different format. If we don't obey it, we'll draw garbage + +#define rcS ((VIDEOINFOHEADER *)(pmtOut->pbFormat))->rcSource +#define rcT ((VIDEOINFOHEADER *)(pmtOut->pbFormat))->rcTarget + + pOutSample->GetMediaType(&pmtOut); + if (pmtOut != NULL && pmtOut->pbFormat != NULL) { + + // spew some debug output + ASSERT(!IsEqualGUID(pmtOut->majortype, GUID_NULL)); +#ifdef DEBUG + fccOut.SetFOURCC(&pmtOut->subtype); + LONG lCompression = HEADER(pmtOut->pbFormat)->biCompression; + LONG lBitCount = HEADER(pmtOut->pbFormat)->biBitCount; + LONG lStride = (HEADER(pmtOut->pbFormat)->biWidth * lBitCount + 7) / 8; + lStride = (lStride + 3) & ~3; + DbgLog((LOG_TRACE,3,TEXT("*Changing output type on the fly to"))); + DbgLog((LOG_TRACE,3,TEXT("FourCC: %lx Compression: %lx BitCount: %ld"), + fccOut.GetFOURCC(), lCompression, lBitCount)); + DbgLog((LOG_TRACE,3,TEXT("biHeight: %ld rcDst: (%ld, %ld, %ld, %ld)"), + HEADER(pmtOut->pbFormat)->biHeight, + rcT.left, rcT.top, rcT.right, rcT.bottom)); + DbgLog((LOG_TRACE,3,TEXT("rcSrc: (%ld, %ld, %ld, %ld) Stride: %ld"), + rcS.left, rcS.top, rcS.right, rcS.bottom, + lStride)); +#endif + + // now switch to using the new format. I am assuming that the + // derived filter will do the right thing when its media type is + // switched and streaming is restarted. + + StopStreaming(); + m_pOutput->CurrentMediaType() = *pmtOut; + DeleteMediaType(pmtOut); + hr = StartStreaming(); + + if (SUCCEEDED(hr)) { + // a new format, means a new empty buffer, so wait for a keyframe + // before passing anything on to the renderer. + // !!! a keyframe may never come, so give up after 30 frames + DbgLog((LOG_TRACE,3,TEXT("Output format change means we must wait for a keyframe"))); + m_nWaitForKey = 30; + + // if this fails, playback will stop, so signal an error + } else { + + // Must release the sample before calling AbortPlayback + // because we might be holding the win16 lock or + // ddraw lock + pOutSample->Release(); + AbortPlayback(hr); + return hr; + } + } + + // After a discontinuity, we need to wait for the next key frame + if (pSample->IsDiscontinuity() == S_OK) { + DbgLog((LOG_TRACE,3,TEXT("Non-key discontinuity - wait for keyframe"))); + m_nWaitForKey = 30; + } + + // Start timing the transform (and log it if PERF is defined) + + if (SUCCEEDED(hr)) { + m_tDecodeStart = timeGetTime(); + MSR_START(m_idTransform); + + // have the derived class transform the data + hr = Transform(pSample, pOutSample); + + // Stop the clock (and log it if PERF is defined) + MSR_STOP(m_idTransform); + m_tDecodeStart = timeGetTime()-m_tDecodeStart; + m_itrAvgDecode = m_tDecodeStart*(10000/16) + 15*(m_itrAvgDecode/16); + + // Maybe we're waiting for a keyframe still? + if (m_nWaitForKey) + m_nWaitForKey--; + if (m_nWaitForKey && pSample->IsSyncPoint() == S_OK) + m_nWaitForKey = FALSE; + + // if so, then we don't want to pass this on to the renderer + if (m_nWaitForKey && hr == NOERROR) { + DbgLog((LOG_TRACE,3,TEXT("still waiting for a keyframe"))); + hr = S_FALSE; + } + } + + if (FAILED(hr)) { + DbgLog((LOG_TRACE,1,TEXT("Error from video transform"))); + } else { + // the Transform() function can return S_FALSE to indicate that the + // sample should not be delivered; we only deliver the sample if it's + // really S_OK (same as NOERROR, of course.) + // Try not to return S_FALSE to a direct draw buffer (it's wasteful) + // Try to take the decision earlier - before you get it. + + if (hr == NOERROR) { + hr = m_pOutput->Deliver(pOutSample); + } else { + // S_FALSE returned from Transform is a PRIVATE agreement + // We should return NOERROR from Receive() in this case because returning S_FALSE + // from Receive() means that this is the end of the stream and no more data should + // be sent. + if (S_FALSE == hr) { + + // We must Release() the sample before doing anything + // like calling the filter graph because having the + // sample means we may have the DirectDraw lock + // (== win16 lock on some versions) + pOutSample->Release(); + m_bSampleSkipped = TRUE; + if (!m_bQualityChanged) { + m_bQualityChanged = TRUE; + NotifyEvent(EC_QUALITY_CHANGE,0,0); + } + return NOERROR; + } + } + } + + // release the output buffer. If the connected pin still needs it, + // it will have addrefed it itself. + pOutSample->Release(); + ASSERT(CritCheckIn(&m_csReceive)); + + return hr; +} + + + +BOOL CVideoTransformFilter::ShouldSkipFrame( IMediaSample * pIn) +{ + REFERENCE_TIME trStart, trStopAt; + HRESULT hr = pIn->GetTime(&trStart, &trStopAt); + + // Don't skip frames with no timestamps + if (hr != S_OK) + return FALSE; + + int itrFrame = (int)(trStopAt - trStart); // frame duration + + if(S_OK==pIn->IsSyncPoint()) { + MSR_INTEGER(m_idFrameType, 1); + if ( m_nKeyFramePeriod < m_nFramesSinceKeyFrame ) { + // record the max + m_nKeyFramePeriod = m_nFramesSinceKeyFrame; + } + m_nFramesSinceKeyFrame = 0; + m_bSkipping = FALSE; + } else { + MSR_INTEGER(m_idFrameType, 2); + if ( m_nFramesSinceKeyFrame>m_nKeyFramePeriod + && m_nKeyFramePeriod>0 + ) { + // We haven't seen the key frame yet, but we were clearly being + // overoptimistic about how frequent they are. + m_nKeyFramePeriod = m_nFramesSinceKeyFrame; + } + } + + + // Whatever we might otherwise decide, + // if we are taking only a small fraction of the required frame time to decode + // then any quality problems are actually coming from somewhere else. + // Could be a net problem at the source for instance. In this case there's + // no point in us skipping frames here. + if (m_itrAvgDecode*4>itrFrame) { + + // Don't skip unless we are at least a whole frame late. + // (We would skip B frames if more than 1/2 frame late, but they're safe). + if ( m_itrLate > itrFrame ) { + + // Don't skip unless the anticipated key frame would be no more than + // 1 frame early. If the renderer has not been waiting (we *guess* + // it hasn't because we're late) then it will allow frames to be + // played early by up to a frame. + + // Let T = Stream time from now to anticipated next key frame + // = (frame duration) * (KeyFramePeriod - FramesSinceKeyFrame) + // So we skip if T - Late < one frame i.e. + // (duration) * (freq - FramesSince) - Late < duration + // or (duration) * (freq - FramesSince - 1) < Late + + // We don't dare skip until we have seen some key frames and have + // some idea how often they occur and they are reasonably frequent. + if (m_nKeyFramePeriod>0) { + // It would be crazy - but we could have a stream with key frames + // a very long way apart - and if they are further than about + // 3.5 minutes apart then we could get arithmetic overflow in + // reference time units. Therefore we switch to mSec at this point + int it = (itrFrame/10000) + * (m_nKeyFramePeriod-m_nFramesSinceKeyFrame - 1); + MSR_INTEGER(m_idTimeTillKey, it); + + // For debug - might want to see the details - dump them as scratch pad +#ifdef VTRANSPERF + MSR_INTEGER(0, itrFrame); + MSR_INTEGER(0, m_nFramesSinceKeyFrame); + MSR_INTEGER(0, m_nKeyFramePeriod); +#endif + if (m_itrLate/10000 > it) { + m_bSkipping = TRUE; + // Now we are committed. Once we start skipping, we + // cannot stop until we hit a key frame. + } else { +#ifdef VTRANSPERF + MSR_INTEGER(0, 777770); // not near enough to next key +#endif + } + } else { +#ifdef VTRANSPERF + MSR_INTEGER(0, 777771); // Next key not predictable +#endif + } + } else { +#ifdef VTRANSPERF + MSR_INTEGER(0, 777772); // Less than one frame late + MSR_INTEGER(0, m_itrLate); + MSR_INTEGER(0, itrFrame); +#endif + } + } else { +#ifdef VTRANSPERF + MSR_INTEGER(0, 777773); // Decode time short - not not worth skipping + MSR_INTEGER(0, m_itrAvgDecode); + MSR_INTEGER(0, itrFrame); +#endif + } + + ++m_nFramesSinceKeyFrame; + + if (m_bSkipping) { + // We will count down the lateness as we skip each frame. + // We re-assess each frame. The key frame might not arrive when expected. + // We reset m_itrLate if we get a new Quality message, but actually that's + // not likely because we're not sending frames on to the Renderer. In + // fact if we DID get another one it would mean that there's a long + // pipe between us and the renderer and we might need an altogether + // better strategy to avoid hunting! + m_itrLate = m_itrLate - itrFrame; + } + + MSR_INTEGER(m_idLate, (int)m_itrLate/10000 ); // Note how late we think we are + if (m_bSkipping) { + if (!m_bQualityChanged) { + m_bQualityChanged = TRUE; + NotifyEvent(EC_QUALITY_CHANGE,0,0); + } + } + return m_bSkipping; +} + + +HRESULT CVideoTransformFilter::AlterQuality(Quality q) +{ + // to reduce the amount of 64 bit arithmetic, m_itrLate is an int. + // +, -, >, == etc are not too bad, but * and / are painful. + if (m_itrLate>300000000) { + // Avoid overflow and silliness - more than 30 secs late is already silly + m_itrLate = 300000000; + } else { + m_itrLate = (int)q.Late; + } + // We ignore the other fields + + // We're actually not very good at handling this. In non-direct draw mode + // most of the time can be spent in the renderer which can skip any frame. + // In that case we'd rather the renderer handled things. + // Nevertheless we will keep an eye on it and if we really start getting + // a very long way behind then we will actually skip - but we'll still tell + // the renderer (or whoever is downstream) that they should handle quality. + + return E_FAIL; // Tell the renderer to do his thing. + +} + + + +// This will avoid several hundred useless warnings if compiled -W4 by MS VC++ v4 +#pragma warning(disable:4514) + diff --git a/ThirdParty/strmbas/vtrans.h b/ThirdParty/strmbas/vtrans.h new file mode 100644 index 0000000..05a8aef --- /dev/null +++ b/ThirdParty/strmbas/vtrans.h @@ -0,0 +1,143 @@ +//------------------------------------------------------------------------------ +// File: VTrans.h +// +// Desc: DirectShow base classes - defines a video transform class. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +// This class is derived from CTransformFilter, but is specialised to handle +// the requirements of video quality control by frame dropping. +// This is a non-in-place transform, (i.e. it copies the data) such as a decoder. + +class CVideoTransformFilter : public CTransformFilter +{ + public: + + CVideoTransformFilter(TCHAR *, LPUNKNOWN, REFCLSID clsid); + ~CVideoTransformFilter(); + HRESULT EndFlush(); + + // ================================================================= + // ----- override these bits --------------------------------------- + // ================================================================= + // The following methods are in CTransformFilter which is inherited. + // They are mentioned here for completeness + // + // These MUST be supplied in a derived class + // + // NOTE: + // virtual HRESULT Transform(IMediaSample * pIn, IMediaSample *pOut); + // virtual HRESULT CheckInputType(const CMediaType* mtIn) PURE; + // virtual HRESULT CheckTransform + // (const CMediaType* mtIn, const CMediaType* mtOut) PURE; + // static CCOMObject * CreateInstance(LPUNKNOWN, HRESULT *); + // virtual HRESULT DecideBufferSize + // (IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES *pprop) PURE; + // virtual HRESULT GetMediaType(int iPosition, CMediaType *pMediaType) PURE; + // + // These MAY also be overridden + // + // virtual HRESULT StopStreaming(); + // virtual HRESULT SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt); + // virtual HRESULT CheckConnect(PIN_DIRECTION dir,IPin *pPin); + // virtual HRESULT BreakConnect(PIN_DIRECTION dir); + // virtual HRESULT CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin); + // virtual HRESULT EndOfStream(void); + // virtual HRESULT BeginFlush(void); + // virtual HRESULT EndFlush(void); + // virtual HRESULT NewSegment + // (REFERENCE_TIME tStart,REFERENCE_TIME tStop,double dRate); +#ifdef PERF + + // If you override this - ensure that you register all these ids + // as well as any of your own, + virtual void RegisterPerfId() { + m_idSkip = MSR_REGISTER(TEXT("Video Transform Skip frame")); + m_idFrameType = MSR_REGISTER(TEXT("Video transform frame type")); + m_idLate = MSR_REGISTER(TEXT("Video Transform Lateness")); + m_idTimeTillKey = MSR_REGISTER(TEXT("Video Transform Estd. time to next key")); + CTransformFilter::RegisterPerfId(); + } +#endif + + protected: + + // =========== QUALITY MANAGEMENT IMPLEMENTATION ======================== + // Frames are assumed to come in three types: + // Type 1: an AVI key frame or an MPEG I frame. + // This frame can be decoded with no history. + // Dropping this frame means that no further frame can be decoded + // until the next type 1 frame. + // Type 1 frames are sync points. + // Type 2: an AVI non-key frame or an MPEG P frame. + // This frame cannot be decoded unless the previous type 1 frame was + // decoded and all type 2 frames since have been decoded. + // Dropping this frame means that no further frame can be decoded + // until the next type 1 frame. + // Type 3: An MPEG B frame. + // This frame cannot be decoded unless the previous type 1 or 2 frame + // has been decoded AND the subsequent type 1 or 2 frame has also + // been decoded. (This requires decoding the frames out of sequence). + // Dropping this frame affects no other frames. This implementation + // does not allow for these. All non-sync-point frames are treated + // as being type 2. + // + // The spacing of frames of type 1 in a file is not guaranteed. There MUST + // be a type 1 frame at (well, near) the start of the file in order to start + // decoding at all. After that there could be one every half second or so, + // there could be one at the start of each scene (aka "cut", "shot") or + // there could be no more at all. + // If there is only a single type 1 frame then NO FRAMES CAN BE DROPPED + // without losing all the rest of the movie. There is no way to tell whether + // this is the case, so we find that we are in the gambling business. + // To try to improve the odds, we record the greatest interval between type 1s + // that we have seen and we bet on things being no worse than this in the + // future. + + // You can tell if it's a type 1 frame by calling IsSyncPoint(). + // there is no architected way to test for a type 3, so you should override + // the quality management here if you have B-frames. + + int m_nKeyFramePeriod; // the largest observed interval between type 1 frames + // 1 means every frame is type 1, 2 means every other. + + int m_nFramesSinceKeyFrame; // Used to count frames since the last type 1. + // becomes the new m_nKeyFramePeriod if greater. + + BOOL m_bSkipping; // we are skipping to the next type 1 frame + +#ifdef PERF + int m_idFrameType; // MSR id Frame type. 1=Key, 2="non-key" + int m_idSkip; // MSR id skipping + int m_idLate; // MSR id lateness + int m_idTimeTillKey; // MSR id for guessed time till next key frame. +#endif + + virtual HRESULT StartStreaming(); + + HRESULT AbortPlayback(HRESULT hr); // if something bad happens + + HRESULT Receive(IMediaSample *pSample); + + HRESULT AlterQuality(Quality q); + + BOOL ShouldSkipFrame(IMediaSample * pIn); + + int m_itrLate; // lateness from last Quality message + // (this overflows at 214 secs late). + int m_tDecodeStart; // timeGetTime when decode started. + int m_itrAvgDecode; // Average decode time in reference units. + + BOOL m_bNoSkip; // debug - no skipping. + + // We send an EC_QUALITY_CHANGE notification to the app if we have to degrade. + // We send one when we start degrading, not one for every frame, this means + // we track whether we've sent one yet. + BOOL m_bQualityChanged; + + // When non-zero, don't pass anything to renderer until next keyframe + // If there are few keys, give up and eventually draw something + int m_nWaitForKey; +}; diff --git a/ThirdParty/strmbas/winctrl.cpp b/ThirdParty/strmbas/winctrl.cpp new file mode 100644 index 0000000..4e269ea --- /dev/null +++ b/ThirdParty/strmbas/winctrl.cpp @@ -0,0 +1,2050 @@ +//------------------------------------------------------------------------------ +// File: WinCtrl.cpp +// +// Desc: DirectShow base classes - implements video control interface class. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +#include + +// The control interface methods require us to be connected + +#define CheckConnected(pin,code) \ +{ \ + if (pin == NULL) { \ + ASSERT(!TEXT("Pin not set")); \ + } else if (pin->IsConnected() == FALSE) { \ + return (code); \ + } \ +} + +// This checks to see whether the window has a drain. An application can in +// most environments set the owner/parent of windows so that they appear in +// a compound document context (for example). In this case, the application +// would probably like to be told of any keyboard/mouse messages. Therefore +// we pass these messages on untranslated, returning TRUE if we're successful + +BOOL WINAPI PossiblyEatMessage(HWND hwndDrain, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (hwndDrain != NULL && !InSendMessage()) + { + switch (uMsg) + { + case WM_CHAR: + case WM_DEADCHAR: + case WM_KEYDOWN: + case WM_KEYUP: + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDBLCLK: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MOUSEACTIVATE: + case WM_MOUSEMOVE: + // If we pass this on we don't get any mouse clicks + //case WM_NCHITTEST: + case WM_NCLBUTTONDBLCLK: + case WM_NCLBUTTONDOWN: + case WM_NCLBUTTONUP: + case WM_NCMBUTTONDBLCLK: + case WM_NCMBUTTONDOWN: + case WM_NCMBUTTONUP: + case WM_NCMOUSEMOVE: + case WM_NCRBUTTONDBLCLK: + case WM_NCRBUTTONDOWN: + case WM_NCRBUTTONUP: + case WM_RBUTTONDBLCLK: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_SYSCHAR: + case WM_SYSDEADCHAR: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + + DbgLog((LOG_TRACE, 2, TEXT("Forwarding %x to drain"))); + PostMessage(hwndDrain, uMsg, wParam, lParam); + + return TRUE; + } + } + return FALSE; +} + + +// This class implements the IVideoWindow control functions (dual interface) +// we support a large number of properties and methods designed to allow the +// client (whether it be an automation controller or a C/C++ application) to +// set and get a number of window related properties such as it's position. +// We also support some methods that duplicate the properties but provide a +// more direct and efficient mechanism as many values may be changed in one + +CBaseControlWindow::CBaseControlWindow( + CBaseFilter *pFilter, // Owning filter + CCritSec *pInterfaceLock, // Locking object + TCHAR *pName, // Object description + LPUNKNOWN pUnk, // Normal COM ownership + HRESULT *phr) : // OLE return code + + CBaseVideoWindow(pName,pUnk), + m_pInterfaceLock(pInterfaceLock), + m_hwndOwner(NULL), + m_hwndDrain(NULL), + m_bAutoShow(TRUE), + m_pFilter(pFilter), + m_bCursorHidden(FALSE), + m_pPin(NULL) +{ + ASSERT(m_pFilter); + ASSERT(m_pInterfaceLock); + ASSERT(phr); + m_BorderColour = VIDEO_COLOUR; +} + + +// Set the title caption on the base window, we don't do any field checking +// as we really don't care what title they intend to have. We can always get +// it back again later with GetWindowText. The only other complication is to +// do the necessary string conversions between ANSI and OLE Unicode strings + +STDMETHODIMP CBaseControlWindow::put_Caption(BSTR strCaption) +{ + CheckPointer(strCaption,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); +#ifdef UNICODE + SetWindowText(m_hwnd, strCaption); +#else + CHAR Caption[CAPTION]; + + WideCharToMultiByte(CP_ACP,0,strCaption,-1,Caption,CAPTION,NULL,NULL); + SetWindowText(m_hwnd, Caption); +#endif + return NOERROR; +} + + +// Get the current base window title caption, once again we do no real field +// checking. We allocate a string for the window title to be filled in with +// which ensures the interface doesn't fiddle around with getting memory. A +// BSTR is a normal C string with the length at position (-1), we use the +// WriteBSTR helper function to create the caption to try and avoid OLE32 + +STDMETHODIMP CBaseControlWindow::get_Caption(BSTR *pstrCaption) +{ + CheckPointer(pstrCaption,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + WCHAR WideCaption[CAPTION]; + +#ifdef UNICODE + GetWindowText(m_hwnd,WideCaption,CAPTION); +#else + // Convert the ASCII caption to a UNICODE string + + TCHAR Caption[CAPTION]; + GetWindowText(m_hwnd,Caption,CAPTION); + MultiByteToWideChar(CP_ACP,0,Caption,-1,WideCaption,CAPTION); +#endif + return WriteBSTR(pstrCaption,WideCaption); +} + + +// Set the window style using GWL_EXSTYLE + +STDMETHODIMP CBaseControlWindow::put_WindowStyleEx(long WindowStyleEx) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + + // Should we be taking off WS_EX_TOPMOST + + if (GetWindowLong(m_hwnd,GWL_EXSTYLE) & WS_EX_TOPMOST) { + if ((WindowStyleEx & WS_EX_TOPMOST) == 0) { + SendMessage(m_hwnd,m_ShowStageTop,(WPARAM) FALSE,(LPARAM) 0); + } + } + + // Likewise should we be adding WS_EX_TOPMOST + + if (WindowStyleEx & WS_EX_TOPMOST) { + SendMessage(m_hwnd,m_ShowStageTop,(WPARAM) TRUE,(LPARAM) 0); + WindowStyleEx &= (~WS_EX_TOPMOST); + if (WindowStyleEx == 0) return NOERROR; + } + return DoSetWindowStyle(WindowStyleEx,GWL_EXSTYLE); +} + + +// Gets the current GWL_EXSTYLE base window style + +STDMETHODIMP CBaseControlWindow::get_WindowStyleEx(long *pWindowStyleEx) +{ + CheckPointer(pWindowStyleEx,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + return DoGetWindowStyle(pWindowStyleEx,GWL_EXSTYLE); +} + + +// Set the window style using GWL_STYLE + +STDMETHODIMP CBaseControlWindow::put_WindowStyle(long WindowStyle) +{ + // These styles cannot be changed dynamically + + if ((WindowStyle & WS_DISABLED) || + (WindowStyle & WS_ICONIC) || + (WindowStyle & WS_MAXIMIZE) || + (WindowStyle & WS_MINIMIZE) || + (WindowStyle & WS_HSCROLL) || + (WindowStyle & WS_VSCROLL)) { + + return E_INVALIDARG; + } + + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + return DoSetWindowStyle(WindowStyle,GWL_STYLE); +} + + +// Get the current GWL_STYLE base window style + +STDMETHODIMP CBaseControlWindow::get_WindowStyle(long *pWindowStyle) +{ + CheckPointer(pWindowStyle,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + return DoGetWindowStyle(pWindowStyle,GWL_STYLE); +} + + +// Change the base window style or the extended styles depending on whether +// WindowLong is GWL_STYLE or GWL_EXSTYLE. We must call SetWindowPos to have +// the window displayed in it's new style after the change which is a little +// tricky if the window is not currently visible as we realise it offscreen. +// In most cases the client will call get_WindowStyle before they call this +// and then AND and OR in extra bit settings according to the requirements + +HRESULT CBaseControlWindow::DoSetWindowStyle(long Style,long WindowLong) +{ + RECT WindowRect; + + // Get the window's visibility before setting the style + BOOL bVisible = IsWindowVisible(m_hwnd); + EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); + + // Set the new style flags for the window + SetWindowLong(m_hwnd,WindowLong,Style); + UINT WindowFlags = SWP_SHOWWINDOW | SWP_FRAMECHANGED | SWP_NOACTIVATE; + WindowFlags |= SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE; + + // Show the window again in the current position + + if (bVisible == TRUE) { + + SetWindowPos(m_hwnd, // Base window handle + HWND_TOP, // Just a place holder + 0,0,0,0, // Leave size and position + WindowFlags); // Just draw it again + + return NOERROR; + } + + // Move the window offscreen so the user doesn't see the changes + + MoveWindow((HWND) m_hwnd, // Base window handle + GetSystemMetrics(SM_CXSCREEN), // Current desktop width + GetSystemMetrics(SM_CYSCREEN), // Likewise it's height + WIDTH(&WindowRect), // Use the same width + HEIGHT(&WindowRect), // Keep height same to + TRUE); // May as well repaint + + // Now show the previously hidden window + + SetWindowPos(m_hwnd, // Base window handle + HWND_TOP, // Just a place holder + 0,0,0,0, // Leave size and position + WindowFlags); // Just draw it again + + ShowWindow(m_hwnd,SW_HIDE); + + if (GetParent(m_hwnd)) { + + MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2); + } + + MoveWindow((HWND) m_hwnd, // Base window handle + WindowRect.left, // Existing x coordinate + WindowRect.top, // Existing y coordinate + WIDTH(&WindowRect), // Use the same width + HEIGHT(&WindowRect), // Keep height same to + TRUE); // May as well repaint + + return NOERROR; +} + + +// Get the current base window style (either GWL_STYLE or GWL_EXSTYLE) + +HRESULT CBaseControlWindow::DoGetWindowStyle(long *pStyle,long WindowLong) +{ + *pStyle = GetWindowLong(m_hwnd,WindowLong); + return NOERROR; +} + + +// Change the visibility of the base window, this takes the same parameters +// as the ShowWindow Win32 API does, so the client can have the window hidden +// or shown, minimised to an icon, or maximised to play in full screen mode +// We pass the request on to the base window to actually make the change + +STDMETHODIMP CBaseControlWindow::put_WindowState(long WindowState) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + DoShowWindow(WindowState); + return NOERROR; +} + + +// Get the current window state, this function returns a subset of the SW bit +// settings available in ShowWindow, if the window is visible then SW_SHOW is +// set, if it is hidden then the SW_HIDDEN is set, if it is either minimised +// or maximised then the SW_MINIMIZE or SW_MAXIMIZE is set respectively. The +// other SW bit settings are really set commands not readable output values + +STDMETHODIMP CBaseControlWindow::get_WindowState(long *pWindowState) +{ + CheckPointer(pWindowState,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + ASSERT(pWindowState); + *pWindowState = FALSE; + + // Is the window visible, a window is termed visible if it is somewhere on + // the current desktop even if it is completely obscured by other windows + // so the flag is a style for each window set with the WS_VISIBLE bit + + if (IsWindowVisible(m_hwnd) == TRUE) { + + // Is the base window iconic + if (IsIconic(m_hwnd) == TRUE) { + *pWindowState |= SW_MINIMIZE; + } + + // Has the window been maximised + else if (IsZoomed(m_hwnd) == TRUE) { + *pWindowState |= SW_MAXIMIZE; + } + + // Window is normal + else { + *pWindowState |= SW_SHOW; + } + + } else { + *pWindowState |= SW_HIDE; + } + return NOERROR; +} + + +// This makes sure that any palette we realise in the base window (through a +// media type or through the overlay interface) is done in the background and +// is therefore mapped to existing device entries rather than taking it over +// as it will do when we this window gets the keyboard focus. An application +// uses this to make sure it doesn't have it's palette removed by the window + +STDMETHODIMP CBaseControlWindow::put_BackgroundPalette(long BackgroundPalette) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cWindowLock(&m_WindowLock); + + // Check this is a valid automation boolean type + + if (BackgroundPalette != OATRUE) { + if (BackgroundPalette != OAFALSE) { + return E_INVALIDARG; + } + } + + // Make sure the window realises any palette it has again + + m_bBackground = (BackgroundPalette == OATRUE ? TRUE : FALSE); + PostMessage(m_hwnd,m_RealizePalette,0,0); + PaintWindow(FALSE); + + return NOERROR; +} + + +// This returns the current background realisation setting + +STDMETHODIMP +CBaseControlWindow::get_BackgroundPalette(long *pBackgroundPalette) +{ + CheckPointer(pBackgroundPalette,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cWindowLock(&m_WindowLock); + + // Get the current background palette setting + + *pBackgroundPalette = (m_bBackground == TRUE ? OATRUE : OAFALSE); + return NOERROR; +} + + +// Change the visibility of the base window + +STDMETHODIMP CBaseControlWindow::put_Visible(long Visible) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + + // Check this is a valid automation boolean type + + if (Visible != OATRUE) { + if (Visible != OAFALSE) { + return E_INVALIDARG; + } + } + + // Convert the boolean visibility into SW_SHOW and SW_HIDE + + INT Mode = (Visible == OATRUE ? SW_SHOWNORMAL : SW_HIDE); + DoShowWindow(Mode); + return NOERROR; +} + + +// Return OATRUE if the window is currently visible otherwise OAFALSE + +STDMETHODIMP CBaseControlWindow::get_Visible(long *pVisible) +{ + CheckPointer(pVisible,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + + // See if the base window has a WS_VISIBLE style - this will return TRUE + // even if the window is completely obscured by other desktop windows, we + // return FALSE if the window is not showing because of earlier calls + + BOOL Mode = IsWindowVisible(m_hwnd); + *pVisible = (Mode == TRUE ? OATRUE : OAFALSE); + return NOERROR; +} + + +// Change the left position of the base window. This keeps the window width +// and height properties the same so it effectively shunts the window left or +// right accordingly - there is the Width property to change that dimension + +STDMETHODIMP CBaseControlWindow::put_Left(long Left) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + BOOL bSuccess; + RECT WindowRect; + + // Get the current window position in a RECT + EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); + + if (GetParent(m_hwnd)) { + + MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2); + } + + // Adjust the coordinates ready for SetWindowPos, the window rectangle we + // get back from GetWindowRect is in left,top,right and bottom while the + // coordinates SetWindowPos wants are left,top,width and height values + + WindowRect.bottom = WindowRect.bottom - WindowRect.top; + WindowRect.right = WindowRect.right - WindowRect.left; + UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE; + + bSuccess = SetWindowPos(m_hwnd, // Window handle + HWND_TOP, // Put it at the top + Left, // New left position + WindowRect.top, // Leave top alone + WindowRect.right, // The WIDTH (not right) + WindowRect.bottom, // The HEIGHT (not bottom) + WindowFlags); // Show window options + + if (bSuccess == FALSE) { + return E_INVALIDARG; + } + return NOERROR; +} + + +// Return the current base window left position + +STDMETHODIMP CBaseControlWindow::get_Left(long *pLeft) +{ + CheckPointer(pLeft,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + RECT WindowRect; + + EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); + *pLeft = WindowRect.left; + return NOERROR; +} + + +// Change the current width of the base window. This property complements the +// left position property so we must keep the left edge constant and expand or +// contract to the right, the alternative would be to change the left edge so +// keeping the right edge constant but this is maybe a little more intuitive + +STDMETHODIMP CBaseControlWindow::put_Width(long Width) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + BOOL bSuccess; + RECT WindowRect; + + // Adjust the coordinates ready for SetWindowPos, the window rectangle we + // get back from GetWindowRect is in left,top,right and bottom while the + // coordinates SetWindowPos wants are left,top,width and height values + + EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); + + if (GetParent(m_hwnd)) { + + MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2); + } + + WindowRect.bottom = WindowRect.bottom - WindowRect.top; + UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE; + + // This seems to have a bug in that calling SetWindowPos on a window with + // just the width changing causes it to ignore the width that you pass in + // and sets it to a mimimum value of 110 pixels wide (Windows NT 3.51) + + bSuccess = SetWindowPos(m_hwnd, // Window handle + HWND_TOP, // Put it at the top + WindowRect.left, // Leave left alone + WindowRect.top, // Leave top alone + Width, // New WIDTH dimension + WindowRect.bottom, // The HEIGHT (not bottom) + WindowFlags); // Show window options + + if (bSuccess == FALSE) { + return E_INVALIDARG; + } + return NOERROR; +} + + +// Return the current base window width + +STDMETHODIMP CBaseControlWindow::get_Width(long *pWidth) +{ + CheckPointer(pWidth,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + RECT WindowRect; + + EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); + *pWidth = WindowRect.right - WindowRect.left; + return NOERROR; +} + + +// This allows the client program to change the top position for the window in +// the same way that changing the left position does not affect the width of +// the image so changing the top position does not affect the window height + +STDMETHODIMP CBaseControlWindow::put_Top(long Top) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + BOOL bSuccess; + RECT WindowRect; + + // Get the current window position in a RECT + EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); + + if (GetParent(m_hwnd)) { + + MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2); + } + + // Adjust the coordinates ready for SetWindowPos, the window rectangle we + // get back from GetWindowRect is in left,top,right and bottom while the + // coordinates SetWindowPos wants are left,top,width and height values + + WindowRect.bottom = WindowRect.bottom - WindowRect.top; + WindowRect.right = WindowRect.right - WindowRect.left; + UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE; + + bSuccess = SetWindowPos(m_hwnd, // Window handle + HWND_TOP, // Put it at the top + WindowRect.left, // Leave left alone + Top, // New top position + WindowRect.right, // The WIDTH (not right) + WindowRect.bottom, // The HEIGHT (not bottom) + WindowFlags); // Show window flags + + if (bSuccess == FALSE) { + return E_INVALIDARG; + } + return NOERROR; +} + + +// Return the current base window top position + +STDMETHODIMP CBaseControlWindow::get_Top(long *pTop) +{ + CheckPointer(pTop,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + RECT WindowRect; + + EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); + *pTop = WindowRect.top; + return NOERROR; +} + + +// Change the height of the window, this complements the top property so when +// we change this we must keep the top position for the base window, as said +// before we could keep the bottom and grow upwards although this is perhaps +// a little more intuitive since we already have a top position property + +STDMETHODIMP CBaseControlWindow::put_Height(long Height) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + BOOL bSuccess; + RECT WindowRect; + + // Adjust the coordinates ready for SetWindowPos, the window rectangle we + // get back from GetWindowRect is in left,top,right and bottom while the + // coordinates SetWindowPos wants are left,top,width and height values + + EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); + + if (GetParent(m_hwnd)) { + + MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2); + } + + WindowRect.right = WindowRect.right - WindowRect.left; + UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE; + + bSuccess = SetWindowPos(m_hwnd, // Window handle + HWND_TOP, // Put it at the top + WindowRect.left, // Leave left alone + WindowRect.top, // Leave top alone + WindowRect.right, // The WIDTH (not right) + Height, // New height dimension + WindowFlags); // Show window flags + + if (bSuccess == FALSE) { + return E_INVALIDARG; + } + return NOERROR; +} + + +// Return the current base window height + +STDMETHODIMP CBaseControlWindow::get_Height(long *pHeight) +{ + CheckPointer(pHeight,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + RECT WindowRect; + + EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); + *pHeight = WindowRect.bottom - WindowRect.top; + return NOERROR; +} + + +// This can be called to change the owning window. Setting the owner is done +// through this function, however to make the window a true child window the +// style must also be set to WS_CHILD. After resetting the owner to NULL an +// application should also set the style to WS_OVERLAPPED | WS_CLIPCHILDREN. + +// We cannot lock the object here because the SetParent causes an interthread +// SendMessage to the owner window. If they are in GetState we will sit here +// incomplete with the critical section locked therefore blocking out source +// filter threads from accessing us. Because the source thread can't enter us +// it can't get buffers or call EndOfStream so the GetState will not complete + +STDMETHODIMP CBaseControlWindow::put_Owner(OAHWND Owner) +{ + // Check we are connected otherwise reject the call + + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + m_hwndOwner = (HWND) Owner; + HWND hwndParent = m_hwndOwner; + + // Add or remove WS_CHILD as appropriate + + LONG Style = GetWindowLong(m_hwnd,GWL_STYLE); + if (Owner == NULL) { + Style &= (~WS_CHILD); + } else { + Style |= (WS_CHILD); + } + SetWindowLong(m_hwnd,GWL_STYLE,Style); + + // Don't call this with the filter locked + + SetParent(m_hwnd,hwndParent); + + PaintWindow(TRUE); + NOTE1("Changed parent %lx",hwndParent); + + return NOERROR; +} + + +// This complements the put_Owner to get the current owning window property +// we always return NOERROR although the returned window handle may be NULL +// to indicate no owning window (the desktop window doesn't qualify as one) +// If an application sets the owner we call SetParent, however that returns +// NULL until the WS_CHILD bit is set on, so we store the owner internally + +STDMETHODIMP CBaseControlWindow::get_Owner(OAHWND *Owner) +{ + CheckPointer(Owner,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + *Owner = (OAHWND) m_hwndOwner; + return NOERROR; +} + + +// And renderer supporting IVideoWindow may have an HWND set who will get any +// keyboard and mouse messages we receive posted on to them. This is separate +// from setting an owning window. By separating the two, applications may get +// messages sent on even when they have set no owner (perhaps it's maximised) + +STDMETHODIMP CBaseControlWindow::put_MessageDrain(OAHWND Drain) +{ + // Check we are connected otherwise reject the call + + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + m_hwndDrain = (HWND) Drain; + return NOERROR; +} + + +// Return the current message drain + +STDMETHODIMP CBaseControlWindow::get_MessageDrain(OAHWND *Drain) +{ + CheckPointer(Drain,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + *Drain = (OAHWND) m_hwndDrain; + return NOERROR; +} + + +// This is called by the filter graph to inform us of a message we should know +// is being sent to our owning window. We have this because as a child window +// we do not get certain messages that are only sent to top level windows. We +// must see the palette changed/changing/query messages so that we know if we +// have the foreground palette or not. We pass the message on to our window +// using SendMessage - this will cause an interthread send message to occur + +STDMETHODIMP +CBaseControlWindow::NotifyOwnerMessage(OAHWND hwnd, // Window handle + long uMsg, // Message ID + LONG_PTR wParam, // Parameters + LONG_PTR lParam) // for message +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + + // Only interested in these Windows messages + + switch (uMsg) { + + case WM_SYSCOLORCHANGE: + case WM_PALETTECHANGED: + case WM_PALETTEISCHANGING: + case WM_QUERYNEWPALETTE: + case WM_DEVMODECHANGE: + case WM_DISPLAYCHANGE: + case WM_ACTIVATEAPP: + + // If we do not have an owner then ignore + + if (m_hwndOwner == NULL) { + return NOERROR; + } + SendMessage(m_hwnd,uMsg,(WPARAM)wParam,(LPARAM)lParam); + break; + + // do NOT fwd WM_MOVE. the parameters are the location of the parent + // window, NOT what the renderer should be looking at. But we need + // to make sure the overlay is moved with the parent window, so we + // do this. + case WM_MOVE: + PostMessage(m_hwnd,WM_PAINT,0,0); + break; + } + return NOERROR; +} + + +// Allow an application to have us set the base window in the foreground. We +// have this because it is difficult for one thread to do do this to a window +// owned by another thread. We ask the base window class to do the real work + +STDMETHODIMP CBaseControlWindow::SetWindowForeground(long Focus) +{ + // Check this is a valid automation boolean type + + if (Focus != OATRUE) { + if (Focus != OAFALSE) { + return E_INVALIDARG; + } + } + + // We shouldn't lock as this sends a message + + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + BOOL bFocus = (Focus == OATRUE ? TRUE : FALSE); + DoSetWindowForeground(bFocus); + + return NOERROR; +} + + +// This allows a client to set the complete window size and position in one +// atomic operation. The same affect can be had by changing each dimension +// in turn through their individual properties although some flashing will +// occur as each of them gets updated (they are better set at design time) + +STDMETHODIMP +CBaseControlWindow::SetWindowPosition(long Left,long Top,long Width,long Height) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + BOOL bSuccess; + + // Set the new size and position + UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE; + + ASSERT(IsWindow(m_hwnd)); + bSuccess = SetWindowPos(m_hwnd, // Window handle + HWND_TOP, // Put it at the top + Left, // Left position + Top, // Top position + Width, // Window width + Height, // Window height + WindowFlags); // Show window flags + ASSERT(bSuccess); +#ifdef DEBUG + DbgLog((LOG_TRACE, 1, TEXT("SWP failed error %d"), GetLastError())); +#endif + if (bSuccess == FALSE) { + return E_INVALIDARG; + } + return NOERROR; +} + + +// This complements the SetWindowPosition to return the current window place +// in device coordinates. As before the same information can be retrived by +// calling the property get functions individually but this is atomic and is +// therefore more suitable to a live environment rather than design time + +STDMETHODIMP +CBaseControlWindow::GetWindowPosition(long *pLeft,long *pTop,long *pWidth,long *pHeight) +{ + // Should check the pointers are not NULL + + CheckPointer(pLeft,E_POINTER); + CheckPointer(pTop,E_POINTER); + CheckPointer(pWidth,E_POINTER); + CheckPointer(pHeight,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + RECT WindowRect; + + // Get the current window coordinates + + EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); + + // Convert the RECT into left,top,width and height values + + *pLeft = WindowRect.left; + *pTop = WindowRect.top; + *pWidth = WindowRect.right - WindowRect.left; + *pHeight = WindowRect.bottom - WindowRect.top; + + return NOERROR; +} + + +// When a window is maximised or iconic calling GetWindowPosition will return +// the current window position (likewise for the properties). However if the +// restored size (ie the size we'll return to when normally shown) is needed +// then this should be used. When in a normal position (neither iconic nor +// maximised) then this returns the same coordinates as GetWindowPosition + +STDMETHODIMP +CBaseControlWindow::GetRestorePosition(long *pLeft,long *pTop,long *pWidth,long *pHeight) +{ + // Should check the pointers are not NULL + + CheckPointer(pLeft,E_POINTER); + CheckPointer(pTop,E_POINTER); + CheckPointer(pWidth,E_POINTER); + CheckPointer(pHeight,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + + // Use GetWindowPlacement to find the restore position + + WINDOWPLACEMENT Place; + Place.length = sizeof(WINDOWPLACEMENT); + EXECUTE_ASSERT(GetWindowPlacement(m_hwnd,&Place)); + + RECT WorkArea; + + // We must take into account any task bar present + + if (SystemParametersInfo(SPI_GETWORKAREA,0,&WorkArea,FALSE) == TRUE) { + if (GetParent(m_hwnd) == NULL) { + Place.rcNormalPosition.top += WorkArea.top; + Place.rcNormalPosition.bottom += WorkArea.top; + Place.rcNormalPosition.left += WorkArea.left; + Place.rcNormalPosition.right += WorkArea.left; + } + } + + // Convert the RECT into left,top,width and height values + + *pLeft = Place.rcNormalPosition.left; + *pTop = Place.rcNormalPosition.top; + *pWidth = Place.rcNormalPosition.right - Place.rcNormalPosition.left; + *pHeight = Place.rcNormalPosition.bottom - Place.rcNormalPosition.top; + + return NOERROR; +} + + +// Return the current border colour, if we are playing something to a subset +// of the base window display there is an outside area exposed. The default +// action is to paint this colour in the Windows background colour (defined +// as value COLOR_WINDOW) We reset to this default when we're disconnected + +STDMETHODIMP CBaseControlWindow::get_BorderColor(long *Color) +{ + CheckPointer(Color,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + *Color = (long) m_BorderColour; + return NOERROR; +} + + +// This can be called to set the current border colour + +STDMETHODIMP CBaseControlWindow::put_BorderColor(long Color) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + + // Have the window repainted with the new border colour + + m_BorderColour = (COLORREF) Color; + PaintWindow(TRUE); + return NOERROR; +} + + +// Delegate fullscreen handling to plug in distributor + +STDMETHODIMP CBaseControlWindow::get_FullScreenMode(long *FullScreenMode) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CheckPointer(FullScreenMode,E_POINTER); + return E_NOTIMPL; +} + + +// Delegate fullscreen handling to plug in distributor + +STDMETHODIMP CBaseControlWindow::put_FullScreenMode(long FullScreenMode) +{ + return E_NOTIMPL; +} + + +// This sets the auto show property, this property causes the base window to +// be displayed whenever we change state. This allows an application to have +// to do nothing to have the window appear but still allow them to change the +// default behaviour if for example they want to keep it hidden for longer + +STDMETHODIMP CBaseControlWindow::put_AutoShow(long AutoShow) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + + // Check this is a valid automation boolean type + + if (AutoShow != OATRUE) { + if (AutoShow != OAFALSE) { + return E_INVALIDARG; + } + } + + m_bAutoShow = (AutoShow == OATRUE ? TRUE : FALSE); + return NOERROR; +} + + +// This can be called to get the current auto show flag. The flag is updated +// when we connect and disconnect and through this interface all of which are +// controlled and serialised by means of the main renderer critical section + +STDMETHODIMP CBaseControlWindow::get_AutoShow(long *AutoShow) +{ + CheckPointer(AutoShow,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + *AutoShow = (m_bAutoShow == TRUE ? OATRUE : OAFALSE); + return NOERROR; +} + + +// Return the minimum ideal image size for the current video. This may differ +// to the actual video dimensions because we may be using DirectDraw hardware +// that has specific stretching requirements. For example the Cirrus Logic +// cards have a minimum stretch factor depending on the overlay surface size + +STDMETHODIMP +CBaseControlWindow::GetMinIdealImageSize(long *pWidth,long *pHeight) +{ + CheckPointer(pWidth,E_POINTER); + CheckPointer(pHeight,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + FILTER_STATE State; + + // Must not be stopped for this to work correctly + + m_pFilter->GetState(0,&State); + if (State == State_Stopped) { + return VFW_E_WRONG_STATE; + } + + RECT DefaultRect = GetDefaultRect(); + *pWidth = WIDTH(&DefaultRect); + *pHeight = HEIGHT(&DefaultRect); + return NOERROR; +} + + +// Return the maximum ideal image size for the current video. This may differ +// to the actual video dimensions because we may be using DirectDraw hardware +// that has specific stretching requirements. For example the Cirrus Logic +// cards have a maximum stretch factor depending on the overlay surface size + +STDMETHODIMP +CBaseControlWindow::GetMaxIdealImageSize(long *pWidth,long *pHeight) +{ + CheckPointer(pWidth,E_POINTER); + CheckPointer(pHeight,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + FILTER_STATE State; + + // Must not be stopped for this to work correctly + + m_pFilter->GetState(0,&State); + if (State == State_Stopped) { + return VFW_E_WRONG_STATE; + } + + RECT DefaultRect = GetDefaultRect(); + *pWidth = WIDTH(&DefaultRect); + *pHeight = HEIGHT(&DefaultRect); + return NOERROR; +} + + +// Allow an application to hide the cursor on our window + +STDMETHODIMP +CBaseControlWindow::HideCursor(long HideCursor) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + + // Check this is a valid automation boolean type + + if (HideCursor != OATRUE) { + if (HideCursor != OAFALSE) { + return E_INVALIDARG; + } + } + + m_bCursorHidden = (HideCursor == OATRUE ? TRUE : FALSE); + return NOERROR; +} + + +// Returns whether we have the cursor hidden or not + +STDMETHODIMP CBaseControlWindow::IsCursorHidden(long *CursorHidden) +{ + CheckPointer(CursorHidden,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + *CursorHidden = (m_bCursorHidden == TRUE ? OATRUE : OAFALSE); + return NOERROR; +} + + +// This class implements the IBasicVideo control functions (dual interface) +// we support a large number of properties and methods designed to allow the +// client (whether it be an automation controller or a C/C++ application) to +// set and get a number of video related properties such as the native video +// size. We support some methods that duplicate the properties but provide a +// more direct and efficient mechanism as many values may be changed in one + +CBaseControlVideo::CBaseControlVideo( + CBaseFilter *pFilter, // Owning filter + CCritSec *pInterfaceLock, // Locking object + TCHAR *pName, // Object description + LPUNKNOWN pUnk, // Normal COM ownership + HRESULT *phr) : // OLE return code + + CBaseBasicVideo(pName,pUnk), + m_pFilter(pFilter), + m_pInterfaceLock(pInterfaceLock), + m_pPin(NULL) +{ + ASSERT(m_pFilter); + ASSERT(m_pInterfaceLock); + ASSERT(phr); +} + +// Return an approximate average time per frame + +STDMETHODIMP CBaseControlVideo::get_AvgTimePerFrame(REFTIME *pAvgTimePerFrame) +{ + CheckPointer(pAvgTimePerFrame,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + + VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); + if (pVideoInfo == NULL) + return E_OUTOFMEMORY; + COARefTime AvgTime(pVideoInfo->AvgTimePerFrame); + *pAvgTimePerFrame = (REFTIME) AvgTime; + + return NOERROR; +} + + +// Return an approximate bit rate for the video + +STDMETHODIMP CBaseControlVideo::get_BitRate(long *pBitRate) +{ + CheckPointer(pBitRate,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + + VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); + if (pVideoInfo == NULL) + return E_OUTOFMEMORY; + *pBitRate = pVideoInfo->dwBitRate; + return NOERROR; +} + + +// Return an approximate bit error rate + +STDMETHODIMP CBaseControlVideo::get_BitErrorRate(long *pBitErrorRate) +{ + CheckPointer(pBitErrorRate,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + + VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); + if (pVideoInfo == NULL) + return E_OUTOFMEMORY; + *pBitErrorRate = pVideoInfo->dwBitErrorRate; + return NOERROR; +} + + +// This returns the current video width + +STDMETHODIMP CBaseControlVideo::get_VideoWidth(long *pVideoWidth) +{ + CheckPointer(pVideoWidth,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + + VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); + if (pVideoInfo == NULL) + return E_OUTOFMEMORY; + *pVideoWidth = pVideoInfo->bmiHeader.biWidth; + return NOERROR; +} + + +// This returns the current video height + +STDMETHODIMP CBaseControlVideo::get_VideoHeight(long *pVideoHeight) +{ + CheckPointer(pVideoHeight,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + + VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); + if (pVideoInfo == NULL) + return E_OUTOFMEMORY; + *pVideoHeight = pVideoInfo->bmiHeader.biHeight; + return NOERROR; +} + + +// This returns the current palette the video is using as an array allocated +// by the user. To remain consistent we use PALETTEENTRY fields to return the +// colours in rather than RGBQUADs that multimedia decided to use. The memory +// is allocated by the user so we simple copy each in turn. We check that the +// number of entries requested and the start position offset are both valid +// If the number of entries evaluates to zero then we return an S_FALSE code + +STDMETHODIMP CBaseControlVideo::GetVideoPaletteEntries(long StartIndex, + long Entries, + long *pRetrieved, + long *pPalette) +{ + CheckPointer(pRetrieved,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + CMediaType MediaType; + + // Get the video format from the derived class + + VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); + if (pVideoInfo == NULL) + return E_OUTOFMEMORY; + BITMAPINFOHEADER *pHeader = HEADER(pVideoInfo); + + // Is the current format palettised + + if (PALETTISED(pVideoInfo) == FALSE) { + *pRetrieved = 0; + return VFW_E_NO_PALETTE_AVAILABLE; + } + + // Do they just want to know how many are available + + if (pPalette == NULL) { + *pRetrieved = pHeader->biClrUsed; + return NOERROR; + } + + // Make sure the start position is a valid offset + + if (StartIndex >= (LONG) pHeader->biClrUsed || StartIndex < 0) { + *pRetrieved = 0; + return E_INVALIDARG; + } + + // Correct the number we can retrieve + + LONG Available = (LONG) pHeader->biClrUsed - StartIndex; + *pRetrieved = max(0,min(Available,Entries)); + if (*pRetrieved == 0) { + return S_FALSE; + } + + // Copy the palette entries to the output buffer + + PALETTEENTRY *pEntries = (PALETTEENTRY *) pPalette; + RGBQUAD *pColours = COLORS(pVideoInfo) + StartIndex; + + for (LONG Count = 0;Count < *pRetrieved;Count++) { + pEntries[Count].peRed = pColours[Count].rgbRed; + pEntries[Count].peGreen = pColours[Count].rgbGreen; + pEntries[Count].peBlue = pColours[Count].rgbBlue; + pEntries[Count].peFlags = 0; + } + return NOERROR; +} + + +// This returns the current video dimensions as a method rather than a number +// of individual property get calls. For the same reasons as said before we +// cannot access the renderer media type directly as the window object thread +// may be updating it since dynamic format changes may change these values + +STDMETHODIMP CBaseControlVideo::GetVideoSize(long *pWidth,long *pHeight) +{ + CheckPointer(pWidth,E_POINTER); + CheckPointer(pHeight,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + + // Get the video format from the derived class + VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); + if (pVideoInfo == NULL) + return E_OUTOFMEMORY; + *pWidth = pVideoInfo->bmiHeader.biWidth; + *pHeight = pVideoInfo->bmiHeader.biHeight; + return NOERROR; +} + + +// Set the source video rectangle as left,top,right and bottom coordinates +// rather than left,top,width and height as per OLE automation interfaces +// Then pass the rectangle on to the window object to set the source + +STDMETHODIMP +CBaseControlVideo::SetSourcePosition(long Left,long Top,long Width,long Height) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT SourceRect; + SourceRect.left = Left; + SourceRect.top = Top; + SourceRect.right = Left + Width; + SourceRect.bottom = Top + Height; + + // Check the source rectangle is valid + + HRESULT hr = CheckSourceRect(&SourceRect); + if (FAILED(hr)) { + return hr; + } + + // Now set the source rectangle + + hr = SetSourceRect(&SourceRect); + if (FAILED(hr)) { + return hr; + } + return OnUpdateRectangles(); +} + + +// Return the source rectangle in left,top,width and height rather than the +// left,top,right and bottom values that RECT uses (and which the window +// object returns through GetSourceRect) which requires a little work + +STDMETHODIMP +CBaseControlVideo::GetSourcePosition(long *pLeft,long *pTop,long *pWidth,long *pHeight) +{ + CheckPointer(pLeft,E_POINTER); + CheckPointer(pTop,E_POINTER); + CheckPointer(pWidth,E_POINTER); + CheckPointer(pHeight,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + RECT SourceRect; + + CAutoLock cInterfaceLock(m_pInterfaceLock); + GetSourceRect(&SourceRect); + + *pLeft = SourceRect.left; + *pTop = SourceRect.top; + *pWidth = WIDTH(&SourceRect); + *pHeight = HEIGHT(&SourceRect); + + return NOERROR; +} + + +// Set the video destination as left,top,right and bottom coordinates rather +// than the left,top,width and height uses as per OLE automation interfaces +// Then pass the rectangle on to the window object to set the destination + +STDMETHODIMP +CBaseControlVideo::SetDestinationPosition(long Left,long Top,long Width,long Height) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT DestinationRect; + + DestinationRect.left = Left; + DestinationRect.top = Top; + DestinationRect.right = Left + Width; + DestinationRect.bottom = Top + Height; + + // Check the target rectangle is valid + + HRESULT hr = CheckTargetRect(&DestinationRect); + if (FAILED(hr)) { + return hr; + } + + // Now set the new target rectangle + + hr = SetTargetRect(&DestinationRect); + if (FAILED(hr)) { + return hr; + } + return OnUpdateRectangles(); +} + + +// Return the destination rectangle in left,top,width and height rather than +// the left,top,right and bottom values that RECT uses (and which the window +// object returns through GetDestinationRect) which requires a little work + +STDMETHODIMP +CBaseControlVideo::GetDestinationPosition(long *pLeft,long *pTop,long *pWidth,long *pHeight) +{ + // Should check the pointers are not NULL + + CheckPointer(pLeft,E_POINTER); + CheckPointer(pTop,E_POINTER); + CheckPointer(pWidth,E_POINTER); + CheckPointer(pHeight,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + RECT DestinationRect; + + CAutoLock cInterfaceLock(m_pInterfaceLock); + GetTargetRect(&DestinationRect); + + *pLeft = DestinationRect.left; + *pTop = DestinationRect.top; + *pWidth = WIDTH(&DestinationRect); + *pHeight = HEIGHT(&DestinationRect); + + return NOERROR; +} + + +// Set the source left position, the source rectangle we get back from the +// window object is a true rectangle in left,top,right and bottom positions +// so all we have to do is to update the left position and pass it back. We +// must keep the current width constant when we're updating this property + +STDMETHODIMP CBaseControlVideo::put_SourceLeft(long SourceLeft) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT SourceRect; + GetSourceRect(&SourceRect); + SourceRect.right = SourceLeft + WIDTH(&SourceRect); + SourceRect.left = SourceLeft; + + // Check the source rectangle is valid + + HRESULT hr = CheckSourceRect(&SourceRect); + if (FAILED(hr)) { + return hr; + } + + // Now set the source rectangle + + hr = SetSourceRect(&SourceRect); + if (FAILED(hr)) { + return hr; + } + return OnUpdateRectangles(); +} + + +// Return the current left source video position + +STDMETHODIMP CBaseControlVideo::get_SourceLeft(long *pSourceLeft) +{ + CheckPointer(pSourceLeft,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT SourceRect; + + GetSourceRect(&SourceRect); + *pSourceLeft = SourceRect.left; + return NOERROR; +} + + +// Set the source width, we get the current source rectangle and then update +// the right position to be the left position (thereby keeping it constant) +// plus the new source width we are passed in (it expands to the right) + +STDMETHODIMP CBaseControlVideo::put_SourceWidth(long SourceWidth) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT SourceRect; + GetSourceRect(&SourceRect); + SourceRect.right = SourceRect.left + SourceWidth; + + // Check the source rectangle is valid + + HRESULT hr = CheckSourceRect(&SourceRect); + if (FAILED(hr)) { + return hr; + } + + // Now set the source rectangle + + hr = SetSourceRect(&SourceRect); + if (FAILED(hr)) { + return hr; + } + return OnUpdateRectangles(); +} + + +// Return the current source width + +STDMETHODIMP CBaseControlVideo::get_SourceWidth(long *pSourceWidth) +{ + CheckPointer(pSourceWidth,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT SourceRect; + + GetSourceRect(&SourceRect); + *pSourceWidth = WIDTH(&SourceRect); + return NOERROR; +} + + +// Set the source top position - changing this property does not affect the +// current source height. So changing this shunts the source rectangle up and +// down appropriately. Changing the height complements this functionality by +// keeping the top position constant and simply changing the source height + +STDMETHODIMP CBaseControlVideo::put_SourceTop(long SourceTop) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT SourceRect; + GetSourceRect(&SourceRect); + SourceRect.bottom = SourceTop + HEIGHT(&SourceRect); + SourceRect.top = SourceTop; + + // Check the source rectangle is valid + + HRESULT hr = CheckSourceRect(&SourceRect); + if (FAILED(hr)) { + return hr; + } + + // Now set the source rectangle + + hr = SetSourceRect(&SourceRect); + if (FAILED(hr)) { + return hr; + } + return OnUpdateRectangles(); +} + + +// Return the current top position + +STDMETHODIMP CBaseControlVideo::get_SourceTop(long *pSourceTop) +{ + CheckPointer(pSourceTop,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT SourceRect; + + GetSourceRect(&SourceRect); + *pSourceTop = SourceRect.top; + return NOERROR; +} + + +// Set the source height + +STDMETHODIMP CBaseControlVideo::put_SourceHeight(long SourceHeight) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT SourceRect; + GetSourceRect(&SourceRect); + SourceRect.bottom = SourceRect.top + SourceHeight; + + // Check the source rectangle is valid + + HRESULT hr = CheckSourceRect(&SourceRect); + if (FAILED(hr)) { + return hr; + } + + // Now set the source rectangle + + hr = SetSourceRect(&SourceRect); + if (FAILED(hr)) { + return hr; + } + return OnUpdateRectangles(); +} + + +// Return the current source height + +STDMETHODIMP CBaseControlVideo::get_SourceHeight(long *pSourceHeight) +{ + CheckPointer(pSourceHeight,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT SourceRect; + + GetSourceRect(&SourceRect); + *pSourceHeight = HEIGHT(&SourceRect); + return NOERROR; +} + + +// Set the target left position, the target rectangle we get back from the +// window object is a true rectangle in left,top,right and bottom positions +// so all we have to do is to update the left position and pass it back. We +// must keep the current width constant when we're updating this property + +STDMETHODIMP CBaseControlVideo::put_DestinationLeft(long DestinationLeft) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT DestinationRect; + GetTargetRect(&DestinationRect); + DestinationRect.right = DestinationLeft + WIDTH(&DestinationRect); + DestinationRect.left = DestinationLeft; + + // Check the target rectangle is valid + + HRESULT hr = CheckTargetRect(&DestinationRect); + if (FAILED(hr)) { + return hr; + } + + // Now set the new target rectangle + + hr = SetTargetRect(&DestinationRect); + if (FAILED(hr)) { + return hr; + } + return OnUpdateRectangles(); +} + + +// Return the left position for the destination rectangle + +STDMETHODIMP CBaseControlVideo::get_DestinationLeft(long *pDestinationLeft) +{ + CheckPointer(pDestinationLeft,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT DestinationRect; + + GetTargetRect(&DestinationRect); + *pDestinationLeft = DestinationRect.left; + return NOERROR; +} + + +// Set the destination width + +STDMETHODIMP CBaseControlVideo::put_DestinationWidth(long DestinationWidth) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT DestinationRect; + GetTargetRect(&DestinationRect); + DestinationRect.right = DestinationRect.left + DestinationWidth; + + // Check the target rectangle is valid + + HRESULT hr = CheckTargetRect(&DestinationRect); + if (FAILED(hr)) { + return hr; + } + + // Now set the new target rectangle + + hr = SetTargetRect(&DestinationRect); + if (FAILED(hr)) { + return hr; + } + return OnUpdateRectangles(); +} + + +// Return the width for the destination rectangle + +STDMETHODIMP CBaseControlVideo::get_DestinationWidth(long *pDestinationWidth) +{ + CheckPointer(pDestinationWidth,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT DestinationRect; + + GetTargetRect(&DestinationRect); + *pDestinationWidth = WIDTH(&DestinationRect); + return NOERROR; +} + + +// Set the target top position - changing this property does not affect the +// current target height. So changing this shunts the target rectangle up and +// down appropriately. Changing the height complements this functionality by +// keeping the top position constant and simply changing the target height + +STDMETHODIMP CBaseControlVideo::put_DestinationTop(long DestinationTop) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT DestinationRect; + GetTargetRect(&DestinationRect); + DestinationRect.bottom = DestinationTop + HEIGHT(&DestinationRect); + DestinationRect.top = DestinationTop; + + // Check the target rectangle is valid + + HRESULT hr = CheckTargetRect(&DestinationRect); + if (FAILED(hr)) { + return hr; + } + + // Now set the new target rectangle + + hr = SetTargetRect(&DestinationRect); + if (FAILED(hr)) { + return hr; + } + return OnUpdateRectangles(); +} + + +// Return the top position for the destination rectangle + +STDMETHODIMP CBaseControlVideo::get_DestinationTop(long *pDestinationTop) +{ + CheckPointer(pDestinationTop,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT DestinationRect; + + GetTargetRect(&DestinationRect); + *pDestinationTop = DestinationRect.top; + return NOERROR; +} + + +// Set the destination height + +STDMETHODIMP CBaseControlVideo::put_DestinationHeight(long DestinationHeight) +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT DestinationRect; + GetTargetRect(&DestinationRect); + DestinationRect.bottom = DestinationRect.top + DestinationHeight; + + // Check the target rectangle is valid + + HRESULT hr = CheckTargetRect(&DestinationRect); + if (FAILED(hr)) { + return hr; + } + + // Now set the new target rectangle + + hr = SetTargetRect(&DestinationRect); + if (FAILED(hr)) { + return hr; + } + return OnUpdateRectangles(); +} + + +// Return the height for the destination rectangle + +STDMETHODIMP CBaseControlVideo::get_DestinationHeight(long *pDestinationHeight) +{ + CheckPointer(pDestinationHeight,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + RECT DestinationRect; + + GetTargetRect(&DestinationRect); + *pDestinationHeight = HEIGHT(&DestinationRect); + return NOERROR; +} + + +// Reset the source rectangle to the full video dimensions + +STDMETHODIMP CBaseControlVideo::SetDefaultSourcePosition() +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + HRESULT hr = SetDefaultSourceRect(); + if (FAILED(hr)) { + return hr; + } + return OnUpdateRectangles(); +} + + +// Return S_OK if we're using the default source otherwise S_FALSE + +STDMETHODIMP CBaseControlVideo::IsUsingDefaultSource() +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + return IsDefaultSourceRect(); +} + + +// Reset the video renderer to use the entire playback area + +STDMETHODIMP CBaseControlVideo::SetDefaultDestinationPosition() +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + HRESULT hr = SetDefaultTargetRect(); + if (FAILED(hr)) { + return hr; + } + return OnUpdateRectangles(); +} + + +// Return S_OK if we're using the default target otherwise S_FALSE + +STDMETHODIMP CBaseControlVideo::IsUsingDefaultDestination() +{ + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + return IsDefaultTargetRect(); +} + + +// Return a copy of the current image in the video renderer + +STDMETHODIMP +CBaseControlVideo::GetCurrentImage(long *pBufferSize,long *pVideoImage) +{ + CheckPointer(pBufferSize,E_POINTER); + CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); + CAutoLock cInterfaceLock(m_pInterfaceLock); + FILTER_STATE State; + + // Make sure we are in a paused state + + if (pVideoImage != NULL) { + m_pFilter->GetState(0,&State); + if (State != State_Paused) { + return VFW_E_NOT_PAUSED; + } + return GetStaticImage(pBufferSize,pVideoImage); + } + + // Just return the memory required + + VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); + if (pVideoInfo == NULL) + return E_OUTOFMEMORY; + RECT SourceRect; + GetSourceRect(&SourceRect); + return GetImageSize(pVideoInfo,pBufferSize,&SourceRect); +} + + +// An application has two ways of using GetCurrentImage, one is to pass a real +// buffer which should be filled with the current image. The other is to pass +// a NULL buffer pointer which is interpreted as asking us to return how much +// memory is required for the image. The constraints for when the latter can +// be called are much looser. To calculate the memory required we synthesize +// a VIDEOINFO that takes into account the source rectangle that's being used + +HRESULT CBaseControlVideo::GetImageSize(VIDEOINFOHEADER *pVideoInfo, + LONG *pBufferSize, + RECT *pSourceRect) +{ + NOTE("Entering GetImageSize"); + ASSERT(pSourceRect); + + // Check we have the correct input parameters + + if (pSourceRect == NULL || + pVideoInfo == NULL || + pBufferSize == NULL) { + + return E_UNEXPECTED; + } + + // Is the data format compatible + + if (pVideoInfo->bmiHeader.biCompression != BI_RGB) { + if (pVideoInfo->bmiHeader.biCompression != BI_BITFIELDS) { + return E_INVALIDARG; + } + } + + ASSERT(IsRectEmpty(pSourceRect) == FALSE); + + BITMAPINFOHEADER bih; + bih.biWidth = WIDTH(pSourceRect); + bih.biHeight = HEIGHT(pSourceRect); + bih.biBitCount = pVideoInfo->bmiHeader.biBitCount; + LONG Size = DIBSIZE(bih); + Size += GetBitmapFormatSize(HEADER(pVideoInfo)) - SIZE_PREHEADER; + *pBufferSize = Size; + + return NOERROR; +} + + +// Given an IMediaSample containing a linear buffer with an image and a type +// describing the bitmap make a rendering of the image into the output buffer +// This may be called by derived classes who render typical video images to +// handle the IBasicVideo GetCurrentImage method. The pVideoImage pointer may +// be NULL when passed to GetCurrentImage in which case GetImageSize will be +// called instead, which will just do the calculation of the memory required + +HRESULT CBaseControlVideo::CopyImage(IMediaSample *pMediaSample, + VIDEOINFOHEADER *pVideoInfo, + LONG *pBufferSize, + BYTE *pVideoImage, + RECT *pSourceRect) +{ + NOTE("Entering CopyImage"); + ASSERT(pSourceRect); + BYTE *pCurrentImage; + + // Check we have an image to copy + + if (pMediaSample == NULL || pSourceRect == NULL || + pVideoInfo == NULL || pVideoImage == NULL || + pBufferSize == NULL) { + + return E_UNEXPECTED; + } + + // Is the data format compatible + + if (pVideoInfo->bmiHeader.biCompression != BI_RGB) { + if (pVideoInfo->bmiHeader.biCompression != BI_BITFIELDS) { + return E_INVALIDARG; + } + } + + ASSERT(IsRectEmpty(pSourceRect) == FALSE); + + BITMAPINFOHEADER bih; + bih.biWidth = WIDTH(pSourceRect); + bih.biHeight = HEIGHT(pSourceRect); + bih.biBitCount = pVideoInfo->bmiHeader.biBitCount; + LONG Size = GetBitmapFormatSize(HEADER(pVideoInfo)) - SIZE_PREHEADER; + LONG Total = Size + DIBSIZE(bih); + + // Make sure we have a large enough buffer + + if (*pBufferSize < Total) { + return E_OUTOFMEMORY; + } + + // Copy the BITMAPINFO + + CopyMemory((PVOID)pVideoImage, (PVOID)&pVideoInfo->bmiHeader, Size); + ((BITMAPINFOHEADER *)pVideoImage)->biWidth = WIDTH(pSourceRect); + ((BITMAPINFOHEADER *)pVideoImage)->biHeight = HEIGHT(pSourceRect); + ((BITMAPINFOHEADER *)pVideoImage)->biSizeImage = DIBSIZE(bih); + BYTE *pImageData = pVideoImage + Size; + + // Get the pointer to it's image data + + HRESULT hr = pMediaSample->GetPointer(&pCurrentImage); + if (FAILED(hr)) { + return hr; + } + + // Now we are ready to start copying the source scan lines + + LONG ScanLine = (pVideoInfo->bmiHeader.biBitCount / 8) * WIDTH(pSourceRect); + LONG LinesToSkip = pVideoInfo->bmiHeader.biHeight; + LinesToSkip -= pSourceRect->top + HEIGHT(pSourceRect); + pCurrentImage += LinesToSkip * DIBWIDTHBYTES(pVideoInfo->bmiHeader); + pCurrentImage += pSourceRect->left * (pVideoInfo->bmiHeader.biBitCount / 8); + + // Even money on this GP faulting sometime... + + for (LONG Line = 0;Line < HEIGHT(pSourceRect);Line++) { + CopyMemory((PVOID)pImageData, (PVOID)pCurrentImage, ScanLine); + pImageData += DIBWIDTHBYTES(*(BITMAPINFOHEADER *)pVideoImage); + pCurrentImage += DIBWIDTHBYTES(pVideoInfo->bmiHeader); + } + return NOERROR; +} + + +// Called when we change media types either during connection or dynamically +// We inform the filter graph and therefore the application that the video +// size may have changed, we don't bother looking to see if it really has as +// we leave that to the application - the dimensions are the event parameters + +HRESULT CBaseControlVideo::OnVideoSizeChange() +{ + // Get the video format from the derived class + + VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); + if (pVideoInfo == NULL) + return E_OUTOFMEMORY; + WORD Width = (WORD) pVideoInfo->bmiHeader.biWidth; + WORD Height = (WORD) pVideoInfo->bmiHeader.biHeight; + + return m_pFilter->NotifyEvent(EC_VIDEO_SIZE_CHANGED, + MAKELPARAM(Width,Height), + MAKEWPARAM(0,0)); +} + + +// Set the video source rectangle. We must check the source rectangle against +// the actual video dimensions otherwise when we come to draw the pictures we +// get access violations as GDI tries to touch data outside of the image data +// Although we store the rectangle in left, top, right and bottom coordinates +// instead of left, top, width and height as OLE uses we do take into account +// that the rectangle is used up to, but not including, the right column and +// bottom row of pixels, see the Win32 documentation on RECT for more details + +HRESULT CBaseControlVideo::CheckSourceRect(RECT *pSourceRect) +{ + CheckPointer(pSourceRect,E_POINTER); + LONG Width,Height; + GetVideoSize(&Width,&Height); + + // Check the coordinates are greater than zero + // and that the rectangle is valid (leftleft >= pSourceRect->right) || + (pSourceRect->left < 0) || + (pSourceRect->top >= pSourceRect->bottom) || + (pSourceRect->top < 0)) { + + return E_INVALIDARG; + } + + // Check the coordinates are less than the extents + + if ((pSourceRect->right > Width) || + (pSourceRect->bottom > Height)) { + + return E_INVALIDARG; + } + return NOERROR; +} + + +// Check the target rectangle has some valid coordinates, which amounts to +// little more than checking the destination rectangle isn't empty. Derived +// classes may call this when they have their SetTargetRect method called to +// check the rectangle validity, we do not update the rectangles passed in +// Although we store the rectangle in left, top, right and bottom coordinates +// instead of left, top, width and height as OLE uses we do take into account +// that the rectangle is used up to, but not including, the right column and +// bottom row of pixels, see the Win32 documentation on RECT for more details + +HRESULT CBaseControlVideo::CheckTargetRect(RECT *pTargetRect) +{ + // Check the pointer is valid + + if (pTargetRect == NULL) { + return E_POINTER; + } + + // These overflow the WIDTH and HEIGHT checks + + if (pTargetRect->left > pTargetRect->right || + pTargetRect->top > pTargetRect->bottom) { + return E_INVALIDARG; + } + + // Check the rectangle has valid coordinates + + if (WIDTH(pTargetRect) <= 0 || HEIGHT(pTargetRect) <= 0) { + return E_INVALIDARG; + } + + ASSERT(IsRectEmpty(pTargetRect) == FALSE); + return NOERROR; +} + diff --git a/ThirdParty/strmbas/winctrl.h b/ThirdParty/strmbas/winctrl.h new file mode 100644 index 0000000..a7c7f5c --- /dev/null +++ b/ThirdParty/strmbas/winctrl.h @@ -0,0 +1,224 @@ +//------------------------------------------------------------------------------ +// File: WinCtrl.h +// +// Desc: DirectShow base classes - defines classes for video control +// interfaces. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +#ifndef __WINCTRL__ +#define __WINCTRL__ + +#define ABSOL(x) (x < 0 ? -x : x) +#define NEGAT(x) (x > 0 ? -x : x) + +// Helper +BOOL WINAPI PossiblyEatMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +class CBaseControlWindow : public CBaseVideoWindow, public CBaseWindow +{ +protected: + + CBaseFilter *m_pFilter; // Pointer to owning media filter + CBasePin *m_pPin; // Controls media types for connection + CCritSec *m_pInterfaceLock; // Externally defined critical section + COLORREF m_BorderColour; // Current window border colour + BOOL m_bAutoShow; // What happens when the state changes + HWND m_hwndOwner; // Owner window that we optionally have + HWND m_hwndDrain; // HWND to post any messages received + BOOL m_bCursorHidden; // Should we hide the window cursor + +public: + + // Internal methods for other objects to get information out + + HRESULT DoSetWindowStyle(long Style,long WindowLong); + HRESULT DoGetWindowStyle(long *pStyle,long WindowLong); + BOOL IsAutoShowEnabled() { return m_bAutoShow; }; + COLORREF GetBorderColour() { return m_BorderColour; }; + HWND GetOwnerWindow() { return m_hwndOwner; }; + BOOL IsCursorHidden() { return m_bCursorHidden; }; + + inline BOOL PossiblyEatMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + return ::PossiblyEatMessage(m_hwndDrain, uMsg, wParam, lParam); + } + + // Derived classes must call this to set the pin the filter is using + // We don't have the pin passed in to the constructor (as we do with + // the CBaseFilter object) because filters typically create the + // pins dynamically when requested in CBaseFilter::GetPin. This can + // not be called from our constructor because is is a virtual method + + void SetControlWindowPin(CBasePin *pPin) { + m_pPin = pPin; + } + +public: + + CBaseControlWindow(CBaseFilter *pFilter, // Owning media filter + CCritSec *pInterfaceLock, // Locking object + TCHAR *pName, // Object description + LPUNKNOWN pUnk, // Normal COM ownership + HRESULT *phr); // OLE return code + + // These are the properties we support + + STDMETHODIMP put_Caption(BSTR strCaption); + STDMETHODIMP get_Caption(BSTR *pstrCaption); + STDMETHODIMP put_AutoShow(long AutoShow); + STDMETHODIMP get_AutoShow(long *AutoShow); + STDMETHODIMP put_WindowStyle(long WindowStyle); + STDMETHODIMP get_WindowStyle(long *pWindowStyle); + STDMETHODIMP put_WindowStyleEx(long WindowStyleEx); + STDMETHODIMP get_WindowStyleEx(long *pWindowStyleEx); + STDMETHODIMP put_WindowState(long WindowState); + STDMETHODIMP get_WindowState(long *pWindowState); + STDMETHODIMP put_BackgroundPalette(long BackgroundPalette); + STDMETHODIMP get_BackgroundPalette(long *pBackgroundPalette); + STDMETHODIMP put_Visible(long Visible); + STDMETHODIMP get_Visible(long *pVisible); + STDMETHODIMP put_Left(long Left); + STDMETHODIMP get_Left(long *pLeft); + STDMETHODIMP put_Width(long Width); + STDMETHODIMP get_Width(long *pWidth); + STDMETHODIMP put_Top(long Top); + STDMETHODIMP get_Top(long *pTop); + STDMETHODIMP put_Height(long Height); + STDMETHODIMP get_Height(long *pHeight); + STDMETHODIMP put_Owner(OAHWND Owner); + STDMETHODIMP get_Owner(OAHWND *Owner); + STDMETHODIMP put_MessageDrain(OAHWND Drain); + STDMETHODIMP get_MessageDrain(OAHWND *Drain); + STDMETHODIMP get_BorderColor(long *Color); + STDMETHODIMP put_BorderColor(long Color); + STDMETHODIMP get_FullScreenMode(long *FullScreenMode); + STDMETHODIMP put_FullScreenMode(long FullScreenMode); + + // And these are the methods + + STDMETHODIMP SetWindowForeground(long Focus); + STDMETHODIMP NotifyOwnerMessage(OAHWND hwnd,long uMsg,LONG_PTR wParam,LONG_PTR lParam); + STDMETHODIMP GetMinIdealImageSize(long *pWidth,long *pHeight); + STDMETHODIMP GetMaxIdealImageSize(long *pWidth,long *pHeight); + STDMETHODIMP SetWindowPosition(long Left,long Top,long Width,long Height); + STDMETHODIMP GetWindowPosition(long *pLeft,long *pTop,long *pWidth,long *pHeight); + STDMETHODIMP GetRestorePosition(long *pLeft,long *pTop,long *pWidth,long *pHeight); + STDMETHODIMP HideCursor(long HideCursor); + STDMETHODIMP IsCursorHidden(long *CursorHidden); +}; + +// This class implements the IBasicVideo interface + +class CBaseControlVideo : public CBaseBasicVideo +{ +protected: + + CBaseFilter *m_pFilter; // Pointer to owning media filter + CBasePin *m_pPin; // Controls media types for connection + CCritSec *m_pInterfaceLock; // Externally defined critical section + +public: + + // Derived classes must provide these for the implementation + + virtual HRESULT IsDefaultTargetRect() PURE; + virtual HRESULT SetDefaultTargetRect() PURE; + virtual HRESULT SetTargetRect(RECT *pTargetRect) PURE; + virtual HRESULT GetTargetRect(RECT *pTargetRect) PURE; + virtual HRESULT IsDefaultSourceRect() PURE; + virtual HRESULT SetDefaultSourceRect() PURE; + virtual HRESULT SetSourceRect(RECT *pSourceRect) PURE; + virtual HRESULT GetSourceRect(RECT *pSourceRect) PURE; + virtual HRESULT GetStaticImage(long *pBufferSize,long *pDIBImage) PURE; + + // Derived classes must override this to return a VIDEOINFO representing + // the video format. We cannot call IPin ConnectionMediaType to get this + // format because various filters dynamically change the type when using + // DirectDraw such that the format shows the position of the logical + // bitmap in a frame buffer surface, so the size might be returned as + // 1024x768 pixels instead of 320x240 which is the real video dimensions + + virtual VIDEOINFOHEADER *GetVideoFormat() PURE; + + // Helper functions for creating memory renderings of a DIB image + + HRESULT GetImageSize(VIDEOINFOHEADER *pVideoInfo, + LONG *pBufferSize, + RECT *pSourceRect); + + HRESULT CopyImage(IMediaSample *pMediaSample, + VIDEOINFOHEADER *pVideoInfo, + LONG *pBufferSize, + BYTE *pVideoImage, + RECT *pSourceRect); + + // Override this if you want notifying when the rectangles change + virtual HRESULT OnUpdateRectangles() { return NOERROR; }; + virtual HRESULT OnVideoSizeChange(); + + // Derived classes must call this to set the pin the filter is using + // We don't have the pin passed in to the constructor (as we do with + // the CBaseFilter object) because filters typically create the + // pins dynamically when requested in CBaseFilter::GetPin. This can + // not be called from our constructor because is is a virtual method + + void SetControlVideoPin(CBasePin *pPin) { + m_pPin = pPin; + } + + // Helper methods for checking rectangles + virtual HRESULT CheckSourceRect(RECT *pSourceRect); + virtual HRESULT CheckTargetRect(RECT *pTargetRect); + +public: + + CBaseControlVideo(CBaseFilter *pFilter, // Owning media filter + CCritSec *pInterfaceLock, // Serialise interface + TCHAR *pName, // Object description + LPUNKNOWN pUnk, // Normal COM ownership + HRESULT *phr); // OLE return code + + // These are the properties we support + + STDMETHODIMP get_AvgTimePerFrame(REFTIME *pAvgTimePerFrame); + STDMETHODIMP get_BitRate(long *pBitRate); + STDMETHODIMP get_BitErrorRate(long *pBitErrorRate); + STDMETHODIMP get_VideoWidth(long *pVideoWidth); + STDMETHODIMP get_VideoHeight(long *pVideoHeight); + STDMETHODIMP put_SourceLeft(long SourceLeft); + STDMETHODIMP get_SourceLeft(long *pSourceLeft); + STDMETHODIMP put_SourceWidth(long SourceWidth); + STDMETHODIMP get_SourceWidth(long *pSourceWidth); + STDMETHODIMP put_SourceTop(long SourceTop); + STDMETHODIMP get_SourceTop(long *pSourceTop); + STDMETHODIMP put_SourceHeight(long SourceHeight); + STDMETHODIMP get_SourceHeight(long *pSourceHeight); + STDMETHODIMP put_DestinationLeft(long DestinationLeft); + STDMETHODIMP get_DestinationLeft(long *pDestinationLeft); + STDMETHODIMP put_DestinationWidth(long DestinationWidth); + STDMETHODIMP get_DestinationWidth(long *pDestinationWidth); + STDMETHODIMP put_DestinationTop(long DestinationTop); + STDMETHODIMP get_DestinationTop(long *pDestinationTop); + STDMETHODIMP put_DestinationHeight(long DestinationHeight); + STDMETHODIMP get_DestinationHeight(long *pDestinationHeight); + + // And these are the methods + + STDMETHODIMP GetVideoSize(long *pWidth,long *pHeight); + STDMETHODIMP SetSourcePosition(long Left,long Top,long Width,long Height); + STDMETHODIMP GetSourcePosition(long *pLeft,long *pTop,long *pWidth,long *pHeight); + STDMETHODIMP GetVideoPaletteEntries(long StartIndex,long Entries,long *pRetrieved,long *pPalette); + STDMETHODIMP SetDefaultSourcePosition(); + STDMETHODIMP IsUsingDefaultSource(); + STDMETHODIMP SetDestinationPosition(long Left,long Top,long Width,long Height); + STDMETHODIMP GetDestinationPosition(long *pLeft,long *pTop,long *pWidth,long *pHeight); + STDMETHODIMP SetDefaultDestinationPosition(); + STDMETHODIMP IsUsingDefaultDestination(); + STDMETHODIMP GetCurrentImage(long *pBufferSize,long *pVideoImage); +}; + +#endif // __WINCTRL__ + diff --git a/ThirdParty/strmbas/winutil.cpp b/ThirdParty/strmbas/winutil.cpp new file mode 100644 index 0000000..46c33ae --- /dev/null +++ b/ThirdParty/strmbas/winutil.cpp @@ -0,0 +1,2681 @@ +//------------------------------------------------------------------------------ +// File: WinUtil.cpp +// +// Desc: DirectShow base classes - implements generic window handler class. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +#include +#include +#include + +static UINT MsgDestroy; + +// Constructor + +CBaseWindow::CBaseWindow(BOOL bDoGetDC, bool bDoPostToDestroy) : + m_hInstance(g_hInst), + m_hwnd(NULL), + m_hdc(NULL), + m_bActivated(FALSE), + m_pClassName(NULL), + m_ClassStyles(0), + m_WindowStyles(0), + m_WindowStylesEx(0), + m_ShowStageMessage(0), + m_ShowStageTop(0), + m_MemoryDC(NULL), + m_hPalette(NULL), + m_bBackground(FALSE), +#ifdef DEBUG + m_bRealizing(FALSE), +#endif + m_bNoRealize(FALSE), + m_bDoPostToDestroy(bDoPostToDestroy) +{ + m_bDoGetDC = bDoGetDC; +} + + +// Prepare a window by spinning off a worker thread to do the creation and +// also poll the message input queue. We leave this to be called by derived +// classes because they might want to override methods like MessageLoop and +// InitialiseWindow, if we do this during construction they'll ALWAYS call +// this base class methods. We make the worker thread create the window so +// it owns it rather than the filter graph thread which is constructing us + +HRESULT CBaseWindow::PrepareWindow() +{ + if (m_hwnd) return NOERROR; + ASSERT(m_hwnd == NULL); + ASSERT(m_hdc == NULL); + + // Get the derived object's window and class styles + + m_pClassName = GetClassWindowStyles(&m_ClassStyles, + &m_WindowStyles, + &m_WindowStylesEx); + if (m_pClassName == NULL) { + return E_FAIL; + } + + // Register our special private messages + m_ShowStageMessage = RegisterWindowMessage(SHOWSTAGE); + + // RegisterWindowMessage() returns 0 if an error occurs. + if (0 == m_ShowStageMessage) { + return AmGetLastErrorToHResult(); + } + + m_ShowStageTop = RegisterWindowMessage(SHOWSTAGETOP); + if (0 == m_ShowStageTop) { + return AmGetLastErrorToHResult(); + } + + m_RealizePalette = RegisterWindowMessage(REALIZEPALETTE); + if (0 == m_RealizePalette) { + return AmGetLastErrorToHResult(); + } + + MsgDestroy = RegisterWindowMessage(TEXT("AM_DESTROY")); + if (0 == MsgDestroy) { + return AmGetLastErrorToHResult(); + } + + return DoCreateWindow(); +} + + +// Destructor just a placeholder so that we know it becomes virtual +// Derived classes MUST call DoneWithWindow in their destructors so +// that no messages arrive after the derived class constructor ends + +#ifdef DEBUG +CBaseWindow::~CBaseWindow() +{ + ASSERT(m_hwnd == NULL); + ASSERT(m_hdc == NULL); +} +#endif + + +// We use the sync worker event to have the window destroyed. All we do is +// signal the event and wait on the window thread handle. Trying to send it +// messages causes too many problems, furthermore to be on the safe side we +// just wait on the thread handle while it returns WAIT_TIMEOUT or there is +// a sent message to process on this thread. If the constructor failed to +// create the thread in the first place then the loop will get terminated + +HRESULT CBaseWindow::DoneWithWindow() +{ + if (!IsWindow(m_hwnd) || (GetWindowThreadProcessId(m_hwnd, NULL) != GetCurrentThreadId())) { + + if (IsWindow(m_hwnd)) { + + if (m_bDoPostToDestroy) { + + CAMEvent m_evDone; + + // We must post a message to destroy the window + // That way we can't be in the middle of processing a + // message posted to our window when we do go away + // Sending a message gives less synchronization. + PostMessage(m_hwnd, MsgDestroy, (WPARAM)(HANDLE)m_evDone, 0); + WaitDispatchingMessages(m_evDone, INFINITE); + } else { + SendMessage(m_hwnd, MsgDestroy, 0, 0); + } + } + + // + // This is not a leak, the window manager automatically free's + // hdc's that were got via GetDC, which is the case here. + // We set it to NULL so that we don't get any asserts later. + // + m_hdc = NULL; + + // + // We need to free this DC though because USER32 does not know + // anything about it. + // + if (m_MemoryDC) + { + EXECUTE_ASSERT(DeleteDC(m_MemoryDC)); + m_MemoryDC = NULL; + } + + // Reset the window variables + m_hwnd = NULL; + + return NOERROR; + } + const HWND hwnd = m_hwnd; + if (hwnd == NULL) { + return NOERROR; + } + + InactivateWindow(); + NOTE("Inactivated"); + + // Reset the window styles before destruction + + SetWindowLong(hwnd,GWL_STYLE,m_WindowStyles); + ASSERT(GetParent(hwnd) == NULL); + NOTE1("Reset window styles %d",m_WindowStyles); + + // UnintialiseWindow sets m_hwnd to NULL so save a copy + UninitialiseWindow(); + DbgLog((LOG_TRACE, 2, TEXT("Destroying 0x%8.8X"), hwnd)); + if (!DestroyWindow(hwnd)) { + DbgLog((LOG_TRACE, 0, TEXT("DestroyWindow %8.8X failed code %d"), + hwnd, GetLastError())); + DbgBreak(""); + } + + // Reset our state so we can be prepared again + + m_pClassName = NULL; + m_ClassStyles = 0; + m_WindowStyles = 0; + m_WindowStylesEx = 0; + m_ShowStageMessage = 0; + m_ShowStageTop = 0; + + return NOERROR; +} + + +// Called at the end to put the window in an inactive state. The pending list +// will always have been cleared by this time so event if the worker thread +// gets has been signaled and gets in to render something it will find both +// the state has been changed and that there are no available sample images +// Since we wait on the window thread to complete we don't lock the object + +HRESULT CBaseWindow::InactivateWindow() +{ + // Has the window been activated + if (m_bActivated == FALSE) { + return S_FALSE; + } + + m_bActivated = FALSE; + ShowWindow(m_hwnd,SW_HIDE); + return NOERROR; +} + + +HRESULT CBaseWindow::CompleteConnect() +{ + m_bActivated = FALSE; + return NOERROR; +} + +// This displays a normal window. We ask the base window class for default +// sizes which unless overriden will return DEFWIDTH and DEFHEIGHT. We go +// through a couple of extra hoops to get the client area the right size +// as the object specifies which accounts for the AdjustWindowRectEx calls +// We also DWORD align the left and top coordinates of the window here to +// maximise the chance of being able to use DCI/DirectDraw primary surface + +HRESULT CBaseWindow::ActivateWindow() +{ + // Has the window been sized and positioned already + + if (m_bActivated == TRUE || GetParent(m_hwnd) != NULL) { + + SetWindowPos(m_hwnd, // Our window handle + HWND_TOP, // Put it at the top + 0, 0, 0, 0, // Leave in current position + SWP_NOMOVE | // Don't change it's place + SWP_NOSIZE); // Change Z-order only + + m_bActivated = TRUE; + return S_FALSE; + } + + // Calculate the desired client rectangle + + RECT WindowRect, ClientRect = GetDefaultRect(); + GetWindowRect(m_hwnd,&WindowRect); + AdjustWindowRectEx(&ClientRect,GetWindowLong(m_hwnd,GWL_STYLE), + FALSE,GetWindowLong(m_hwnd,GWL_EXSTYLE)); + + // Align left and top edges on DWORD boundaries + + UINT WindowFlags = (SWP_NOACTIVATE | SWP_FRAMECHANGED); + WindowRect.left -= (WindowRect.left & 3); + WindowRect.top -= (WindowRect.top & 3); + + SetWindowPos(m_hwnd, // Window handle + HWND_TOP, // Put it at the top + WindowRect.left, // Align left edge + WindowRect.top, // And also top place + WIDTH(&ClientRect), // Horizontal size + HEIGHT(&ClientRect), // Vertical size + WindowFlags); // Don't show window + + m_bActivated = TRUE; + return NOERROR; +} + + +// This can be used to DWORD align the window for maximum performance + +HRESULT CBaseWindow::PerformanceAlignWindow() +{ + RECT ClientRect,WindowRect; + GetWindowRect(m_hwnd,&WindowRect); + ASSERT(m_bActivated == TRUE); + + // Don't do this if we're owned + + if (GetParent(m_hwnd)) { + return NOERROR; + } + + // Align left and top edges on DWORD boundaries + + GetClientRect(m_hwnd, &ClientRect); + MapWindowPoints(m_hwnd, HWND_DESKTOP, (LPPOINT) &ClientRect, 2); + WindowRect.left -= (ClientRect.left & 3); + WindowRect.top -= (ClientRect.top & 3); + UINT WindowFlags = (SWP_NOACTIVATE | SWP_NOSIZE); + + SetWindowPos(m_hwnd, // Window handle + HWND_TOP, // Put it at the top + WindowRect.left, // Align left edge + WindowRect.top, // And also top place + (int) 0,(int) 0, // Ignore these sizes + WindowFlags); // Don't show window + + return NOERROR; +} + + +// Install a palette into the base window - we may be called by a different +// thread to the one that owns the window. We have to be careful how we do +// the palette realisation as we could be a different thread to the window +// which would cause an inter thread send message. Therefore we realise the +// palette by sending it a special message but without the window locked + +HRESULT CBaseWindow::SetPalette(HPALETTE hPalette) +{ + // We must own the window lock during the change + { + CAutoLock cWindowLock(&m_WindowLock); + CAutoLock cPaletteLock(&m_PaletteLock); + ASSERT(hPalette); + m_hPalette = hPalette; + } + return SetPalette(); +} + + +HRESULT CBaseWindow::SetPalette() +{ + if (!m_bNoRealize) { + SendMessage(m_hwnd, m_RealizePalette, 0, 0); + return S_OK; + } else { + // Just select the palette + ASSERT(m_hdc); + ASSERT(m_MemoryDC); + + CAutoLock cPaletteLock(&m_PaletteLock); + SelectPalette(m_hdc,m_hPalette,m_bBackground); + SelectPalette(m_MemoryDC,m_hPalette,m_bBackground); + + return S_OK; + } +} + + +void CBaseWindow::UnsetPalette() +{ + CAutoLock cWindowLock(&m_WindowLock); + CAutoLock cPaletteLock(&m_PaletteLock); + + // Get a standard VGA colour palette + + HPALETTE hPalette = (HPALETTE) GetStockObject(DEFAULT_PALETTE); + ASSERT(hPalette); + + SelectPalette(GetWindowHDC(), hPalette, TRUE); + SelectPalette(GetMemoryHDC(), hPalette, TRUE); + + m_hPalette = NULL; +} + + +void CBaseWindow::LockPaletteLock() +{ + m_PaletteLock.Lock(); +} + + +void CBaseWindow::UnlockPaletteLock() +{ + m_PaletteLock.Unlock(); +} + + +// Realise our palettes in the window and device contexts + +HRESULT CBaseWindow::DoRealisePalette(BOOL bForceBackground) +{ + { + CAutoLock cPaletteLock(&m_PaletteLock); + + if (m_hPalette == NULL) { + return NOERROR; + } + + // Realize the palette on the window thread + ASSERT(m_hdc); + ASSERT(m_MemoryDC); + + SelectPalette(m_hdc,m_hPalette,m_bBackground || bForceBackground); + SelectPalette(m_MemoryDC,m_hPalette,m_bBackground); + } + + // If we grab a critical section here we can deadlock + // with the window thread because one of the side effects + // of RealizePalette is to send a WM_PALETTECHANGED message + // to every window in the system. In our handling + // of WM_PALETTECHANGED we used to grab this CS too. + // The really bad case is when our renderer calls DoRealisePalette() + // while we're in the middle of processing a palette change + // for another window. + // So don't hold the critical section while actually realising + // the palette. In any case USER is meant to manage palette + // handling - we shouldn't have to serialize everything as well + ASSERT(CritCheckOut(&m_WindowLock)); + ASSERT(CritCheckOut(&m_PaletteLock)); + + EXECUTE_ASSERT(RealizePalette(m_hdc) != GDI_ERROR); + EXECUTE_ASSERT(RealizePalette(m_MemoryDC) != GDI_ERROR); + + return (GdiFlush() == FALSE ? S_FALSE : S_OK); +} + + +// This is the global window procedure + +LRESULT CALLBACK WndProc(HWND hwnd, // Window handle + UINT uMsg, // Message ID + WPARAM wParam, // First parameter + LPARAM lParam) // Other parameter +{ + + // Get the window long that holds our window object pointer + // If it is NULL then we are initialising the window in which + // case the object pointer has been passed in the window creation + // structure. IF we get any messages before WM_NCCREATE we will + // pass them to DefWindowProc. + + CBaseWindow *pBaseWindow = (CBaseWindow *)GetWindowLongPtr(hwnd,0); + if (pBaseWindow == NULL) { + + // Get the structure pointer from the create struct. + // We can only do this for WM_NCCREATE which should be one of + // the first messages we receive. Anything before this will + // have to be passed to DefWindowProc (i.e. WM_GETMINMAXINFO) + + // If the message is WM_NCCREATE we set our pBaseWindow pointer + // and will then place it in the window structure + + // turn off WS_EX_LAYOUTRTL style for quartz windows + if (uMsg == WM_NCCREATE) { + SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~0x400000); + } + + if ((uMsg != WM_NCCREATE) + || (NULL == (pBaseWindow = *(CBaseWindow**) ((LPCREATESTRUCT)lParam)->lpCreateParams))) + { + return(DefWindowProc(hwnd, uMsg, wParam, lParam)); + } + + // Set the window LONG to be the object who created us +#ifdef DEBUG + SetLastError(0); // because of the way SetWindowLong works +#endif + LONG_PTR rc = SetWindowLongPtr(hwnd, (DWORD) 0, (LONG_PTR) pBaseWindow); +#ifdef DEBUG + if (0 == rc) { + // SetWindowLong MIGHT have failed. (Read the docs which admit + // that it is awkward to work out if you have had an error.) + LONG lasterror = GetLastError(); + ASSERT(0 == lasterror); + // If this is not the case we have not set the pBaseWindow pointer + // into the window structure and we will blow up. + } +#endif + + } + // See if this is the packet of death + if (uMsg == MsgDestroy && uMsg != 0) { + pBaseWindow->DoneWithWindow(); + if (pBaseWindow->m_bDoPostToDestroy) { + EXECUTE_ASSERT(SetEvent((HANDLE)wParam)); + } + return 0; + } + return pBaseWindow->OnReceiveMessage(hwnd,uMsg,wParam,lParam); +} + + +// When the window size changes we adjust our member variables that +// contain the dimensions of the client rectangle for our window so +// that we come to render an image we will know whether to stretch + +BOOL CBaseWindow::OnSize(LONG Width, LONG Height) +{ + m_Width = Width; + m_Height = Height; + return TRUE; +} + + +// This function handles the WM_CLOSE message + +BOOL CBaseWindow::OnClose() +{ + ShowWindow(m_hwnd,SW_HIDE); + return TRUE; +} + + +// This is called by the worker window thread when it receives a terminate +// message from the window object destructor to delete all the resources we +// allocated during initialisation. By the time the worker thread exits all +// processing will have been completed as the source filter disconnection +// flushes the image pending sample, therefore the GdiFlush should succeed + +HRESULT CBaseWindow::UninitialiseWindow() +{ + // Have we already cleaned up + + if (m_hwnd == NULL) { + ASSERT(m_hdc == NULL); + ASSERT(m_MemoryDC == NULL); + return NOERROR; + } + + // Release the window resources + + EXECUTE_ASSERT(GdiFlush()); + + if (m_hdc) + { + EXECUTE_ASSERT(ReleaseDC(m_hwnd,m_hdc)); + m_hdc = NULL; + } + + if (m_MemoryDC) + { + EXECUTE_ASSERT(DeleteDC(m_MemoryDC)); + m_MemoryDC = NULL; + } + + // Reset the window variables + m_hwnd = NULL; + + return NOERROR; +} + + +// This is called by the worker window thread after it has created the main +// window and it wants to initialise the rest of the owner objects window +// variables such as the device contexts. We execute this function with the +// critical section still locked. Nothing in this function must generate any +// SendMessage calls to the window because this is executing on the window +// thread so the message will never be processed and we will deadlock + +HRESULT CBaseWindow::InitialiseWindow(HWND hwnd) +{ + // Initialise the window variables + + ASSERT(IsWindow(hwnd)); + m_hwnd = hwnd; + + if (m_bDoGetDC) + { + EXECUTE_ASSERT(m_hdc = GetDC(hwnd)); + EXECUTE_ASSERT(m_MemoryDC = CreateCompatibleDC(m_hdc)); + + EXECUTE_ASSERT(SetStretchBltMode(m_hdc,COLORONCOLOR)); + EXECUTE_ASSERT(SetStretchBltMode(m_MemoryDC,COLORONCOLOR)); + } + + return NOERROR; +} + +HRESULT CBaseWindow::DoCreateWindow() +{ + WNDCLASS wndclass; // Used to register classes + BOOL bRegistered; // Is this class registered + HWND hwnd; // Handle to our window + + bRegistered = GetClassInfo(m_hInstance, // Module instance + m_pClassName, // Window class + &wndclass); // Info structure + + // if the window is to be used for drawing puposes and we are getting a DC + // for the entire lifetime of the window then changes the class style to do + // say so. If we don't set this flag then the DC comes from the cache and is + // really bad. + if (m_bDoGetDC) + { + m_ClassStyles |= CS_OWNDC; + } + + if (bRegistered == FALSE) { + + // Register the renderer window class + + wndclass.lpszClassName = m_pClassName; + wndclass.style = m_ClassStyles; + wndclass.lpfnWndProc = WndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = sizeof(CBaseWindow *); + wndclass.hInstance = m_hInstance; + wndclass.hIcon = NULL; + wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH) NULL; + wndclass.lpszMenuName = NULL; + + RegisterClass(&wndclass); + } + + // Create the frame window. Pass the pBaseWindow information in the + // CreateStruct which allows our message handling loop to get hold of + // the pBaseWindow pointer. + + CBaseWindow *pBaseWindow = this; // The owner window object + hwnd = CreateWindowEx(m_WindowStylesEx, // Extended styles + m_pClassName, // Registered name + TEXT("ActiveMovie Window"), // Window title + m_WindowStyles, // Window styles + CW_USEDEFAULT, // Start x position + CW_USEDEFAULT, // Start y position + DEFWIDTH, // Window width + DEFHEIGHT, // Window height + NULL, // Parent handle + NULL, // Menu handle + m_hInstance, // Instance handle + &pBaseWindow); // Creation data + + // If we failed signal an error to the object constructor (based on the + // last Win32 error on this thread) then signal the constructor thread + // to continue, release the mutex to let others have a go and exit + + if (hwnd == NULL) { + DWORD Error = GetLastError(); + return AmHresultFromWin32(Error); + } + + // Check the window LONG is the object who created us + ASSERT(GetWindowLongPtr(hwnd, 0) == (LONG_PTR)this); + + // Initialise the window and then signal the constructor so that it can + // continue and then finally unlock the object's critical section. The + // window class is left registered even after we terminate the thread + // as we don't know when the last window has been closed. So we allow + // the operating system to free the class resources as appropriate + + InitialiseWindow(hwnd); + + DbgLog((LOG_TRACE, 2, TEXT("Created window class (%s) HWND(%8.8X)"), + m_pClassName, hwnd)); + + return S_OK; +} + + +// The base class provides some default handling and calls DefWindowProc + +LRESULT CBaseWindow::OnReceiveMessage(HWND hwnd, // Window handle + UINT uMsg, // Message ID + WPARAM wParam, // First parameter + LPARAM lParam) // Other parameter +{ + ASSERT(IsWindow(hwnd)); + + if (PossiblyEatMessage(uMsg, wParam, lParam)) + return 0; + + // This is sent by the IVideoWindow SetWindowForeground method. If the + // window is invisible we will show it and make it topmost without the + // foreground focus. If the window is visible it will also be made the + // topmost window without the foreground focus. If wParam is TRUE then + // for both cases the window will be forced into the foreground focus + + if (uMsg == m_ShowStageMessage) { + + BOOL bVisible = IsWindowVisible(hwnd); + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | + (bVisible ? SWP_NOACTIVATE : 0)); + + // Should we bring the window to the foreground + if (wParam == TRUE) { + SetForegroundWindow(hwnd); + } + return (LRESULT) 1; + } + + // When we go fullscreen we have to add the WS_EX_TOPMOST style to the + // video window so that it comes out above any task bar (this is more + // relevant to WindowsNT than Windows95). However the SetWindowPos call + // must be on the same thread as that which created the window. The + // wParam parameter can be TRUE or FALSE to set and reset the topmost + + if (uMsg == m_ShowStageTop) { + HWND HwndTop = (wParam == TRUE ? HWND_TOPMOST : HWND_NOTOPMOST); + BOOL bVisible = IsWindowVisible(hwnd); + SetWindowPos(hwnd, HwndTop, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | + (wParam == TRUE ? SWP_SHOWWINDOW : 0) | + (bVisible ? SWP_NOACTIVATE : 0)); + return (LRESULT) 1; + } + + // New palette stuff + if (uMsg == m_RealizePalette) { + ASSERT(m_hwnd == hwnd); + return OnPaletteChange(m_hwnd,WM_QUERYNEWPALETTE); + } + + switch (uMsg) { + + // Repaint the window if the system colours change + + case WM_SYSCOLORCHANGE: + + InvalidateRect(hwnd,NULL,FALSE); + return (LRESULT) 1; + + // Somebody has changed the palette + case WM_PALETTECHANGED: + + OnPaletteChange((HWND)wParam,uMsg); + return (LRESULT) 0; + + // We are about to receive the keyboard focus so we ask GDI to realise + // our logical palette again and hopefully it will be fully installed + // without any mapping having to be done during any picture rendering + + case WM_QUERYNEWPALETTE: + ASSERT(m_hwnd == hwnd); + return OnPaletteChange(m_hwnd,uMsg); + + // do NOT fwd WM_MOVE. the parameters are the location of the parent + // window, NOT what the renderer should be looking at. But we need + // to make sure the overlay is moved with the parent window, so we + // do this. + case WM_MOVE: + if (IsWindowVisible(m_hwnd)) { + PostMessage(m_hwnd,WM_PAINT,0,0); + } + break; + + // Store the width and height as useful base class members + + case WM_SIZE: + + OnSize(LOWORD(lParam), HIWORD(lParam)); + return (LRESULT) 0; + + // Intercept the WM_CLOSE messages to hide the window + + case WM_CLOSE: + + OnClose(); + return (LRESULT) 0; + } + return DefWindowProc(hwnd,uMsg,wParam,lParam); +} + + +// This handles the Windows palette change messages - if we do realise our +// palette then we return TRUE otherwise we return FALSE. If our window is +// foreground application then we should get first choice of colours in the +// system palette entries. We get best performance when our logical palette +// includes the standard VGA colours (at the beginning and end) otherwise +// GDI may have to map from our palette to the device palette while drawing + +LRESULT CBaseWindow::OnPaletteChange(HWND hwnd,UINT Message) +{ + // First check we are not changing the palette during closedown + + if (m_hwnd == NULL || hwnd == NULL) { + return (LRESULT) 0; + } + ASSERT(!m_bRealizing); + + // Should we realise our palette again + + if ((Message == WM_QUERYNEWPALETTE || hwnd != m_hwnd)) { + // It seems that even if we're invisible that we can get asked + // to realize our palette and this can cause really ugly side-effects + // Seems like there's another bug but this masks it a least for the + // shutting down case. + if (!IsWindowVisible(m_hwnd)) { + DbgLog((LOG_TRACE, 1, TEXT("Realizing when invisible!"))); + return (LRESULT) 0; + } + + // Avoid recursion with multiple graphs in the same app +#ifdef DEBUG + m_bRealizing = TRUE; +#endif + DoRealisePalette(Message != WM_QUERYNEWPALETTE); +#ifdef DEBUG + m_bRealizing = FALSE; +#endif + + // Should we redraw the window with the new palette + if (Message == WM_PALETTECHANGED) { + InvalidateRect(m_hwnd,NULL,FALSE); + } + } + + return (LRESULT) 1; +} + + +// Determine if the window exists. + +bool CBaseWindow::WindowExists() +{ + return !!IsWindow(m_hwnd); +} + + +// Return the default window rectangle + +RECT CBaseWindow::GetDefaultRect() +{ + RECT DefaultRect = {0,0,DEFWIDTH,DEFHEIGHT}; + ASSERT(m_hwnd); + // ASSERT(m_hdc); + return DefaultRect; +} + + +// Return the current window width + +LONG CBaseWindow::GetWindowWidth() +{ + ASSERT(m_hwnd); + // ASSERT(m_hdc); + return m_Width; +} + + +// Return the current window height + +LONG CBaseWindow::GetWindowHeight() +{ + ASSERT(m_hwnd); + // ASSERT(m_hdc); + return m_Height; +} + + +// Return the window handle + +HWND CBaseWindow::GetWindowHWND() +{ + ASSERT(m_hwnd); + // ASSERT(m_hdc); + return m_hwnd; +} + + +// Return the window drawing device context + +HDC CBaseWindow::GetWindowHDC() +{ + ASSERT(m_hwnd); + ASSERT(m_hdc); + return m_hdc; +} + + +// Return the offscreen window drawing device context + +HDC CBaseWindow::GetMemoryHDC() +{ + ASSERT(m_hwnd); + ASSERT(m_MemoryDC); + return m_MemoryDC; +} + + +#ifdef DEBUG +HPALETTE CBaseWindow::GetPalette() +{ + // The palette lock should always be held when accessing + // m_hPalette. + ASSERT(CritCheckIn(&m_PaletteLock)); + return m_hPalette; +} +#endif // DEBUG + + +// This is available to clients who want to change the window visiblity. It's +// little more than an indirection to the Win32 ShowWindow although these is +// some benefit in going through here as this function may change sometime + +HRESULT CBaseWindow::DoShowWindow(LONG ShowCmd) +{ + ShowWindow(m_hwnd,ShowCmd); + return NOERROR; +} + + +// Generate a WM_PAINT message for the video window + +void CBaseWindow::PaintWindow(BOOL bErase) +{ + InvalidateRect(m_hwnd,NULL,bErase); +} + + +// Allow an application to have us set the video window in the foreground. We +// have this because it is difficult for one thread to do do this to a window +// owned by another thread. Rather than expose the message we use to execute +// the inter thread send message we provide the interface function. All we do +// is to SendMessage to the video window renderer thread with a WM_SHOWSTAGE + +void CBaseWindow::DoSetWindowForeground(BOOL bFocus) +{ + SendMessage(m_hwnd,m_ShowStageMessage,(WPARAM) bFocus,(LPARAM) 0); +} + + +// Constructor initialises the owning object pointer. Since we are a worker +// class for the main window object we have relatively few state variables to +// look after. We are given device context handles to use later on as well as +// the source and destination rectangles (but reset them here just in case) + +CDrawImage::CDrawImage(CBaseWindow *pBaseWindow) : + m_pBaseWindow(pBaseWindow), + m_hdc(NULL), + m_MemoryDC(NULL), + m_bStretch(FALSE), + m_pMediaType(NULL), + m_bUsingImageAllocator(FALSE) +{ + ASSERT(pBaseWindow); + ResetPaletteVersion(); + SetRectEmpty(&m_TargetRect); + SetRectEmpty(&m_SourceRect); + + m_perfidRenderTime = MSR_REGISTER(TEXT("Single Blt time")); +} + + +// Overlay the image time stamps on the picture. Access to this method is +// serialised by the caller. We display the sample start and end times on +// top of the video using TextOut on the device context we are handed. If +// there isn't enough room in the window for the times we don't show them + +void CDrawImage::DisplaySampleTimes(IMediaSample *pSample) +{ +#ifdef DEBUG + // + // Only allow the "annoying" time messages if the users has turned the + // logging "way up" + // + BOOL bAccept = DbgCheckModuleLevel(LOG_TRACE, 5); + if (bAccept == FALSE) { + return; + } +#endif + + TCHAR szTimes[TIMELENGTH]; // Time stamp strings + ASSERT(pSample); // Quick sanity check + RECT ClientRect; // Client window size + SIZE Size; // Size of text output + + // Get the time stamps and window size + + pSample->GetTime((REFERENCE_TIME*)&m_StartSample, (REFERENCE_TIME*)&m_EndSample); + HWND hwnd = m_pBaseWindow->GetWindowHWND(); + EXECUTE_ASSERT(GetClientRect(hwnd,&ClientRect)); + + // Format the sample time stamps + + (void)StringCchPrintf(szTimes, NUMELMS(szTimes), TEXT("%08d : %08d"), + m_StartSample.Millisecs(), + m_EndSample.Millisecs()); + + ASSERT(lstrlen(szTimes) < TIMELENGTH); + + // Put the times in the middle at the bottom of the window + + GetTextExtentPoint32(m_hdc,szTimes,lstrlen(szTimes),&Size); + INT XPos = ((ClientRect.right - ClientRect.left) - Size.cx) / 2; + INT YPos = ((ClientRect.bottom - ClientRect.top) - Size.cy) * 4 / 5; + + // Check the window is big enough to have sample times displayed + + if ((XPos > 0) && (YPos > 0)) { + TextOut(m_hdc,XPos,YPos,szTimes,lstrlen(szTimes)); + } +} + + +// This is called when the drawing code sees that the image has a down level +// palette cookie. We simply call the SetDIBColorTable Windows API with the +// palette that is found after the BITMAPINFOHEADER - we return no errors + +void CDrawImage::UpdateColourTable(HDC hdc,BITMAPINFOHEADER *pbmi) +{ + ASSERT(pbmi->biClrUsed); + RGBQUAD *pColourTable = (RGBQUAD *)(pbmi+1); + + // Set the new palette in the device context + + UINT uiReturn = SetDIBColorTable(hdc,(UINT) 0, + pbmi->biClrUsed, + pColourTable); + + // Should always succeed but check in debug builds + ASSERT(uiReturn == pbmi->biClrUsed); +} + + +// No source rectangle scaling is done by the base class + +RECT CDrawImage::ScaleSourceRect(const RECT *pSource) +{ + ASSERT(pSource); + return *pSource; +} + + +// This is called when the funky output pin uses our allocator. The samples we +// allocate are special because the memory is shared between us and GDI thus +// removing one copy when we ask for the image to be rendered. The source type +// information is in the main renderer m_mtIn field which is initialised when +// the media type is agreed in SetMediaType, the media type may be changed on +// the fly if, for example, the source filter needs to change the palette + +void CDrawImage::FastRender(IMediaSample *pMediaSample) +{ + BITMAPINFOHEADER *pbmi; // Image format data + DIBDATA *pDibData; // Stores DIB information + BYTE *pImage; // Pointer to image data + HBITMAP hOldBitmap; // Store the old bitmap + CImageSample *pSample; // Pointer to C++ object + + ASSERT(m_pMediaType); + + // From the untyped source format block get the VIDEOINFO and subsequently + // the BITMAPINFOHEADER structure. We can cast the IMediaSample interface + // to a CImageSample object so we can retrieve it's DIBSECTION details + + pbmi = HEADER(m_pMediaType->Format()); + pSample = (CImageSample *) pMediaSample; + pDibData = pSample->GetDIBData(); + hOldBitmap = (HBITMAP) SelectObject(m_MemoryDC,pDibData->hBitmap); + + // Get a pointer to the real image data + + HRESULT hr = pMediaSample->GetPointer(&pImage); + if (FAILED(hr)) { + return; + } + + // Do we need to update the colour table, we increment our palette cookie + // each time we get a dynamic format change. The sample palette cookie is + // stored in the DIBDATA structure so we try to keep the fields in sync + // By the time we get to draw the images the format change will be done + // so all we do is ask the renderer for what it's palette version is + + if (pDibData->PaletteVersion < GetPaletteVersion()) { + ASSERT(pbmi->biBitCount <= iPALETTE); + UpdateColourTable(m_MemoryDC,pbmi); + pDibData->PaletteVersion = GetPaletteVersion(); + } + + // This allows derived classes to change the source rectangle that we do + // the drawing with. For example a renderer may ask a codec to stretch + // the video from 320x240 to 640x480, in which case the source we see in + // here will still be 320x240, although the source we want to draw with + // should be scaled up to 640x480. The base class implementation of this + // method does nothing but return the same rectangle as we are passed in + + RECT SourceRect = ScaleSourceRect(&m_SourceRect); + + // Is the window the same size as the video + + if (m_bStretch == FALSE) { + + // Put the image straight into the window + + BitBlt( + (HDC) m_hdc, // Target device HDC + m_TargetRect.left, // X sink position + m_TargetRect.top, // Y sink position + m_TargetRect.right - m_TargetRect.left, // Destination width + m_TargetRect.bottom - m_TargetRect.top, // Destination height + m_MemoryDC, // Source device context + SourceRect.left, // X source position + SourceRect.top, // Y source position + SRCCOPY); // Simple copy + + } else { + + // Stretch the image when copying to the window + + StretchBlt( + (HDC) m_hdc, // Target device HDC + m_TargetRect.left, // X sink position + m_TargetRect.top, // Y sink position + m_TargetRect.right - m_TargetRect.left, // Destination width + m_TargetRect.bottom - m_TargetRect.top, // Destination height + m_MemoryDC, // Source device HDC + SourceRect.left, // X source position + SourceRect.top, // Y source position + SourceRect.right - SourceRect.left, // Source width + SourceRect.bottom - SourceRect.top, // Source height + SRCCOPY); // Simple copy + } + + // This displays the sample times over the top of the image. This used to + // draw the times into the offscreen device context however that actually + // writes the text into the image data buffer which may not be writable + + #ifdef DEBUG + DisplaySampleTimes(pMediaSample); + #endif + + // Put the old bitmap back into the device context so we don't leak + SelectObject(m_MemoryDC,hOldBitmap); +} + + +// This is called when there is a sample ready to be drawn, unfortunately the +// output pin was being rotten and didn't choose our super excellent shared +// memory DIB allocator so we have to do this slow render using boring old GDI +// SetDIBitsToDevice and StretchDIBits. The down side of using these GDI +// functions is that the image data has to be copied across from our address +// space into theirs before going to the screen (although in reality the cost +// is small because all they do is to map the buffer into their address space) + +void CDrawImage::SlowRender(IMediaSample *pMediaSample) +{ + // Get the BITMAPINFOHEADER for the connection + + ASSERT(m_pMediaType); + BITMAPINFOHEADER *pbmi = HEADER(m_pMediaType->Format()); + BYTE *pImage; + + // Get the image data buffer + + HRESULT hr = pMediaSample->GetPointer(&pImage); + if (FAILED(hr)) { + return; + } + + // This allows derived classes to change the source rectangle that we do + // the drawing with. For example a renderer may ask a codec to stretch + // the video from 320x240 to 640x480, in which case the source we see in + // here will still be 320x240, although the source we want to draw with + // should be scaled up to 640x480. The base class implementation of this + // method does nothing but return the same rectangle as we are passed in + + RECT SourceRect = ScaleSourceRect(&m_SourceRect); + + LONG lAdjustedSourceTop = SourceRect.top; + // if the origin of bitmap is bottom-left, adjust soruce_rect_top + // to be the bottom-left corner instead of the top-left. + if (pbmi->biHeight > 0) { + lAdjustedSourceTop = pbmi->biHeight - SourceRect.bottom; + } + // Is the window the same size as the video + + if (m_bStretch == FALSE) { + + // Put the image straight into the window + + SetDIBitsToDevice( + (HDC) m_hdc, // Target device HDC + m_TargetRect.left, // X sink position + m_TargetRect.top, // Y sink position + m_TargetRect.right - m_TargetRect.left, // Destination width + m_TargetRect.bottom - m_TargetRect.top, // Destination height + SourceRect.left, // X source position + lAdjustedSourceTop, // Adjusted Y source position + (UINT) 0, // Start scan line + pbmi->biHeight, // Scan lines present + pImage, // Image data + (BITMAPINFO *) pbmi, // DIB header + DIB_RGB_COLORS); // Type of palette + + } else { + + // Stretch the image when copying to the window + + StretchDIBits( + (HDC) m_hdc, // Target device HDC + m_TargetRect.left, // X sink position + m_TargetRect.top, // Y sink position + m_TargetRect.right - m_TargetRect.left, // Destination width + m_TargetRect.bottom - m_TargetRect.top, // Destination height + SourceRect.left, // X source position + lAdjustedSourceTop, // Adjusted Y source position + SourceRect.right - SourceRect.left, // Source width + SourceRect.bottom - SourceRect.top, // Source height + pImage, // Image data + (BITMAPINFO *) pbmi, // DIB header + DIB_RGB_COLORS, // Type of palette + SRCCOPY); // Simple image copy + } + + // This shows the sample reference times over the top of the image which + // looks a little flickery. I tried using GdiSetBatchLimit and GdiFlush to + // control the screen updates but it doesn't quite work as expected and + // only partially reduces the flicker. I also tried using a memory context + // and combining the two in that before doing a final BitBlt operation to + // the screen, unfortunately this has considerable performance penalties + // and also means that this code is not executed when compiled retail + + #ifdef DEBUG + DisplaySampleTimes(pMediaSample); + #endif +} + + +// This is called with an IMediaSample interface on the image to be drawn. We +// decide on the drawing mechanism based on who's allocator we are using. We +// may be called when the window wants an image painted by WM_PAINT messages +// We can't realise the palette here because we have the renderer lock, any +// call to realise may cause an interthread send message to the window thread +// which may in turn be waiting to get the renderer lock before servicing it + +BOOL CDrawImage::DrawImage(IMediaSample *pMediaSample) +{ + ASSERT(m_hdc); + ASSERT(m_MemoryDC); + NotifyStartDraw(); + + // If the output pin used our allocator then the samples passed are in + // fact CVideoSample objects that contain CreateDIBSection data that we + // use to do faster image rendering, they may optionally also contain a + // DirectDraw surface pointer in which case we do not do the drawing + + if (m_bUsingImageAllocator == FALSE) { + SlowRender(pMediaSample); + EXECUTE_ASSERT(GdiFlush()); + NotifyEndDraw(); + return TRUE; + } + + // This is a DIBSECTION buffer + + FastRender(pMediaSample); + EXECUTE_ASSERT(GdiFlush()); + NotifyEndDraw(); + return TRUE; +} + + +BOOL CDrawImage::DrawVideoImageHere( + HDC hdc, + IMediaSample *pMediaSample, + LPRECT lprcSrc, + LPRECT lprcDst + ) +{ + ASSERT(m_pMediaType); + BITMAPINFOHEADER *pbmi = HEADER(m_pMediaType->Format()); + BYTE *pImage; + + // Get the image data buffer + + HRESULT hr = pMediaSample->GetPointer(&pImage); + if (FAILED(hr)) { + return FALSE; + } + + RECT SourceRect; + RECT TargetRect; + + if (lprcSrc) { + SourceRect = *lprcSrc; + } + else SourceRect = ScaleSourceRect(&m_SourceRect); + + if (lprcDst) { + TargetRect = *lprcDst; + } + else TargetRect = m_TargetRect; + + LONG lAdjustedSourceTop = SourceRect.top; + // if the origin of bitmap is bottom-left, adjust soruce_rect_top + // to be the bottom-left corner instead of the top-left. + if (pbmi->biHeight > 0) { + lAdjustedSourceTop = pbmi->biHeight - SourceRect.bottom; + } + + + // Stretch the image when copying to the DC + + BOOL bRet = (0 != StretchDIBits(hdc, + TargetRect.left, + TargetRect.top, + TargetRect.right - TargetRect.left, + TargetRect.bottom - TargetRect.top, + SourceRect.left, + lAdjustedSourceTop, + SourceRect.right - SourceRect.left, + SourceRect.bottom - SourceRect.top, + pImage, + (BITMAPINFO *)pbmi, + DIB_RGB_COLORS, + SRCCOPY)); + return bRet; +} + + +// This is called by the owning window object after it has created the window +// and it's drawing contexts. We are constructed with the base window we'll +// be drawing into so when given the notification we retrive the device HDCs +// to draw with. We cannot call these in our constructor as they are virtual + +void CDrawImage::SetDrawContext() +{ + m_MemoryDC = m_pBaseWindow->GetMemoryHDC(); + m_hdc = m_pBaseWindow->GetWindowHDC(); +} + + +// This is called to set the target rectangle in the video window, it will be +// called whenever a WM_SIZE message is retrieved from the message queue. We +// simply store the rectangle and use it later when we do the drawing calls + +void CDrawImage::SetTargetRect(RECT *pTargetRect) +{ + ASSERT(pTargetRect); + m_TargetRect = *pTargetRect; + SetStretchMode(); +} + + +// Return the current target rectangle + +void CDrawImage::GetTargetRect(RECT *pTargetRect) +{ + ASSERT(pTargetRect); + *pTargetRect = m_TargetRect; +} + + +// This is called when we want to change the section of the image to draw. We +// use this information in the drawing operation calls later on. We must also +// see if the source and destination rectangles have the same dimensions. If +// not we must stretch during the drawing rather than a direct pixel copy + +void CDrawImage::SetSourceRect(RECT *pSourceRect) +{ + ASSERT(pSourceRect); + m_SourceRect = *pSourceRect; + SetStretchMode(); +} + + +// Return the current source rectangle + +void CDrawImage::GetSourceRect(RECT *pSourceRect) +{ + ASSERT(pSourceRect); + *pSourceRect = m_SourceRect; +} + + +// This is called when either the source or destination rectanges change so we +// can update the stretch flag. If the rectangles don't match we stretch the +// video during the drawing otherwise we call the fast pixel copy functions +// NOTE the source and/or the destination rectangle may be completely empty + +void CDrawImage::SetStretchMode() +{ + // Calculate the overall rectangle dimensions + + LONG SourceWidth = m_SourceRect.right - m_SourceRect.left; + LONG SinkWidth = m_TargetRect.right - m_TargetRect.left; + LONG SourceHeight = m_SourceRect.bottom - m_SourceRect.top; + LONG SinkHeight = m_TargetRect.bottom - m_TargetRect.top; + + m_bStretch = TRUE; + if (SourceWidth == SinkWidth) { + if (SourceHeight == SinkHeight) { + m_bStretch = FALSE; + } + } +} + + +// Tell us whose allocator we are using. This should be called with TRUE if +// the filter agrees to use an allocator based around the CImageAllocator +// SDK base class - whose image buffers are made through CreateDIBSection. +// Otherwise this should be called with FALSE and we will draw the images +// using SetDIBitsToDevice and StretchDIBitsToDevice. None of these calls +// can handle buffers which have non zero strides (like DirectDraw uses) + +void CDrawImage::NotifyAllocator(BOOL bUsingImageAllocator) +{ + m_bUsingImageAllocator = bUsingImageAllocator; +} + + +// Are we using the image DIBSECTION allocator + +BOOL CDrawImage::UsingImageAllocator() +{ + return m_bUsingImageAllocator; +} + + +// We need the media type of the connection so that we can get the BITMAPINFO +// from it. We use that in the calls to draw the image such as StretchDIBits +// and also when updating the colour table held in shared memory DIBSECTIONs + +void CDrawImage::NotifyMediaType(CMediaType *pMediaType) +{ + m_pMediaType = pMediaType; +} + + +// We store in this object a cookie maintaining the current palette version. +// Each time a palettised format is changed we increment this value so that +// when we come to draw the images we look at the colour table value they +// have and if less than the current we know to update it. This version is +// only needed and indeed used when working with shared memory DIBSECTIONs + +LONG CDrawImage::GetPaletteVersion() +{ + return m_PaletteVersion; +} + + +// Resets the current palette version number + +void CDrawImage::ResetPaletteVersion() +{ + m_PaletteVersion = PALETTE_VERSION; +} + + +// Increment the current palette version + +void CDrawImage::IncrementPaletteVersion() +{ + m_PaletteVersion++; +} + + +// Constructor must initialise the base allocator. Each sample we create has a +// palette version cookie on board. When the source filter changes the palette +// during streaming the window object increments an internal cookie counter it +// keeps as well. When it comes to render the samples it looks at the cookie +// values and if they don't match then it knows to update the sample's colour +// table. However we always create samples with a cookie of PALETTE_VERSION +// If there have been multiple format changes and we disconnect and reconnect +// thereby causing the samples to be reallocated we will create them with a +// cookie much lower than the current version, this isn't a problem since it +// will be seen by the window object and the versions will then be updated + +CImageAllocator::CImageAllocator(CBaseFilter *pFilter, + TCHAR *pName, + HRESULT *phr) : + CBaseAllocator(pName,NULL,phr,TRUE,TRUE), + m_pFilter(pFilter) +{ + ASSERT(phr); + ASSERT(pFilter); +} + + +// Check our DIB buffers have been released + +#ifdef DEBUG +CImageAllocator::~CImageAllocator() +{ + ASSERT(m_bCommitted == FALSE); +} +#endif + + +// Called from destructor and also from base class to free resources. We work +// our way through the list of media samples deleting the DIBSECTION created +// for each. All samples should be back in our list so there is no chance a +// filter is still using one to write on the display or hold on a pending list + +void CImageAllocator::Free() +{ + ASSERT(m_lAllocated == m_lFree.GetCount()); + EXECUTE_ASSERT(GdiFlush()); + CImageSample *pSample; + DIBDATA *pDibData; + + while (m_lFree.GetCount() != 0) { + pSample = (CImageSample *) m_lFree.RemoveHead(); + pDibData = pSample->GetDIBData(); + EXECUTE_ASSERT(DeleteObject(pDibData->hBitmap)); + EXECUTE_ASSERT(CloseHandle(pDibData->hMapping)); + delete pSample; + } + + m_lAllocated = 0; +} + + +// Prepare the allocator by checking all the input parameters + +STDMETHODIMP CImageAllocator::CheckSizes(ALLOCATOR_PROPERTIES *pRequest) +{ + // Check we have a valid connection + + if (m_pMediaType == NULL) { + return VFW_E_NOT_CONNECTED; + } + + // NOTE We always create a DIB section with the source format type which + // may contain a source palette. When we do the BitBlt drawing operation + // the target display device may contain a different palette (we may not + // have the focus) in which case GDI will do after the palette mapping + + VIDEOINFOHEADER *pVideoInfo = (VIDEOINFOHEADER *) m_pMediaType->Format(); + + // When we call CreateDIBSection it implicitly maps only enough memory + // for the image as defined by thee BITMAPINFOHEADER. If the user asks + // for an image smaller than this then we reject the call, if they ask + // for an image larger than this then we return what they can have + + if ((DWORD) pRequest->cbBuffer < pVideoInfo->bmiHeader.biSizeImage) { + return E_INVALIDARG; + } + + // Reject buffer prefixes + + if (pRequest->cbPrefix > 0) { + return E_INVALIDARG; + } + + pRequest->cbBuffer = pVideoInfo->bmiHeader.biSizeImage; + return NOERROR; +} + + +// Agree the number of media sample buffers and their sizes. The base class +// this allocator is derived from allows samples to be aligned only on byte +// boundaries NOTE the buffers are not allocated until the Commit call + +STDMETHODIMP CImageAllocator::SetProperties( + ALLOCATOR_PROPERTIES * pRequest, + ALLOCATOR_PROPERTIES * pActual) +{ + ALLOCATOR_PROPERTIES Adjusted = *pRequest; + + // Check the parameters fit with the current connection + + HRESULT hr = CheckSizes(&Adjusted); + if (FAILED(hr)) { + return hr; + } + return CBaseAllocator::SetProperties(&Adjusted, pActual); +} + + +// Commit the memory by allocating the agreed number of media samples. For +// each sample we are committed to creating we have a CImageSample object +// that we use to manage it's resources. This is initialised with a DIBDATA +// structure that contains amongst other things the GDI DIBSECTION handle +// We will access the renderer media type during this so we must have locked +// (to prevent the format changing for example). The class overrides Commit +// and Decommit to do this locking (base class Commit in turn calls Alloc) + +HRESULT CImageAllocator::Alloc(void) +{ + ASSERT(m_pMediaType); + CImageSample *pSample; + DIBDATA DibData; + + // Check the base allocator says it's ok to continue + + HRESULT hr = CBaseAllocator::Alloc(); + if (FAILED(hr)) { + return hr; + } + + // We create a new memory mapped object although we don't map it into our + // address space because GDI does that in CreateDIBSection. It is possible + // that we run out of resources before creating all the samples in which + // case the available sample list is left with those already created + + ASSERT(m_lAllocated == 0); + while (m_lAllocated < m_lCount) { + + // Create and initialise a shared memory GDI buffer + + HRESULT hr = CreateDIB(m_lSize,DibData); + if (FAILED(hr)) { + return hr; + } + + // Create the sample object and pass it the DIBDATA + + pSample = CreateImageSample(DibData.pBase,m_lSize); + if (pSample == NULL) { + EXECUTE_ASSERT(DeleteObject(DibData.hBitmap)); + EXECUTE_ASSERT(CloseHandle(DibData.hMapping)); + return E_OUTOFMEMORY; + } + + // Add the completed sample to the available list + + pSample->SetDIBData(&DibData); + m_lFree.Add(pSample); + m_lAllocated++; + } + return NOERROR; +} + + +// We have a virtual method that allocates the samples so that a derived class +// may override it and allocate more specialised sample objects. So long as it +// derives its samples from CImageSample then all this code will still work ok + +CImageSample *CImageAllocator::CreateImageSample(LPBYTE pData,LONG Length) +{ + HRESULT hr = NOERROR; + CImageSample *pSample; + + // Allocate the new sample and check the return codes + + pSample = new CImageSample((CBaseAllocator *) this, // Base class + NAME("Video sample"), // DEBUG name + (HRESULT *) &hr, // Return code + (LPBYTE) pData, // DIB address + (LONG) Length); // Size of DIB + + if (pSample == NULL || FAILED(hr)) { + delete pSample; + return NULL; + } + return pSample; +} + + +// This function allocates a shared memory block for use by the source filter +// generating DIBs for us to render. The memory block is created in shared +// memory so that GDI doesn't have to copy the memory when we do a BitBlt + +HRESULT CImageAllocator::CreateDIB(LONG InSize,DIBDATA &DibData) +{ + BITMAPINFO *pbmi; // Format information for pin + BYTE *pBase; // Pointer to the actual image + HANDLE hMapping; // Handle to mapped object + HBITMAP hBitmap; // DIB section bitmap handle + + // Create a file mapping object and map into our address space + + hMapping = CreateFileMapping(hMEMORY, // Use system page file + NULL, // No security attributes + PAGE_READWRITE, // Full access to memory + (DWORD) 0, // Less than 4Gb in size + InSize, // Size of buffer + NULL); // No name to section + if (hMapping == NULL) { + DWORD Error = GetLastError(); + return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, Error); + } + + // NOTE We always create a DIB section with the source format type which + // may contain a source palette. When we do the BitBlt drawing operation + // the target display device may contain a different palette (we may not + // have the focus) in which case GDI will do after the palette mapping + + pbmi = (BITMAPINFO *) HEADER(m_pMediaType->Format()); + if (m_pMediaType == NULL) { + DbgBreak("Invalid media type"); + } + + hBitmap = CreateDIBSection((HDC) NULL, // NO device context + pbmi, // Format information + DIB_RGB_COLORS, // Use the palette + (VOID **) &pBase, // Pointer to image data + hMapping, // Mapped memory handle + (DWORD) 0); // Offset into memory + + if (hBitmap == NULL || pBase == NULL) { + EXECUTE_ASSERT(CloseHandle(hMapping)); + DWORD Error = GetLastError(); + return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, Error); + } + + // Initialise the DIB information structure + + DibData.hBitmap = hBitmap; + DibData.hMapping = hMapping; + DibData.pBase = pBase; + DibData.PaletteVersion = PALETTE_VERSION; + GetObject(hBitmap,sizeof(DIBSECTION),(VOID *)&DibData.DibSection); + + return NOERROR; +} + + +// We use the media type during the DIBSECTION creation + +void CImageAllocator::NotifyMediaType(CMediaType *pMediaType) +{ + m_pMediaType = pMediaType; +} + + +// Overriden to increment the owning object's reference count + +STDMETHODIMP_(ULONG) CImageAllocator::NonDelegatingAddRef() +{ + return m_pFilter->AddRef(); +} + + +// Overriden to decrement the owning object's reference count + +STDMETHODIMP_(ULONG) CImageAllocator::NonDelegatingRelease() +{ + return m_pFilter->Release(); +} + + +// If you derive a class from CMediaSample that has to transport specialised +// member variables and entry points then there are three alternate solutions +// The first is to create a memory buffer larger than actually required by the +// sample and store your information either at the beginning of it or at the +// end, the former being moderately safer allowing for misbehaving transform +// filters. You then adjust the buffer address when you create the base media +// sample. This has the disadvantage of breaking up the memory allocated to +// the samples into separate blocks. The second solution is to implement a +// class derived from CMediaSample and support additional interface(s) that +// convey your private data. This means defining a custom interface. The final +// alternative is to create a class that inherits from CMediaSample and adds +// the private data structures, when you get an IMediaSample in your Receive() +// call check to see if your allocator is being used, and if it is then cast +// the IMediaSample into one of your objects. Additional checks can be made +// to ensure the sample's this pointer is known to be one of your own objects + +CImageSample::CImageSample(CBaseAllocator *pAllocator, + TCHAR *pName, + HRESULT *phr, + LPBYTE pBuffer, + LONG length) : + CMediaSample(pName,pAllocator,phr,pBuffer,length), + m_bInit(FALSE) +{ + ASSERT(pAllocator); + ASSERT(pBuffer); +} + + +// Set the shared memory DIB information + +void CImageSample::SetDIBData(DIBDATA *pDibData) +{ + ASSERT(pDibData); + m_DibData = *pDibData; + m_bInit = TRUE; +} + + +// Retrieve the shared memory DIB data + +DIBDATA *CImageSample::GetDIBData() +{ + ASSERT(m_bInit == TRUE); + return &m_DibData; +} + + +// This class handles the creation of a palette. It is fairly specialist and +// is intended to simplify palette management for video renderer filters. It +// is for this reason that the constructor requires three other objects with +// which it interacts, namely a base media filter, a base window and a base +// drawing object although the base window or the draw object may be NULL to +// ignore that part of us. We try not to create and install palettes unless +// absolutely necessary as they typically require WM_PALETTECHANGED messages +// to be sent to every window thread in the system which is very expensive + +CImagePalette::CImagePalette(CBaseFilter *pBaseFilter, + CBaseWindow *pBaseWindow, + CDrawImage *pDrawImage) : + m_pBaseWindow(pBaseWindow), + m_pFilter(pBaseFilter), + m_pDrawImage(pDrawImage), + m_hPalette(NULL) +{ + ASSERT(m_pFilter); +} + + +// Destructor + +#ifdef DEBUG +CImagePalette::~CImagePalette() +{ + ASSERT(m_hPalette == NULL); +} +#endif + + +// We allow dynamic format changes of the palette but rather than change the +// palette every time we call this to work out whether an update is required. +// If the original type didn't use a palette and the new one does (or vica +// versa) then we return TRUE. If neither formats use a palette we'll return +// FALSE. If both formats use a palette we compare their colours and return +// FALSE if they match. This therefore short circuits palette creation unless +// absolutely necessary since installing palettes is an expensive operation + +BOOL CImagePalette::ShouldUpdate(const VIDEOINFOHEADER *pNewInfo, + const VIDEOINFOHEADER *pOldInfo) +{ + // We may not have a current format yet + + if (pOldInfo == NULL) { + return TRUE; + } + + // Do both formats not require a palette + + if (ContainsPalette(pNewInfo) == FALSE) { + if (ContainsPalette(pOldInfo) == FALSE) { + return FALSE; + } + } + + // Compare the colours to see if they match + + DWORD VideoEntries = pNewInfo->bmiHeader.biClrUsed; + if (ContainsPalette(pNewInfo) == TRUE) + if (ContainsPalette(pOldInfo) == TRUE) + if (pOldInfo->bmiHeader.biClrUsed == VideoEntries) + if (pOldInfo->bmiHeader.biClrUsed > 0) + if (memcmp((PVOID) GetBitmapPalette(pNewInfo), + (PVOID) GetBitmapPalette(pOldInfo), + VideoEntries * sizeof(RGBQUAD)) == 0) { + + return FALSE; + } + return TRUE; +} + + +// This is normally called when the input pin type is set to install a palette +// We will typically be called from two different places. The first is when we +// have negotiated a palettised media type after connection, the other is when +// we receive a new type during processing with an updated palette in which +// case we must remove and release the resources held by the current palette + +// We can be passed an optional device name if we wish to prepare a palette +// for a specific monitor on a multi monitor system + +HRESULT CImagePalette::PreparePalette(const CMediaType *pmtNew, + const CMediaType *pmtOld, + LPSTR szDevice) +{ + const VIDEOINFOHEADER *pNewInfo = (VIDEOINFOHEADER *) pmtNew->Format(); + const VIDEOINFOHEADER *pOldInfo = (VIDEOINFOHEADER *) pmtOld->Format(); + ASSERT(pNewInfo); + + // This is an performance optimisation, when we get a media type we check + // to see if the format requires a palette change. If either we need one + // when previously we didn't or vica versa then this returns TRUE, if we + // previously needed a palette and we do now it compares their colours + + if (ShouldUpdate(pNewInfo,pOldInfo) == FALSE) { + NOTE("No update needed"); + return S_FALSE; + } + + // We must notify the filter graph that the application may have changed + // the palette although in practice we don't bother checking to see if it + // is really different. If it tries to get the palette either the window + // or renderer lock will ensure it doesn't get in until we are finished + + RemovePalette(); + m_pFilter->NotifyEvent(EC_PALETTE_CHANGED,0,0); + + // Do we need a palette for the new format + + if (ContainsPalette(pNewInfo) == FALSE) { + NOTE("New has no palette"); + return S_FALSE; + } + + if (m_pBaseWindow) { + m_pBaseWindow->LockPaletteLock(); + } + + // If we're changing the palette on the fly then we increment our palette + // cookie which is compared against the cookie also stored in all of our + // DIBSECTION media samples. If they don't match when we come to draw it + // then we know the sample is out of date and we'll update it's palette + + NOTE("Making new colour palette"); + m_hPalette = MakePalette(pNewInfo, szDevice); + ASSERT(m_hPalette != NULL); + + if (m_pBaseWindow) { + m_pBaseWindow->UnlockPaletteLock(); + } + + // The window in which the new palette is to be realised may be a NULL + // pointer to signal that no window is in use, if so we don't call it + // Some filters just want to use this object to create/manage palettes + + if (m_pBaseWindow) m_pBaseWindow->SetPalette(m_hPalette); + + // This is the only time where we need access to the draw object to say + // to it that a new palette will be arriving on a sample real soon. The + // constructor may take a NULL pointer in which case we don't call this + + if (m_pDrawImage) m_pDrawImage->IncrementPaletteVersion(); + return NOERROR; +} + + +// Helper function to copy a palette out of any kind of VIDEOINFO (ie it may +// be YUV or true colour) into a palettised VIDEOINFO. We use this changing +// palettes on DirectDraw samples as a source filter can attach a palette to +// any buffer (eg YUV) and hand it back. We make a new palette out of that +// format and then copy the palette colours into the current connection type + +HRESULT CImagePalette::CopyPalette(const CMediaType *pSrc,CMediaType *pDest) +{ + // Reset the destination palette before starting + + VIDEOINFOHEADER *pDestInfo = (VIDEOINFOHEADER *) pDest->Format(); + pDestInfo->bmiHeader.biClrUsed = 0; + pDestInfo->bmiHeader.biClrImportant = 0; + + // Does the destination have a palette + + if (PALETTISED(pDestInfo) == FALSE) { + NOTE("No destination palette"); + return S_FALSE; + } + + // Does the source contain a palette + + const VIDEOINFOHEADER *pSrcInfo = (VIDEOINFOHEADER *) pSrc->Format(); + if (ContainsPalette(pSrcInfo) == FALSE) { + NOTE("No source palette"); + return S_FALSE; + } + + // The number of colours may be zero filled + + DWORD PaletteEntries = pSrcInfo->bmiHeader.biClrUsed; + if (PaletteEntries == 0) { + DWORD Maximum = (1 << pSrcInfo->bmiHeader.biBitCount); + NOTE1("Setting maximum colours (%d)",Maximum); + PaletteEntries = Maximum; + } + + // Make sure the destination has enough room for the palette + + ASSERT(pSrcInfo->bmiHeader.biClrUsed <= iPALETTE_COLORS); + ASSERT(pSrcInfo->bmiHeader.biClrImportant <= PaletteEntries); + ASSERT(COLORS(pDestInfo) == GetBitmapPalette(pDestInfo)); + pDestInfo->bmiHeader.biClrUsed = PaletteEntries; + pDestInfo->bmiHeader.biClrImportant = pSrcInfo->bmiHeader.biClrImportant; + ULONG BitmapSize = GetBitmapFormatSize(HEADER(pSrcInfo)); + + if (pDest->FormatLength() < BitmapSize) { + NOTE("Reallocating destination"); + pDest->ReallocFormatBuffer(BitmapSize); + } + + // Now copy the palette colours across + + CopyMemory((PVOID) COLORS(pDestInfo), + (PVOID) GetBitmapPalette(pSrcInfo), + PaletteEntries * sizeof(RGBQUAD)); + + return NOERROR; +} + + +// This is normally called when the palette is changed (typically during a +// dynamic format change) to remove any palette we previously installed. We +// replace it (if necessary) in the video window with a standard VGA palette +// that should always be available even if this is a true colour display + +HRESULT CImagePalette::RemovePalette() +{ + if (m_pBaseWindow) { + m_pBaseWindow->LockPaletteLock(); + } + + // Do we have a palette to remove + + if (m_hPalette != NULL) { + + if (m_pBaseWindow) { + // Make sure that the window's palette handle matches + // our palette handle. + ASSERT(m_hPalette == m_pBaseWindow->GetPalette()); + + m_pBaseWindow->UnsetPalette(); + } + + EXECUTE_ASSERT(DeleteObject(m_hPalette)); + m_hPalette = NULL; + } + + if (m_pBaseWindow) { + m_pBaseWindow->UnlockPaletteLock(); + } + + return NOERROR; +} + + +// Called to create a palette for the object, the data structure used by GDI +// to describe a palette is a LOGPALETTE, this includes a variable number of +// PALETTEENTRY fields which are the colours, we have to convert the RGBQUAD +// colour fields we are handed in a BITMAPINFO from the media type into these +// This handles extraction of palettes from true colour and YUV media formats + +// We can be passed an optional device name if we wish to prepare a palette +// for a specific monitor on a multi monitor system + +HPALETTE CImagePalette::MakePalette(const VIDEOINFOHEADER *pVideoInfo, LPSTR szDevice) +{ + ASSERT(ContainsPalette(pVideoInfo) == TRUE); + ASSERT(pVideoInfo->bmiHeader.biClrUsed <= iPALETTE_COLORS); + BITMAPINFOHEADER *pHeader = HEADER(pVideoInfo); + + const RGBQUAD *pColours; // Pointer to the palette + LOGPALETTE *lp; // Used to create a palette + HPALETTE hPalette; // Logical palette object + + lp = (LOGPALETTE *) new BYTE[sizeof(LOGPALETTE) + SIZE_PALETTE]; + if (lp == NULL) { + return NULL; + } + + // Unfortunately for some hare brained reason a GDI palette entry (a + // PALETTEENTRY structure) is different to a palette entry from a DIB + // format (a RGBQUAD structure) so we have to do the field conversion + // The VIDEOINFO containing the palette may be a true colour type so + // we use GetBitmapPalette to skip over any bit fields if they exist + + lp->palVersion = PALVERSION; + lp->palNumEntries = (USHORT) pHeader->biClrUsed; + if (lp->palNumEntries == 0) lp->palNumEntries = (1 << pHeader->biBitCount); + pColours = GetBitmapPalette(pVideoInfo); + + for (DWORD dwCount = 0;dwCount < lp->palNumEntries;dwCount++) { + lp->palPalEntry[dwCount].peRed = pColours[dwCount].rgbRed; + lp->palPalEntry[dwCount].peGreen = pColours[dwCount].rgbGreen; + lp->palPalEntry[dwCount].peBlue = pColours[dwCount].rgbBlue; + lp->palPalEntry[dwCount].peFlags = 0; + } + + MakeIdentityPalette(lp->palPalEntry, lp->palNumEntries, szDevice); + + // Create a logical palette + + hPalette = CreatePalette(lp); + ASSERT(hPalette != NULL); + delete[] lp; + return hPalette; +} + + +// GDI does a fair job of compressing the palette entries you give it, so for +// example if you have five entries with an RGB colour (0,0,0) it will remove +// all but one of them. When you subsequently draw an image it will map from +// your logical palette to the compressed device palette. This function looks +// to see if it is trying to be an identity palette and if so sets the flags +// field in the PALETTEENTRYs so they remain expanded to boost performance + +// We can be passed an optional device name if we wish to prepare a palette +// for a specific monitor on a multi monitor system + +HRESULT CImagePalette::MakeIdentityPalette(PALETTEENTRY *pEntry,INT iColours, LPSTR szDevice) +{ + PALETTEENTRY SystemEntries[10]; // System palette entries + BOOL bIdentityPalette = TRUE; // Is an identity palette + ASSERT(iColours <= iPALETTE_COLORS); // Should have a palette + const int PalLoCount = 10; // First ten reserved colours + const int PalHiStart = 246; // Last VGA palette entries + + // Does this have the full colour range + + if (iColours < 10) { + return S_FALSE; + } + + // Apparently some displays have odd numbers of system colours + + // Get a DC on the right monitor - it's ugly, but this is the way you have + // to do it + HDC hdc; + if (szDevice == NULL || lstrcmpiA(szDevice, "DISPLAY") == 0) + hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); + else + hdc = CreateDCA(NULL, szDevice, NULL, NULL); + if (NULL == hdc) { + return E_OUTOFMEMORY; + } + INT Reserved = GetDeviceCaps(hdc,NUMRESERVED); + if (Reserved != 20) { + DeleteDC(hdc); + return S_FALSE; + } + + // Compare our palette against the first ten system entries. The reason I + // don't do a memory compare between our two arrays of colours is because + // I am not sure what will be in the flags fields for the system entries + + UINT Result = GetSystemPaletteEntries(hdc,0,PalLoCount,SystemEntries); + UINT Count = 0; + for (Count = 0;Count < Result;Count++) { + if (SystemEntries[Count].peRed != pEntry[Count].peRed || + SystemEntries[Count].peGreen != pEntry[Count].peGreen || + SystemEntries[Count].peBlue != pEntry[Count].peBlue) { + bIdentityPalette = FALSE; + } + } + + // And likewise compare against the last ten entries + + Result = GetSystemPaletteEntries(hdc,PalHiStart,PalLoCount,SystemEntries); + for (Count = 0;Count < Result;Count++) { + if (INT(Count) + PalHiStart < iColours) { + if (SystemEntries[Count].peRed != pEntry[PalHiStart + Count].peRed || + SystemEntries[Count].peGreen != pEntry[PalHiStart + Count].peGreen || + SystemEntries[Count].peBlue != pEntry[PalHiStart + Count].peBlue) { + bIdentityPalette = FALSE; + } + } + } + + // If not an identity palette then return S_FALSE + + DeleteDC(hdc); + if (bIdentityPalette == FALSE) { + return S_FALSE; + } + + // Set the non VGA entries so that GDI doesn't map them + + for (Count = PalLoCount;INT(Count) < min(PalHiStart,iColours);Count++) { + pEntry[Count].peFlags = PC_NOCOLLAPSE; + } + return NOERROR; +} + + +// Constructor initialises the VIDEOINFO we keep storing the current display +// format. The format can be changed at any time, to reset the format held +// by us call the RefreshDisplayType directly (it's a public method). Since +// more than one thread will typically call us (ie window threads resetting +// the type and source threads in the type checking methods) we have a lock + +CImageDisplay::CImageDisplay() +{ + RefreshDisplayType(NULL); +} + + + +// This initialises the format we hold which contains the display device type +// We do a conversion on the display device type in here so that when we start +// type checking input formats we can assume that certain fields have been set +// correctly, an example is when we make the 16 bit mask fields explicit. This +// is normally called when we receive WM_DEVMODECHANGED device change messages + +// The optional szDeviceName parameter tells us which monitor we are interested +// in for a multi monitor system + +HRESULT CImageDisplay::RefreshDisplayType(LPSTR szDeviceName) +{ + CAutoLock cDisplayLock(this); + + // Set the preferred format type + + ZeroMemory((PVOID)&m_Display,sizeof(VIDEOINFOHEADER)+sizeof(TRUECOLORINFO)); + m_Display.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + m_Display.bmiHeader.biBitCount = FALSE; + + // Get the bit depth of a device compatible bitmap + + // get caps of whichever monitor they are interested in (multi monitor) + HDC hdcDisplay; + // it's ugly, but this is the way you have to do it + if (szDeviceName == NULL || lstrcmpiA(szDeviceName, "DISPLAY") == 0) + hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL); + else + hdcDisplay = CreateDCA(NULL, szDeviceName, NULL, NULL); + if (hdcDisplay == NULL) { + ASSERT(FALSE); + DbgLog((LOG_ERROR,1,TEXT("ACK! Can't get a DC for %hs"), + szDeviceName ? szDeviceName : "")); + return E_FAIL; + } else { + DbgLog((LOG_TRACE,3,TEXT("Created a DC for %s"), + szDeviceName ? szDeviceName : "")); + } + HBITMAP hbm = CreateCompatibleBitmap(hdcDisplay,1,1); + if ( hbm ) + { + GetDIBits(hdcDisplay,hbm,0,1,NULL,(BITMAPINFO *)&m_Display.bmiHeader,DIB_RGB_COLORS); + + // This call will get the colour table or the proper bitfields + GetDIBits(hdcDisplay,hbm,0,1,NULL,(BITMAPINFO *)&m_Display.bmiHeader,DIB_RGB_COLORS); + DeleteObject(hbm); + } + DeleteDC(hdcDisplay); + + // Complete the display type initialisation + + ASSERT(CheckHeaderValidity(&m_Display)); + UpdateFormat(&m_Display); + DbgLog((LOG_TRACE,3,TEXT("New DISPLAY bit depth =%d"), + m_Display.bmiHeader.biBitCount)); + return NOERROR; +} + + +// We assume throughout this code that any bitfields masks are allowed no +// more than eight bits to store a colour component. This checks that the +// bit count assumption is enforced and also makes sure that all the bits +// set are contiguous. We return a boolean TRUE if the field checks out ok + +BOOL CImageDisplay::CheckBitFields(const VIDEOINFO *pInput) +{ + DWORD *pBitFields = (DWORD *) BITMASKS(pInput); + + for (INT iColour = iRED;iColour <= iBLUE;iColour++) { + + // First of all work out how many bits are set + + DWORD SetBits = CountSetBits(pBitFields[iColour]); + if (SetBits > iMAXBITS || SetBits == 0) { + NOTE1("Bit fields for component %d invalid",iColour); + return FALSE; + } + + // Next work out the number of zero bits prefix + DWORD PrefixBits = CountPrefixBits(pBitFields[iColour]); + + // This is going to see if all the bits set are contiguous (as they + // should be). We know how much to shift them right by from the + // count of prefix bits. The number of bits set defines a mask, we + // invert this (ones complement) and AND it with the shifted bit + // fields. If the result is NON zero then there are bit(s) sticking + // out the left hand end which means they are not contiguous + + DWORD TestField = pBitFields[iColour] >> PrefixBits; + DWORD Mask = ULONG_MAX << SetBits; + if (TestField & Mask) { + NOTE1("Bit fields for component %d not contiguous",iColour); + return FALSE; + } + } + return TRUE; +} + + +// This counts the number of bits set in the input field + +DWORD CImageDisplay::CountSetBits(DWORD Field) +{ + // This is a relatively well known bit counting algorithm + + DWORD Count = 0; + DWORD init = Field; + + // Until the input is exhausted, count the number of bits + + while (init) { + init = init & (init - 1); // Turn off the bottommost bit + Count++; + } + return Count; +} + + +// This counts the number of zero bits upto the first one set NOTE the input +// field should have been previously checked to ensure there is at least one +// set although if we don't find one set we return the impossible value 32 + +DWORD CImageDisplay::CountPrefixBits(DWORD Field) +{ + DWORD Mask = 1; + DWORD Count = 0; + + while (TRUE) { + if (Field & Mask) { + return Count; + } + Count++; + + ASSERT(Mask != 0x80000000); + if (Mask == 0x80000000) { + return Count; + } + Mask <<= 1; + } +} + + +// This is called to check the BITMAPINFOHEADER for the input type. There are +// many implicit dependancies between the fields in a header structure which +// if we validate now make for easier manipulation in subsequent handling. We +// also check that the BITMAPINFOHEADER matches it's specification such that +// fields likes the number of planes is one, that it's structure size is set +// correctly and that the bitmap dimensions have not been set as negative + +BOOL CImageDisplay::CheckHeaderValidity(const VIDEOINFO *pInput) +{ + // Check the bitmap width and height are not negative. + + if (pInput->bmiHeader.biWidth <= 0 || + pInput->bmiHeader.biHeight <= 0) { + NOTE("Invalid bitmap dimensions"); + return FALSE; + } + + // Check the compression is either BI_RGB or BI_BITFIELDS + + if (pInput->bmiHeader.biCompression != BI_RGB) { + if (pInput->bmiHeader.biCompression != BI_BITFIELDS) { + NOTE("Invalid compression format"); + return FALSE; + } + } + + // If BI_BITFIELDS compression format check the colour depth + + if (pInput->bmiHeader.biCompression == BI_BITFIELDS) { + if (pInput->bmiHeader.biBitCount != 16) { + if (pInput->bmiHeader.biBitCount != 32) { + NOTE("BI_BITFIELDS not 16/32 bit depth"); + return FALSE; + } + } + } + + // Check the assumptions about the layout of the bit fields + + if (pInput->bmiHeader.biCompression == BI_BITFIELDS) { + if (CheckBitFields(pInput) == FALSE) { + NOTE("Bit fields are not valid"); + return FALSE; + } + } + + // Are the number of planes equal to one + + if (pInput->bmiHeader.biPlanes != 1) { + NOTE("Number of planes not one"); + return FALSE; + } + + // Check the image size is consistent (it can be zero) + + if (pInput->bmiHeader.biSizeImage != GetBitmapSize(&pInput->bmiHeader)) { + if (pInput->bmiHeader.biSizeImage) { + NOTE("Image size incorrectly set"); + return FALSE; + } + } + + // Check the size of the structure + + if (pInput->bmiHeader.biSize != sizeof(BITMAPINFOHEADER)) { + NOTE("Size of BITMAPINFOHEADER wrong"); + return FALSE; + } + return CheckPaletteHeader(pInput); +} + + +// This runs a few simple tests against the palette fields in the input to +// see if it looks vaguely correct. The tests look at the number of palette +// colours present, the number considered important and the biCompression +// field which should always be BI_RGB as no other formats are meaningful + +BOOL CImageDisplay::CheckPaletteHeader(const VIDEOINFO *pInput) +{ + // The checks here are for palettised videos only + + if (PALETTISED(pInput) == FALSE) { + if (pInput->bmiHeader.biClrUsed) { + NOTE("Invalid palette entries"); + return FALSE; + } + return TRUE; + } + + // Compression type of BI_BITFIELDS is meaningless for palette video + + if (pInput->bmiHeader.biCompression != BI_RGB) { + NOTE("Palettised video must be BI_RGB"); + return FALSE; + } + + // Check the number of palette colours is correct + + if (pInput->bmiHeader.biClrUsed > PALETTE_ENTRIES(pInput)) { + NOTE("Too many colours in palette"); + return FALSE; + } + + // The number of important colours shouldn't exceed the number used + + if (pInput->bmiHeader.biClrImportant > pInput->bmiHeader.biClrUsed) { + NOTE("Too many important colours"); + return FALSE; + } + return TRUE; +} + + +// Return the format of the video display + +const VIDEOINFO *CImageDisplay::GetDisplayFormat() +{ + return &m_Display; +} + + +// Return TRUE if the display uses a palette + +BOOL CImageDisplay::IsPalettised() +{ + return PALETTISED(&m_Display); +} + + +// Return the bit depth of the current display setting + +WORD CImageDisplay::GetDisplayDepth() +{ + return m_Display.bmiHeader.biBitCount; +} + + +// Initialise the optional fields in a VIDEOINFO. These are mainly to do with +// the source and destination rectangles and palette information such as the +// number of colours present. It simplifies our code just a little if we don't +// have to keep checking for all the different valid permutations in a header +// every time we want to do anything with it (an example would be creating a +// palette). We set the base class media type before calling this function so +// that the media types between the pins match after a connection is made + +HRESULT CImageDisplay::UpdateFormat(VIDEOINFO *pVideoInfo) +{ + ASSERT(pVideoInfo); + + BITMAPINFOHEADER *pbmi = HEADER(pVideoInfo); + SetRectEmpty(&pVideoInfo->rcSource); + SetRectEmpty(&pVideoInfo->rcTarget); + + // Set the number of colours explicitly + + if (PALETTISED(pVideoInfo)) { + if (pVideoInfo->bmiHeader.biClrUsed == 0) { + pVideoInfo->bmiHeader.biClrUsed = PALETTE_ENTRIES(pVideoInfo); + } + } + + // The number of important colours shouldn't exceed the number used, on + // some displays the number of important colours is not initialised when + // retrieving the display type so we set the colours used correctly + + if (pVideoInfo->bmiHeader.biClrImportant > pVideoInfo->bmiHeader.biClrUsed) { + pVideoInfo->bmiHeader.biClrImportant = PALETTE_ENTRIES(pVideoInfo); + } + + // Change the image size field to be explicit + + if (pVideoInfo->bmiHeader.biSizeImage == 0) { + pVideoInfo->bmiHeader.biSizeImage = GetBitmapSize(&pVideoInfo->bmiHeader); + } + return NOERROR; +} + + +// Lots of video rendering filters want code to check proposed formats are ok +// This checks the VIDEOINFO we are passed as a media type. If the media type +// is a valid media type then we return NOERROR otherwise E_INVALIDARG. Note +// however we only accept formats that can be easily displayed in the display +// so if we are on a 16 bit device we will not accept 24 bit images. The one +// complexity is that most displays draw 8 bit palettised images efficiently +// Also if the input format is less colour bits per pixel then we also accept + +HRESULT CImageDisplay::CheckVideoType(const VIDEOINFO *pInput) +{ + // First of all check the VIDEOINFOHEADER looks correct + + if (CheckHeaderValidity(pInput) == FALSE) { + return E_INVALIDARG; + } + + // Virtually all devices support palettised images efficiently + + if (m_Display.bmiHeader.biBitCount == pInput->bmiHeader.biBitCount) { + if (PALETTISED(pInput) == TRUE) { + ASSERT(PALETTISED(&m_Display) == TRUE); + NOTE("(Video) Type connection ACCEPTED"); + return NOERROR; + } + } + + + // Is the display depth greater than the input format + + if (m_Display.bmiHeader.biBitCount > pInput->bmiHeader.biBitCount) { + NOTE("(Video) Mismatch agreed"); + return NOERROR; + } + + // Is the display depth less than the input format + + if (m_Display.bmiHeader.biBitCount < pInput->bmiHeader.biBitCount) { + NOTE("(Video) Format mismatch"); + return E_INVALIDARG; + } + + + // Both input and display formats are either BI_RGB or BI_BITFIELDS + + ASSERT(m_Display.bmiHeader.biBitCount == pInput->bmiHeader.biBitCount); + ASSERT(PALETTISED(pInput) == FALSE); + ASSERT(PALETTISED(&m_Display) == FALSE); + + // BI_RGB 16 bit representation is implicitly RGB555, and likewise BI_RGB + // 24 bit representation is RGB888. So we initialise a pointer to the bit + // fields they really mean and check against the display device format + // This is only going to be called when both formats are equal bits pixel + + const DWORD *pInputMask = GetBitMasks(pInput); + const DWORD *pDisplayMask = GetBitMasks((VIDEOINFO *)&m_Display); + + if (pInputMask[iRED] != pDisplayMask[iRED] || + pInputMask[iGREEN] != pDisplayMask[iGREEN] || + pInputMask[iBLUE] != pDisplayMask[iBLUE]) { + + NOTE("(Video) Bit field mismatch"); + return E_INVALIDARG; + } + + NOTE("(Video) Type connection ACCEPTED"); + return NOERROR; +} + + +// Return the bit masks for the true colour VIDEOINFO provided + +const DWORD *CImageDisplay::GetBitMasks(const VIDEOINFO *pVideoInfo) +{ + static const DWORD FailMasks[] = {0,0,0}; + + if (pVideoInfo->bmiHeader.biCompression == BI_BITFIELDS) { + return BITMASKS(pVideoInfo); + } + + ASSERT(pVideoInfo->bmiHeader.biCompression == BI_RGB); + + switch (pVideoInfo->bmiHeader.biBitCount) { + case 16: return bits555; + case 24: return bits888; + case 32: return bits888; + default: return FailMasks; + } +} + + +// Check to see if we can support media type pmtIn as proposed by the output +// pin - We first check that the major media type is video and also identify +// the media sub type. Then we thoroughly check the VIDEOINFO type provided +// As well as the contained VIDEOINFO being correct the major type must be +// video, the subtype a recognised video format and the type GUID correct + +HRESULT CImageDisplay::CheckMediaType(const CMediaType *pmtIn) +{ + // Does this have a VIDEOINFOHEADER format block + + const GUID *pFormatType = pmtIn->FormatType(); + if (*pFormatType != FORMAT_VideoInfo) { + NOTE("Format GUID not a VIDEOINFOHEADER"); + return E_INVALIDARG; + } + ASSERT(pmtIn->Format()); + + // Check the format looks reasonably ok + + ULONG Length = pmtIn->FormatLength(); + if (Length < SIZE_VIDEOHEADER) { + NOTE("Format smaller than a VIDEOHEADER"); + return E_FAIL; + } + + VIDEOINFO *pInput = (VIDEOINFO *) pmtIn->Format(); + + // Check the major type is MEDIATYPE_Video + + const GUID *pMajorType = pmtIn->Type(); + if (*pMajorType != MEDIATYPE_Video) { + NOTE("Major type not MEDIATYPE_Video"); + return E_INVALIDARG; + } + + // Check we can identify the media subtype + + const GUID *pSubType = pmtIn->Subtype(); + if (GetBitCount(pSubType) == USHRT_MAX) { + NOTE("Invalid video media subtype"); + return E_INVALIDARG; + } + return CheckVideoType(pInput); +} + + +// Given a video format described by a VIDEOINFO structure we return the mask +// that is used to obtain the range of acceptable colours for this type, for +// example, the mask for a 24 bit true colour format is 0xFF in all cases. A +// 16 bit 5:6:5 display format uses 0xF8, 0xFC and 0xF8, therefore given any +// RGB triplets we can AND them with these fields to find one that is valid + +BOOL CImageDisplay::GetColourMask(DWORD *pMaskRed, + DWORD *pMaskGreen, + DWORD *pMaskBlue) +{ + CAutoLock cDisplayLock(this); + *pMaskRed = 0xFF; + *pMaskGreen = 0xFF; + *pMaskBlue = 0xFF; + + // If this format is palettised then it doesn't have bit fields + + if (m_Display.bmiHeader.biBitCount < 16) { + return FALSE; + } + + // If this is a 24 bit true colour display then it can handle all the + // possible colour component ranges described by a byte. It is never + // allowed for a 24 bit colour depth image to have BI_BITFIELDS set + + if (m_Display.bmiHeader.biBitCount == 24) { + ASSERT(m_Display.bmiHeader.biCompression == BI_RGB); + return TRUE; + } + + // Calculate the mask based on the format's bit fields + + const DWORD *pBitFields = (DWORD *) GetBitMasks((VIDEOINFO *)&m_Display); + DWORD *pOutputMask[] = { pMaskRed, pMaskGreen, pMaskBlue }; + + // We know from earlier testing that there are no more than iMAXBITS + // bits set in the mask and that they are all contiguous. All that + // therefore remains is to shift them into the correct position + + for (INT iColour = iRED;iColour <= iBLUE;iColour++) { + + // This works out how many bits there are and where they live + + DWORD PrefixBits = CountPrefixBits(pBitFields[iColour]); + DWORD SetBits = CountSetBits(pBitFields[iColour]); + + // The first shift moves the bit field so that it is right justified + // in the DWORD, after which we then shift it back left which then + // puts the leading bit in the bytes most significant bit position + + *(pOutputMask[iColour]) = pBitFields[iColour] >> PrefixBits; + *(pOutputMask[iColour]) <<= (iMAXBITS - SetBits); + } + return TRUE; +} + + +/* Helper to convert to VIDEOINFOHEADER2 +*/ +STDAPI ConvertVideoInfoToVideoInfo2(AM_MEDIA_TYPE *pmt) +{ + ASSERT(pmt->formattype == FORMAT_VideoInfo); + VIDEOINFO *pVideoInfo = (VIDEOINFO *)pmt->pbFormat; + PVOID pvNew = CoTaskMemAlloc(pmt->cbFormat + sizeof(VIDEOINFOHEADER2) - + sizeof(VIDEOINFOHEADER)); + if (pvNew == NULL) { + return E_OUTOFMEMORY; + } + CopyMemory(pvNew, pmt->pbFormat, FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader)); + ZeroMemory((PBYTE)pvNew + FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader), + sizeof(VIDEOINFOHEADER2) - sizeof(VIDEOINFOHEADER)); + CopyMemory((PBYTE)pvNew + FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader), + pmt->pbFormat + FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader), + pmt->cbFormat - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader)); + VIDEOINFOHEADER2 *pVideoInfo2 = (VIDEOINFOHEADER2 *)pvNew; + pVideoInfo2->dwPictAspectRatioX = (DWORD)pVideoInfo2->bmiHeader.biWidth; + pVideoInfo2->dwPictAspectRatioY = (DWORD)pVideoInfo2->bmiHeader.biHeight; + pmt->formattype = FORMAT_VideoInfo2; + CoTaskMemFree(pmt->pbFormat); + pmt->pbFormat = (PBYTE)pvNew; + pmt->cbFormat += sizeof(VIDEOINFOHEADER2) - sizeof(VIDEOINFOHEADER); + return S_OK; +} diff --git a/ThirdParty/strmbas/winutil.h b/ThirdParty/strmbas/winutil.h new file mode 100644 index 0000000..50f7bf3 --- /dev/null +++ b/ThirdParty/strmbas/winutil.h @@ -0,0 +1,413 @@ +//------------------------------------------------------------------------------ +// File: WinUtil.h +// +// Desc: DirectShow base classes - defines generic handler classes. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +// Make sure that you call PrepareWindow to initialise the window after +// the object has been constructed. It is a separate method so that +// derived classes can override useful methods like MessageLoop. Also +// any derived class must call DoneWithWindow in its destructor. If it +// doesn't a message may be retrieved and call a derived class member +// function while a thread is executing the base class destructor code + +#ifndef __WINUTIL__ +#define __WINUTIL__ + +const int DEFWIDTH = 320; // Initial window width +const int DEFHEIGHT = 240; // Initial window height +const int CAPTION = 256; // Maximum length of caption +const int TIMELENGTH = 50; // Maximum length of times +const int PROFILESTR = 128; // Normal profile string +const WORD PALVERSION = 0x300; // GDI palette version +const LONG PALETTE_VERSION = (LONG) 1; // Initial palette version +const COLORREF VIDEO_COLOUR = 0; // Defaults to black background +const HANDLE hMEMORY = (HANDLE) (-1); // Says to open as memory file + +#define WIDTH(x) ((*(x)).right - (*(x)).left) +#define HEIGHT(x) ((*(x)).bottom - (*(x)).top) +#define SHOWSTAGE TEXT("WM_SHOWSTAGE") +#define SHOWSTAGETOP TEXT("WM_SHOWSTAGETOP") +#define REALIZEPALETTE TEXT("WM_REALIZEPALETTE") + +class AM_NOVTABLE CBaseWindow +{ +protected: + + HINSTANCE m_hInstance; // Global module instance handle + HWND m_hwnd; // Handle for our window + HDC m_hdc; // Device context for the window + LONG m_Width; // Client window width + LONG m_Height; // Client window height + BOOL m_bActivated; // Has the window been activated + LPTSTR m_pClassName; // Static string holding class name + DWORD m_ClassStyles; // Passed in to our constructor + DWORD m_WindowStyles; // Likewise the initial window styles + DWORD m_WindowStylesEx; // And the extended window styles + UINT m_ShowStageMessage; // Have the window shown with focus + UINT m_ShowStageTop; // Makes the window WS_EX_TOPMOST + UINT m_RealizePalette; // Makes us realize our new palette + HDC m_MemoryDC; // Used for fast BitBlt operations + HPALETTE m_hPalette; // Handle to any palette we may have + BYTE m_bNoRealize; // Don't realize palette now + BYTE m_bBackground; // Should we realise in background + BYTE m_bRealizing; // already realizing the palette + CCritSec m_WindowLock; // Serialise window object access + BOOL m_bDoGetDC; // Should this window get a DC + bool m_bDoPostToDestroy; // Use PostMessage to destroy + CCritSec m_PaletteLock; // This lock protects m_hPalette. + // It should be held anytime the + // program use the value of m_hPalette. + + // Maps windows message procedure into C++ methods + friend LRESULT CALLBACK WndProc(HWND hwnd, // Window handle + UINT uMsg, // Message ID + WPARAM wParam, // First parameter + LPARAM lParam); // Other parameter + + virtual LRESULT OnPaletteChange(HWND hwnd, UINT Message); + +public: + + CBaseWindow(BOOL bDoGetDC = TRUE, bool bPostToDestroy = false); + +#ifdef DEBUG + virtual ~CBaseWindow(); +#endif + + virtual HRESULT DoneWithWindow(); + virtual HRESULT PrepareWindow(); + virtual HRESULT InactivateWindow(); + virtual HRESULT ActivateWindow(); + virtual BOOL OnSize(LONG Width, LONG Height); + virtual BOOL OnClose(); + virtual RECT GetDefaultRect(); + virtual HRESULT UninitialiseWindow(); + virtual HRESULT InitialiseWindow(HWND hwnd); + + HRESULT CompleteConnect(); + HRESULT DoCreateWindow(); + + HRESULT PerformanceAlignWindow(); + HRESULT DoShowWindow(LONG ShowCmd); + void PaintWindow(BOOL bErase); + void DoSetWindowForeground(BOOL bFocus); + virtual HRESULT SetPalette(HPALETTE hPalette); + void SetRealize(BOOL bRealize) + { + m_bNoRealize = !bRealize; + } + + // Jump over to the window thread to set the current palette + HRESULT SetPalette(); + void UnsetPalette(void); + virtual HRESULT DoRealisePalette(BOOL bForceBackground = FALSE); + + void LockPaletteLock(); + void UnlockPaletteLock(); + + virtual BOOL PossiblyEatMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) + { return FALSE; }; + + // Access our window information + + bool WindowExists(); + LONG GetWindowWidth(); + LONG GetWindowHeight(); + HWND GetWindowHWND(); + HDC GetMemoryHDC(); + HDC GetWindowHDC(); + + #ifdef DEBUG + HPALETTE GetPalette(); + #endif // DEBUG + + // This is the window procedure the derived object should override + + virtual LRESULT OnReceiveMessage(HWND hwnd, // Window handle + UINT uMsg, // Message ID + WPARAM wParam, // First parameter + LPARAM lParam); // Other parameter + + // Must be overriden to return class and window styles + + virtual LPTSTR GetClassWindowStyles( + DWORD *pClassStyles, // Class styles + DWORD *pWindowStyles, // Window styles + DWORD *pWindowStylesEx) PURE; // Extended styles +}; + + +// This helper class is entirely subservient to the owning CBaseWindow object +// All this object does is to split out the actual drawing operation from the +// main object (because it was becoming too large). We have a number of entry +// points to set things like the draw device contexts, to implement the actual +// drawing and to set the destination rectangle in the client window. We have +// no critical section locking in this class because we are used exclusively +// by the owning window object which looks after serialising calls into us + +// If you want to use this class make sure you call NotifyAllocator once the +// allocate has been agreed, also call NotifyMediaType with a pointer to a +// NON stack based CMediaType once that has been set (we keep a pointer to +// the original rather than taking a copy). When the palette changes call +// IncrementPaletteVersion (easiest thing to do is to also call this method +// in the SetMediaType method most filters implement). Finally before you +// start rendering anything call SetDrawContext so that we can get the HDCs +// for drawing from the CBaseWindow object we are given during construction + +class CDrawImage +{ +protected: + + CBaseWindow *m_pBaseWindow; // Owning video window object + CRefTime m_StartSample; // Start time for the current sample + CRefTime m_EndSample; // And likewise it's end sample time + HDC m_hdc; // Main window device context + HDC m_MemoryDC; // Offscreen draw device context + RECT m_TargetRect; // Target destination rectangle + RECT m_SourceRect; // Source image rectangle + BOOL m_bStretch; // Do we have to stretch the images + BOOL m_bUsingImageAllocator; // Are the samples shared DIBSECTIONs + CMediaType *m_pMediaType; // Pointer to the current format + int m_perfidRenderTime; // Time taken to render an image + LONG m_PaletteVersion; // Current palette version cookie + + // Draw the video images in the window + + void SlowRender(IMediaSample *pMediaSample); + void FastRender(IMediaSample *pMediaSample); + void DisplaySampleTimes(IMediaSample *pSample); + void UpdateColourTable(HDC hdc,BITMAPINFOHEADER *pbmi); + void SetStretchMode(); + +public: + + // Used to control the image drawing + + CDrawImage(CBaseWindow *pBaseWindow); + BOOL DrawImage(IMediaSample *pMediaSample); + BOOL DrawVideoImageHere(HDC hdc, IMediaSample *pMediaSample, + LPRECT lprcSrc, LPRECT lprcDst); + void SetDrawContext(); + void SetTargetRect(RECT *pTargetRect); + void SetSourceRect(RECT *pSourceRect); + void GetTargetRect(RECT *pTargetRect); + void GetSourceRect(RECT *pSourceRect); + virtual RECT ScaleSourceRect(const RECT *pSource); + + // Handle updating palettes as they change + + LONG GetPaletteVersion(); + void ResetPaletteVersion(); + void IncrementPaletteVersion(); + + // Tell us media types and allocator assignments + + void NotifyAllocator(BOOL bUsingImageAllocator); + void NotifyMediaType(CMediaType *pMediaType); + BOOL UsingImageAllocator(); + + // Called when we are about to draw an image + + void NotifyStartDraw() { + MSR_START(m_perfidRenderTime); + }; + + // Called when we complete an image rendering + + void NotifyEndDraw() { + MSR_STOP(m_perfidRenderTime); + }; +}; + + +// This is the structure used to keep information about each GDI DIB. All the +// samples we create from our allocator will have a DIBSECTION allocated to +// them. When we receive the sample we know we can BitBlt straight to an HDC + +typedef struct tagDIBDATA { + + LONG PaletteVersion; // Current palette version in use + DIBSECTION DibSection; // Details of DIB section allocated + HBITMAP hBitmap; // Handle to bitmap for drawing + HANDLE hMapping; // Handle to shared memory block + BYTE *pBase; // Pointer to base memory address + +} DIBDATA; + + +// This class inherits from CMediaSample and uses all of it's methods but it +// overrides the constructor to initialise itself with the DIBDATA structure +// When we come to render an IMediaSample we will know if we are using our own +// allocator, and if we are, we can cast the IMediaSample to a pointer to one +// of these are retrieve the DIB section information and hence the HBITMAP + +class CImageSample : public CMediaSample +{ +protected: + + DIBDATA m_DibData; // Information about the DIBSECTION + BOOL m_bInit; // Is the DIB information setup + +public: + + // Constructor + + CImageSample(CBaseAllocator *pAllocator, + TCHAR *pName, + HRESULT *phr, + LPBYTE pBuffer, + LONG length); + + // Maintain the DIB/DirectDraw state + + void SetDIBData(DIBDATA *pDibData); + DIBDATA *GetDIBData(); +}; + + +// This is an allocator based on the abstract CBaseAllocator base class that +// allocates sample buffers in shared memory. The number and size of these +// are determined when the output pin calls Prepare on us. The shared memory +// blocks are used in subsequent calls to GDI CreateDIBSection, once that +// has been done the output pin can fill the buffers with data which will +// then be handed to GDI through BitBlt calls and thereby remove one copy + +class CImageAllocator : public CBaseAllocator +{ +protected: + + CBaseFilter *m_pFilter; // Delegate reference counts to + CMediaType *m_pMediaType; // Pointer to the current format + + // Used to create and delete samples + + HRESULT Alloc(); + void Free(); + + // Manage the shared DIBSECTION and DCI/DirectDraw buffers + + HRESULT CreateDIB(LONG InSize,DIBDATA &DibData); + STDMETHODIMP CheckSizes(ALLOCATOR_PROPERTIES *pRequest); + virtual CImageSample *CreateImageSample(LPBYTE pData,LONG Length); + +public: + + // Constructor and destructor + + CImageAllocator(CBaseFilter *pFilter,TCHAR *pName,HRESULT *phr); +#ifdef DEBUG + ~CImageAllocator(); +#endif + + STDMETHODIMP_(ULONG) NonDelegatingAddRef(); + STDMETHODIMP_(ULONG) NonDelegatingRelease(); + void NotifyMediaType(CMediaType *pMediaType); + + // Agree the number of buffers to be used and their size + + STDMETHODIMP SetProperties( + ALLOCATOR_PROPERTIES *pRequest, + ALLOCATOR_PROPERTIES *pActual); +}; + + +// This class is a fairly specialised helper class for image renderers that +// have to create and manage palettes. The CBaseWindow class looks after +// realising palettes once they have been installed. This class can be used +// to create the palette handles from a media format (which must contain a +// VIDEOINFO structure in the format block). We try to make the palette an +// identity palette to maximise performance and also only change palettes +// if actually required to (we compare palette colours before updating). +// All the methods are virtual so that they can be overriden if so required + +class CImagePalette +{ +protected: + + CBaseWindow *m_pBaseWindow; // Window to realise palette in + CBaseFilter *m_pFilter; // Media filter to send events + CDrawImage *m_pDrawImage; // Object who will be drawing + HPALETTE m_hPalette; // The palette handle we own + +public: + + CImagePalette(CBaseFilter *pBaseFilter, + CBaseWindow *pBaseWindow, + CDrawImage *pDrawImage); + +#ifdef DEBUG + virtual ~CImagePalette(); +#endif + + static HPALETTE MakePalette(const VIDEOINFOHEADER *pVideoInfo, LPSTR szDevice); + HRESULT RemovePalette(); + static HRESULT MakeIdentityPalette(PALETTEENTRY *pEntry,INT iColours, LPSTR szDevice); + HRESULT CopyPalette(const CMediaType *pSrc,CMediaType *pDest); + BOOL ShouldUpdate(const VIDEOINFOHEADER *pNewInfo,const VIDEOINFOHEADER *pOldInfo); + HRESULT PreparePalette(const CMediaType *pmtNew,const CMediaType *pmtOld,LPSTR szDevice); + + BOOL DrawVideoImageHere(HDC hdc, IMediaSample *pMediaSample, LPRECT lprcSrc, LPRECT lprcDst) + { + return m_pDrawImage->DrawVideoImageHere(hdc, pMediaSample, lprcSrc,lprcDst); + } +}; + + +// Another helper class really for video based renderers. Most such renderers +// need to know what the display format is to some degree or another. This +// class initialises itself with the display format. The format can be asked +// for through GetDisplayFormat and various other accessor functions. If a +// filter detects a display format change (perhaps it gets a WM_DEVMODECHANGE +// message then it can call RefreshDisplayType to reset that format). Also +// many video renderers will want to check formats as they are proposed by +// source filters. This class provides methods to check formats and only +// accept those video formats that can be efficiently drawn using GDI calls + +class CImageDisplay : public CCritSec +{ +protected: + + // This holds the display format; biSize should not be too big, so we can + // safely use the VIDEOINFO structure + VIDEOINFO m_Display; + + static DWORD CountSetBits(const DWORD Field); + static DWORD CountPrefixBits(const DWORD Field); + static BOOL CheckBitFields(const VIDEOINFO *pInput); + +public: + + // Constructor and destructor + + CImageDisplay(); + + // Used to manage BITMAPINFOHEADERs and the display format + + const VIDEOINFO *GetDisplayFormat(); + HRESULT RefreshDisplayType(LPSTR szDeviceName); + static BOOL CheckHeaderValidity(const VIDEOINFO *pInput); + static BOOL CheckPaletteHeader(const VIDEOINFO *pInput); + BOOL IsPalettised(); + WORD GetDisplayDepth(); + + // Provide simple video format type checking + + HRESULT CheckMediaType(const CMediaType *pmtIn); + HRESULT CheckVideoType(const VIDEOINFO *pInput); + HRESULT UpdateFormat(VIDEOINFO *pVideoInfo); + const DWORD *GetBitMasks(const VIDEOINFO *pVideoInfo); + + BOOL GetColourMask(DWORD *pMaskRed, + DWORD *pMaskGreen, + DWORD *pMaskBlue); +}; + +// Convert a FORMAT_VideoInfo to FORMAT_VideoInfo2 +STDAPI ConvertVideoInfoToVideoInfo2(AM_MEDIA_TYPE *pmt); + +#endif // __WINUTIL__ + diff --git a/ThirdParty/strmbas/wxdebug.cpp b/ThirdParty/strmbas/wxdebug.cpp new file mode 100644 index 0000000..0be7347 --- /dev/null +++ b/ThirdParty/strmbas/wxdebug.cpp @@ -0,0 +1,1420 @@ +//------------------------------------------------------------------------------ +// File: WXDebug.cpp +// +// Desc: DirectShow base classes - implements ActiveX system debugging +// facilities. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +#define _WINDLL + +#include +#include +#include + +#ifdef DEBUG +#ifdef UNICODE +#ifndef _UNICODE +#define _UNICODE +#endif // _UNICODE +#endif // UNICODE +#endif // DEBUG + +#ifdef DEBUG + +// The Win32 wsprintf() function writes a maximum of 1024 characters to it's output buffer. +// See the documentation for wsprintf()'s lpOut parameter for more information. +const INT iDEBUGINFO = 1024; // Used to format strings + +/* For every module and executable we store a debugging level for each of + the five categories (eg LOG_ERROR and LOG_TIMING). This makes it easy + to isolate and debug individual modules without seeing everybody elses + spurious debug output. The keys are stored in the registry under the + HKEY_LOCAL_MACHINE\SOFTWARE\Debug\\ key values + NOTE these must be in the same order as their enumeration definition */ + +TCHAR *pKeyNames[] = { + TEXT("TIMING"), // Timing and performance measurements + TEXT("TRACE"), // General step point call tracing + TEXT("MEMORY"), // Memory and object allocation/destruction + TEXT("LOCKING"), // Locking/unlocking of critical sections + TEXT("ERROR"), // Debug error notification + TEXT("CUSTOM1"), + TEXT("CUSTOM2"), + TEXT("CUSTOM3"), + TEXT("CUSTOM4"), + TEXT("CUSTOM5") + }; + +const TCHAR CAutoTrace::_szEntering[] = TEXT("->: %s"); +const TCHAR CAutoTrace::_szLeaving[] = TEXT("<-: %s"); + +const INT iMAXLEVELS = NUMELMS(pKeyNames); // Maximum debug categories + +HINSTANCE m_hInst; // Module instance handle +TCHAR m_ModuleName[iDEBUGINFO]; // Cut down module name +DWORD m_Levels[iMAXLEVELS]; // Debug level per category +CRITICAL_SECTION m_CSDebug; // Controls access to list +DWORD m_dwNextCookie; // Next active object ID +ObjectDesc *pListHead = NULL; // First active object +DWORD m_dwObjectCount; // Active object count +BOOL m_bInit = FALSE; // Have we been initialised +HANDLE m_hOutput = INVALID_HANDLE_VALUE; // Optional output written here +DWORD dwWaitTimeout = INFINITE; // Default timeout value +DWORD dwTimeOffset; // Time of first DbgLog call +bool g_fUseKASSERT = false; // don't create messagebox +bool g_fDbgInDllEntryPoint = false; +bool g_fAutoRefreshLevels = false; + +const TCHAR *pBaseKey = TEXT("SOFTWARE\\Debug"); +const TCHAR *pGlobalKey = TEXT("GLOBAL"); +static CHAR *pUnknownName = "UNKNOWN"; + +TCHAR *TimeoutName = TEXT("TIMEOUT"); + +/* This sets the instance handle that the debug library uses to find + the module's file name from the Win32 GetModuleFileName function */ + +void WINAPI DbgInitialise(HINSTANCE hInst) +{ + InitializeCriticalSection(&m_CSDebug); + m_bInit = TRUE; + + m_hInst = hInst; + DbgInitModuleName(); + if (GetProfileInt(m_ModuleName, TEXT("BreakOnLoad"), 0)) + DebugBreak(); + DbgInitModuleSettings(false); + DbgInitGlobalSettings(true); + dwTimeOffset = timeGetTime(); +} + + +/* This is called to clear up any resources the debug library uses - at the + moment we delete our critical section and the object list. The values we + retrieve from the registry are all done during initialisation but we don't + go looking for update notifications while we are running, if the values + are changed then the application has to be restarted to pick them up */ + +void WINAPI DbgTerminate() +{ + if (m_hOutput != INVALID_HANDLE_VALUE) { + EXECUTE_ASSERT(CloseHandle(m_hOutput)); + m_hOutput = INVALID_HANDLE_VALUE; + } + DeleteCriticalSection(&m_CSDebug); + m_bInit = FALSE; +} + + +/* This is called by DbgInitLogLevels to read the debug settings + for each logging category for this module from the registry */ + +void WINAPI DbgInitKeyLevels(HKEY hKey, bool fTakeMax) +{ + LONG lReturn; // Create key return value + LONG lKeyPos; // Current key category + DWORD dwKeySize; // Size of the key value + DWORD dwKeyType; // Receives it's type + DWORD dwKeyValue; // This fields value + + /* Try and read a value for each key position in turn */ + for (lKeyPos = 0;lKeyPos < iMAXLEVELS;lKeyPos++) { + + dwKeySize = sizeof(DWORD); + lReturn = RegQueryValueEx( + hKey, // Handle to an open key + pKeyNames[lKeyPos], // Subkey name derivation + NULL, // Reserved field + &dwKeyType, // Returns the field type + (LPBYTE) &dwKeyValue, // Returns the field's value + &dwKeySize ); // Number of bytes transferred + + /* If either the key was not available or it was not a DWORD value + then we ensure only the high priority debug logging is output + but we try and update the field to a zero filled DWORD value */ + + if (lReturn != ERROR_SUCCESS || dwKeyType != REG_DWORD) { + + dwKeyValue = 0; + lReturn = RegSetValueEx( + hKey, // Handle of an open key + pKeyNames[lKeyPos], // Address of subkey name + (DWORD) 0, // Reserved field + REG_DWORD, // Type of the key field + (PBYTE) &dwKeyValue, // Value for the field + sizeof(DWORD)); // Size of the field buffer + + if (lReturn != ERROR_SUCCESS) { + DbgLog((LOG_ERROR,0,TEXT("Could not create subkey %s"),pKeyNames[lKeyPos])); + dwKeyValue = 0; + } + } + if(fTakeMax) + { + m_Levels[lKeyPos] = max(dwKeyValue,m_Levels[lKeyPos]); + } + else + { + if((m_Levels[lKeyPos] & LOG_FORCIBLY_SET) == 0) { + m_Levels[lKeyPos] = dwKeyValue; + } + } + } + + /* Read the timeout value for catching hangs */ + dwKeySize = sizeof(DWORD); + lReturn = RegQueryValueEx( + hKey, // Handle to an open key + TimeoutName, // Subkey name derivation + NULL, // Reserved field + &dwKeyType, // Returns the field type + (LPBYTE) &dwWaitTimeout, // Returns the field's value + &dwKeySize ); // Number of bytes transferred + + /* If either the key was not available or it was not a DWORD value + then we ensure only the high priority debug logging is output + but we try and update the field to a zero filled DWORD value */ + + if (lReturn != ERROR_SUCCESS || dwKeyType != REG_DWORD) { + + dwWaitTimeout = INFINITE; + lReturn = RegSetValueEx( + hKey, // Handle of an open key + TimeoutName, // Address of subkey name + (DWORD) 0, // Reserved field + REG_DWORD, // Type of the key field + (PBYTE) &dwWaitTimeout, // Value for the field + sizeof(DWORD)); // Size of the field buffer + + if (lReturn != ERROR_SUCCESS) { + DbgLog((LOG_ERROR,0,TEXT("Could not create subkey %s"),TimeoutName)); + dwWaitTimeout = INFINITE; + } + } +} + +void WINAPI DbgOutString(LPCTSTR psz) +{ + if (m_hOutput != INVALID_HANDLE_VALUE) { + UINT cb = lstrlen(psz); + DWORD dw; +#ifdef UNICODE + CHAR szDest[2048]; + WideCharToMultiByte(CP_ACP, 0, psz, -1, szDest, NUMELMS(szDest), 0, 0); + WriteFile (m_hOutput, szDest, cb, &dw, NULL); +#else + WriteFile (m_hOutput, psz, cb, &dw, NULL); +#endif + } else { + OutputDebugString (psz); + } +} + +/* Called by DbgInitGlobalSettings to setup alternate logging destinations + */ + +void WINAPI DbgInitLogTo ( + HKEY hKey) +{ + LONG lReturn; + DWORD dwKeyType; + DWORD dwKeySize; + TCHAR szFile[MAX_PATH] = {0}; + static const TCHAR cszKey[] = TEXT("LogToFile"); + + dwKeySize = MAX_PATH; + lReturn = RegQueryValueEx( + hKey, // Handle to an open key + cszKey, // Subkey name derivation + NULL, // Reserved field + &dwKeyType, // Returns the field type + (LPBYTE) szFile, // Returns the field's value + &dwKeySize); // Number of bytes transferred + + // create an empty key if it does not already exist + // + if (lReturn != ERROR_SUCCESS || dwKeyType != REG_SZ) + { + dwKeySize = sizeof(TCHAR); + lReturn = RegSetValueEx( + hKey, // Handle of an open key + cszKey, // Address of subkey name + (DWORD) 0, // Reserved field + REG_SZ, // Type of the key field + (PBYTE)szFile, // Value for the field + dwKeySize); // Size of the field buffer + } + + // if an output-to was specified. try to open it. + // + if (m_hOutput != INVALID_HANDLE_VALUE) { + EXECUTE_ASSERT(CloseHandle (m_hOutput)); + m_hOutput = INVALID_HANDLE_VALUE; + } + if (szFile[0] != 0) + { + if (!lstrcmpi(szFile, TEXT("Console"))) { + m_hOutput = GetStdHandle (STD_OUTPUT_HANDLE); + if (m_hOutput == INVALID_HANDLE_VALUE) { + AllocConsole (); + m_hOutput = GetStdHandle (STD_OUTPUT_HANDLE); + } + SetConsoleTitle (TEXT("ActiveX Debug Output")); + } else if (szFile[0] && + lstrcmpi(szFile, TEXT("Debug")) && + lstrcmpi(szFile, TEXT("Debugger")) && + lstrcmpi(szFile, TEXT("Deb"))) + { + m_hOutput = CreateFile(szFile, GENERIC_WRITE, + FILE_SHARE_READ, + NULL, OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (INVALID_HANDLE_VALUE != m_hOutput) + { + static const TCHAR cszBar[] = TEXT("\r\n\r\n=====DbgInitialize()=====\r\n\r\n"); + SetFilePointer (m_hOutput, 0, NULL, FILE_END); + DbgOutString (cszBar); + } + } + } +} + + + +/* This is called by DbgInitLogLevels to read the global debug settings for + each logging category for this module from the registry. Normally each + module has it's own values set for it's different debug categories but + setting the global SOFTWARE\Debug\Global applies them to ALL modules */ + +void WINAPI DbgInitGlobalSettings(bool fTakeMax) +{ + LONG lReturn; // Create key return value + TCHAR szInfo[iDEBUGINFO]; // Constructs key names + HKEY hGlobalKey; // Global override key + + /* Construct the global base key name */ + (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("%s\\%s"),pBaseKey,pGlobalKey); + + /* Create or open the key for this module */ + lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE, // Handle of an open key + szInfo, // Address of subkey name + (DWORD) 0, // Reserved value + NULL, // Address of class name + (DWORD) 0, // Special options flags + KEY_ALL_ACCESS, // Desired security access + NULL, // Key security descriptor + &hGlobalKey, // Opened handle buffer + NULL); // What really happened + + if (lReturn != ERROR_SUCCESS) { + DbgLog((LOG_ERROR,0,TEXT("Could not access GLOBAL module key"))); + return; + } + + DbgInitKeyLevels(hGlobalKey, fTakeMax); + RegCloseKey(hGlobalKey); +} + + +/* This sets the debugging log levels for the different categories. We start + by opening (or creating if not already available) the SOFTWARE\Debug key + that all these settings live under. We then look at the global values + set under SOFTWARE\Debug\Global which apply on top of the individual + module settings. We then load the individual module registry settings */ + +void WINAPI DbgInitModuleSettings(bool fTakeMax) +{ + LONG lReturn; // Create key return value + TCHAR szInfo[iDEBUGINFO]; // Constructs key names + HKEY hModuleKey; // Module key handle + + /* Construct the base key name */ + (void)StringCchPrintf(szInfo,NUMELMS(szInfo), TEXT("%s\\%s"),pBaseKey,m_ModuleName); + + /* Create or open the key for this module */ + lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE, // Handle of an open key + szInfo, // Address of subkey name + (DWORD) 0, // Reserved value + NULL, // Address of class name + (DWORD) 0, // Special options flags + KEY_ALL_ACCESS, // Desired security access + NULL, // Key security descriptor + &hModuleKey, // Opened handle buffer + NULL); // What really happened + + if (lReturn != ERROR_SUCCESS) { + DbgLog((LOG_ERROR,0,TEXT("Could not access module key"))); + return; + } + + DbgInitLogTo(hModuleKey); + DbgInitKeyLevels(hModuleKey, fTakeMax); + RegCloseKey(hModuleKey); +} + + +/* Initialise the module file name */ + +void WINAPI DbgInitModuleName() +{ + TCHAR FullName[iDEBUGINFO]; // Load the full path and module name + TCHAR *pName; // Searches from the end for a backslash + + GetModuleFileName(m_hInst,FullName,iDEBUGINFO); + pName = _tcsrchr(FullName,'\\'); + if (pName == NULL) { + pName = FullName; + } else { + pName++; + } + (void)StringCchCopy(m_ModuleName,NUMELMS(m_ModuleName), pName); +} + +struct MsgBoxMsg +{ + HWND hwnd; + TCHAR *szTitle; + TCHAR *szMessage; + DWORD dwFlags; + INT iResult; +}; + +// +// create a thread to call MessageBox(). calling MessageBox() on +// random threads at bad times can confuse the host (eg IE). +// +DWORD WINAPI MsgBoxThread( + LPVOID lpParameter // thread data + ) +{ + MsgBoxMsg *pmsg = (MsgBoxMsg *)lpParameter; + pmsg->iResult = MessageBox( + pmsg->hwnd, + pmsg->szTitle, + pmsg->szMessage, + pmsg->dwFlags); + + return 0; +} + +INT MessageBoxOtherThread( + HWND hwnd, + TCHAR *szTitle, + TCHAR *szMessage, + DWORD dwFlags) +{ + if(g_fDbgInDllEntryPoint) + { + // can't wait on another thread because we have the loader + // lock held in the dll entry point. + return MessageBox(hwnd, szTitle, szMessage, dwFlags); + } + else + { + MsgBoxMsg msg = {hwnd, szTitle, szMessage, dwFlags, 0}; + DWORD dwid; + HANDLE hThread = CreateThread( + 0, // security + 0, // stack size + MsgBoxThread, + (void *)&msg, // arg + 0, // flags + &dwid); + if(hThread) + { + WaitForSingleObject(hThread, INFINITE); + CloseHandle(hThread); + return msg.iResult; + } + + // break into debugger on failure. + return IDCANCEL; + } +} + +/* Displays a message box if the condition evaluated to FALSE */ + +void WINAPI DbgAssert(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine) +{ + if(g_fUseKASSERT) + { + DbgKernelAssert(pCondition, pFileName, iLine); + } + else + { + + TCHAR szInfo[iDEBUGINFO]; + + (void)StringCchPrintf(szInfo, NUMELMS(szInfo), TEXT("%s \nAt line %d of %s\nContinue? (Cancel to debug)"), + pCondition, iLine, pFileName); + + INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("ASSERT Failed"), + MB_SYSTEMMODAL | + MB_ICONHAND | + MB_YESNOCANCEL | + MB_SETFOREGROUND); + switch (MsgId) + { + case IDNO: /* Kill the application */ + + FatalAppExit(FALSE, TEXT("Application terminated")); + break; + + case IDCANCEL: /* Break into the debugger */ + + DebugBreak(); + break; + + case IDYES: /* Ignore assertion continue execution */ + break; + } + } +} + +/* Displays a message box at a break point */ + +void WINAPI DbgBreakPoint(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine) +{ + if(g_fUseKASSERT) + { + DbgKernelAssert(pCondition, pFileName, iLine); + } + else + { + TCHAR szInfo[iDEBUGINFO]; + + (void)StringCchPrintf(szInfo, NUMELMS(szInfo), TEXT("%s \nAt line %d of %s\nContinue? (Cancel to debug)"), + pCondition, iLine, pFileName); + + INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("Hard coded break point"), + MB_SYSTEMMODAL | + MB_ICONHAND | + MB_YESNOCANCEL | + MB_SETFOREGROUND); + switch (MsgId) + { + case IDNO: /* Kill the application */ + + FatalAppExit(FALSE, TEXT("Application terminated")); + break; + + case IDCANCEL: /* Break into the debugger */ + + DebugBreak(); + break; + + case IDYES: /* Ignore break point continue execution */ + break; + } + } +} + +void WINAPI DbgBreakPoint(const TCHAR *pFileName,INT iLine,const TCHAR* szFormatString,...) +{ + // A debug break point message can have at most 2000 characters if + // ANSI or UNICODE characters are being used. A debug break point message + // can have between 1000 and 2000 double byte characters in it. If a + // particular message needs more characters, then the value of this constant + // should be increased. + const DWORD MAX_BREAK_POINT_MESSAGE_SIZE = 2000; + + TCHAR szBreakPointMessage[MAX_BREAK_POINT_MESSAGE_SIZE]; + + const DWORD MAX_CHARS_IN_BREAK_POINT_MESSAGE = sizeof(szBreakPointMessage) / sizeof(TCHAR); + + va_list va; + va_start( va, szFormatString ); + + HRESULT hr = StringCchVPrintf( szBreakPointMessage, MAX_CHARS_IN_BREAK_POINT_MESSAGE, szFormatString, va ); + + va_end(va); + + if( S_OK != hr ) { + DbgBreak( "ERROR in DbgBreakPoint(). The variable length debug message could not be displayed because _vsnprintf() failed." ); + return; + } + + ::DbgBreakPoint( szBreakPointMessage, pFileName, iLine ); +} + + +/* When we initialised the library we stored in the m_Levels array the current + debug output level for this module for each of the five categories. When + some debug logging is sent to us it can be sent with a combination of the + categories (if it is applicable to many for example) in which case we map + the type's categories into their current debug levels and see if any of + them can be accepted. The function looks at each bit position in turn from + the input type field and then compares it's debug level with the modules. + + A level of 0 means that output is always sent to the debugger. This is + due to producing output if the input level is <= m_Levels. +*/ + + +BOOL WINAPI DbgCheckModuleLevel(DWORD Type,DWORD Level) +{ + if(g_fAutoRefreshLevels) + { + // re-read the registry every second. We cannot use RegNotify() to + // notice registry changes because it's not available on win9x. + static int g_dwLastRefresh = 0; + DWORD dwTime = timeGetTime(); + if(dwTime - g_dwLastRefresh > 1000) { + g_dwLastRefresh = dwTime; + + // there's a race condition: multiple threads could update the + // values. plus read and write not synchronized. no harm + // though. + DbgInitModuleSettings(false); + } + } + + + DWORD Mask = 0x01; + + // If no valid bits are set return FALSE + if ((Type & ((1<m_szName = szObjectName; + pObject->m_wszName = wszObjectName; + pObject->m_dwCookie = ++m_dwNextCookie; + pObject->m_pNext = pListHead; + + pListHead = pObject; + m_dwObjectCount++; + + DWORD ObjectCookie = pObject->m_dwCookie; + ASSERT(ObjectCookie); + + if(wszObjectName) { + DbgLog((LOG_MEMORY,2,TEXT("Object created %d (%ls) %d Active"), + pObject->m_dwCookie, wszObjectName, m_dwObjectCount)); + } else { + DbgLog((LOG_MEMORY,2,TEXT("Object created %d (%hs) %d Active"), + pObject->m_dwCookie, szObjectName, m_dwObjectCount)); + } + + LeaveCriticalSection(&m_CSDebug); + return ObjectCookie; +} + + +/* This is called by the CBaseObject destructor when an object is about to be + destroyed, we are passed the cookie we returned during construction that + identifies this object. We scan the object list for a matching cookie and + remove the object if successful. We also update the active object count */ + +BOOL WINAPI DbgRegisterObjectDestruction(DWORD dwCookie) +{ + /* Grab the list critical section */ + EnterCriticalSection(&m_CSDebug); + + ObjectDesc *pObject = pListHead; + ObjectDesc *pPrevious = NULL; + + /* Scan the object list looking for a cookie match */ + + while (pObject) { + if (pObject->m_dwCookie == dwCookie) { + break; + } + pPrevious = pObject; + pObject = pObject->m_pNext; + } + + if (pObject == NULL) { + DbgBreak("Apparently destroying a bogus object"); + LeaveCriticalSection(&m_CSDebug); + return FALSE; + } + + /* Is the object at the head of the list */ + + if (pPrevious == NULL) { + pListHead = pObject->m_pNext; + } else { + pPrevious->m_pNext = pObject->m_pNext; + } + + /* Delete the object and update the housekeeping information */ + + m_dwObjectCount--; + + if(pObject->m_wszName) { + DbgLog((LOG_MEMORY,2,TEXT("Object destroyed %d (%ls) %d Active"), + pObject->m_dwCookie, pObject->m_wszName, m_dwObjectCount)); + } else { + DbgLog((LOG_MEMORY,2,TEXT("Object destroyed %d (%hs) %d Active"), + pObject->m_dwCookie, pObject->m_szName, m_dwObjectCount)); + } + + delete pObject; + LeaveCriticalSection(&m_CSDebug); + return TRUE; +} + + +/* This runs through the active object list displaying their details */ + +void WINAPI DbgDumpObjectRegister() +{ + TCHAR szInfo[iDEBUGINFO]; + + /* Grab the list critical section */ + + EnterCriticalSection(&m_CSDebug); + ObjectDesc *pObject = pListHead; + + /* Scan the object list displaying the name and cookie */ + + DbgLog((LOG_MEMORY,2,TEXT(""))); + DbgLog((LOG_MEMORY,2,TEXT(" ID Object Description"))); + DbgLog((LOG_MEMORY,2,TEXT(""))); + + while (pObject) { + if(pObject->m_wszName) { + #ifdef UNICODE + LPCTSTR FORMAT_STRING = TEXT("%5d (%8x) %30s"); + #else + LPCTSTR FORMAT_STRING = TEXT("%5d (%8x) %30S"); + #endif + + (void)StringCchPrintf(szInfo,NUMELMS(szInfo), FORMAT_STRING, pObject->m_dwCookie, &pObject, pObject->m_wszName); + + } else { + #ifdef UNICODE + LPCTSTR FORMAT_STRING = TEXT("%5d (%8x) %30S"); + #else + LPCTSTR FORMAT_STRING = TEXT("%5d (%8x) %30s"); + #endif + + (void)StringCchPrintf(szInfo,NUMELMS(szInfo),FORMAT_STRING,pObject->m_dwCookie, &pObject, pObject->m_szName); + } + DbgLog((LOG_MEMORY,2,szInfo)); + pObject = pObject->m_pNext; + } + + (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("Total object count %5d"),m_dwObjectCount); + DbgLog((LOG_MEMORY,2,TEXT(""))); + DbgLog((LOG_MEMORY,1,szInfo)); + LeaveCriticalSection(&m_CSDebug); +} + +/* Debug infinite wait stuff */ +DWORD WINAPI DbgWaitForSingleObject(HANDLE h) +{ + DWORD dwWaitResult; + do { + dwWaitResult = WaitForSingleObject(h, dwWaitTimeout); + ASSERT(dwWaitResult == WAIT_OBJECT_0); + } while (dwWaitResult == WAIT_TIMEOUT); + return dwWaitResult; +} +DWORD WINAPI DbgWaitForMultipleObjects(DWORD nCount, + CONST HANDLE *lpHandles, + BOOL bWaitAll) +{ + DWORD dwWaitResult; + do { + dwWaitResult = WaitForMultipleObjects(nCount, + lpHandles, + bWaitAll, + dwWaitTimeout); + ASSERT((DWORD)(dwWaitResult - WAIT_OBJECT_0) < MAXIMUM_WAIT_OBJECTS); + } while (dwWaitResult == WAIT_TIMEOUT); + return dwWaitResult; +} + +void WINAPI DbgSetWaitTimeout(DWORD dwTimeout) +{ + dwWaitTimeout = dwTimeout; +} + +#endif /* DEBUG */ + +#ifdef _OBJBASE_H_ + + /* Stuff for printing out our GUID names */ + + GUID_STRING_ENTRY g_GuidNames[] = { + #define OUR_GUID_ENTRY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + { #name, { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } }, + #include + }; + + CGuidNameList GuidNames; + int g_cGuidNames = sizeof(g_GuidNames) / sizeof(g_GuidNames[0]); + + char *CGuidNameList::operator [] (const GUID &guid) + { + for (int i = 0; i < g_cGuidNames; i++) { + if (g_GuidNames[i].guid == guid) { + return g_GuidNames[i].szName; + } + } + if (guid == GUID_NULL) { + return "GUID_NULL"; + } + + // !!! add something to print FOURCC guids? + + // shouldn't this print the hex CLSID? + return "Unknown GUID Name"; + } + +#endif /* _OBJBASE_H_ */ + +/* CDisp class - display our data types */ + +// clashes with REFERENCE_TIME +CDisp::CDisp(LONGLONG ll, int Format) +{ + // note: this could be combined with CDisp(LONGLONG) by + // introducing a default format of CDISP_REFTIME + LARGE_INTEGER li; + li.QuadPart = ll; + switch (Format) { + case CDISP_DEC: + { + TCHAR temp[20]; + int pos=20; + temp[--pos] = 0; + int digit; + // always output at least one digit + do { + // Get the rightmost digit - we only need the low word + digit = li.LowPart % 10; + li.QuadPart /= 10; + temp[--pos] = (TCHAR) digit+L'0'; + } while (li.QuadPart); + (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("%s"), temp+pos); + break; + } + case CDISP_HEX: + default: + (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("0x%X%8.8X"), li.HighPart, li.LowPart); + } +}; + +CDisp::CDisp(REFCLSID clsid) +{ + WCHAR strClass[CHARS_IN_GUID+1]; + StringFromGUID2(clsid, strClass, sizeof(strClass) / sizeof(strClass[0])); + ASSERT(sizeof(m_String)/sizeof(m_String[0]) >= CHARS_IN_GUID+1); + #ifdef UNICODE + (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("%s"), strClass); + #else + (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("%S"), strClass); + #endif +}; + +#ifdef __STREAMS__ +/* Display stuff */ +CDisp::CDisp(CRefTime llTime) +{ + LPTSTR lpsz = m_String; + size_t len = NUMELMS(m_String); + LONGLONG llDiv; + if (llTime < 0) { + llTime = -llTime; + (void)StringCchPrintf(lpsz, len, TEXT("-")); + size_t t = lstrlen(lpsz); + lpsz += t; + len -= t; + } + llDiv = (LONGLONG)24 * 3600 * 10000000; + if (llTime >= llDiv) { + (void)StringCchPrintf(lpsz, len, TEXT("%d days "), (LONG)(llTime / llDiv)); + size_t t = lstrlen(lpsz); + lpsz += t; + len -= t; + llTime = llTime % llDiv; + } + llDiv = (LONGLONG)3600 * 10000000; + if (llTime >= llDiv) { + (void)StringCchPrintf(lpsz, len, TEXT("%d hrs "), (LONG)(llTime / llDiv)); + size_t t = lstrlen(lpsz); + lpsz += t; + len -= t; + llTime = llTime % llDiv; + } + llDiv = (LONGLONG)60 * 10000000; + if (llTime >= llDiv) { + (void)StringCchPrintf(lpsz, len, TEXT("%d mins "), (LONG)(llTime / llDiv)); + size_t t = lstrlen(lpsz); + lpsz += t; + len -= t; + llTime = llTime % llDiv; + } + (void)StringCchPrintf(lpsz, len, TEXT("%d.%3.3d sec"), + (LONG)llTime / 10000000, + (LONG)((llTime % 10000000) / 10000)); +}; + +#endif // __STREAMS__ + + +/* Display pin */ +CDisp::CDisp(IPin *pPin) +{ + PIN_INFO pi; + TCHAR str[MAX_PIN_NAME]; + CLSID clsid; + + if (pPin) { + pPin->QueryPinInfo(&pi); + pi.pFilter->GetClassID(&clsid); + QueryPinInfoReleaseFilter(pi); + #ifndef UNICODE + WideCharToMultiByte(GetACP(), 0, pi.achName, lstrlenW(pi.achName) + 1, + str, MAX_PIN_NAME, NULL, NULL); + #else + (void)StringCchCopy(str, NUMELMS(str), pi.achName); + #endif + } else { + (void)StringCchCopy(str, NUMELMS(str), TEXT("NULL IPin")); + } + + size_t len = lstrlen(str)+64; + m_pString = (PTCHAR) new TCHAR[len]; + if (!m_pString) { + return; + } + + #ifdef UNICODE + LPCTSTR FORMAT_STRING = TEXT("%S(%s)"); + #else + LPCTSTR FORMAT_STRING = TEXT("%s(%s)"); + #endif + + (void)StringCchPrintf(m_pString, len, FORMAT_STRING, GuidNames[clsid], str); +} + +/* Display filter or pin */ +CDisp::CDisp(IUnknown *pUnk) +{ + IBaseFilter *pf; + HRESULT hr = pUnk->QueryInterface(IID_IBaseFilter, (void **)&pf); + if(SUCCEEDED(hr)) + { + FILTER_INFO fi; + hr = pf->QueryFilterInfo(&fi); + if(SUCCEEDED(hr)) + { + QueryFilterInfoReleaseGraph(fi); + + size_t len = lstrlenW(fi.achName) + 1; + m_pString = new TCHAR[len]; + if(m_pString) + { + #ifdef UNICODE + LPCTSTR FORMAT_STRING = TEXT("%s"); + #else + LPCTSTR FORMAT_STRING = TEXT("%S"); + #endif + + (void)StringCchPrintf(m_pString, len, FORMAT_STRING, fi.achName); + } + } + + pf->Release(); + + return; + } + + IPin *pp; + hr = pUnk->QueryInterface(IID_IPin, (void **)&pp); + if(SUCCEEDED(hr)) + { + CDisp::CDisp(pp); + pp->Release(); + return; + } +} + + +CDisp::~CDisp() +{ +} + +CDispBasic::~CDispBasic() +{ + if (m_pString != m_String) { + delete [] m_pString; + } +} + +CDisp::CDisp(double d) +{ +#ifdef DEBUG + (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("%.16g"), d); +#else + (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("%d.%03d"), (int) d, (int) ((d - (int) d) * 1000)); +#endif +} + + +/* If built for debug this will display the media type details. We convert the + major and subtypes into strings and also ask the base classes for a string + description of the subtype, so MEDIASUBTYPE_RGB565 becomes RGB 565 16 bit + We also display the fields in the BITMAPINFOHEADER structure, this should + succeed as we do not accept input types unless the format is big enough */ + +#ifdef DEBUG +void WINAPI DisplayType(LPTSTR label, const AM_MEDIA_TYPE *pmtIn) +{ + + /* Dump the GUID types and a short description */ + + DbgLog((LOG_TRACE,5,TEXT(""))); + DbgLog((LOG_TRACE,2,TEXT("%s M type %hs S type %hs"), label, + GuidNames[pmtIn->majortype], + GuidNames[pmtIn->subtype])); + DbgLog((LOG_TRACE,5,TEXT("Subtype description %s"),GetSubtypeName(&pmtIn->subtype))); + + /* Dump the generic media types */ + + if (pmtIn->bTemporalCompression) { + DbgLog((LOG_TRACE,5,TEXT("Temporally compressed"))); + } else { + DbgLog((LOG_TRACE,5,TEXT("Not temporally compressed"))); + } + + if (pmtIn->bFixedSizeSamples) { + DbgLog((LOG_TRACE,5,TEXT("Sample size %d"),pmtIn->lSampleSize)); + } else { + DbgLog((LOG_TRACE,5,TEXT("Variable size samples"))); + } + + if (pmtIn->formattype == FORMAT_VideoInfo) { + /* Dump the contents of the BITMAPINFOHEADER structure */ + BITMAPINFOHEADER *pbmi = HEADER(pmtIn->pbFormat); + VIDEOINFOHEADER *pVideoInfo = (VIDEOINFOHEADER *)pmtIn->pbFormat; + + DbgLog((LOG_TRACE,5,TEXT("Source rectangle (Left %d Top %d Right %d Bottom %d)"), + pVideoInfo->rcSource.left, + pVideoInfo->rcSource.top, + pVideoInfo->rcSource.right, + pVideoInfo->rcSource.bottom)); + + DbgLog((LOG_TRACE,5,TEXT("Target rectangle (Left %d Top %d Right %d Bottom %d)"), + pVideoInfo->rcTarget.left, + pVideoInfo->rcTarget.top, + pVideoInfo->rcTarget.right, + pVideoInfo->rcTarget.bottom)); + + DbgLog((LOG_TRACE,5,TEXT("Size of BITMAPINFO structure %d"),pbmi->biSize)); + if (pbmi->biCompression < 256) { + DbgLog((LOG_TRACE,2,TEXT("%dx%dx%d bit (%d)"), + pbmi->biWidth, pbmi->biHeight, + pbmi->biBitCount, pbmi->biCompression)); + } else { + DbgLog((LOG_TRACE,2,TEXT("%dx%dx%d bit '%4.4hs'"), + pbmi->biWidth, pbmi->biHeight, + pbmi->biBitCount, &pbmi->biCompression)); + } + + DbgLog((LOG_TRACE,2,TEXT("Image size %d"),pbmi->biSizeImage)); + DbgLog((LOG_TRACE,5,TEXT("Planes %d"),pbmi->biPlanes)); + DbgLog((LOG_TRACE,5,TEXT("X Pels per metre %d"),pbmi->biXPelsPerMeter)); + DbgLog((LOG_TRACE,5,TEXT("Y Pels per metre %d"),pbmi->biYPelsPerMeter)); + DbgLog((LOG_TRACE,5,TEXT("Colours used %d"),pbmi->biClrUsed)); + + } else if (pmtIn->majortype == MEDIATYPE_Audio) { + DbgLog((LOG_TRACE,2,TEXT(" Format type %hs"), + GuidNames[pmtIn->formattype])); + DbgLog((LOG_TRACE,2,TEXT(" Subtype %hs"), + GuidNames[pmtIn->subtype])); + + if ((pmtIn->subtype != MEDIASUBTYPE_MPEG1Packet) + && (pmtIn->cbFormat >= sizeof(PCMWAVEFORMAT))) + { + /* Dump the contents of the WAVEFORMATEX type-specific format structure */ + + WAVEFORMATEX *pwfx = (WAVEFORMATEX *) pmtIn->pbFormat; + DbgLog((LOG_TRACE,2,TEXT("wFormatTag %u"), pwfx->wFormatTag)); + DbgLog((LOG_TRACE,2,TEXT("nChannels %u"), pwfx->nChannels)); + DbgLog((LOG_TRACE,2,TEXT("nSamplesPerSec %lu"), pwfx->nSamplesPerSec)); + DbgLog((LOG_TRACE,2,TEXT("nAvgBytesPerSec %lu"), pwfx->nAvgBytesPerSec)); + DbgLog((LOG_TRACE,2,TEXT("nBlockAlign %u"), pwfx->nBlockAlign)); + DbgLog((LOG_TRACE,2,TEXT("wBitsPerSample %u"), pwfx->wBitsPerSample)); + + /* PCM uses a WAVEFORMAT and does not have the extra size field */ + + if (pmtIn->cbFormat >= sizeof(WAVEFORMATEX)) { + DbgLog((LOG_TRACE,2,TEXT("cbSize %u"), pwfx->cbSize)); + } + } else { + } + + } else { + DbgLog((LOG_TRACE,2,TEXT(" Format type %hs"), + GuidNames[pmtIn->formattype])); + // !!!! should add code to dump wave format, others + } +} + + +void WINAPI DumpGraph(IFilterGraph *pGraph, DWORD dwLevel) +{ + if( !pGraph ) + { + return; + } + + IEnumFilters *pFilters; + + DbgLog((LOG_TRACE,dwLevel,TEXT("DumpGraph [%x]"), pGraph)); + + if (FAILED(pGraph->EnumFilters(&pFilters))) { + DbgLog((LOG_TRACE,dwLevel,TEXT("EnumFilters failed!"))); + } + + IBaseFilter *pFilter; + ULONG n; + while (pFilters->Next(1, &pFilter, &n) == S_OK) { + FILTER_INFO info; + + if (FAILED(pFilter->QueryFilterInfo(&info))) { + DbgLog((LOG_TRACE,dwLevel,TEXT(" Filter [%x] -- failed QueryFilterInfo"), pFilter)); + } else { + QueryFilterInfoReleaseGraph(info); + + // !!! should QueryVendorInfo here! + + DbgLog((LOG_TRACE,dwLevel,TEXT(" Filter [%x] '%ls'"), pFilter, info.achName)); + + IEnumPins *pins; + + if (FAILED(pFilter->EnumPins(&pins))) { + DbgLog((LOG_TRACE,dwLevel,TEXT("EnumPins failed!"))); + } else { + + IPin *pPin; + while (pins->Next(1, &pPin, &n) == S_OK) { + PIN_INFO info; + + if (FAILED(pPin->QueryPinInfo(&info))) { + DbgLog((LOG_TRACE,dwLevel,TEXT(" Pin [%x] -- failed QueryPinInfo"), pPin)); + } else { + QueryPinInfoReleaseFilter(info); + + IPin *pPinConnected = NULL; + + HRESULT hr = pPin->ConnectedTo(&pPinConnected); + + if (pPinConnected) { + DbgLog((LOG_TRACE,dwLevel,TEXT(" Pin [%x] '%ls' [%sput]") + TEXT(" Connected to pin [%x]"), + pPin, info.achName, + info.dir == PINDIR_INPUT ? TEXT("In") : TEXT("Out"), + pPinConnected)); + + pPinConnected->Release(); + + // perhaps we should really dump the type both ways as a sanity + // check? + if (info.dir == PINDIR_OUTPUT) { + AM_MEDIA_TYPE mt; + + hr = pPin->ConnectionMediaType(&mt); + + if (SUCCEEDED(hr)) { + DisplayType(TEXT("Connection type"), &mt); + + FreeMediaType(mt); + } + } + } else { + DbgLog((LOG_TRACE,dwLevel, + TEXT(" Pin [%x] '%ls' [%sput]"), + pPin, info.achName, + info.dir == PINDIR_INPUT ? TEXT("In") : TEXT("Out"))); + + } + } + + pPin->Release(); + + } + + pins->Release(); + } + + } + + pFilter->Release(); + } + + pFilters->Release(); + +} + +#endif + diff --git a/ThirdParty/strmbas/wxdebug.h b/ThirdParty/strmbas/wxdebug.h new file mode 100644 index 0000000..bc98967 --- /dev/null +++ b/ThirdParty/strmbas/wxdebug.h @@ -0,0 +1,393 @@ +//------------------------------------------------------------------------------ +// File: WXDebug.h +// +// Desc: DirectShow base classes - provides debugging facilities. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +#ifndef __WXDEBUG1__ +#define __WXDEBUG1__ + +// This library provides fairly straight forward debugging functionality, this +// is split into two main sections. The first is assertion handling, there are +// three types of assertions provided here. The most commonly used one is the +// ASSERT(condition) macro which will pop up a message box including the file +// and line number if the condition evaluates to FALSE. Then there is the +// EXECUTE_ASSERT macro which is the same as ASSERT except the condition will +// still be executed in NON debug builds. The final type of assertion is the +// KASSERT macro which is more suitable for pure (perhaps kernel) filters as +// the condition is printed onto the debugger rather than in a message box. +// +// The other part of the debug module facilties is general purpose logging. +// This is accessed by calling DbgLog(). The function takes a type and level +// field which define the type of informational string you are presenting and +// it's relative importance. The type field can be a combination (one or more) +// of LOG_TIMING, LOG_TRACE, LOG_MEMORY, LOG_LOCKING and LOG_ERROR. The level +// is a DWORD value where zero defines highest important. Use of zero as the +// debug logging level is to be encouraged ONLY for major errors or events as +// they will ALWAYS be displayed on the debugger. Other debug output has it's +// level matched against the current debug output level stored in the registry +// for this module and if less than the current setting it will be displayed. +// +// Each module or executable has it's own debug output level for each of the +// five types. These are read in when the DbgInitialise function is called +// for DLLs linking to STRMBASE.LIB this is done automatically when the DLL +// is loaded, executables must call it explicitely with the module instance +// handle given to them through the WINMAIN entry point. An executable must +// also call DbgTerminate when they have finished to clean up the resources +// the debug library uses, once again this is done automatically for DLLs + +// These are the five different categories of logging information + +enum { LOG_TIMING = 0x01, // Timing and performance measurements + LOG_TRACE = 0x02, // General step point call tracing + LOG_MEMORY = 0x04, // Memory and object allocation/destruction + LOG_LOCKING = 0x08, // Locking/unlocking of critical sections + LOG_ERROR = 0x10, // Debug error notification + LOG_CUSTOM1 = 0x20, + LOG_CUSTOM2 = 0x40, + LOG_CUSTOM3 = 0x80, + LOG_CUSTOM4 = 0x100, + LOG_CUSTOM5 = 0x200, +}; + +#define LOG_FORCIBLY_SET 0x80000000 + +enum { CDISP_HEX = 0x01, + CDISP_DEC = 0x02}; + +// For each object created derived from CBaseObject (in debug builds) we +// create a descriptor that holds it's name (statically allocated memory) +// and a cookie we assign it. We keep a list of all the active objects +// we have registered so that we can dump a list of remaining objects + +typedef struct tag_ObjectDesc { + const CHAR *m_szName; + const WCHAR *m_wszName; + DWORD m_dwCookie; + tag_ObjectDesc *m_pNext; +} ObjectDesc; + +#define DLLIMPORT __declspec(dllimport) +#define DLLEXPORT __declspec(dllexport) + +#ifdef DEBUG + + #define NAME(x) TEXT(x) + + // These are used internally by the debug library (PRIVATE) + + void WINAPI DbgInitKeyLevels(HKEY hKey, bool fTakeMax); + void WINAPI DbgInitGlobalSettings(bool fTakeMax); + void WINAPI DbgInitModuleSettings(bool fTakeMax); + void WINAPI DbgInitModuleName(); + DWORD WINAPI DbgRegisterObjectCreation( + const CHAR *szObjectName, const WCHAR *wszObjectName); + + BOOL WINAPI DbgRegisterObjectDestruction(DWORD dwCookie); + + // These are the PUBLIC entry points + + BOOL WINAPI DbgCheckModuleLevel(DWORD Type,DWORD Level); + void WINAPI DbgSetModuleLevel(DWORD Type,DWORD Level); + void WINAPI DbgSetAutoRefreshLevels(bool fAuto); + + // Initialise the library with the module handle + + void WINAPI DbgInitialise(HINSTANCE hInst); + void WINAPI DbgTerminate(); + + void WINAPI DbgDumpObjectRegister(); + + // Display error and logging to the user + + void WINAPI DbgAssert(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine); + void WINAPI DbgBreakPoint(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine); + void WINAPI DbgBreakPoint(const TCHAR *pFileName,INT iLine,const TCHAR* szFormatString,...); + + void WINAPI DbgKernelAssert(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine); + void WINAPI DbgLogInfo(DWORD Type,DWORD Level,const TCHAR *pFormat,...); +#ifdef UNICODE + void WINAPI DbgLogInfo(DWORD Type,DWORD Level,const CHAR *pFormat,...); + void WINAPI DbgAssert(const CHAR *pCondition,const CHAR *pFileName,INT iLine); + void WINAPI DbgBreakPoint(const CHAR *pCondition,const CHAR *pFileName,INT iLine); + void WINAPI DbgKernelAssert(const CHAR *pCondition,const CHAR *pFileName,INT iLine); +#endif + void WINAPI DbgOutString(LPCTSTR psz); + + // Debug infinite wait stuff + DWORD WINAPI DbgWaitForSingleObject(HANDLE h); + DWORD WINAPI DbgWaitForMultipleObjects(DWORD nCount, + CONST HANDLE *lpHandles, + BOOL bWaitAll); + void WINAPI DbgSetWaitTimeout(DWORD dwTimeout); + +#ifdef __strmif_h__ + // Display a media type: Terse at level 2, verbose at level 5 + void WINAPI DisplayType(LPTSTR label, const AM_MEDIA_TYPE *pmtIn); + + // Dump lots of information about a filter graph + void WINAPI DumpGraph(IFilterGraph *pGraph, DWORD dwLevel); +#endif + + #define KASSERT(_x_) if (!(_x_)) \ + DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__) + + // Break on the debugger without putting up a message box + // message goes to debugger instead + + #define KDbgBreak(_x_) \ + DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__) + + // We chose a common name for our ASSERT macro, MFC also uses this name + // So long as the implementation evaluates the condition and handles it + // then we will be ok. Rather than override the behaviour expected we + // will leave whatever first defines ASSERT as the handler (i.e. MFC) + #ifndef ASSERT + #define ASSERT(_x_) if (!(_x_)) \ + DbgAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__) + #endif + + #define DbgAssertAligned( _ptr_, _alignment_ ) ASSERT( ((DWORD_PTR) (_ptr_)) % (_alignment_) == 0) + + // Put up a message box informing the user of a halt + // condition in the program + + #define DbgBreak(_x_) \ + DbgBreakPoint(TEXT(#_x_),TEXT(__FILE__),__LINE__) + + #define EXECUTE_ASSERT(_x_) ASSERT(_x_) + #define DbgLog(_x_) DbgLogInfo _x_ + // MFC style trace macros + + #define NOTE(_x_) DbgLog((LOG_TRACE,5,TEXT(_x_))) + #define NOTE1(_x_,a) DbgLog((LOG_TRACE,5,TEXT(_x_),a)) + #define NOTE2(_x_,a,b) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b)) + #define NOTE3(_x_,a,b,c) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c)) + #define NOTE4(_x_,a,b,c,d) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d)) + #define NOTE5(_x_,a,b,c,d,e) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d,e)) + +#else + + // Retail builds make public debug functions inert - WARNING the source + // files do not define or build any of the entry points in debug builds + // (public entry points compile to nothing) so if you go trying to call + // any of the private entry points in your source they won't compile + + #define NAME(_x_) ((TCHAR *) NULL) + + #define DbgInitialise(hInst) + #define DbgTerminate() + #define DbgLog(_x_) 0 + #define DbgOutString(psz) + #define DbgAssertAligned( _ptr_, _alignment_ ) 0 + + #define DbgRegisterObjectCreation(pObjectName) + #define DbgRegisterObjectDestruction(dwCookie) + #define DbgDumpObjectRegister() + + #define DbgCheckModuleLevel(Type,Level) + #define DbgSetModuleLevel(Type,Level) + #define DbgSetAutoRefreshLevels(fAuto) + + #define DbgWaitForSingleObject(h) WaitForSingleObject(h, INFINITE) + #define DbgWaitForMultipleObjects(nCount, lpHandles, bWaitAll) \ + WaitForMultipleObjects(nCount, lpHandles, bWaitAll, INFINITE) + #define DbgSetWaitTimeout(dwTimeout) + + #define KDbgBreak(_x_) + #define DbgBreak(_x_) + + #define KASSERT(_x_) ((void)0) + #ifndef ASSERT + #define ASSERT(_x_) ((void)0) + #endif + #define EXECUTE_ASSERT(_x_) ((void)(_x_)) + + // MFC style trace macros + + #define NOTE(_x_) ((void)0) + #define NOTE1(_x_,a) ((void)0) + #define NOTE2(_x_,a,b) ((void)0) + #define NOTE3(_x_,a,b,c) ((void)0) + #define NOTE4(_x_,a,b,c,d) ((void)0) + #define NOTE5(_x_,a,b,c,d,e) ((void)0) + + #define DisplayType(label, pmtIn) ((void)0) + #define DumpGraph(pGraph, label) ((void)0) +#endif + + +// Checks a pointer which should be non NULL - can be used as follows. + +#define CheckPointer(p,ret) {if((p)==NULL) return (ret);} + +// HRESULT Foo(VOID *pBar) +// { +// CheckPointer(pBar,E_INVALIDARG) +// } +// +// Or if the function returns a boolean +// +// BOOL Foo(VOID *pBar) +// { +// CheckPointer(pBar,FALSE) +// } + +// These validate pointers when symbol VFWROBUST is defined +// This will normally be defined in debug not retail builds + +#ifdef DEBUG + #define VFWROBUST +#endif + +#ifdef VFWROBUST + + #define ValidateReadPtr(p,cb) \ + {if(IsBadReadPtr((PVOID)p,cb) == TRUE) \ + DbgBreak("Invalid read pointer");} + + #define ValidateWritePtr(p,cb) \ + {if(IsBadWritePtr((PVOID)p,cb) == TRUE) \ + DbgBreak("Invalid write pointer");} + + #define ValidateReadWritePtr(p,cb) \ + {ValidateReadPtr(p,cb) ValidateWritePtr(p,cb)} + + #define ValidateStringPtr(p) \ + {if(IsBadStringPtr((LPCTSTR)p,INFINITE) == TRUE) \ + DbgBreak("Invalid string pointer");} + + #define ValidateStringPtrA(p) \ + {if(IsBadStringPtrA((LPCSTR)p,INFINITE) == TRUE) \ + DbgBreak("Invalid ANSI string pointer");} + + #define ValidateStringPtrW(p) \ + {if(IsBadStringPtrW((LPCWSTR)p,INFINITE) == TRUE) \ + DbgBreak("Invalid UNICODE string pointer");} + +#else + #define ValidateReadPtr(p,cb) 0 + #define ValidateWritePtr(p,cb) 0 + #define ValidateReadWritePtr(p,cb) 0 + #define ValidateStringPtr(p) 0 + #define ValidateStringPtrA(p) 0 + #define ValidateStringPtrW(p) 0 +#endif + + +#ifdef _OBJBASE_H_ + + // Outputting GUID names. If you want to include the name + // associated with a GUID (eg CLSID_...) then + // + // GuidNames[yourGUID] + // + // Returns the name defined in uuids.h as a string + + typedef struct { + CHAR *szName; + GUID guid; + } GUID_STRING_ENTRY; + + class CGuidNameList { + public: + CHAR *operator [] (const GUID& guid); + }; + + extern CGuidNameList GuidNames; + +#endif + +#ifndef REMIND + // REMIND macro - generates warning as reminder to complete coding + // (eg) usage: + // + // #pragma message (REMIND("Add automation support")) + + + #define QUOTE(x) #x + #define QQUOTE(y) QUOTE(y) + #define REMIND(str) __FILE__ "(" QQUOTE(__LINE__) ") : " str +#endif + +// Method to display objects in a useful format +// +// eg If you want to display a LONGLONG ll in a debug string do (eg) +// +// DbgLog((LOG_TRACE, n, TEXT("Value is %s"), (LPCTSTR)CDisp(ll, CDISP_HEX))); + + +class CDispBasic +{ +public: + CDispBasic() { m_pString = m_String; }; + ~CDispBasic(); +protected: + PTCHAR m_pString; // normally points to m_String... unless too much data + TCHAR m_String[50]; +}; +class CDisp : public CDispBasic +{ +public: + CDisp(LONGLONG ll, int Format = CDISP_HEX); // Display a LONGLONG in CDISP_HEX or CDISP_DEC form + CDisp(REFCLSID clsid); // Display a GUID + CDisp(double d); // Display a floating point number +#ifdef __strmif_h__ +#ifdef __STREAMS__ + CDisp(CRefTime t); // Display a Reference Time +#endif + CDisp(IPin *pPin); // Display a pin as {filter clsid}(pin name) + CDisp(IUnknown *pUnk); // Display a filter or pin +#endif // __strmif_h__ + ~CDisp(); + + // Implement cast to (LPCTSTR) as parameter to logger + operator LPCTSTR() + { + return (LPCTSTR)m_pString; + }; +}; + + +#if defined(DEBUG) +class CAutoTrace +{ +private: + const TCHAR* _szBlkName; + const int _level; + static const TCHAR _szEntering[]; + static const TCHAR _szLeaving[]; +public: + CAutoTrace(const TCHAR* szBlkName, const int level = 15) + : _szBlkName(szBlkName), _level(level) + {DbgLog((LOG_TRACE, _level, _szEntering, _szBlkName));} + + ~CAutoTrace() + {DbgLog((LOG_TRACE, _level, _szLeaving, _szBlkName));} +}; + +#if defined (__FUNCTION__) + +#define AMTRACEFN() CAutoTrace __trace(TEXT(__FUNCTION__)) +#define AMTRACE(_x_) CAutoTrace __trace(TEXT(__FUNCTION__)) + +#else + +#define AMTRACE(_x_) CAutoTrace __trace _x_ +#define AMTRACEFN() + +#endif + +#else + +#define AMTRACE(_x_) +#define AMTRACEFN() + +#endif + +#endif // __WXDEBUG__ + + diff --git a/ThirdParty/strmbas/wxlist.cpp b/ThirdParty/strmbas/wxlist.cpp new file mode 100644 index 0000000..9657f09 --- /dev/null +++ b/ThirdParty/strmbas/wxlist.cpp @@ -0,0 +1,885 @@ +//------------------------------------------------------------------------------ +// File: WXList.cpp +// +// Desc: DirectShow base classes - implements a non-MFC based generic list +// template class. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +/* A generic list of pointers to objects. + Objectives: avoid using MFC libraries in ndm kernel mode and + provide a really useful list type. + + The class is thread safe in that separate threads may add and + delete items in the list concurrently although the application + must ensure that constructor and destructor access is suitably + synchronised. + + The list name must not conflict with MFC classes as an + application may use both + + The nodes form a doubly linked, NULL terminated chain with an anchor + block (the list object per se) holding pointers to the first and last + nodes and a count of the nodes. + There is a node cache to reduce the allocation and freeing overhead. + It optionally (determined at construction time) has an Event which is + set whenever the list becomes non-empty and reset whenever it becomes + empty. + It optionally (determined at construction time) has a Critical Section + which is entered during the important part of each operation. (About + all you can do outside it is some parameter checking). + + The node cache is a repository of nodes that are NOT in the list to speed + up storage allocation. Each list has its own cache to reduce locking and + serialising. The list accesses are serialised anyway for a given list - a + common cache would mean that we would have to separately serialise access + of all lists within the cache. Because the cache only stores nodes that are + not in the list, releasing the cache does not release any list nodes. This + means that list nodes can be copied or rechained from one list to another + without danger of creating a dangling reference if the original cache goes + away. + + Questionable design decisions: + 1. Retaining the warts for compatibility + 2. Keeping an element count -i.e. counting whenever we do anything + instead of only when we want the count. + 3. Making the chain pointers NULL terminated. If the list object + itself looks just like a node and the list is kept as a ring then + it reduces the number of special cases. All inserts look the same. +*/ + + +#include + +/* set cursor to the position of each element of list in turn */ +#define INTERNALTRAVERSELIST(list, cursor) \ +for ( cursor = (list).GetHeadPositionI() \ + ; cursor!=NULL \ + ; cursor = (list).Next(cursor) \ + ) + + +/* set cursor to the position of each element of list in turn + in reverse order +*/ +#define INTERNALREVERSETRAVERSELIST(list, cursor) \ +for ( cursor = (list).GetTailPositionI() \ + ; cursor!=NULL \ + ; cursor = (list).Prev(cursor) \ + ) + +/* Constructor calls a separate initialisation function that + creates a node cache, optionally creates a lock object + and optionally creates a signaling object. + + By default we create a locking object, a DEFAULTCACHE sized + cache but no event object so the list cannot be used in calls + to WaitForSingleObject +*/ +CBaseList::CBaseList(TCHAR *pName, // Descriptive list name + INT iItems) : // Node cache size +#ifdef DEBUG + CBaseObject(pName), +#endif + m_pFirst(NULL), + m_pLast(NULL), + m_Count(0), + m_Cache(iItems) +{ +} // constructor + +CBaseList::CBaseList(TCHAR *pName) : // Descriptive list name +#ifdef DEBUG + CBaseObject(pName), +#endif + m_pFirst(NULL), + m_pLast(NULL), + m_Count(0), + m_Cache(DEFAULTCACHE) +{ +} // constructor + +#ifdef UNICODE +CBaseList::CBaseList(CHAR *pName, // Descriptive list name + INT iItems) : // Node cache size +#ifdef DEBUG + CBaseObject(pName), +#endif + m_pFirst(NULL), + m_pLast(NULL), + m_Count(0), + m_Cache(iItems) +{ +} // constructor + +CBaseList::CBaseList(CHAR *pName) : // Descriptive list name +#ifdef DEBUG + CBaseObject(pName), +#endif + m_pFirst(NULL), + m_pLast(NULL), + m_Count(0), + m_Cache(DEFAULTCACHE) +{ +} // constructor + +#endif + +/* The destructor enumerates all the node objects in the list and + in the cache deleting each in turn. We do not do any processing + on the objects that the list holds (i.e. points to) so if they + represent interfaces for example the creator of the list should + ensure that each of them is released before deleting us +*/ +CBaseList::~CBaseList() +{ + /* Delete all our list nodes */ + + RemoveAll(); + +} // destructor + +/* Remove all the nodes from the list but don't do anything + with the objects that each node looks after (this is the + responsibility of the creator). + Aa a last act we reset the signalling event + (if available) to indicate to clients that the list + does not have any entries in it. +*/ +void CBaseList::RemoveAll() +{ + /* Free up all the CNode objects NOTE we don't bother putting the + deleted nodes into the cache as this method is only really called + in serious times of change such as when we are being deleted at + which point the cache will be deleted anway */ + + CNode *pn = m_pFirst; + while (pn) { + CNode *op = pn; + pn = pn->Next(); + delete op; + } + + /* Reset the object count and the list pointers */ + + m_Count = 0; + m_pFirst = m_pLast = NULL; + +} // RemoveAll + + + +/* Return a position enumerator for the entire list. + A position enumerator is a pointer to a node object cast to a + transparent type so all we do is return the head/tail node + pointer in the list. + WARNING because the position is a pointer to a node there is + an implicit assumption for users a the list class that after + deleting an object from the list that any other position + enumerators that you have may be invalid (since the node + may be gone). +*/ +POSITION CBaseList::GetHeadPositionI() const +{ + return (POSITION) m_pFirst; +} // GetHeadPosition + + + +POSITION CBaseList::GetTailPositionI() const +{ + return (POSITION) m_pLast; +} // GetTailPosition + + + +/* Get the number of objects in the list, + Get the lock before accessing the count. + Locking may not be entirely necessary but it has the side effect + of making sure that all operations are complete before we get it. + So for example if a list is being added to this list then that + will have completed in full before we continue rather than seeing + an intermediate albeit valid state +*/ +int CBaseList::GetCountI() const +{ + return m_Count; +} // GetCount + + + +/* Return the object at rp, update rp to the next object from + the list or NULL if you have moved over the last object. + You may still call this function once we return NULL but + we will continue to return a NULL position value +*/ +void *CBaseList::GetNextI(POSITION& rp) const +{ + /* have we reached the end of the list */ + + if (rp == NULL) { + return NULL; + } + + /* Lock the object before continuing */ + + void *pObject; + + /* Copy the original position then step on */ + + CNode *pn = (CNode *) rp; + ASSERT(pn != NULL); + rp = (POSITION) pn->Next(); + + /* Get the object at the original position from the list */ + + pObject = pn->GetData(); + // ASSERT(pObject != NULL); // NULL pointers in the list are allowed. + return pObject; +} //GetNext + + + +/* Return the object at p. + Asking for the object at NULL ASSERTs then returns NULL + The object is NOT locked. The list is not being changed + in any way. If another thread is busy deleting the object + then locking would only result in a change from one bad + behaviour to another. +*/ +void *CBaseList::GetI(POSITION p) const +{ + if (p == NULL) { + return NULL; + } + + CNode * pn = (CNode *) p; + void *pObject = pn->GetData(); + // ASSERT(pObject != NULL); // NULL pointers in the list are allowed. + return pObject; +} //Get + + + +/* Return the first position in the list which holds the given pointer. + Return NULL if it's not found. +*/ +POSITION CBaseList::FindI( void * pObj) const +{ + POSITION pn; + INTERNALTRAVERSELIST(*this, pn){ + if (GetI(pn)==pObj) { + return pn; + } + } + return NULL; +} // Find + + + +/* Remove the first node in the list (deletes the pointer to its object + from the list, does not free the object itself). + Return the pointer to its object or NULL if empty +*/ +void *CBaseList::RemoveHeadI() +{ + /* All we do is get the head position and ask for that to be deleted. + We could special case this since some of the code path checking + in Remove() is redundant as we know there is no previous + node for example but it seems to gain little over the + added complexity + */ + + return RemoveI((POSITION)m_pFirst); +} // RemoveHead + + + +/* Remove the last node in the list (deletes the pointer to its object + from the list, does not free the object itself). + Return the pointer to its object or NULL if empty +*/ +void *CBaseList::RemoveTailI() +{ + /* All we do is get the tail position and ask for that to be deleted. + We could special case this since some of the code path checking + in Remove() is redundant as we know there is no previous + node for example but it seems to gain little over the + added complexity + */ + + return RemoveI((POSITION)m_pLast); +} // RemoveTail + + + +/* Remove the pointer to the object in this position from the list. + Deal with all the chain pointers + Return a pointer to the object removed from the list. + The node object that is freed as a result + of this operation is added to the node cache where + it can be used again. + Remove(NULL) is a harmless no-op - but probably is a wart. +*/ +void *CBaseList::RemoveI(POSITION pos) +{ + /* Lock the critical section before continuing */ + + // ASSERT (pos!=NULL); // Removing NULL is to be harmless! + if (pos==NULL) return NULL; + + + CNode *pCurrent = (CNode *) pos; + ASSERT(pCurrent != NULL); + + /* Update the previous node */ + + CNode *pNode = pCurrent->Prev(); + if (pNode == NULL) { + m_pFirst = pCurrent->Next(); + } else { + pNode->SetNext(pCurrent->Next()); + } + + /* Update the following node */ + + pNode = pCurrent->Next(); + if (pNode == NULL) { + m_pLast = pCurrent->Prev(); + } else { + pNode->SetPrev(pCurrent->Prev()); + } + + /* Get the object this node was looking after */ + + void *pObject = pCurrent->GetData(); + + // ASSERT(pObject != NULL); // NULL pointers in the list are allowed. + + /* Try and add the node object to the cache - + a NULL return code from the cache means we ran out of room. + The cache size is fixed by a constructor argument when the + list is created and defaults to DEFAULTCACHE. + This means that the cache will have room for this many + node objects. So if you have a list of media samples + and you know there will never be more than five active at + any given time of them for example then override the default + constructor + */ + + m_Cache.AddToCache(pCurrent); + + /* If the list is empty then reset the list event */ + + --m_Count; + ASSERT(m_Count >= 0); + return pObject; +} // Remove + + + +/* Add this object to the tail end of our list + Return the new tail position. +*/ + +POSITION CBaseList::AddTailI(void *pObject) +{ + /* Lock the critical section before continuing */ + + CNode *pNode; + // ASSERT(pObject); // NULL pointers in the list are allowed. + + /* If there is a node objects in the cache then use + that otherwise we will have to create a new one */ + + pNode = (CNode *) m_Cache.RemoveFromCache(); + if (pNode == NULL) { + pNode = new CNode; + } + + /* Check we have a valid object */ + + if (pNode == NULL) { + return NULL; + } + + /* Initialise all the CNode object + just in case it came from the cache + */ + + pNode->SetData(pObject); + pNode->SetNext(NULL); + pNode->SetPrev(m_pLast); + + if (m_pLast == NULL) { + m_pFirst = pNode; + } else { + m_pLast->SetNext(pNode); + } + + /* Set the new last node pointer and also increment the number + of list entries, the critical section is unlocked when we + exit the function + */ + + m_pLast = pNode; + ++m_Count; + + return (POSITION) pNode; +} // AddTail(object) + + + +/* Add this object to the head end of our list + Return the new head position. +*/ +POSITION CBaseList::AddHeadI(void *pObject) +{ + CNode *pNode; + // ASSERT(pObject); // NULL pointers in the list are allowed. + + /* If there is a node objects in the cache then use + that otherwise we will have to create a new one */ + + pNode = (CNode *) m_Cache.RemoveFromCache(); + if (pNode == NULL) { + pNode = new CNode; + } + + /* Check we have a valid object */ + + if (pNode == NULL) { + return NULL; + } + + /* Initialise all the CNode object + just in case it came from the cache + */ + + pNode->SetData(pObject); + + /* chain it in (set four pointers) */ + pNode->SetPrev(NULL); + pNode->SetNext(m_pFirst); + + if (m_pFirst == NULL) { + m_pLast = pNode; + } else { + m_pFirst->SetPrev(pNode); + } + m_pFirst = pNode; + + ++m_Count; + + return (POSITION) pNode; +} // AddHead(object) + + + +/* Add all the elements in *pList to the tail of this list. + Return TRUE if it all worked, FALSE if it didn't. + If it fails some elements may have been added. +*/ +BOOL CBaseList::AddTail(CBaseList *pList) +{ + /* lock the object before starting then enumerate + each entry in the source list and add them one by one to + our list (while still holding the object lock) + Lock the other list too. + */ + POSITION pos = pList->GetHeadPositionI(); + + while (pos) { + if (NULL == AddTailI(pList->GetNextI(pos))) { + return FALSE; + } + } + return TRUE; +} // AddTail(list) + + + +/* Add all the elements in *pList to the head of this list. + Return TRUE if it all worked, FALSE if it didn't. + If it fails some elements may have been added. +*/ +BOOL CBaseList::AddHead(CBaseList *pList) +{ + /* lock the object before starting then enumerate + each entry in the source list and add them one by one to + our list (while still holding the object lock) + Lock the other list too. + + To avoid reversing the list, traverse it backwards. + */ + + POSITION pos; + + INTERNALREVERSETRAVERSELIST(*pList, pos) { + if (NULL== AddHeadI(pList->GetI(pos))){ + return FALSE; + } + } + return TRUE; +} // AddHead(list) + + + +/* Add the object after position p + p is still valid after the operation. + AddAfter(NULL,x) adds x to the start - same as AddHead + Return the position of the new object, NULL if it failed +*/ +POSITION CBaseList::AddAfterI(POSITION pos, void * pObj) +{ + if (pos==NULL) + return AddHeadI(pObj); + + /* As someone else might be furkling with the list - + Lock the critical section before continuing + */ + CNode *pAfter = (CNode *) pos; + ASSERT(pAfter != NULL); + if (pAfter==m_pLast) + return AddTailI(pObj); + + /* set pnode to point to a new node, preferably from the cache */ + + CNode *pNode = (CNode *) m_Cache.RemoveFromCache(); + if (pNode == NULL) { + pNode = new CNode; + } + + /* Check we have a valid object */ + + if (pNode == NULL) { + return NULL; + } + + /* Initialise all the CNode object + just in case it came from the cache + */ + + pNode->SetData(pObj); + + /* It is to be added to the middle of the list - there is a before + and after node. Chain it after pAfter, before pBefore. + */ + CNode * pBefore = pAfter->Next(); + ASSERT(pBefore != NULL); + + /* chain it in (set four pointers) */ + pNode->SetPrev(pAfter); + pNode->SetNext(pBefore); + pBefore->SetPrev(pNode); + pAfter->SetNext(pNode); + + ++m_Count; + + return (POSITION) pNode; + +} // AddAfter(object) + + + +BOOL CBaseList::AddAfter(POSITION p, CBaseList *pList) +{ + POSITION pos; + INTERNALTRAVERSELIST(*pList, pos) { + /* p follows along the elements being added */ + p = AddAfterI(p, pList->GetI(pos)); + if (p==NULL) return FALSE; + } + return TRUE; +} // AddAfter(list) + + + +/* Mirror images: + Add the element or list after position p. + p is still valid after the operation. + AddBefore(NULL,x) adds x to the end - same as AddTail +*/ +POSITION CBaseList::AddBeforeI(POSITION pos, void * pObj) +{ + if (pos==NULL) + return AddTailI(pObj); + + /* set pnode to point to a new node, preferably from the cache */ + + CNode *pBefore = (CNode *) pos; + ASSERT(pBefore != NULL); + if (pBefore==m_pFirst) + return AddHeadI(pObj); + + CNode * pNode = (CNode *) m_Cache.RemoveFromCache(); + if (pNode == NULL) { + pNode = new CNode; + } + + /* Check we have a valid object */ + + if (pNode == NULL) { + return NULL; + } + + /* Initialise all the CNode object + just in case it came from the cache + */ + + pNode->SetData(pObj); + + /* It is to be added to the middle of the list - there is a before + and after node. Chain it after pAfter, before pBefore. + */ + + CNode * pAfter = pBefore->Prev(); + ASSERT(pAfter != NULL); + + /* chain it in (set four pointers) */ + pNode->SetPrev(pAfter); + pNode->SetNext(pBefore); + pBefore->SetPrev(pNode); + pAfter->SetNext(pNode); + + ++m_Count; + + return (POSITION) pNode; + +} // Addbefore(object) + + + +BOOL CBaseList::AddBefore(POSITION p, CBaseList *pList) +{ + POSITION pos; + INTERNALREVERSETRAVERSELIST(*pList, pos) { + /* p follows along the elements being added */ + p = AddBeforeI(p, pList->GetI(pos)); + if (p==NULL) return FALSE; + } + return TRUE; +} // AddBefore(list) + + + +/* Split *this after position p in *this + Retain as *this the tail portion of the original *this + Add the head portion to the tail end of *pList + Return TRUE if it all worked, FALSE if it didn't. + + e.g. + foo->MoveToTail(foo->GetHeadPosition(), bar); + moves one element from the head of foo to the tail of bar + foo->MoveToTail(NULL, bar); + is a no-op + foo->MoveToTail(foo->GetTailPosition, bar); + concatenates foo onto the end of bar and empties foo. + + A better, except excessively long name might be + MoveElementsFromHeadThroughPositionToOtherTail +*/ +BOOL CBaseList::MoveToTail + (POSITION pos, CBaseList *pList) +{ + /* Algorithm: + Note that the elements (including their order) in the concatenation + of *pList to the head of *this is invariant. + 1. Count elements to be moved + 2. Join *pList onto the head of this to make one long chain + 3. Set first/Last pointers in *this and *pList + 4. Break the chain at the new place + 5. Adjust counts + 6. Set/Reset any events + */ + + if (pos==NULL) return TRUE; // no-op. Eliminates special cases later. + + + /* Make cMove the number of nodes to move */ + CNode * p = (CNode *)pos; + int cMove = 0; // number of nodes to move + while(p!=NULL) { + p = p->Prev(); + ++cMove; + } + + + /* Join the two chains together */ + if (pList->m_pLast!=NULL) + pList->m_pLast->SetNext(m_pFirst); + if (m_pFirst!=NULL) + m_pFirst->SetPrev(pList->m_pLast); + + + /* set first and last pointers */ + p = (CNode *)pos; + + if (pList->m_pFirst==NULL) + pList->m_pFirst = m_pFirst; + m_pFirst = p->Next(); + if (m_pFirst==NULL) + m_pLast = NULL; + pList->m_pLast = p; + + + /* Break the chain after p to create the new pieces */ + if (m_pFirst!=NULL) + m_pFirst->SetPrev(NULL); + p->SetNext(NULL); + + + /* Adjust the counts */ + m_Count -= cMove; + pList->m_Count += cMove; + + return TRUE; + +} // MoveToTail + + + +/* Mirror image of MoveToTail: + Split *this before position p in *this. + Retain in *this the head portion of the original *this + Add the tail portion to the start (i.e. head) of *pList + Return TRUE if it all worked, FALSE if it didn't. + + e.g. + foo->MoveToHead(foo->GetTailPosition(), bar); + moves one element from the tail of foo to the head of bar + foo->MoveToHead(NULL, bar); + is a no-op + foo->MoveToHead(foo->GetHeadPosition, bar); + concatenates foo onto the start of bar and empties foo. +*/ +BOOL CBaseList::MoveToHead + (POSITION pos, CBaseList *pList) +{ + + /* See the comments on the algorithm in MoveToTail */ + + if (pos==NULL) return TRUE; // no-op. Eliminates special cases later. + + /* Make cMove the number of nodes to move */ + CNode * p = (CNode *)pos; + int cMove = 0; // number of nodes to move + while(p!=NULL) { + p = p->Next(); + ++cMove; + } + + + /* Join the two chains together */ + if (pList->m_pFirst!=NULL) + pList->m_pFirst->SetPrev(m_pLast); + if (m_pLast!=NULL) + m_pLast->SetNext(pList->m_pFirst); + + + /* set first and last pointers */ + p = (CNode *)pos; + + + if (pList->m_pLast==NULL) + pList->m_pLast = m_pLast; + + m_pLast = p->Prev(); + if (m_pLast==NULL) + m_pFirst = NULL; + pList->m_pFirst = p; + + + /* Break the chain after p to create the new pieces */ + if (m_pLast!=NULL) + m_pLast->SetNext(NULL); + p->SetPrev(NULL); + + + /* Adjust the counts */ + m_Count -= cMove; + pList->m_Count += cMove; + + return TRUE; + +} // MoveToHead + + + +/* Reverse the order of the [pointers to] objects in *this +*/ +void CBaseList::Reverse() +{ + /* algorithm: + The obvious booby trap is that you flip pointers around and lose + addressability to the node that you are going to process next. + The easy way to avoid this is do do one chain at a time. + + Run along the forward chain, + For each node, set the reverse pointer to the one ahead of us. + The reverse chain is now a copy of the old forward chain, including + the NULL termination. + + Run along the reverse chain (i.e. old forward chain again) + For each node set the forward pointer of the node ahead to point back + to the one we're standing on. + The first node needs special treatment, + it's new forward pointer is NULL. + Finally set the First/Last pointers + + */ + CNode * p; + + // Yes we COULD use a traverse, but it would look funny! + p = m_pFirst; + while (p!=NULL) { + CNode * q; + q = p->Next(); + p->SetNext(p->Prev()); + p->SetPrev(q); + p = q; + } + + p = m_pFirst; + m_pFirst = m_pLast; + m_pLast = p; + + +#if 0 // old version + + if (m_pFirst==NULL) return; // empty list + if (m_pFirst->Next()==NULL) return; // single node list + + + /* run along forward chain */ + for ( p = m_pFirst + ; p!=NULL + ; p = p->Next() + ){ + p->SetPrev(p->Next()); + } + + + /* special case first element */ + m_pFirst->SetNext(NULL); // fix the old first element + + + /* run along new reverse chain i.e. old forward chain again */ + for ( p = m_pFirst // start at the old first element + ; p->Prev()!=NULL // while there's a node still to be set + ; p = p->Prev() // work in the same direction as before + ){ + p->Prev()->SetNext(p); + } + + + /* fix forward and reverse pointers + - the triple XOR swap would work but all the casts look hideous */ + p = m_pFirst; + m_pFirst = m_pLast; + m_pLast = p; +#endif + +} // Reverse diff --git a/ThirdParty/strmbas/wxlist.h b/ThirdParty/strmbas/wxlist.h new file mode 100644 index 0000000..1e360f7 --- /dev/null +++ b/ThirdParty/strmbas/wxlist.h @@ -0,0 +1,545 @@ +//------------------------------------------------------------------------------ +// File: WXList.h +// +// Desc: DirectShow base classes - defines a non-MFC generic template list +// class. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +/* A generic list of pointers to objects. + No storage management or copying is done on the objects pointed to. + Objectives: avoid using MFC libraries in ndm kernel mode and + provide a really useful list type. + + The class is thread safe in that separate threads may add and + delete items in the list concurrently although the application + must ensure that constructor and destructor access is suitably + synchronised. An application can cause deadlock with operations + which use two lists by simultaneously calling + list1->Operation(list2) and list2->Operation(list1). So don't! + + The names must not conflict with MFC classes as an application + may use both. + */ + +#ifndef __WXLIST__ +#define __WXLIST__ + + /* A POSITION represents (in some fashion that's opaque) a cursor + on the list that can be set to identify any element. NULL is + a valid value and several operations regard NULL as the position + "one step off the end of the list". (In an n element list there + are n+1 places to insert and NULL is that "n+1-th" value). + The POSITION of an element in the list is only invalidated if + that element is deleted. Move operations may mean that what + was a valid POSITION in one list is now a valid POSITION in + a different list. + + Some operations which at first sight are illegal are allowed as + harmless no-ops. For instance RemoveHead is legal on an empty + list and it returns NULL. This allows an atomic way to test if + there is an element there, and if so, get it. The two operations + AddTail and RemoveHead thus implement a MONITOR (See Hoare's paper). + + Single element operations return POSITIONs, non-NULL means it worked. + whole list operations return a BOOL. TRUE means it all worked. + + This definition is the same as the POSITION type for MFCs, so we must + avoid defining it twice. + */ +#ifndef __AFX_H__ +struct __POSITION { int unused; }; +typedef __POSITION* POSITION; +#endif + +const int DEFAULTCACHE = 10; /* Default node object cache size */ + +/* A class representing one node in a list. + Each node knows a pointer to it's adjacent nodes and also a pointer + to the object that it looks after. + All of these pointers can be retrieved or set through member functions. +*/ +class CBaseList +#ifdef DEBUG + : public CBaseObject +#endif +{ + /* Making these classes inherit from CBaseObject does nothing + functionally but it allows us to check there are no memory + leaks in debug builds. + */ + +public: + +#ifdef DEBUG + class CNode : public CBaseObject { +#else + class CNode { +#endif + + CNode *m_pPrev; /* Previous node in the list */ + CNode *m_pNext; /* Next node in the list */ + void *m_pObject; /* Pointer to the object */ + + public: + + /* Constructor - initialise the object's pointers */ + CNode() +#ifdef DEBUG + : CBaseObject(NAME("List node")) +#endif + { + }; + + + /* Return the previous node before this one */ + CNode *Prev() const { return m_pPrev; }; + + + /* Return the next node after this one */ + CNode *Next() const { return m_pNext; }; + + + /* Set the previous node before this one */ + void SetPrev(CNode *p) { m_pPrev = p; }; + + + /* Set the next node after this one */ + void SetNext(CNode *p) { m_pNext = p; }; + + + /* Get the pointer to the object for this node */ + void *GetData() const { return m_pObject; }; + + + /* Set the pointer to the object for this node */ + void SetData(void *p) { m_pObject = p; }; + }; + + class CNodeCache + { + public: + CNodeCache(INT iCacheSize) : m_iCacheSize(iCacheSize), + m_pHead(NULL), + m_iUsed(0) + {}; + ~CNodeCache() { + CNode *pNode = m_pHead; + while (pNode) { + CNode *pCurrent = pNode; + pNode = pNode->Next(); + delete pCurrent; + } + }; + void AddToCache(CNode *pNode) + { + if (m_iUsed < m_iCacheSize) { + pNode->SetNext(m_pHead); + m_pHead = pNode; + m_iUsed++; + } else { + delete pNode; + } + }; + CNode *RemoveFromCache() + { + CNode *pNode = m_pHead; + if (pNode != NULL) { + m_pHead = pNode->Next(); + m_iUsed--; + ASSERT(m_iUsed >= 0); + } else { + ASSERT(m_iUsed == 0); + } + return pNode; + }; + private: + INT m_iCacheSize; + INT m_iUsed; + CNode *m_pHead; + }; + +protected: + + CNode* m_pFirst; /* Pointer to first node in the list */ + CNode* m_pLast; /* Pointer to the last node in the list */ + LONG m_Count; /* Number of nodes currently in the list */ + +private: + + CNodeCache m_Cache; /* Cache of unused node pointers */ + +private: + + /* These override the default copy constructor and assignment + operator for all list classes. They are in the private class + declaration section so that anybody trying to pass a list + object by value will generate a compile time error of + "cannot access the private member function". If these were + not here then the compiler will create default constructors + and assignment operators which when executed first take a + copy of all member variables and then during destruction + delete them all. This must not be done for any heap + allocated data. + */ + CBaseList(const CBaseList &refList); + CBaseList &operator=(const CBaseList &refList); + +public: + + CBaseList(TCHAR *pName, + INT iItems); + + CBaseList(TCHAR *pName); +#ifdef UNICODE + CBaseList(CHAR *pName, + INT iItems); + + CBaseList(CHAR *pName); +#endif + ~CBaseList(); + + /* Remove all the nodes from *this i.e. make the list empty */ + void RemoveAll(); + + + /* Return a cursor which identifies the first element of *this */ + POSITION GetHeadPositionI() const; + + + /* Return a cursor which identifies the last element of *this */ + POSITION GetTailPositionI() const; + + + /* Return the number of objects in *this */ + int GetCountI() const; + +protected: + /* Return the pointer to the object at rp, + Update rp to the next node in *this + but make it NULL if it was at the end of *this. + This is a wart retained for backwards compatibility. + GetPrev is not implemented. + Use Next, Prev and Get separately. + */ + void *GetNextI(POSITION& rp) const; + + + /* Return a pointer to the object at p + Asking for the object at NULL will return NULL harmlessly. + */ + void *GetI(POSITION p) const; + +public: + /* return the next / prev position in *this + return NULL when going past the end/start. + Next(NULL) is same as GetHeadPosition() + Prev(NULL) is same as GetTailPosition() + An n element list therefore behaves like a n+1 element + cycle with NULL at the start/end. + + !!WARNING!! - This handling of NULL is DIFFERENT from GetNext. + + Some reasons are: + 1. For a list of n items there are n+1 positions to insert + These are conveniently encoded as the n POSITIONs and NULL. + 2. If you are keeping a list sorted (fairly common) and you + search forward for an element to insert before and don't + find it you finish up with NULL as the element before which + to insert. You then want that NULL to be a valid POSITION + so that you can insert before it and you want that insertion + point to mean the (n+1)-th one that doesn't have a POSITION. + (symmetrically if you are working backwards through the list). + 3. It simplifies the algebra which the methods generate. + e.g. AddBefore(p,x) is identical to AddAfter(Prev(p),x) + in ALL cases. All the other arguments probably are reflections + of the algebraic point. + */ + POSITION Next(POSITION pos) const + { + if (pos == NULL) { + return (POSITION) m_pFirst; + } + CNode *pn = (CNode *) pos; + return (POSITION) pn->Next(); + } //Next + + // See Next + POSITION Prev(POSITION pos) const + { + if (pos == NULL) { + return (POSITION) m_pLast; + } + CNode *pn = (CNode *) pos; + return (POSITION) pn->Prev(); + } //Prev + + + /* Return the first position in *this which holds the given + pointer. Return NULL if the pointer was not not found. + */ +protected: + POSITION FindI( void * pObj) const; + + /* Remove the first node in *this (deletes the pointer to its + object from the list, does not free the object itself). + Return the pointer to its object. + If *this was already empty it will harmlessly return NULL. + */ + void *RemoveHeadI(); + + + /* Remove the last node in *this (deletes the pointer to its + object from the list, does not free the object itself). + Return the pointer to its object. + If *this was already empty it will harmlessly return NULL. + */ + void *RemoveTailI(); + + + /* Remove the node identified by p from the list (deletes the pointer + to its object from the list, does not free the object itself). + Asking to Remove the object at NULL will harmlessly return NULL. + Return the pointer to the object removed. + */ + void *RemoveI(POSITION p); + + /* Add single object *pObj to become a new last element of the list. + Return the new tail position, NULL if it fails. + If you are adding a COM objects, you might want AddRef it first. + Other existing POSITIONs in *this are still valid + */ + POSITION AddTailI(void * pObj); +public: + + + /* Add all the elements in *pList to the tail of *this. + This duplicates all the nodes in *pList (i.e. duplicates + all its pointers to objects). It does not duplicate the objects. + If you are adding a list of pointers to a COM object into the list + it's a good idea to AddRef them all it when you AddTail it. + Return TRUE if it all worked, FALSE if it didn't. + If it fails some elements may have been added. + Existing POSITIONs in *this are still valid + + If you actually want to MOVE the elements, use MoveToTail instead. + */ + BOOL AddTail(CBaseList *pList); + + + /* Mirror images of AddHead: */ + + /* Add single object to become a new first element of the list. + Return the new head position, NULL if it fails. + Existing POSITIONs in *this are still valid + */ +protected: + POSITION AddHeadI(void * pObj); +public: + + /* Add all the elements in *pList to the head of *this. + Same warnings apply as for AddTail. + Return TRUE if it all worked, FALSE if it didn't. + If it fails some of the objects may have been added. + + If you actually want to MOVE the elements, use MoveToHead instead. + */ + BOOL AddHead(CBaseList *pList); + + + /* Add the object *pObj to *this after position p in *this. + AddAfter(NULL,x) adds x to the start - equivalent to AddHead + Return the position of the object added, NULL if it failed. + Existing POSITIONs in *this are undisturbed, including p. + */ +protected: + POSITION AddAfterI(POSITION p, void * pObj); +public: + + /* Add the list *pList to *this after position p in *this + AddAfter(NULL,x) adds x to the start - equivalent to AddHead + Return TRUE if it all worked, FALSE if it didn't. + If it fails, some of the objects may be added + Existing POSITIONs in *this are undisturbed, including p. + */ + BOOL AddAfter(POSITION p, CBaseList *pList); + + + /* Mirror images: + Add the object *pObj to this-List after position p in *this. + AddBefore(NULL,x) adds x to the end - equivalent to AddTail + Return the position of the new object, NULL if it fails + Existing POSITIONs in *this are undisturbed, including p. + */ + protected: + POSITION AddBeforeI(POSITION p, void * pObj); + public: + + /* Add the list *pList to *this before position p in *this + AddAfter(NULL,x) adds x to the start - equivalent to AddHead + Return TRUE if it all worked, FALSE if it didn't. + If it fails, some of the objects may be added + Existing POSITIONs in *this are undisturbed, including p. + */ + BOOL AddBefore(POSITION p, CBaseList *pList); + + + /* Note that AddAfter(p,x) is equivalent to AddBefore(Next(p),x) + even in cases where p is NULL or Next(p) is NULL. + Similarly for mirror images etc. + This may make it easier to argue about programs. + */ + + + + /* The following operations do not copy any elements. + They move existing blocks of elements around by switching pointers. + They are fairly efficient for long lists as for short lists. + (Alas, the Count slows things down). + + They split the list into two parts. + One part remains as the original list, the other part + is appended to the second list. There are eight possible + variations: + Split the list {after/before} a given element + keep the {head/tail} portion in the original list + append the rest to the {head/tail} of the new list. + + Since After is strictly equivalent to Before Next + we are not in serious need of the Before/After variants. + That leaves only four. + + If you are processing a list left to right and dumping + the bits that you have processed into another list as + you go, the Tail/Tail variant gives the most natural result. + If you are processing in reverse order, Head/Head is best. + + By using NULL positions and empty lists judiciously either + of the other two can be built up in two operations. + + The definition of NULL (see Next/Prev etc) means that + degenerate cases include + "move all elements to new list" + "Split a list into two lists" + "Concatenate two lists" + (and quite a few no-ops) + + !!WARNING!! The type checking won't buy you much if you get list + positions muddled up - e.g. use a POSITION that's in a different + list and see what a mess you get! + */ + + /* Split *this after position p in *this + Retain as *this the tail portion of the original *this + Add the head portion to the tail end of *pList + Return TRUE if it all worked, FALSE if it didn't. + + e.g. + foo->MoveToTail(foo->GetHeadPosition(), bar); + moves one element from the head of foo to the tail of bar + foo->MoveToTail(NULL, bar); + is a no-op, returns NULL + foo->MoveToTail(foo->GetTailPosition, bar); + concatenates foo onto the end of bar and empties foo. + + A better, except excessively long name might be + MoveElementsFromHeadThroughPositionToOtherTail + */ + BOOL MoveToTail(POSITION pos, CBaseList *pList); + + + /* Mirror image: + Split *this before position p in *this. + Retain in *this the head portion of the original *this + Add the tail portion to the start (i.e. head) of *pList + + e.g. + foo->MoveToHead(foo->GetTailPosition(), bar); + moves one element from the tail of foo to the head of bar + foo->MoveToHead(NULL, bar); + is a no-op, returns NULL + foo->MoveToHead(foo->GetHeadPosition, bar); + concatenates foo onto the start of bar and empties foo. + */ + BOOL MoveToHead(POSITION pos, CBaseList *pList); + + + /* Reverse the order of the [pointers to] objects in *this + */ + void Reverse(); + + + /* set cursor to the position of each element of list in turn */ + #define TRAVERSELIST(list, cursor) \ + for ( cursor = (list).GetHeadPosition() \ + ; cursor!=NULL \ + ; cursor = (list).Next(cursor) \ + ) + + + /* set cursor to the position of each element of list in turn + in reverse order + */ + #define REVERSETRAVERSELIST(list, cursor) \ + for ( cursor = (list).GetTailPosition() \ + ; cursor!=NULL \ + ; cursor = (list).Prev(cursor) \ + ) + +}; // end of class declaration + +template class CGenericList : public CBaseList +{ +public: + CGenericList(TCHAR *pName, + INT iItems, + BOOL bLock = TRUE, + BOOL bAlert = FALSE) : + CBaseList(pName, iItems) { + UNREFERENCED_PARAMETER(bAlert); + UNREFERENCED_PARAMETER(bLock); + }; + CGenericList(TCHAR *pName) : + CBaseList(pName) { + }; + + POSITION GetHeadPosition() const { return (POSITION)m_pFirst; } + POSITION GetTailPosition() const { return (POSITION)m_pLast; } + int GetCount() const { return m_Count; } + + OBJECT *GetNext(POSITION& rp) const { return (OBJECT *) GetNextI(rp); } + + OBJECT *Get(POSITION p) const { return (OBJECT *) GetI(p); } + OBJECT *GetHead() const { return Get(GetHeadPosition()); } + + OBJECT *RemoveHead() { return (OBJECT *) RemoveHeadI(); } + + OBJECT *RemoveTail() { return (OBJECT *) RemoveTailI(); } + + OBJECT *Remove(POSITION p) { return (OBJECT *) RemoveI(p); } + POSITION AddBefore(POSITION p, OBJECT * pObj) { return AddBeforeI(p, pObj); } + POSITION AddAfter(POSITION p, OBJECT * pObj) { return AddAfterI(p, pObj); } + POSITION AddHead(OBJECT * pObj) { return AddHeadI(pObj); } + POSITION AddTail(OBJECT * pObj) { return AddTailI(pObj); } + BOOL AddTail(CGenericList *pList) + { return CBaseList::AddTail((CBaseList *) pList); } + BOOL AddHead(CGenericList *pList) + { return CBaseList::AddHead((CBaseList *) pList); } + BOOL AddAfter(POSITION p, CGenericList *pList) + { return CBaseList::AddAfter(p, (CBaseList *) pList); }; + BOOL AddBefore(POSITION p, CGenericList *pList) + { return CBaseList::AddBefore(p, (CBaseList *) pList); }; + POSITION Find( OBJECT * pObj) const { return FindI(pObj); } +}; // end of class declaration + + + +/* These define the standard list types */ + +typedef CGenericList CBaseObjectList; +typedef CGenericList CBaseInterfaceList; + +#endif /* __WXLIST__ */ + diff --git a/ThirdParty/strmbas/wxutil.cpp b/ThirdParty/strmbas/wxutil.cpp new file mode 100644 index 0000000..6665c5b --- /dev/null +++ b/ThirdParty/strmbas/wxutil.cpp @@ -0,0 +1,1256 @@ +//------------------------------------------------------------------------------ +// File: WXUtil.cpp +// +// Desc: DirectShow base classes - implements helper classes for building +// multimedia filters. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +#include + +// +// Declare function from largeint.h we need so that PPC can build +// + +// +// Enlarged integer divide - 64-bits / 32-bits > 32-bits +// + +#ifndef _X86_ + +#define LLtoU64(x) (*(unsigned __int64*)(void*)(&(x))) + +__inline +ULONG +WINAPI +EnlargedUnsignedDivide ( + IN ULARGE_INTEGER Dividend, + IN ULONG Divisor, + IN PULONG Remainder + ) +{ + // return remainder if necessary + if (Remainder != NULL) + *Remainder = (ULONG)(LLtoU64(Dividend) % Divisor); + return (ULONG)(LLtoU64(Dividend) / Divisor); +} + +#else +__inline +ULONG +WINAPI +EnlargedUnsignedDivide ( + IN ULARGE_INTEGER Dividend, + IN ULONG Divisor, + IN PULONG Remainder + ) +{ + ULONG ulResult; + _asm { + mov eax,Dividend.LowPart + mov edx,Dividend.HighPart + mov ecx,Remainder + div Divisor + or ecx,ecx + jz short label + mov [ecx],edx +label: + mov ulResult,eax + } + return ulResult; +} +#endif + +// --- CAMEvent ----------------------- +CAMEvent::CAMEvent(BOOL fManualReset) +{ + m_hEvent = CreateEvent(NULL, fManualReset, FALSE, NULL); +} + +CAMEvent::~CAMEvent() +{ + if (m_hEvent) { + EXECUTE_ASSERT(CloseHandle(m_hEvent)); + } +} + + +// --- CAMMsgEvent ----------------------- +// One routine. The rest is handled in CAMEvent + +BOOL CAMMsgEvent::WaitMsg(DWORD dwTimeout) +{ + // wait for the event to be signalled, or for the + // timeout (in MS) to expire. allow SENT messages + // to be processed while we wait + DWORD dwWait; + DWORD dwStartTime; + + // set the waiting period. + DWORD dwWaitTime = dwTimeout; + + // the timeout will eventually run down as we iterate + // processing messages. grab the start time so that + // we can calculate elapsed times. + if (dwWaitTime != INFINITE) { + dwStartTime = timeGetTime(); + } + + do { + dwWait = MsgWaitForMultipleObjects(1,&m_hEvent,FALSE, dwWaitTime, QS_SENDMESSAGE); + if (dwWait == WAIT_OBJECT_0 + 1) { + MSG Message; + PeekMessage(&Message,NULL,0,0,PM_NOREMOVE); + + // If we have an explicit length of time to wait calculate + // the next wake up point - which might be now. + // If dwTimeout is INFINITE, it stays INFINITE + if (dwWaitTime != INFINITE) { + + DWORD dwElapsed = timeGetTime()-dwStartTime; + + dwWaitTime = + (dwElapsed >= dwTimeout) + ? 0 // wake up with WAIT_TIMEOUT + : dwTimeout-dwElapsed; + } + } + } while (dwWait == WAIT_OBJECT_0 + 1); + + // return TRUE if we woke on the event handle, + // FALSE if we timed out. + return (dwWait == WAIT_OBJECT_0); +} + +// --- CAMThread ---------------------- + + +CAMThread::CAMThread() + : m_EventSend(TRUE) // must be manual-reset for CheckRequest() +{ + m_hThread = NULL; +} + +CAMThread::~CAMThread() { + Close(); +} + + +// when the thread starts, it calls this function. We unwrap the 'this' +//pointer and call ThreadProc. +DWORD WINAPI +CAMThread::InitialThreadProc(LPVOID pv) +{ + HRESULT hrCoInit = CAMThread::CoInitializeHelper(); + if(FAILED(hrCoInit)) { + DbgLog((LOG_ERROR, 1, TEXT("CoInitializeEx failed."))); + } + + CAMThread * pThread = (CAMThread *) pv; + + HRESULT hr = pThread->ThreadProc(); + + if(SUCCEEDED(hrCoInit)) { + CoUninitialize(); + } + + return hr; +} + +BOOL +CAMThread::Create() +{ + DWORD threadid; + + CAutoLock lock(&m_AccessLock); + + if (ThreadExists()) { + return FALSE; + } + + m_hThread = CreateThread( + NULL, + 0, + CAMThread::InitialThreadProc, + this, + 0, + &threadid); + + if (!m_hThread) { + return FALSE; + } + + return TRUE; +} + +DWORD +CAMThread::CallWorker(DWORD dwParam) +{ + // lock access to the worker thread for scope of this object + CAutoLock lock(&m_AccessLock); + + if (!ThreadExists()) { + return (DWORD) E_FAIL; + } + + // set the parameter + m_dwParam = dwParam; + + // signal the worker thread + m_EventSend.Set(); + + // wait for the completion to be signalled + m_EventComplete.Wait(); + + // done - this is the thread's return value + return m_dwReturnVal; +} + +// Wait for a request from the client +DWORD +CAMThread::GetRequest() +{ + m_EventSend.Wait(); + return m_dwParam; +} + +// is there a request? +BOOL +CAMThread::CheckRequest(DWORD * pParam) +{ + if (!m_EventSend.Check()) { + return FALSE; + } else { + if (pParam) { + *pParam = m_dwParam; + } + return TRUE; + } +} + +// reply to the request +void +CAMThread::Reply(DWORD dw) +{ + m_dwReturnVal = dw; + + // The request is now complete so CheckRequest should fail from + // now on + // + // This event should be reset BEFORE we signal the client or + // the client may Set it before we reset it and we'll then + // reset it (!) + + m_EventSend.Reset(); + + // Tell the client we're finished + + m_EventComplete.Set(); +} + +HRESULT CAMThread::CoInitializeHelper() +{ + // call CoInitializeEx and tell OLE not to create a window (this + // thread probably won't dispatch messages and will hang on + // broadcast msgs o/w). + // + // If CoInitEx is not available, threads that don't call CoCreate + // aren't affected. Threads that do will have to handle the + // failure. Perhaps we should fall back to CoInitialize and risk + // hanging? + // + + // older versions of ole32.dll don't have CoInitializeEx + + HRESULT hr = E_FAIL; + HINSTANCE hOle = GetModuleHandle(TEXT("ole32.dll")); + if(hOle) + { + typedef HRESULT (STDAPICALLTYPE *PCoInitializeEx)( + LPVOID pvReserved, DWORD dwCoInit); + PCoInitializeEx pCoInitializeEx = + (PCoInitializeEx)(GetProcAddress(hOle, "CoInitializeEx")); + if(pCoInitializeEx) + { + hr = (*pCoInitializeEx)(0, COINIT_DISABLE_OLE1DDE ); + } + } + else + { + // caller must load ole32.dll + DbgBreak("couldn't locate ole32.dll"); + } + + return hr; +} + + +// destructor for CMsgThread - cleans up any messages left in the +// queue when the thread exited +CMsgThread::~CMsgThread() +{ + if (m_hThread != NULL) { + WaitForSingleObject(m_hThread, INFINITE); + EXECUTE_ASSERT(CloseHandle(m_hThread)); + } + + POSITION pos = m_ThreadQueue.GetHeadPosition(); + while (pos) { + CMsg * pMsg = m_ThreadQueue.GetNext(pos); + delete pMsg; + } + m_ThreadQueue.RemoveAll(); + + if (m_hSem != NULL) { + EXECUTE_ASSERT(CloseHandle(m_hSem)); + } +} + +BOOL +CMsgThread::CreateThread( + ) +{ + m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL); + if (m_hSem == NULL) { + return FALSE; + } + + m_hThread = ::CreateThread(NULL, 0, DefaultThreadProc, + (LPVOID)this, 0, &m_ThreadId); + return m_hThread != NULL; +} + + +// This is the threads message pump. Here we get and dispatch messages to +// clients thread proc until the client refuses to process a message. +// The client returns a non-zero value to stop the message pump, this +// value becomes the threads exit code. + +DWORD WINAPI +CMsgThread::DefaultThreadProc( + LPVOID lpParam + ) +{ + CMsgThread *lpThis = (CMsgThread *)lpParam; + CMsg msg; + LRESULT lResult; + + // !!! + CoInitialize(NULL); + + // allow a derived class to handle thread startup + lpThis->OnThreadInit(); + + do { + lpThis->GetThreadMsg(&msg); + lResult = lpThis->ThreadMessageProc(msg.uMsg,msg.dwFlags, + msg.lpParam, msg.pEvent); + } while (lResult == 0L); + + // !!! + CoUninitialize(); + + return (DWORD)lResult; +} + + +// Block until the next message is placed on the list m_ThreadQueue. +// copies the message to the message pointed to by *pmsg +void +CMsgThread::GetThreadMsg(CMsg *msg) +{ + CMsg * pmsg = NULL; + + // keep trying until a message appears + while (TRUE) { + { + CAutoLock lck(&m_Lock); + pmsg = m_ThreadQueue.RemoveHead(); + if (pmsg == NULL) { + m_lWaiting++; + } else { + break; + } + } + // the semaphore will be signalled when it is non-empty + WaitForSingleObject(m_hSem, INFINITE); + } + // copy fields to caller's CMsg + *msg = *pmsg; + + // this CMsg was allocated by the 'new' in PutThreadMsg + delete pmsg; + +} + + +// NOTE: as we need to use the same binaries on Win95 as on NT this code should +// be compiled WITHOUT unicode being defined. Otherwise we will not pick up +// these internal routines and the binary will not run on Win95. + +#ifndef UNICODE +// Windows 95 doesn't implement this, so we provide an implementation. +// LPWSTR +// WINAPI +// lstrcpyWInternal( +// LPWSTR lpString1, +// LPCWSTR lpString2 +// ) +// { +// LPWSTR lpReturn = lpString1; +// while (*lpString1++ = *lpString2++); +// +// return lpReturn; +// } + +// Windows 95 doesn't implement this, so we provide an implementation. +LPWSTR +WINAPI +lstrcpynWInternal( + LPWSTR lpString1, + LPCWSTR lpString2, + int iMaxLength + ) +{ + ASSERT(iMaxLength); + LPWSTR lpReturn = lpString1; + if (iMaxLength) { + while (--iMaxLength && (*lpString1++ = *lpString2++)); + + // If we ran out of room (which will be the case if + // iMaxLength is now 0) we still need to terminate the + // string. + if (!iMaxLength) *lpString1 = L'\0'; + } + return lpReturn; +} + +int +WINAPI +lstrcmpWInternal( + LPCWSTR lpString1, + LPCWSTR lpString2 + ) +{ + do { + WCHAR c1 = *lpString1; + WCHAR c2 = *lpString2; + if (c1 != c2) + return (int) c1 - (int) c2; + } while (*lpString1++ && *lpString2++); + return 0; +} + + +int +WINAPI +lstrcmpiWInternal( + LPCWSTR lpString1, + LPCWSTR lpString2 + ) +{ + do { + WCHAR c1 = *lpString1; + WCHAR c2 = *lpString2; + if (c1 >= L'A' && c1 <= L'Z') + c1 -= (WCHAR) (L'A' - L'a'); + if (c2 >= L'A' && c2 <= L'Z') + c2 -= (WCHAR) (L'A' - L'a'); + + if (c1 != c2) + return (int) c1 - (int) c2; + } while (*lpString1++ && *lpString2++); + + return 0; +} + + +int +WINAPI +lstrlenWInternal( + LPCWSTR lpString + ) +{ + int i = -1; + while (*(lpString+(++i))) + ; + return i; +} + + +// int WINAPIV wsprintfWInternal(LPWSTR wszOut, LPCWSTR pszFmt, ...) +// { +// char fmt[256]; // !!! +// char ach[256]; // !!! +// int i; +// +// va_list va; +// va_start(va, pszFmt); +// WideCharToMultiByte(GetACP(), 0, pszFmt, -1, fmt, 256, NULL, NULL); +// (void)StringCchVPrintf(ach, NUMELMS(ach), fmt, va); +// i = lstrlenA(ach); +// va_end(va); +// +// MultiByteToWideChar(CP_ACP, 0, ach, -1, wszOut, i+1); +// +// return i; +// } +#else + +// need to provide the implementations in unicode for non-unicode +// builds linking with the unicode strmbase.lib +//LPWSTR WINAPI lstrcpyWInternal( +// LPWSTR lpString1, +// LPCWSTR lpString2 +// ) +//{ +// return lstrcpyW(lpString1, lpString2); +//} + +LPWSTR WINAPI lstrcpynWInternal( + LPWSTR lpString1, + LPCWSTR lpString2, + int iMaxLength + ) +{ + return lstrcpynW(lpString1, lpString2, iMaxLength); +} + +int WINAPI lstrcmpWInternal( + LPCWSTR lpString1, + LPCWSTR lpString2 + ) +{ + return lstrcmpW(lpString1, lpString2); +} + + +int WINAPI lstrcmpiWInternal( + LPCWSTR lpString1, + LPCWSTR lpString2 + ) +{ + return lstrcmpiW(lpString1, lpString2); +} + + +int WINAPI lstrlenWInternal( + LPCWSTR lpString + ) +{ + return lstrlenW(lpString); +} + + +//int WINAPIV wsprintfWInternal( +// LPWSTR wszOut, LPCWSTR pszFmt, ...) +//{ +// va_list va; +// va_start(va, pszFmt); +// int i = wvsprintfW(wszOut, pszFmt, va); +// va_end(va); +// return i; +//} +#endif + + +// Helper function - convert int to WSTR +void WINAPI IntToWstr(int i, LPWSTR wstr, size_t len) +{ +#ifdef UNICODE + (void)StringCchPrintf(wstr, len, L"%d", i); +#else + TCHAR temp[32]; + (void)StringCchPrintf(temp, NUMELMS(temp), "%d", i); + MultiByteToWideChar(CP_ACP, 0, temp, -1, wstr, int(len) ); +#endif +} // IntToWstr + + +#if 0 +void * memchrInternal(const void *pv, int c, size_t sz) +{ + BYTE *pb = (BYTE *) pv; + while (sz--) { + if (*pb == c) + return (void *) pb; + pb++; + } + return NULL; +} +#endif + + +#define MEMORY_ALIGNMENT 4 +#define MEMORY_ALIGNMENT_LOG2 2 +#define MEMORY_ALIGNMENT_MASK MEMORY_ALIGNMENT - 1 + +void * __stdcall memmoveInternal(void * dst, const void * src, size_t count) +{ + void * ret = dst; + +#ifdef _X86_ + if (dst <= src || (char *)dst >= ((char *)src + count)) { + + /* + * Non-Overlapping Buffers + * copy from lower addresses to higher addresses + */ + _asm { + mov esi,src + mov edi,dst + mov ecx,count + cld + mov edx,ecx + and edx,MEMORY_ALIGNMENT_MASK + shr ecx,MEMORY_ALIGNMENT_LOG2 + rep movsd + or ecx,edx + jz memmove_done + rep movsb +memmove_done: + } + } + else { + + /* + * Overlapping Buffers + * copy from higher addresses to lower addresses + */ + _asm { + mov esi,src + mov edi,dst + mov ecx,count + std + add esi,ecx + add edi,ecx + dec esi + dec edi + rep movsb + cld + } + } +#else + MoveMemory(dst, src, count); +#endif + + return ret; +} + +/* Arithmetic functions to help with time format conversions +*/ + +#ifdef _M_ALPHA +// work around bug in version 12.00.8385 of the alpha compiler where +// UInt32x32To64 sign-extends its arguments (?) +#undef UInt32x32To64 +#define UInt32x32To64(a, b) (((ULONGLONG)((ULONG)(a)) & 0xffffffff) * ((ULONGLONG)((ULONG)(b)) & 0xffffffff)) +#endif + +/* Compute (a * b + d) / c */ +LONGLONG WINAPI llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG d) +{ + /* Compute the absolute values to avoid signed arithmetic problems */ + ULARGE_INTEGER ua, ub; + DWORDLONG uc; + + ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a); + ub.QuadPart = (DWORDLONG)(b >= 0 ? b : -b); + uc = (DWORDLONG)(c >= 0 ? c : -c); + BOOL bSign = (a < 0) ^ (b < 0); + + /* Do long multiplication */ + ULARGE_INTEGER p[2]; + p[0].QuadPart = UInt32x32To64(ua.LowPart, ub.LowPart); + + /* This next computation cannot overflow into p[1].HighPart because + the max number we can compute here is: + + (2 ** 32 - 1) * (2 ** 32 - 1) + // ua.LowPart * ub.LowPart + (2 ** 32) * (2 ** 31) * (2 ** 32 - 1) * 2 // x.LowPart * y.HighPart * 2 + + == 2 ** 96 - 2 ** 64 + (2 ** 64 - 2 ** 33 + 1) + == 2 ** 96 - 2 ** 33 + 1 + < 2 ** 96 + */ + + ULARGE_INTEGER x; + x.QuadPart = UInt32x32To64(ua.LowPart, ub.HighPart) + + UInt32x32To64(ua.HighPart, ub.LowPart) + + p[0].HighPart; + p[0].HighPart = x.LowPart; + p[1].QuadPart = UInt32x32To64(ua.HighPart, ub.HighPart) + x.HighPart; + + if (d != 0) { + ULARGE_INTEGER ud[2]; + if (bSign) { + ud[0].QuadPart = (DWORDLONG)(-d); + if (d > 0) { + /* -d < 0 */ + ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1; + } else { + ud[1].QuadPart = (DWORDLONG)0; + } + } else { + ud[0].QuadPart = (DWORDLONG)d; + if (d < 0) { + ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1; + } else { + ud[1].QuadPart = (DWORDLONG)0; + } + } + /* Now do extended addition */ + ULARGE_INTEGER uliTotal; + + /* Add ls DWORDs */ + uliTotal.QuadPart = (DWORDLONG)ud[0].LowPart + p[0].LowPart; + p[0].LowPart = uliTotal.LowPart; + + /* Propagate carry */ + uliTotal.LowPart = uliTotal.HighPart; + uliTotal.HighPart = 0; + + /* Add 2nd most ls DWORDs */ + uliTotal.QuadPart += (DWORDLONG)ud[0].HighPart + p[0].HighPart; + p[0].HighPart = uliTotal.LowPart; + + /* Propagate carry */ + uliTotal.LowPart = uliTotal.HighPart; + uliTotal.HighPart = 0; + + /* Add MS DWORDLONGs - no carry expected */ + p[1].QuadPart += ud[1].QuadPart + uliTotal.QuadPart; + + /* Now see if we got a sign change from the addition */ + if ((LONG)p[1].HighPart < 0) { + bSign = !bSign; + + /* Negate the current value (ugh!) */ + p[0].QuadPart = ~p[0].QuadPart; + p[1].QuadPart = ~p[1].QuadPart; + p[0].QuadPart += 1; + p[1].QuadPart += (p[0].QuadPart == 0); + } + } + + /* Now for the division */ + if (c < 0) { + bSign = !bSign; + } + + + /* This will catch c == 0 and overflow */ + if (uc <= p[1].QuadPart) { + return bSign ? (LONGLONG)0x8000000000000000 : + (LONGLONG)0x7FFFFFFFFFFFFFFF; + } + + DWORDLONG ullResult; + + /* Do the division */ + /* If the dividend is a DWORD_LONG use the compiler */ + if (p[1].QuadPart == 0) { + ullResult = p[0].QuadPart / uc; + return bSign ? -(LONGLONG)ullResult : (LONGLONG)ullResult; + } + + /* If the divisor is a DWORD then its simpler */ + ULARGE_INTEGER ulic; + ulic.QuadPart = uc; + if (ulic.HighPart == 0) { + ULARGE_INTEGER uliDividend; + ULARGE_INTEGER uliResult; + DWORD dwDivisor = (DWORD)uc; + // ASSERT(p[1].HighPart == 0 && p[1].LowPart < dwDivisor); + uliDividend.HighPart = p[1].LowPart; + uliDividend.LowPart = p[0].HighPart; +#ifndef USE_LARGEINT + uliResult.HighPart = (DWORD)(uliDividend.QuadPart / dwDivisor); + p[0].HighPart = (DWORD)(uliDividend.QuadPart % dwDivisor); + uliResult.LowPart = 0; + uliResult.QuadPart = p[0].QuadPart / dwDivisor + uliResult.QuadPart; +#else + /* NOTE - this routine will take exceptions if + the result does not fit in a DWORD + */ + if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) { + uliResult.HighPart = EnlargedUnsignedDivide( + uliDividend, + dwDivisor, + &p[0].HighPart); + } else { + uliResult.HighPart = 0; + } + uliResult.LowPart = EnlargedUnsignedDivide( + p[0], + dwDivisor, + NULL); +#endif + return bSign ? -(LONGLONG)uliResult.QuadPart : + (LONGLONG)uliResult.QuadPart; + } + + + ullResult = 0; + + /* OK - do long division */ + for (int i = 0; i < 64; i++) { + ullResult <<= 1; + + /* Shift 128 bit p left 1 */ + p[1].QuadPart <<= 1; + if ((p[0].HighPart & 0x80000000) != 0) { + p[1].LowPart++; + } + p[0].QuadPart <<= 1; + + /* Compare */ + if (uc <= p[1].QuadPart) { + p[1].QuadPart -= uc; + ullResult += 1; + } + } + + return bSign ? - (LONGLONG)ullResult : (LONGLONG)ullResult; +} + +LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG d) +{ + ULARGE_INTEGER ua; + DWORD ub; + DWORD uc; + + /* Compute the absolute values to avoid signed arithmetic problems */ + ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a); + ub = (DWORD)(b >= 0 ? b : -b); + uc = (DWORD)(c >= 0 ? c : -c); + BOOL bSign = (a < 0) ^ (b < 0); + + /* Do long multiplication */ + ULARGE_INTEGER p0; + DWORD p1; + p0.QuadPart = UInt32x32To64(ua.LowPart, ub); + + if (ua.HighPart != 0) { + ULARGE_INTEGER x; + x.QuadPart = UInt32x32To64(ua.HighPart, ub) + p0.HighPart; + p0.HighPart = x.LowPart; + p1 = x.HighPart; + } else { + p1 = 0; + } + + if (d != 0) { + ULARGE_INTEGER ud0; + DWORD ud1; + + if (bSign) { + // + // Cast d to LONGLONG first otherwise -0x80000000 sign extends + // incorrectly + // + ud0.QuadPart = (DWORDLONG)(-(LONGLONG)d); + if (d > 0) { + /* -d < 0 */ + ud1 = (DWORD)-1; + } else { + ud1 = (DWORD)0; + } + } else { + ud0.QuadPart = (DWORDLONG)d; + if (d < 0) { + ud1 = (DWORD)-1; + } else { + ud1 = (DWORD)0; + } + } + /* Now do extended addition */ + ULARGE_INTEGER uliTotal; + + /* Add ls DWORDs */ + uliTotal.QuadPart = (DWORDLONG)ud0.LowPart + p0.LowPart; + p0.LowPart = uliTotal.LowPart; + + /* Propagate carry */ + uliTotal.LowPart = uliTotal.HighPart; + uliTotal.HighPart = 0; + + /* Add 2nd most ls DWORDs */ + uliTotal.QuadPart += (DWORDLONG)ud0.HighPart + p0.HighPart; + p0.HighPart = uliTotal.LowPart; + + /* Add MS DWORDLONGs - no carry expected */ + p1 += ud1 + uliTotal.HighPart; + + /* Now see if we got a sign change from the addition */ + if ((LONG)p1 < 0) { + bSign = !bSign; + + /* Negate the current value (ugh!) */ + p0.QuadPart = ~p0.QuadPart; + p1 = ~p1; + p0.QuadPart += 1; + p1 += (p0.QuadPart == 0); + } + } + + /* Now for the division */ + if (c < 0) { + bSign = !bSign; + } + + + /* This will catch c == 0 and overflow */ + if (uc <= p1) { + return bSign ? (LONGLONG)0x8000000000000000 : + (LONGLONG)0x7FFFFFFFFFFFFFFF; + } + + /* Do the division */ + + /* If the divisor is a DWORD then its simpler */ + ULARGE_INTEGER uliDividend; + ULARGE_INTEGER uliResult; + DWORD dwDivisor = uc; + uliDividend.HighPart = p1; + uliDividend.LowPart = p0.HighPart; + /* NOTE - this routine will take exceptions if + the result does not fit in a DWORD + */ + if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) { + uliResult.HighPart = EnlargedUnsignedDivide( + uliDividend, + dwDivisor, + &p0.HighPart); + } else { + uliResult.HighPart = 0; + } + uliResult.LowPart = EnlargedUnsignedDivide( + p0, + dwDivisor, + NULL); + return bSign ? -(LONGLONG)uliResult.QuadPart : + (LONGLONG)uliResult.QuadPart; +} + +#ifdef _DEBUG +/******************************Public*Routine******************************\ +* Debug CCritSec helpers +* +* We provide debug versions of the Constructor, destructor, Lock and Unlock +* routines. The debug code tracks who owns each critical section by +* maintaining a depth count. +* +* History: +* +\**************************************************************************/ + +CCritSec::CCritSec() +{ + InitializeCriticalSection(&m_CritSec); + m_currentOwner = m_lockCount = 0; + m_fTrace = FALSE; +} + +CCritSec::~CCritSec() +{ + DeleteCriticalSection(&m_CritSec); +} + +void CCritSec::Lock() +{ + UINT tracelevel=3; + DWORD us = GetCurrentThreadId(); + DWORD currentOwner = m_currentOwner; + if (currentOwner && (currentOwner != us)) { + // already owned, but not by us + if (m_fTrace) { + DbgLog((LOG_LOCKING, 2, TEXT("Thread %d about to wait for lock %x owned by %d"), + GetCurrentThreadId(), &m_CritSec, currentOwner)); + tracelevel=2; + // if we saw the message about waiting for the critical + // section we ensure we see the message when we get the + // critical section + } + } + EnterCriticalSection(&m_CritSec); + if (0 == m_lockCount++) { + // we now own it for the first time. Set owner information + m_currentOwner = us; + + if (m_fTrace) { + DbgLog((LOG_LOCKING, tracelevel, TEXT("Thread %d now owns lock %x"), m_currentOwner, &m_CritSec)); + } + } +} + +void CCritSec::Unlock() { + if (0 == --m_lockCount) { + // about to be unowned + if (m_fTrace) { + DbgLog((LOG_LOCKING, 3, TEXT("Thread %d releasing lock %x"), m_currentOwner, &m_CritSec)); + } + + m_currentOwner = 0; + } + LeaveCriticalSection(&m_CritSec); +} + +void WINAPI DbgLockTrace(CCritSec * pcCrit, BOOL fTrace) +{ + pcCrit->m_fTrace = fTrace; +} + +BOOL WINAPI CritCheckIn(CCritSec * pcCrit) +{ + return (GetCurrentThreadId() == pcCrit->m_currentOwner); +} + +BOOL WINAPI CritCheckIn(const CCritSec * pcCrit) +{ + return (GetCurrentThreadId() == pcCrit->m_currentOwner); +} + +BOOL WINAPI CritCheckOut(CCritSec * pcCrit) +{ + return (GetCurrentThreadId() != pcCrit->m_currentOwner); +} + +BOOL WINAPI CritCheckOut(const CCritSec * pcCrit) +{ + return (GetCurrentThreadId() != pcCrit->m_currentOwner); +} +#else +CCritSec::CCritSec() { + InitializeCriticalSection(&m_CritSec); +}; + +CCritSec::~CCritSec() { + DeleteCriticalSection(&m_CritSec); +}; + +void CCritSec::Lock() { + EnterCriticalSection(&m_CritSec); +}; + +void CCritSec::Unlock() { + LeaveCriticalSection(&m_CritSec); +}; +#endif + + +STDAPI WriteBSTR(BSTR *pstrDest, LPCWSTR szSrc) +{ + *pstrDest = SysAllocString( szSrc ); + if( !(*pstrDest) ) return E_OUTOFMEMORY; + return NOERROR; +} + + +STDAPI FreeBSTR(BSTR* pstr) +{ + if( *pstr == NULL ) return S_FALSE; + SysFreeString( *pstr ); + return NOERROR; +} + + +// Return a wide string - allocating memory for it +// Returns: +// S_OK - no error +// E_POINTER - ppszReturn == NULL +// E_OUTOFMEMORY - can't allocate memory for returned string +STDAPI AMGetWideString(LPCWSTR psz, LPWSTR *ppszReturn) +{ + CheckPointer(ppszReturn, E_POINTER); + ValidateReadWritePtr(ppszReturn, sizeof(LPWSTR)); + DWORD nameLen = sizeof(WCHAR) * (lstrlenW(psz)+1); + *ppszReturn = (LPWSTR)CoTaskMemAlloc(nameLen); + if (*ppszReturn == NULL) { + return E_OUTOFMEMORY; + } + CopyMemory(*ppszReturn, psz, nameLen); + return NOERROR; +} + +// Waits for the HANDLE hObject. While waiting messages sent +// to windows on our thread by SendMessage will be processed. +// Using this function to do waits and mutual exclusion +// avoids some deadlocks in objects with windows. +// Return codes are the same as for WaitForSingleObject +DWORD WINAPI WaitDispatchingMessages( + HANDLE hObject, + DWORD dwWait, + HWND hwnd, + UINT uMsg, + HANDLE hEvent) +{ + BOOL bPeeked = FALSE; + DWORD dwResult; + DWORD dwStart; + DWORD dwThreadPriority; + + static UINT uMsgId = 0; + + HANDLE hObjects[2] = { hObject, hEvent }; + if (dwWait != INFINITE && dwWait != 0) { + dwStart = GetTickCount(); + } + for (; ; ) { + DWORD nCount = NULL != hEvent ? 2 : 1; + + // Minimize the chance of actually dispatching any messages + // by seeing if we can lock immediately. + dwResult = WaitForMultipleObjects(nCount, hObjects, FALSE, 0); + if (dwResult < WAIT_OBJECT_0 + nCount) { + break; + } + + DWORD dwTimeOut = dwWait; + if (dwTimeOut > 10) { + dwTimeOut = 10; + } + dwResult = MsgWaitForMultipleObjects( + nCount, + hObjects, + FALSE, + dwTimeOut, + hwnd == NULL ? QS_SENDMESSAGE : + QS_SENDMESSAGE + QS_POSTMESSAGE); + if (dwResult == WAIT_OBJECT_0 + nCount || + dwResult == WAIT_TIMEOUT && dwTimeOut != dwWait) { + MSG msg; + if (hwnd != NULL) { + while (PeekMessage(&msg, hwnd, uMsg, uMsg, PM_REMOVE)) { + DispatchMessage(&msg); + } + } + // Do this anyway - the previous peek doesn't flush out the + // messages + PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); + + if (dwWait != INFINITE && dwWait != 0) { + DWORD dwNow = GetTickCount(); + + // Working with differences handles wrap-around + DWORD dwDiff = dwNow - dwStart; + if (dwDiff > dwWait) { + dwWait = 0; + } else { + dwWait -= dwDiff; + } + dwStart = dwNow; + } + if (!bPeeked) { + // Raise our priority to prevent our message queue + // building up + dwThreadPriority = GetThreadPriority(GetCurrentThread()); + if (dwThreadPriority < THREAD_PRIORITY_HIGHEST) { + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + } + bPeeked = TRUE; + } + } else { + break; + } + } + if (bPeeked) { + SetThreadPriority(GetCurrentThread(), dwThreadPriority); + if (HIWORD(GetQueueStatus(QS_POSTMESSAGE)) & QS_POSTMESSAGE) { + if (uMsgId == 0) { + uMsgId = RegisterWindowMessage(TEXT("AMUnblock")); + } + if (uMsgId != 0) { + MSG msg; + // Remove old ones + while (PeekMessage(&msg, (HWND)-1, uMsgId, uMsgId, PM_REMOVE)) { + } + } + PostThreadMessage(GetCurrentThreadId(), uMsgId, 0, 0); + } + } + return dwResult; +} + +HRESULT AmGetLastErrorToHResult() +{ + DWORD dwLastError = GetLastError(); + if(dwLastError != 0) + { + return HRESULT_FROM_WIN32(dwLastError); + } + else + { + return E_FAIL; + } +} + +IUnknown* QzAtlComPtrAssign(IUnknown** pp, IUnknown* lp) +{ + if (lp != NULL) + lp->AddRef(); + if (*pp) + (*pp)->Release(); + *pp = lp; + return lp; +} + +/****************************************************************************** + +CompatibleTimeSetEvent + + CompatibleTimeSetEvent() sets the TIME_KILL_SYNCHRONOUS flag before calling +timeSetEvent() if the current operating system supports it. TIME_KILL_SYNCHRONOUS +is supported on Windows XP and later operating systems. + +Parameters: +- The same parameters as timeSetEvent(). See timeSetEvent()'s documentation in +the Platform SDK for more information. + +Return Value: +- The same return value as timeSetEvent(). See timeSetEvent()'s documentation in +the Platform SDK for more information. + +******************************************************************************/ +MMRESULT CompatibleTimeSetEvent( UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent ) +{ + #if WINVER >= 0x0501 + { + static bool fCheckedVersion = false; + static bool fTimeKillSynchronousFlagAvailable = false; + + if( !fCheckedVersion ) { + fTimeKillSynchronousFlagAvailable = TimeKillSynchronousFlagAvailable(); + fCheckedVersion = true; + } + + if( fTimeKillSynchronousFlagAvailable ) { + fuEvent = fuEvent | TIME_KILL_SYNCHRONOUS; + } + } + #endif // WINVER >= 0x0501 + + return timeSetEvent( uDelay, uResolution, lpTimeProc, dwUser, fuEvent ); +} + +bool TimeKillSynchronousFlagAvailable( void ) +{ + OSVERSIONINFO osverinfo; + + osverinfo.dwOSVersionInfoSize = sizeof(osverinfo); + + if( GetVersionEx( &osverinfo ) ) { + + // Windows XP's major version is 5 and its' minor version is 1. + // timeSetEvent() started supporting the TIME_KILL_SYNCHRONOUS flag + // in Windows XP. + if( (osverinfo.dwMajorVersion > 5) || + ( (osverinfo.dwMajorVersion == 5) && (osverinfo.dwMinorVersion >= 1) ) ) { + return true; + } + } + + return false; +} diff --git a/ThirdParty/strmbas/wxutil.h b/ThirdParty/strmbas/wxutil.h new file mode 100644 index 0000000..e58d2f7 --- /dev/null +++ b/ThirdParty/strmbas/wxutil.h @@ -0,0 +1,532 @@ +//------------------------------------------------------------------------------ +// File: WXUtil.h +// +// Desc: DirectShow base classes - defines helper classes and functions for +// building multimedia filters. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------ + + +#ifndef __WXUTIL__ +#define __WXUTIL__ + +// eliminate spurious "statement has no effect" warnings. +#pragma warning(disable: 4705) + +// wrapper for whatever critical section we have +class CCritSec { + + // make copy constructor and assignment operator inaccessible + + CCritSec(const CCritSec &refCritSec); + CCritSec &operator=(const CCritSec &refCritSec); + + CRITICAL_SECTION m_CritSec; + +#ifdef _DEBUG +public: + DWORD m_currentOwner; + DWORD m_lockCount; + BOOL m_fTrace; // Trace this one +public: + CCritSec(); + ~CCritSec(); + void Lock(); + void Unlock(); +#else + +public: + CCritSec(); + + ~CCritSec(); + + void Lock(); + + void Unlock(); +#endif +}; + +// +// To make deadlocks easier to track it is useful to insert in the +// code an assertion that says whether we own a critical section or +// not. We make the routines that do the checking globals to avoid +// having different numbers of member functions in the debug and +// retail class implementations of CCritSec. In addition we provide +// a routine that allows usage of specific critical sections to be +// traced. This is NOT on by default - there are far too many. +// + +#ifdef _DEBUG + BOOL WINAPI CritCheckIn(CCritSec * pcCrit); + BOOL WINAPI CritCheckIn(const CCritSec * pcCrit); + BOOL WINAPI CritCheckOut(CCritSec * pcCrit); + BOOL WINAPI CritCheckOut(const CCritSec * pcCrit); + void WINAPI DbgLockTrace(CCritSec * pcCrit, BOOL fTrace); +#else + #define CritCheckIn(x) TRUE + #define CritCheckOut(x) TRUE + #define DbgLockTrace(pc, fT) +#endif + + +// locks a critical section, and unlocks it automatically +// when the lock goes out of scope +class CAutoLock { + + // make copy constructor and assignment operator inaccessible + + CAutoLock(const CAutoLock &refAutoLock); + CAutoLock &operator=(const CAutoLock &refAutoLock); + +protected: + CCritSec * m_pLock; + +public: + CAutoLock(CCritSec * plock) + { + m_pLock = plock; + m_pLock->Lock(); + }; + + ~CAutoLock() { + m_pLock->Unlock(); + }; +}; + + + +// wrapper for event objects +class CAMEvent +{ + + // make copy constructor and assignment operator inaccessible + + CAMEvent(const CAMEvent &refEvent); + CAMEvent &operator=(const CAMEvent &refEvent); + +protected: + HANDLE m_hEvent; +public: + CAMEvent(BOOL fManualReset = FALSE); + ~CAMEvent(); + + // Cast to HANDLE - we don't support this as an lvalue + operator HANDLE () const { return m_hEvent; }; + + void Set() {EXECUTE_ASSERT(SetEvent(m_hEvent));}; + BOOL Wait(DWORD dwTimeout = INFINITE) { + return (WaitForSingleObject(m_hEvent, dwTimeout) == WAIT_OBJECT_0); + }; + void Reset() { ResetEvent(m_hEvent); }; + BOOL Check() { return Wait(0); }; +}; + + +// wrapper for event objects that do message processing +// This adds ONE method to the CAMEvent object to allow sent +// messages to be processed while waiting + +class CAMMsgEvent : public CAMEvent +{ + +public: + + // Allow SEND messages to be processed while waiting + BOOL WaitMsg(DWORD dwTimeout = INFINITE); +}; + +// old name supported for the time being +#define CTimeoutEvent CAMEvent + +// support for a worker thread + +// simple thread class supports creation of worker thread, synchronization +// and communication. Can be derived to simplify parameter passing +class AM_NOVTABLE CAMThread { + + // make copy constructor and assignment operator inaccessible + + CAMThread(const CAMThread &refThread); + CAMThread &operator=(const CAMThread &refThread); + + CAMEvent m_EventSend; + CAMEvent m_EventComplete; + + DWORD m_dwParam; + DWORD m_dwReturnVal; + +protected: + HANDLE m_hThread; + + // thread will run this function on startup + // must be supplied by derived class + virtual DWORD ThreadProc() = 0; + +public: + CAMThread(); + virtual ~CAMThread(); + + CCritSec m_AccessLock; // locks access by client threads + CCritSec m_WorkerLock; // locks access to shared objects + + // thread initially runs this. param is actually 'this'. function + // just gets this and calls ThreadProc + static DWORD WINAPI InitialThreadProc(LPVOID pv); + + // start thread running - error if already running + BOOL Create(); + + // signal the thread, and block for a response + // + DWORD CallWorker(DWORD); + + // accessor thread calls this when done with thread (having told thread + // to exit) + void Close() { + #pragma warning( push ) + // C4312: 'type cast' : conversion from 'LONG' to 'PVOID' of greater size + // + // This code works correctly on 32-bit and 64-bit systems. + #pragma warning( disable : 4312 ) + HANDLE hThread = (HANDLE)InterlockedExchangePointer(&m_hThread, 0); + #pragma warning( pop ) + + if (hThread) { + WaitForSingleObject(hThread, INFINITE); + CloseHandle(hThread); + } + }; + + // ThreadExists + // Return TRUE if the thread exists. FALSE otherwise + BOOL ThreadExists(void) const + { + if (m_hThread == 0) { + return FALSE; + } else { + return TRUE; + } + } + + // wait for the next request + DWORD GetRequest(); + + // is there a request? + BOOL CheckRequest(DWORD * pParam); + + // reply to the request + void Reply(DWORD); + + // If you want to do WaitForMultipleObjects you'll need to include + // this handle in your wait list or you won't be responsive + HANDLE GetRequestHandle() const { return m_EventSend; }; + + // Find out what the request was + DWORD GetRequestParam() const { return m_dwParam; }; + + // call CoInitializeEx (COINIT_DISABLE_OLE1DDE) if + // available. S_FALSE means it's not available. + static HRESULT CoInitializeHelper(); +}; + + +// CQueue +// +// Implements a simple Queue ADT. The queue contains a finite number of +// objects, access to which is controlled by a semaphore. The semaphore +// is created with an initial count (N). Each time an object is added +// a call to WaitForSingleObject is made on the semaphore's handle. When +// this function returns a slot has been reserved in the queue for the new +// object. If no slots are available the function blocks until one becomes +// available. Each time an object is removed from the queue ReleaseSemaphore +// is called on the semaphore's handle, thus freeing a slot in the queue. +// If no objects are present in the queue the function blocks until an +// object has been added. + +#define DEFAULT_QUEUESIZE 2 + +template class CQueue { +private: + HANDLE hSemPut; // Semaphore controlling queue "putting" + HANDLE hSemGet; // Semaphore controlling queue "getting" + CRITICAL_SECTION CritSect; // Thread seriallization + int nMax; // Max objects allowed in queue + int iNextPut; // Array index of next "PutMsg" + int iNextGet; // Array index of next "GetMsg" + T *QueueObjects; // Array of objects (ptr's to void) + + void Initialize(int n) { + iNextPut = iNextGet = 0; + nMax = n; + InitializeCriticalSection(&CritSect); + hSemPut = CreateSemaphore(NULL, n, n, NULL); + hSemGet = CreateSemaphore(NULL, 0, n, NULL); + QueueObjects = new T[n]; + } + + +public: + CQueue(int n) { + Initialize(n); + } + + CQueue() { + Initialize(DEFAULT_QUEUESIZE); + } + + ~CQueue() { + delete [] QueueObjects; + DeleteCriticalSection(&CritSect); + CloseHandle(hSemPut); + CloseHandle(hSemGet); + } + + T GetQueueObject() { + int iSlot; + T Object; + LONG lPrevious; + + // Wait for someone to put something on our queue, returns straight + // away is there is already an object on the queue. + // + WaitForSingleObject(hSemGet, INFINITE); + + EnterCriticalSection(&CritSect); + iSlot = iNextGet++ % nMax; + Object = QueueObjects[iSlot]; + LeaveCriticalSection(&CritSect); + + // Release anyone waiting to put an object onto our queue as there + // is now space available in the queue. + // + ReleaseSemaphore(hSemPut, 1L, &lPrevious); + return Object; + } + + void PutQueueObject(T Object) { + int iSlot; + LONG lPrevious; + + // Wait for someone to get something from our queue, returns straight + // away is there is already an empty slot on the queue. + // + WaitForSingleObject(hSemPut, INFINITE); + + EnterCriticalSection(&CritSect); + iSlot = iNextPut++ % nMax; + QueueObjects[iSlot] = Object; + LeaveCriticalSection(&CritSect); + + // Release anyone waiting to remove an object from our queue as there + // is now an object available to be removed. + // + ReleaseSemaphore(hSemGet, 1L, &lPrevious); + } +}; + +// miscellaneous string conversion functions +// NOTE: as we need to use the same binaries on Win95 as on NT this code should +// be compiled WITHOUT unicode being defined. Otherwise we will not pick up +// these internal routines and the binary will not run on Win95. + +// int WINAPIV wsprintfWInternal(LPWSTR, LPCWSTR, ...); + +//LPWSTR +//WINAPI +//lstrcpyWInternal( +// LPWSTR lpString1, +// LPCWSTR lpString2 +// ); +LPWSTR +WINAPI +lstrcpynWInternal( + LPWSTR lpString1, + LPCWSTR lpString2, + int iMaxLength + ); +int +WINAPI +lstrcmpWInternal( + LPCWSTR lpString1, + LPCWSTR lpString2 + ); +int +WINAPI +lstrcmpiWInternal( + LPCWSTR lpString1, + LPCWSTR lpString2 + ); +int +WINAPI +lstrlenWInternal( + LPCWSTR lpString + ); + +#ifndef UNICODE +#define wsprintfW wsprintfWInternal +#define lstrcpyW lstrcpyWInternal +#define lstrcpynW lstrcpynWInternal +#define lstrcmpW lstrcmpWInternal +#define lstrcmpiW lstrcmpiWInternal +#define lstrlenW lstrlenWInternal +#endif + +extern "C" +void * __stdcall memmoveInternal(void *, const void *, size_t); + +inline void * __cdecl memchrInternal(const void *buf, int chr, size_t cnt) +{ +#ifdef _X86_ + void *pRet = NULL; + + _asm { + cld // make sure we get the direction right + mov ecx, cnt // num of bytes to scan + mov edi, buf // pointer byte stream + mov eax, chr // byte to scan for + repne scasb // look for the byte in the byte stream + jnz exit_memchr // Z flag set if byte found + dec edi // scasb always increments edi even when it + // finds the required byte + mov pRet, edi +exit_memchr: + } + return pRet; + +#else + while ( cnt && (*(unsigned char *)buf != (unsigned char)chr) ) { + buf = (unsigned char *)buf + 1; + cnt--; + } + + return(cnt ? (void *)buf : NULL); +#endif +} + +void WINAPI IntToWstr(int i, LPWSTR wstr, size_t len); + +#define WstrToInt(sz) _wtoi(sz) +#define atoiW(sz) _wtoi(sz) +#define atoiA(sz) atoi(sz) + +// These are available to help managing bitmap VIDEOINFOHEADER media structures + +extern const DWORD bits555[3]; +extern const DWORD bits565[3]; +extern const DWORD bits888[3]; + +// These help convert between VIDEOINFOHEADER and BITMAPINFO structures + +STDAPI_(const GUID) GetTrueColorType(const BITMAPINFOHEADER *pbmiHeader); +STDAPI_(const GUID) GetBitmapSubtype(const BITMAPINFOHEADER *pbmiHeader); +STDAPI_(WORD) GetBitCount(const GUID *pSubtype); + +// strmbase.lib implements this for compatibility with people who +// managed to link to this directly. we don't want to advertise it. +// +// STDAPI_(/* T */ CHAR *) GetSubtypeName(const GUID *pSubtype); + +STDAPI_(CHAR *) GetSubtypeNameA(const GUID *pSubtype); +STDAPI_(WCHAR *) GetSubtypeNameW(const GUID *pSubtype); + +#ifdef UNICODE +#define GetSubtypeName GetSubtypeNameW +#else +#define GetSubtypeName GetSubtypeNameA +#endif + +STDAPI_(LONG) GetBitmapFormatSize(const BITMAPINFOHEADER *pHeader); +STDAPI_(DWORD) GetBitmapSize(const BITMAPINFOHEADER *pHeader); +STDAPI_(BOOL) ContainsPalette(const VIDEOINFOHEADER *pVideoInfo); +STDAPI_(const RGBQUAD *) GetBitmapPalette(const VIDEOINFOHEADER *pVideoInfo); + + +// Compares two interfaces and returns TRUE if they are on the same object +BOOL WINAPI IsEqualObject(IUnknown *pFirst, IUnknown *pSecond); + +// This is for comparing pins +#define EqualPins(pPin1, pPin2) IsEqualObject(pPin1, pPin2) + + +// Arithmetic helper functions + +// Compute (a * b + rnd) / c +LONGLONG WINAPI llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG rnd); +LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG rnd); + + +// Avoids us dyna-linking to SysAllocString to copy BSTR strings +STDAPI WriteBSTR(BSTR * pstrDest, LPCWSTR szSrc); +STDAPI FreeBSTR(BSTR* pstr); + +// Return a wide string - allocating memory for it +// Returns: +// S_OK - no error +// E_POINTER - ppszReturn == NULL +// E_OUTOFMEMORY - can't allocate memory for returned string +STDAPI AMGetWideString(LPCWSTR pszString, LPWSTR *ppszReturn); + +// Special wait for objects owning windows +DWORD WINAPI WaitDispatchingMessages( + HANDLE hObject, + DWORD dwWait, + HWND hwnd = NULL, + UINT uMsg = 0, + HANDLE hEvent = NULL); + +// HRESULT_FROM_WIN32 converts ERROR_SUCCESS to a success code, but in +// our use of HRESULT_FROM_WIN32, it typically means a function failed +// to call SetLastError(), and we still want a failure code. +// +#define AmHresultFromWin32(x) (MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, x)) + +// call GetLastError and return an HRESULT value that will fail the +// SUCCEEDED() macro. +HRESULT AmGetLastErrorToHResult(void); + +// duplicate of ATL's CComPtr to avoid linker conflicts. + +IUnknown* QzAtlComPtrAssign(IUnknown** pp, IUnknown* lp); + +template +class QzCComPtr +{ +public: + typedef T _PtrClass; + QzCComPtr() {p=NULL;} + QzCComPtr(T* lp) + { + if ((p = lp) != NULL) + p->AddRef(); + } + QzCComPtr(const QzCComPtr& lp) + { + if ((p = lp.p) != NULL) + p->AddRef(); + } + ~QzCComPtr() {if (p) p->Release();} + void Release() {if (p) p->Release(); p=NULL;} + operator T*() {return (T*)p;} + T& operator*() {ASSERT(p!=NULL); return *p; } + //The assert on operator& usually indicates a bug. If this is really + //what is needed, however, take the address of the p member explicitly. + T** operator&() { ASSERT(p==NULL); return &p; } + T* operator->() { ASSERT(p!=NULL); return p; } + T* operator=(T* lp){return (T*)QzAtlComPtrAssign((IUnknown**)&p, lp);} + T* operator=(const QzCComPtr& lp) + { + return (T*)QzAtlComPtrAssign((IUnknown**)&p, lp.p); + } +#if _MSC_VER>1020 + bool operator!(){return (p == NULL);} +#else + BOOL operator!(){return (p == NULL) ? TRUE : FALSE;} +#endif + T* p; +}; + +MMRESULT CompatibleTimeSetEvent( UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent ); +bool TimeKillSynchronousFlagAvailable( void ); + +#endif /* __WXUTIL__ */ diff --git a/ThirdParty/videoInput/CMakeLists.txt b/ThirdParty/videoInput/CMakeLists.txt new file mode 100644 index 0000000..b3e0122 --- /dev/null +++ b/ThirdParty/videoInput/CMakeLists.txt @@ -0,0 +1,26 @@ +# +# Stuff the average programmer needs to change +# +set(SRCS + videoInput.cpp) +set(HFILES + videoInput.h) +set(INCLUDE_DIRECTORIES ${BASE_INCLUDE_DIRECTORIES}) +set(LIBRARY_NAME videoInput) +if(WIN32) + set(INCLUDE_DIRECTORIES ${INCLUDE_DIRECTORIES} ${QEDIT_PATH}) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D_LIB;/D_WIN32_WINNT=0x0501) +endif(WIN32) +set(SRCS ${SRCS} ${HFILES}) + +add_library(${LIBRARY_NAME} STATIC ${SRCS}) + +target_compile_definitions(${LIBRARY_NAME} PRIVATE ${PREPROCESSOR_DEFINITIONS}) + +target_include_directories(${LIBRARY_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${BASE_INCLUDE_DIRECTORIES} + "${CMAKE_CURRENT_SOURCE_DIR}/../strmbas" +) + +target_link_libraries(${LIBRARY_NAME} PUBLIC strmbas) \ No newline at end of file diff --git a/ThirdParty/videoInput/Win/videoInput.vcxproj b/ThirdParty/videoInput/Win/videoInput.vcxproj new file mode 100644 index 0000000..d682eeb --- /dev/null +++ b/ThirdParty/videoInput/Win/videoInput.vcxproj @@ -0,0 +1,133 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {74EFD4AB-32C0-397D-AB90-A265D0CA656D} + 10.0.16299.0 + Win32Proj + x64 + videoInput + NoUpgrade + + + + StaticLibrary + Unicode + v141 + + + StaticLibrary + Unicode + v141 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + F:\IT-Dim\trunk\ThirdParty\videoInput\Win\Debug\ + videoInput.dir\Debug\ + videoInput + .lib + F:\IT-Dim\trunk\ThirdParty\videoInput\Win\Release\ + videoInput.dir\Release\ + videoInput + .lib + + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\Include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + Debug/ + EnableFastChecks + CompileAsCpp + ProgramDatabase + 4996 + Sync + Disabled + true + Disabled + NotUsing + MultiThreadedDebugDLL + true + Level3 + WIN32;_WINDOWS;__WXDEBUG__=1;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_LIB;_WIN32_WINNT=0x0501;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_LIB;_WIN32_WINNT=0x0501;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\Include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\Include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + %(AdditionalOptions) /machine:x64 + + + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\Include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + Release/ + CompileAsCpp + 4996 + Sync + AnySuitable + true + MaxSpeed + NotUsing + MultiThreadedDLL + true + Level3 + WIN32;_WINDOWS;NDEBUG;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;__WXDEBUG__=1;_LIB;_WIN32_WINNT=0x0501;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + + + WIN32;_WINDOWS;NDEBUG;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;__WXDEBUG__=1;_LIB;_WIN32_WINNT=0x0501;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\Include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\Include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + %(AdditionalOptions) /machine:x64 + + + + + + + + + {C08529ED-6D79-37D3-ADE8-50F312522BA0} + strmbas + + + + + + \ No newline at end of file diff --git a/ThirdParty/videoInput/Win/videoInput.vcxproj.filters b/ThirdParty/videoInput/Win/videoInput.vcxproj.filters new file mode 100644 index 0000000..4200fe3 --- /dev/null +++ b/ThirdParty/videoInput/Win/videoInput.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + Source Files + + + + + Header Files + + + + + {51D244FA-C21C-3174-8217-FDB3769212C0} + + + {A07A887B-0B8A-3ED7-BD7F-43C26975F88D} + + + diff --git a/ThirdParty/videoInput/videoInput.cpp b/ThirdParty/videoInput/videoInput.cpp new file mode 100644 index 0000000..9038c41 --- /dev/null +++ b/ThirdParty/videoInput/videoInput.cpp @@ -0,0 +1,2340 @@ +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +//THE SOFTWARE. + +#define DEBUG 1 +#define _DEBUG 1 + +#include "videoInput.h" +#include "tchar.h" + +//Include Directshow stuff here so we don't worry about needing all the h files. +#include "DShow.h" +#include "streams.h" +#pragma include_alias( "dxtrans.h", "qedit.h" ) +#define __IDxtCompositor_INTERFACE_DEFINED__ +#define __IDxtAlphaSetter_INTERFACE_DEFINED__ +#define __IDxtJpeg_INTERFACE_DEFINED__ +#define __IDxtKey_INTERFACE_DEFINED__ +#include "qedit.h" +#include "vector" +#include "Aviriff.h" +#include "Windows.h" + +//for threading +#include + +/////////////////////////// HANDY FUNCTIONS ///////////////////////////// + +void MyFreeMediaType(AM_MEDIA_TYPE& mt){ + if (mt.cbFormat != 0) + { + CoTaskMemFree((PVOID)mt.pbFormat); + mt.cbFormat = 0; + mt.pbFormat = NULL; + } + if (mt.pUnk != NULL) + { + // Unecessary because pUnk should not be used, but safest. + mt.pUnk->Release(); + mt.pUnk = NULL; + } +} + +void MyDeleteMediaType(AM_MEDIA_TYPE *pmt) +{ + if (pmt != NULL) + { + MyFreeMediaType(*pmt); + CoTaskMemFree(pmt); + } +} + +////////////////////////////// CALLBACK //////////////////////////////// + +//Callback class +class SampleGrabberCallback : public ISampleGrabberCB{ +public: + + //------------------------------------------------ + SampleGrabberCallback(){ + InitializeCriticalSection(&critSection); + freezeCheck = 0; + + + bufferSetup = false; + newFrame = false; + latestBufferLength = 0; + + hEvent = CreateEvent(NULL, true, false, NULL); + } + + + //------------------------------------------------ + ~SampleGrabberCallback(){ + ptrBuffer = NULL; + DeleteCriticalSection(&critSection); + CloseHandle(hEvent); + if(bufferSetup){ + delete pixels; + } + } + + + //------------------------------------------------ + bool setupBuffer(int numBytesIn){ + if(bufferSetup){ + return false; + }else{ + numBytes = numBytesIn; + pixels = new unsigned char[numBytes]; + bufferSetup = true; + newFrame = false; + latestBufferLength = 0; + } + return true; + } + + + //------------------------------------------------ + STDMETHODIMP_(ULONG) AddRef() { return 1; } + STDMETHODIMP_(ULONG) Release() { return 2; } + + + //------------------------------------------------ + STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject){ + *ppvObject = static_cast(this); + return S_OK; + } + + + //This method is meant to have less overhead + //------------------------------------------------ + STDMETHODIMP SampleCB(double Time, IMediaSample *pSample){ + if(WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) return S_OK; + + HRESULT hr = pSample->GetPointer(&ptrBuffer); + + if(hr == S_OK){ + latestBufferLength = pSample->GetActualDataLength(); + if(latestBufferLength == numBytes){ + EnterCriticalSection(&critSection); + memcpy(pixels, ptrBuffer, latestBufferLength); + newFrame = true; + freezeCheck = 1; + LeaveCriticalSection(&critSection); + SetEvent(hEvent); + }else{ + printf("ERROR: SampleCB() - buffer sizes do not match\n"); + } + } + + return S_OK; + } + + + //This method is meant to have more overhead + STDMETHODIMP BufferCB(double Time, BYTE *pBuffer, long BufferLen){ + return E_NOTIMPL; + } + + int freezeCheck; + + int latestBufferLength; + int numBytes; + bool newFrame; + bool bufferSetup; + unsigned char * pixels; + unsigned char * ptrBuffer; + CRITICAL_SECTION critSection; + HANDLE hEvent; +}; + + +////////////////////////////// VIDEO DEVICE //////////////////////////////// + +// ---------------------------------------------------------------------- +// Should this class also be the callback? +// +// ---------------------------------------------------------------------- + +videoDevice::videoDevice(){ + + pCaptureGraph = NULL; // Capture graph builder object + pGraph = NULL; // Graph builder object + pControl = NULL; // Media control object + pVideoInputFilter = NULL; // Video Capture filter + pGrabber = NULL; // Grabs frame + pDestFilter = NULL; // Null Renderer Filter + pGrabberF = NULL; // Grabber Filter + pMediaEvent = NULL; + streamConf = NULL; + pAmMediaType = NULL; + + //This is our callback class that processes the frame. + sgCallback = new SampleGrabberCallback(); + sgCallback->newFrame = false; + + //Default values for capture type + videoType = MEDIASUBTYPE_RGB24; + connection = PhysConn_Video_Composite; + storeConn = 0; + + videoSize = 0; + width = 0; + height = 0; + tryWidth = 0; + tryHeight = 0; + nFramesForReconnect= 10000; + nFramesRunning = 0; + myID = -1; + + tryDiffSize = false; + useCrossbar = false; + readyToCapture = false; + sizeSet = false; + setupStarted = false; + specificFormat = false; + autoReconnect = false; + requestedFrameTime = -1; + + memset(wDeviceName, 0, sizeof(WCHAR) * 255); + memset(nDeviceName, 0, sizeof(char) * 255); + +} + + +// ---------------------------------------------------------------------- +// The only place we are doing new +// +// ---------------------------------------------------------------------- + +void videoDevice::setSize(int w, int h){ + if(sizeSet){ + if(verbose)printf("SETUP: Error device size should not be set more than once \n"); + } + else + { + width = w; + height = h; + videoSize = w*h*3; + sizeSet = true; + pixels = new unsigned char[videoSize]; + pBuffer = new char[videoSize]; + + memset(pixels, 0 , videoSize); + sgCallback->setupBuffer(videoSize); + + } +} + + +// ---------------------------------------------------------------------- +// Borrowed from the SDK, use it to take apart the graph from +// the capture device downstream to the null renderer +// ---------------------------------------------------------------------- + +void videoDevice::NukeDownstream(IBaseFilter *pBF){ + IPin *pP, *pTo; + ULONG u; + IEnumPins *pins = NULL; + PIN_INFO pininfo; + HRESULT hr = pBF->EnumPins(&pins); + pins->Reset(); + while (hr == NOERROR) + { + hr = pins->Next(1, &pP, &u); + if (hr == S_OK && pP) + { + pP->ConnectedTo(&pTo); + if (pTo) + { + hr = pTo->QueryPinInfo(&pininfo); + if (hr == NOERROR) + { + if (pininfo.dir == PINDIR_INPUT) + { + NukeDownstream(pininfo.pFilter); + pGraph->Disconnect(pTo); + pGraph->Disconnect(pP); + pGraph->RemoveFilter(pininfo.pFilter); + } + pininfo.pFilter->Release(); + pininfo.pFilter = NULL; + } + pTo->Release(); + } + pP->Release(); + } + } + if (pins) pins->Release(); +} + + +// ---------------------------------------------------------------------- +// Also from SDK +// ---------------------------------------------------------------------- + +void videoDevice::destroyGraph(){ + HRESULT hr = NULL; + int FuncRetval=0; + int NumFilters=0; + + int i = 0; + while (hr == NOERROR) + { + IEnumFilters * pEnum = 0; + ULONG cFetched; + + // We must get the enumerator again every time because removing a filter from the graph + // invalidates the enumerator. We always get only the first filter from each enumerator. + hr = pGraph->EnumFilters(&pEnum); + if (FAILED(hr)) { if(verbose)printf("SETUP: pGraph->EnumFilters() failed. \n"); return; } + + IBaseFilter * pFilter = NULL; + if (pEnum->Next(1, &pFilter, &cFetched) == S_OK) + { + FILTER_INFO FilterInfo={0}; + hr = pFilter->QueryFilterInfo(&FilterInfo); + FilterInfo.pGraph->Release(); + + int count = 0; + char buffer[255]; + memset(buffer, 0, 255 * sizeof(char)); + + while( FilterInfo.achName[count] != 0x00 ) + { + buffer[count] = FilterInfo.achName[count]; + count++; + } + + if(verbose)printf("SETUP: removing filter %s...\n", buffer); + hr = pGraph->RemoveFilter(pFilter); + if (FAILED(hr)) { if(verbose)printf("SETUP: pGraph->RemoveFilter() failed. \n"); return; } + if(verbose)printf("SETUP: filter removed %s \n",buffer); + + pFilter->Release(); + pFilter = NULL; + } + else break; + pEnum->Release(); + pEnum = NULL; + i++; + } + + return; +} + + +// ---------------------------------------------------------------------- +// Our deconstructor, attempts to tear down graph and release filters etc +// Does checking to make sure it only is freeing if it needs to +// Probably could be a lot cleaner! :) +// ---------------------------------------------------------------------- + +videoDevice::~videoDevice(){ + + if(setupStarted){ if(verbose)printf("\nSETUP: Disconnecting device %i\n", myID); } + else{ + if(sgCallback){ + sgCallback->Release(); + delete sgCallback; + } + return; + } + + HRESULT HR = NULL; + + //Stop the callback and free it + if( (sgCallback) && (pGrabber) ) + { + pGrabber->SetCallback(NULL, 1); + if(verbose)printf("SETUP: freeing Grabber Callback\n"); + sgCallback->Release(); + + //delete our pixels + if(sizeSet){ + delete[] pixels; + delete[] pBuffer; + } + + delete sgCallback; + } + + //Check to see if the graph is running, if so stop it. + if( (pControl) ) + { + HR = pControl->Pause(); + if (FAILED(HR)) if(verbose)printf("ERROR - Could not pause pControl\n"); + + HR = pControl->Stop(); + if (FAILED(HR)) if(verbose)printf("ERROR - Could not stop pControl\n"); + } + + //Disconnect filters from capture device + if( (pVideoInputFilter) )NukeDownstream(pVideoInputFilter); + + //Release and zero pointers to our filters etc + if( (pDestFilter) ){ if(verbose)printf("SETUP: freeing Renderer \n"); + (pDestFilter)->Release(); + (pDestFilter) = 0; + } + if( (pVideoInputFilter) ){ if(verbose)printf("SETUP: freeing Capture Source \n"); + (pVideoInputFilter)->Release(); + (pVideoInputFilter) = 0; + } + if( (pGrabberF) ){ if(verbose)printf("SETUP: freeing Grabber Filter \n"); + (pGrabberF)->Release(); + (pGrabberF) = 0; + } + if( (pGrabber) ){ if(verbose)printf("SETUP: freeing Grabber \n"); + (pGrabber)->Release(); + (pGrabber) = 0; + } + if( (pControl) ){ if(verbose)printf("SETUP: freeing Control \n"); + (pControl)->Release(); + (pControl) = 0; + } + if( (pMediaEvent) ){ if(verbose)printf("SETUP: freeing Media Event \n"); + (pMediaEvent)->Release(); + (pMediaEvent) = 0; + } + if( (streamConf) ){ if(verbose)printf("SETUP: freeing Stream \n"); + (streamConf)->Release(); + (streamConf) = 0; + } + + if( (pAmMediaType) ){ if(verbose)printf("SETUP: freeing Media Type \n"); + MyDeleteMediaType(pAmMediaType); + } + + if((pMediaEvent)){ + if(verbose)printf("SETUP: freeing Media Event \n"); + (pMediaEvent)->Release(); + (pMediaEvent) = 0; + } + + //Destroy the graph + if( (pGraph) )destroyGraph(); + + //Release and zero our capture graph and our main graph + if( (pCaptureGraph) ){ if(verbose)printf("SETUP: freeing Capture Graph \n"); + (pCaptureGraph)->Release(); + (pCaptureGraph) = 0; + } + if( (pGraph) ){ if(verbose)printf("SETUP: freeing Main Graph \n"); + (pGraph)->Release(); + (pGraph) = 0; + } + + //delete our pointers + delete pDestFilter; + delete pVideoInputFilter; + delete pGrabberF; + delete pGrabber; + delete pControl; + delete streamConf; + delete pMediaEvent; + delete pCaptureGraph; + delete pGraph; + + if(verbose)printf("SETUP: Device %i disconnected and freed\n\n",myID); +} + + +////////////////////////////// VIDEO INPUT //////////////////////////////// +//////////////////////////// PUBLIC METHODS /////////////////////////////// + + +// ---------------------------------------------------------------------- +// Constructor - creates instances of videoDevice and adds the various +// media subtypes to check. +// ---------------------------------------------------------------------- + +videoInput::videoInput(){ + //start com + comInit(); + + devicesFound = 0; + callbackSetCount = 0; + bCallback = true; + + //setup a max no of device objects + for(int i=0; i= VI_MAX_CAMERAS || VDList[deviceNumber]->readyToCapture) return; + + if( idealFramerate > 0 ){ + VDList[deviceNumber]->requestedFrameTime = (unsigned long)(10000000 / idealFramerate); + } +} + + +// ---------------------------------------------------------------------- +// Set the requested framerate - no guarantee you will get this +// +// ---------------------------------------------------------------------- + +void videoInput::setAutoReconnectOnFreeze(int deviceNumber, bool doReconnect, int numMissedFramesBeforeReconnect){ + if(deviceNumber >= VI_MAX_CAMERAS) return; + + VDList[deviceNumber]->autoReconnect = doReconnect; + VDList[deviceNumber]->nFramesForReconnect = numMissedFramesBeforeReconnect; + +} + + +// ---------------------------------------------------------------------- +// Setup a device with the default settings +// +// ---------------------------------------------------------------------- + +bool videoInput::setupDevice(int deviceNumber){ + if(deviceNumber >= VI_MAX_CAMERAS || VDList[deviceNumber]->readyToCapture) return false; + + if(setup(deviceNumber))return true; + return false; +} + + +// ---------------------------------------------------------------------- +// Setup a device with the default size but specify input type +// +// ---------------------------------------------------------------------- + +bool videoInput::setupDevice(int deviceNumber, int connection){ + if(deviceNumber >= VI_MAX_CAMERAS || VDList[deviceNumber]->readyToCapture) return false; + + setPhyCon(deviceNumber, connection); + if(setup(deviceNumber))return true; + return false; +} + + +// ---------------------------------------------------------------------- +// Setup a device with the default connection but specify size +// +// ---------------------------------------------------------------------- + +bool videoInput::setupDevice(int deviceNumber, int w, int h){ + if(deviceNumber >= VI_MAX_CAMERAS || VDList[deviceNumber]->readyToCapture) return false; + + setAttemptCaptureSize(deviceNumber,w,h); + if(setup(deviceNumber))return true; + return false; +} + + +// ---------------------------------------------------------------------- +// Setup a device with specific size and connection +// +// ---------------------------------------------------------------------- + +bool videoInput::setupDevice(int deviceNumber, int w, int h, int connection){ + if(deviceNumber >= VI_MAX_CAMERAS || VDList[deviceNumber]->readyToCapture) return false; + + setAttemptCaptureSize(deviceNumber,w,h); + setPhyCon(deviceNumber, connection); + if(setup(deviceNumber))return true; + return false; +} + + +// ---------------------------------------------------------------------- +// Setup the default video format of the device +// Must be called after setup! +// See #define formats in header file (eg VI_NTSC_M ) +// +// ---------------------------------------------------------------------- + +bool videoInput::setFormat(int deviceNumber, int format){ + if(deviceNumber >= VI_MAX_CAMERAS || !VDList[deviceNumber]->readyToCapture) return false; + + bool returnVal = false; + + if(format >= 0 && format < VI_NUM_FORMATS){ + VDList[deviceNumber]->formatType = formatTypes[format]; + VDList[deviceNumber]->specificFormat = true; + + if(VDList[deviceNumber]->specificFormat){ + + HRESULT hr = getDevice(&VDList[deviceNumber]->pVideoInputFilter, deviceNumber, VDList[deviceNumber]->wDeviceName, VDList[deviceNumber]->nDeviceName); + if(hr != S_OK){ + return false; + } + + IAMAnalogVideoDecoder *pVideoDec = NULL; + hr = VDList[deviceNumber]->pCaptureGraph->FindInterface(NULL, &MEDIATYPE_Video, VDList[deviceNumber]->pVideoInputFilter, IID_IAMAnalogVideoDecoder, (void **)&pVideoDec); + + //in case the settings window some how freed them first + if(VDList[deviceNumber]->pVideoInputFilter)VDList[deviceNumber]->pVideoInputFilter->Release(); + if(VDList[deviceNumber]->pVideoInputFilter)VDList[deviceNumber]->pVideoInputFilter = NULL; + + if(FAILED(hr)){ + printf("SETUP: couldn't set requested format\n"); + }else{ + long lValue = 0; + hr = pVideoDec->get_AvailableTVFormats(&lValue); + if( SUCCEEDED(hr) && (lValue & VDList[deviceNumber]->formatType) ) + { + hr = pVideoDec->put_TVFormat(VDList[deviceNumber]->formatType); + if( FAILED(hr) ){ + printf("SETUP: couldn't set requested format\n"); + }else{ + returnVal = true; + } + } + + pVideoDec->Release(); + pVideoDec = NULL; + } + } + } + + return returnVal; +} + +// ---------------------------------------------------------------------- +// Our static function for returning device names - thanks Peter! +// Must call listDevices first. +// +// ---------------------------------------------------------------------- +char videoInput::deviceNames[VI_MAX_CAMERAS][255]={{0}}; + +char * videoInput::getDeviceName(int deviceID){ + if( deviceID >= VI_MAX_CAMERAS ){ + return NULL; + } + return deviceNames[deviceID]; +} + + +// ---------------------------------------------------------------------- +// Our static function for finding num devices available etc +// +// ---------------------------------------------------------------------- + +int videoInput::listDevices(bool silent){ + + //COM Library Intialization + comInit(); + + if(!silent)printf("\nVIDEOINPUT SPY MODE!\n\n"); + + + ICreateDevEnum *pDevEnum = NULL; + IEnumMoniker *pEnum = NULL; + int deviceCounter = 0; + + HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, + CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, + reinterpret_cast(&pDevEnum)); + + + if (SUCCEEDED(hr)) + { + // Create an enumerator for the video capture category. + hr = pDevEnum->CreateClassEnumerator( + CLSID_VideoInputDeviceCategory, + &pEnum, 0); + + if(hr == S_OK){ + + if(!silent)printf("SETUP: Looking For Capture Devices\n"); + IMoniker *pMoniker = NULL; + + while (pEnum->Next(1, &pMoniker, NULL) == S_OK){ + + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, + (void**)(&pPropBag)); + + if (FAILED(hr)){ + pMoniker->Release(); + continue; // Skip this one, maybe the next one will work. + } + + + // Find the description or friendly name. + VARIANT varName; + VariantInit(&varName); + hr = pPropBag->Read(L"Description", &varName, 0); + + if (FAILED(hr)) hr = pPropBag->Read(L"FriendlyName", &varName, 0); + + if (SUCCEEDED(hr)){ + + hr = pPropBag->Read(L"FriendlyName", &varName, 0); + + int count = 0; + int maxLen = sizeof(deviceNames[0])/sizeof(deviceNames[0][0]) - 2; + while( varName.bstrVal[count] != 0x00 && count < maxLen) { + deviceNames[deviceCounter][count] = varName.bstrVal[count]; + count++; + } + deviceNames[deviceCounter][count] = 0; + + if(!silent)printf("SETUP: %i) %s \n",deviceCounter, deviceNames[deviceCounter]); + } + + pPropBag->Release(); + pPropBag = NULL; + + pMoniker->Release(); + pMoniker = NULL; + + deviceCounter++; + } + + pDevEnum->Release(); + pDevEnum = NULL; + + pEnum->Release(); + pEnum = NULL; + } + + if(!silent)printf("SETUP: %i Device(s) found\n\n", deviceCounter); + } + + comUnInit(); + + return deviceCounter; +} + + +// ---------------------------------------------------------------------- +// +// +// ---------------------------------------------------------------------- + +int videoInput::getWidth(int id){ + + if(isDeviceSetup(id)) + { + return VDList[id] ->width; + } + + return 0; + +} + + +// ---------------------------------------------------------------------- +// +// +// ---------------------------------------------------------------------- + +int videoInput::getHeight(int id){ + + if(isDeviceSetup(id)) + { + return VDList[id] ->height; + } + + return 0; + +} + + +// ---------------------------------------------------------------------- +// +// +// ---------------------------------------------------------------------- + +int videoInput::getSize(int id){ + + if(isDeviceSetup(id)) + { + return VDList[id] ->videoSize; + } + + return 0; + +} + + +// ---------------------------------------------------------------------- +// Uses a supplied buffer +// ---------------------------------------------------------------------- + +bool videoInput::getPixels(int id, unsigned char * dstBuffer, bool flipRedAndBlue, bool flipImage){ + + bool success = false; + + if(isDeviceSetup(id)){ + if(bCallback){ + //callback capture + + DWORD result = WaitForSingleObject(VDList[id]->sgCallback->hEvent, 1000); + if( result != WAIT_OBJECT_0) return false; + + //double paranoia - mutexing with both event and critical section + EnterCriticalSection(&VDList[id]->sgCallback->critSection); + + unsigned char * src = VDList[id]->sgCallback->pixels; + unsigned char * dst = dstBuffer; + int height = VDList[id]->height; + int width = VDList[id]->width; + + processPixels(src, dst, width, height, flipRedAndBlue, flipImage); + VDList[id]->sgCallback->newFrame = false; + + LeaveCriticalSection(&VDList[id]->sgCallback->critSection); + + ResetEvent(VDList[id]->sgCallback->hEvent); + + success = true; + + } + else{ + //regular capture method + long bufferSize = VDList[id]->videoSize; + HRESULT hr = VDList[id]->pGrabber->GetCurrentBuffer(&bufferSize, (long *)VDList[id]->pBuffer); + if(hr==S_OK){ + int numBytes = VDList[id]->videoSize; + if (numBytes == bufferSize){ + + unsigned char * src = (unsigned char * )VDList[id]->pBuffer; + unsigned char * dst = dstBuffer; + int height = VDList[id]->height; + int width = VDList[id]->width; + + processPixels(src, dst, width, height, flipRedAndBlue, flipImage); + success = true; + }else{ + if(verbose)printf("ERROR: GetPixels() - bufferSizes do not match!\n"); + } + }else{ + if(verbose)printf("ERROR: GetPixels() - Unable to grab frame for device %i\n", id); + } + } + } + + return success; +} + + +// ---------------------------------------------------------------------- +// Returns a buffer +// ---------------------------------------------------------------------- +unsigned char * videoInput::getPixels(int id, bool flipRedAndBlue, bool flipImage){ + + if(isDeviceSetup(id)){ + getPixels(id, VDList[id]->pixels, flipRedAndBlue, flipImage); + } + + return VDList[id]->pixels; +} + + + +// ---------------------------------------------------------------------- +// +// +// ---------------------------------------------------------------------- +bool videoInput::isFrameNew(int id){ + if(!isDeviceSetup(id)) return false; + if(!bCallback)return true; + + bool result = false; + bool freeze = false; + + //again super paranoia! + EnterCriticalSection(&VDList[id]->sgCallback->critSection); + result = VDList[id]->sgCallback->newFrame; + + //we need to give it some time at the begining to start up so lets check after 400 frames + if(VDList[id]->nFramesRunning > 400 && VDList[id]->sgCallback->freezeCheck > VDList[id]->nFramesForReconnect ){ + freeze = true; + } + + //we increment the freezeCheck var here - the callback resets it to 1 + //so as long as the callback is running this var should never get too high. + //if the callback is not running then this number will get high and trigger the freeze action below + VDList[id]->sgCallback->freezeCheck++; + LeaveCriticalSection(&VDList[id]->sgCallback->critSection); + + VDList[id]->nFramesRunning++; + + if(freeze && VDList[id]->autoReconnect){ + if(verbose)printf("ERROR: Device seems frozen - attempting to reconnect\n"); + if( !restartDevice(VDList[id]->myID) ){ + if(verbose)printf("ERROR: Unable to reconnect to device\n"); + }else{ + if(verbose)printf("SUCCESS: Able to reconnect to device\n"); + } + } + + return result; +} + + +// ---------------------------------------------------------------------- +// +// +// ---------------------------------------------------------------------- + +bool videoInput::isDeviceSetup(int id){ + + if(idreadyToCapture)return true; + else return false; + +} + + +// ---------------------------------------------------------------------- +// Gives us a little pop up window to adjust settings +// We do this in a seperate thread now! +// ---------------------------------------------------------------------- + + +void __cdecl videoInput::basicThread(void * objPtr){ + + //get a reference to the video device + //not a copy as we need to free the filter + videoDevice * vd = *( (videoDevice **)(objPtr) ); + ShowFilterPropertyPages(vd->pVideoInputFilter); + + //now we free the filter and make sure it set to NULL + if(vd->pVideoInputFilter)vd->pVideoInputFilter->Release(); + if(vd->pVideoInputFilter)vd->pVideoInputFilter = NULL; + + return; +} + +void videoInput::showSettingsWindow(int id){ + + if(isDeviceSetup(id)){ + + HANDLE myTempThread; + + //we reconnect to the device as we have freed our reference to it + //why have we freed our reference? because there seemed to be an issue + //with some mpeg devices if we didn't + HRESULT hr = getDevice(&VDList[id]->pVideoInputFilter, id, VDList[id]->wDeviceName, VDList[id]->nDeviceName); + if(hr == S_OK){ + myTempThread = (HANDLE)_beginthread(basicThread, 0, (void *)&VDList[id]); + } + } +} + + +// Set a video signal setting using IAMVideoProcAmp +bool videoInput::getVideoSettingFilter(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long ¤tValue, long &flags, long &defaultValue){ + if( !isDeviceSetup(deviceID) )return false; + + HRESULT hr; + bool isSuccessful = false; + + videoDevice * VD = VDList[deviceID]; + + hr = getDevice(&VD->pVideoInputFilter, deviceID, VD->wDeviceName, VD->nDeviceName); + if (FAILED(hr)){ + printf("setVideoSetting - getDevice Error\n"); + return false; + } + + IAMVideoProcAmp *pAMVideoProcAmp = NULL; + + hr = VD->pVideoInputFilter->QueryInterface(IID_IAMVideoProcAmp, (void**)&pAMVideoProcAmp); + if(FAILED(hr)){ + printf("setVideoSetting - QueryInterface Error\n"); + if(VD->pVideoInputFilter)VD->pVideoInputFilter->Release(); + if(VD->pVideoInputFilter)VD->pVideoInputFilter = NULL; + return false; + } + + if (verbose) printf("Setting video setting %ld.\n", Property); + + pAMVideoProcAmp->GetRange(Property, &min, &max, &SteppingDelta, &defaultValue, &flags); + if (verbose) printf("Range for video setting %ld: Min:%ld Max:%ld SteppingDelta:%ld Default:%ld Flags:%ld\n", Property, min, max, SteppingDelta, defaultValue, flags); + pAMVideoProcAmp->Get(Property, ¤tValue, &flags); + + if(pAMVideoProcAmp)pAMVideoProcAmp->Release(); + if(VD->pVideoInputFilter)VD->pVideoInputFilter->Release(); + if(VD->pVideoInputFilter)VD->pVideoInputFilter = NULL; + + return true; + +} + + +// Set a video signal setting using IAMVideoProcAmp +bool videoInput::setVideoSettingFilterPct(int deviceID, long Property, float pctValue, long Flags){ + if( !isDeviceSetup(deviceID) )return false; + + long min, max, currentValue, flags, defaultValue, stepAmnt; + + if( !getVideoSettingFilter(deviceID, Property, min, max, stepAmnt, currentValue, flags, defaultValue) )return false; + + if(pctValue > 1.0)pctValue = 1.0; + else if(pctValue < 0)pctValue = 0.0; + + float range = (float)max - (float)min; + if(range <= 0)return false; + if(stepAmnt == 0) return false; + + long value = (long)( (float)min + range * pctValue ); + long rasterValue = value; + + //if the range is the stepAmnt then it is just a switch + //so we either set the value to low or high + if( range == stepAmnt ){ + if( pctValue < 0.5)rasterValue = min; + else rasterValue = max; + }else{ + //we need to rasterize the value to the stepping amnt + long mod = value % stepAmnt; + float halfStep = (float)stepAmnt * 0.5; + if( mod < halfStep ) rasterValue -= mod; + else rasterValue += stepAmnt - mod; + printf("RASTER - pctValue is %f - value is %i - step is %i - mod is %i - rasterValue is %i\n", pctValue, value, stepAmnt, mod, rasterValue); + } + + return setVideoSettingFilter(deviceID, Property, rasterValue, Flags, false); +} + + +// Set a video signal setting using IAMVideoProcAmp +bool videoInput::setVideoSettingFilter(int deviceID, long Property, long lValue, long Flags, bool useDefaultValue){ + if( !isDeviceSetup(deviceID) )return false; + + HRESULT hr; + bool isSuccessful = false; + + videoDevice * VD = VDList[deviceID]; + + hr = getDevice(&VD->pVideoInputFilter, deviceID, VD->wDeviceName, VD->nDeviceName); + if (FAILED(hr)){ + printf("setVideoSetting - getDevice Error\n"); + return false; + } + + IAMVideoProcAmp *pAMVideoProcAmp = NULL; + + hr = VD->pVideoInputFilter->QueryInterface(IID_IAMVideoProcAmp, (void**)&pAMVideoProcAmp); + if(FAILED(hr)){ + printf("setVideoSetting - QueryInterface Error\n"); + if(VD->pVideoInputFilter)VD->pVideoInputFilter->Release(); + if(VD->pVideoInputFilter)VD->pVideoInputFilter = NULL; + return false; + } + + if (verbose) printf("Setting video setting %ld.\n", Property); + long CurrVal, Min, Max, SteppingDelta, Default, CapsFlags, AvailableCapsFlags = 0; + + + pAMVideoProcAmp->GetRange(Property, &Min, &Max, &SteppingDelta, &Default, &AvailableCapsFlags); + if (verbose) printf("Range for video setting %ld: Min:%ld Max:%ld SteppingDelta:%ld Default:%ld Flags:%ld\n", Property, Min, Max, SteppingDelta, Default, AvailableCapsFlags); + pAMVideoProcAmp->Get(Property, &CurrVal, &CapsFlags); + + if (verbose) printf("Current value: %ld Flags %ld (%s)\n", CurrVal, CapsFlags, (CapsFlags == 1 ? "Auto" : (CapsFlags == 2 ? "Manual" : "Unknown"))); + + if (useDefaultValue) { + pAMVideoProcAmp->Set(Property, Default, VideoProcAmp_Flags_Auto); + } + else{ + // Perhaps add a check that lValue and Flags are within the range aquired from GetRange above + pAMVideoProcAmp->Set(Property, lValue, Flags); + } + + if(pAMVideoProcAmp)pAMVideoProcAmp->Release(); + if(VD->pVideoInputFilter)VD->pVideoInputFilter->Release(); + if(VD->pVideoInputFilter)VD->pVideoInputFilter = NULL; + + return true; + +} + + +bool videoInput::setVideoSettingCameraPct(int deviceID, long Property, float pctValue, long Flags){ + if( !isDeviceSetup(deviceID) )return false; + + long min, max, currentValue, flags, defaultValue, stepAmnt; + + if( !getVideoSettingCamera(deviceID, Property, min, max, stepAmnt, currentValue, flags, defaultValue) )return false; + + if(pctValue > 1.0)pctValue = 1.0; + else if(pctValue < 0)pctValue = 0.0; + + float range = (float)max - (float)min; + if(range <= 0)return false; + if(stepAmnt == 0) return false; + + long value = (long)( (float)min + range * pctValue ); + long rasterValue = value; + + //if the range is the stepAmnt then it is just a switch + //so we either set the value to low or high + if( range == stepAmnt ){ + if( pctValue < 0.5)rasterValue = min; + else rasterValue = max; + }else{ + //we need to rasterize the value to the stepping amnt + long mod = value % stepAmnt; + float halfStep = (float)stepAmnt * 0.5; + if( mod < halfStep ) rasterValue -= mod; + else rasterValue += stepAmnt - mod; + printf("RASTER - pctValue is %f - value is %i - step is %i - mod is %i - rasterValue is %i\n", pctValue, value, stepAmnt, mod, rasterValue); + } + + return setVideoSettingCamera(deviceID, Property, rasterValue, Flags, false); +} + + +bool videoInput::setVideoSettingCamera(int deviceID, long Property, long lValue, long Flags, bool useDefaultValue){ + IAMCameraControl *pIAMCameraControl; + if(isDeviceSetup(deviceID)) + { + HRESULT hr; + hr = getDevice(&VDList[deviceID]->pVideoInputFilter, deviceID, VDList[deviceID]->wDeviceName, VDList[deviceID]->nDeviceName); + + if (verbose) printf("Setting video setting %ld.\n", Property); + hr = VDList[deviceID]->pVideoInputFilter->QueryInterface(IID_IAMCameraControl, (void**)&pIAMCameraControl); + if (FAILED(hr)) { + printf("Error\n"); + return false; + } + else + { + long CurrVal, Min, Max, SteppingDelta, Default, CapsFlags, AvailableCapsFlags; + pIAMCameraControl->GetRange(Property, &Min, &Max, &SteppingDelta, &Default, &AvailableCapsFlags); + if (verbose) printf("Range for video setting %ld: Min:%ld Max:%ld SteppingDelta:%ld Default:%ld Flags:%ld\n", Property, Min, Max, SteppingDelta, Default, AvailableCapsFlags); + pIAMCameraControl->Get(Property, &CurrVal, &CapsFlags); + if (verbose) printf("Current value: %ld Flags %ld (%s)\n", CurrVal, CapsFlags, (CapsFlags == 1 ? "Auto" : (CapsFlags == 2 ? "Manual" : "Unknown"))); + if (useDefaultValue) { + pIAMCameraControl->Set(Property, Default, CameraControl_Flags_Auto); + } + else + { + // Perhaps add a check that lValue and Flags are within the range aquired from GetRange above + pIAMCameraControl->Set(Property, lValue, Flags); + } + pIAMCameraControl->Release(); + return true; + } + } + return false; +} + + + +bool videoInput::getVideoSettingCamera(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long ¤tValue, long &flags, long &defaultValue){ + if( !isDeviceSetup(deviceID) )return false; + + HRESULT hr; + bool isSuccessful = false; + + videoDevice * VD = VDList[deviceID]; + + hr = getDevice(&VD->pVideoInputFilter, deviceID, VD->wDeviceName, VD->nDeviceName); + if (FAILED(hr)){ + printf("setVideoSetting - getDevice Error\n"); + return false; + } + + IAMCameraControl *pIAMCameraControl = NULL; + + hr = VD->pVideoInputFilter->QueryInterface(IID_IAMCameraControl, (void**)&pIAMCameraControl); + if(FAILED(hr)){ + printf("setVideoSetting - QueryInterface Error\n"); + if(VD->pVideoInputFilter)VD->pVideoInputFilter->Release(); + if(VD->pVideoInputFilter)VD->pVideoInputFilter = NULL; + return false; + } + + if (verbose) printf("Setting video setting %ld.\n", Property); + + pIAMCameraControl->GetRange(Property, &min, &max, &SteppingDelta, &defaultValue, &flags); + if (verbose) printf("Range for video setting %ld: Min:%ld Max:%ld SteppingDelta:%ld Default:%ld Flags:%ld\n", Property, min, max, SteppingDelta, defaultValue, flags); + pIAMCameraControl->Get(Property, ¤tValue, &flags); + + if(pIAMCameraControl)pIAMCameraControl->Release(); + if(VD->pVideoInputFilter)VD->pVideoInputFilter->Release(); + if(VD->pVideoInputFilter)VD->pVideoInputFilter = NULL; + + return true; + +} + + +// ---------------------------------------------------------------------- +// Shutsdown the device, deletes the object and creates a new object +// so it is ready to be setup again +// ---------------------------------------------------------------------- + +void videoInput::stopDevice(int id){ + if(id < VI_MAX_CAMERAS) + { + delete VDList[id]; + VDList[id] = new videoDevice(); + } + +} + +// ---------------------------------------------------------------------- +// Restarts the device with the same settings it was using +// +// ---------------------------------------------------------------------- + +bool videoInput::restartDevice(int id){ + if(isDeviceSetup(id)) + { + int conn = VDList[id]->storeConn; + int tmpW = VDList[id]->width; + int tmpH = VDList[id]->height; + + bool bFormat = VDList[id]->specificFormat; + long format = VDList[id]->formatType; + + int nReconnect = VDList[id]->nFramesForReconnect; + bool bReconnect = VDList[id]->autoReconnect; + + unsigned long avgFrameTime = VDList[id]->requestedFrameTime; + + stopDevice(id); + + //set our fps if needed + if( avgFrameTime != -1){ + VDList[id]->requestedFrameTime = avgFrameTime; + } + + if( setupDevice(id, tmpW, tmpH, conn) ){ + //reapply the format - ntsc / pal etc + if( bFormat ){ + setFormat(id, format); + } + if( bReconnect ){ + setAutoReconnectOnFreeze(id, true, nReconnect); + } + return true; + } + } + return false; +} + +// ---------------------------------------------------------------------- +// Shuts down all devices, deletes objects and unitializes com if needed +// +// ---------------------------------------------------------------------- +videoInput::~videoInput(){ + + for(int i = 0; i < VI_MAX_CAMERAS; i++) + { + delete VDList[i]; + } + //Unitialize com + comUnInit(); +} + + +////////////////////////////// VIDEO INPUT //////////////////////////////// +//////////////////////////// PRIVATE METHODS ////////////////////////////// + +// ---------------------------------------------------------------------- +// We only should init com if it hasn't been done so by our apps thread +// Use a static counter to keep track of other times it has been inited +// (do we need to worry about multithreaded apps?) +// ---------------------------------------------------------------------- + +bool videoInput::comInit(){ + HRESULT hr = NULL; + + //no need for us to start com more than once + if(comInitCount == 0 ){ + + // Initialize the COM library. + //CoInitializeEx so videoInput can run in another thread + #ifdef VI_COM_MULTI_THREADED + hr = CoInitializeEx(NULL,COINIT_MULTITHREADED); + #else + hr = CoInitialize(NULL); + #endif + //this is the only case where there might be a problem + //if another library has started com as single threaded + //and we need it multi-threaded - send warning but don't fail + if( hr == RPC_E_CHANGED_MODE){ + if(verbose)printf("SETUP - COM already setup - threaded VI might not be possible\n"); + } + } + + comInitCount++; + return true; +} + + +// ---------------------------------------------------------------------- +// Same as above but to unitialize com, decreases counter and frees com +// if no one else is using it +// ---------------------------------------------------------------------- + +bool videoInput::comUnInit(){ + if(comInitCount > 0)comInitCount--; //decrease the count of instances using com + + if(comInitCount == 0){ + CoUninitialize(); //if there are no instances left - uninitialize com + return true; + } + + return false; +} + + +// ---------------------------------------------------------------------- +// This is the size we ask for - we might not get it though :) +// +// ---------------------------------------------------------------------- + +void videoInput::setAttemptCaptureSize(int id, int w, int h){ + + VDList[id]->tryWidth = w; + VDList[id]->tryHeight = h; + VDList[id]->tryDiffSize = true; + +} + + +// ---------------------------------------------------------------------- +// Set the connection type +// (maybe move to private?) +// ---------------------------------------------------------------------- + +void videoInput::setPhyCon(int id, int conn){ + + switch(conn){ + + case 0: + VDList[id]->connection = PhysConn_Video_Composite; + break; + case 1: + VDList[id]->connection = PhysConn_Video_SVideo; + break; + case 2: + VDList[id]->connection = PhysConn_Video_Tuner; + break; + case 3: + VDList[id]->connection = PhysConn_Video_USB; + break; + case 4: + VDList[id]->connection = PhysConn_Video_1394; + break; + default: + return; //if it is not these types don't set crossbar + break; + } + + VDList[id]->storeConn = conn; + VDList[id]->useCrossbar = true; +} + + +// ---------------------------------------------------------------------- +// Check that we are not trying to setup a non-existant device +// Then start the graph building! +// ---------------------------------------------------------------------- + +bool videoInput::setup(int deviceNumber){ + devicesFound = getDeviceCount(); + + if(deviceNumber>devicesFound-1) + { + if(verbose)printf("SETUP: device[%i] not found - you have %i devices available\n", deviceNumber, devicesFound); + if(devicesFound>=0) if(verbose)printf("SETUP: this means that the last device you can use is device[%i] \n", devicesFound-1); + return false; + } + + if(VDList[deviceNumber]->readyToCapture) + { + if(verbose)printf("SETUP: can't setup, device %i is currently being used\n",VDList[deviceNumber]->myID); + return false; + } + + HRESULT hr = start(deviceNumber, VDList[deviceNumber]); + if(hr == S_OK)return true; + else return false; +} + + +// ---------------------------------------------------------------------- +// Does both vertical buffer flipping and bgr to rgb swapping +// You have any combination of those. +// ---------------------------------------------------------------------- + +void videoInput::processPixels(unsigned char * src, unsigned char * dst, int width, int height, bool bRGB, bool bFlip){ + + int widthInBytes = width * 3; + int numBytes = widthInBytes * height; + + if(!bRGB){ + + int x = 0; + int y = 0; + + if(bFlip){ + for(int y = 0; y < height; y++){ + memcpy(dst + (y * widthInBytes), src + ( (height -y -1) * widthInBytes), widthInBytes); + } + + }else{ + memcpy(dst, src, numBytes); + } + }else{ + if(bFlip){ + + int x = 0; + int y = (height - 1) * widthInBytes; + src += y; + + for(int i = 0; i < numBytes; i+=3){ + if(x >= width){ + x = 0; + src -= widthInBytes*2; + } + + *dst = *(src+2); + dst++; + + *dst = *(src+1); + dst++; + + *dst = *src; + dst++; + + src+=3; + x++; + } + } + else{ + for(int i = 0; i < numBytes; i+=3){ + *dst = *(src+2); + dst++; + + *dst = *(src+1); + dst++; + + *dst = *src; + dst++; + + src+=3; + } + } + } +} + + +//------------------------------------------------------------------------------------------ +void videoInput::getMediaSubtypeAsString(GUID type, char * typeAsString){ + + char tmpStr[8]; + if( type == MEDIASUBTYPE_RGB24) sprintf(tmpStr, "RGB24"); + else if(type == MEDIASUBTYPE_RGB32) sprintf(tmpStr, "RGB32"); + else if(type == MEDIASUBTYPE_RGB555)sprintf(tmpStr, "RGB555"); + else if(type == MEDIASUBTYPE_RGB565)sprintf(tmpStr, "RGB565"); + else if(type == MEDIASUBTYPE_YUY2) sprintf(tmpStr, "YUY2"); + else if(type == MEDIASUBTYPE_YVYU) sprintf(tmpStr, "YVYU"); + else if(type == MEDIASUBTYPE_YUYV) sprintf(tmpStr, "YUYV"); + else if(type == MEDIASUBTYPE_IYUV) sprintf(tmpStr, "IYUV"); + else if(type == MEDIASUBTYPE_UYVY) sprintf(tmpStr, "UYVY"); + else if(type == MEDIASUBTYPE_YV12) sprintf(tmpStr, "YV12"); + else if(type == MEDIASUBTYPE_YVU9) sprintf(tmpStr, "YVU9"); + else if(type == MEDIASUBTYPE_Y411) sprintf(tmpStr, "Y411"); + else if(type == MEDIASUBTYPE_Y41P) sprintf(tmpStr, "Y41P"); + else if(type == MEDIASUBTYPE_Y211) sprintf(tmpStr, "Y211"); + else if(type == MEDIASUBTYPE_AYUV) sprintf(tmpStr, "AYUV"); + else if(type == MEDIASUBTYPE_Y800) sprintf(tmpStr, "Y800"); + else if(type == MEDIASUBTYPE_Y8) sprintf(tmpStr, "Y8"); + else if(type == MEDIASUBTYPE_GREY) sprintf(tmpStr, "GREY"); + else sprintf(tmpStr, "OTHER"); + + memcpy(typeAsString, tmpStr, sizeof(char)*8); +} + +//------------------------------------------------------------------------------------------- +static void findClosestSizeAndSubtype(videoDevice * VD, int widthIn, int heightIn, int &widthOut, int &heightOut, GUID & mediatypeOut){ + HRESULT hr; + + //find perfect match or closest size + int nearW = 9999999; + int nearH = 9999999; + bool foundClosestMatch = true; + + int iCount = 0; + int iSize = 0; + hr = VD->streamConf->GetNumberOfCapabilities(&iCount, &iSize); + + if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) + { + //For each format type RGB24 YUV2 etc + for (int iFormat = 0; iFormat < iCount; iFormat++) + { + VIDEO_STREAM_CONFIG_CAPS scc; + AM_MEDIA_TYPE *pmtConfig; + hr = VD->streamConf->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc); + + if (SUCCEEDED(hr)){ + + //his is how many diff sizes are available for the format + int stepX = scc.OutputGranularityX; + int stepY = scc.OutputGranularityY; + + int tempW = 999999; + int tempH = 999999; + + //Don't want to get stuck in a loop + if(stepX < 1 || stepY < 1) continue; + + //if(verbose)printf("min is %i %i max is %i %i - res is %i %i \n", scc.MinOutputSize.cx, scc.MinOutputSize.cy, scc.MaxOutputSize.cx, scc.MaxOutputSize.cy, stepX, stepY); + //if(verbose)printf("min frame duration is %i max duration is %i\n", scc.MinFrameInterval, scc.MaxFrameInterval); + + bool exactMatch = false; + bool exactMatchX = false; + bool exactMatchY = false; + + for(int x = scc.MinOutputSize.cx; x <= scc.MaxOutputSize.cx; x+= stepX){ + //If we find an exact match + if( widthIn == x ){ + exactMatchX = true; + tempW = x; + } + //Otherwise lets find the closest match based on width + else if( abs(widthIn-x) < abs(widthIn-tempW) ){ + tempW = x; + } + } + + for(int y = scc.MinOutputSize.cy; y <= scc.MaxOutputSize.cy; y+= stepY){ + //If we find an exact match + if( heightIn == y){ + exactMatchY = true; + tempH = y; + } + //Otherwise lets find the closest match based on height + else if( abs(heightIn-y) < abs(heightIn-tempH) ){ + tempH = y; + } + } + + //see if we have an exact match! + if(exactMatchX && exactMatchY){ + foundClosestMatch = false; + exactMatch = true; + + widthOut = widthIn; + heightOut = heightIn; + mediatypeOut = pmtConfig->subtype; + } + + //otherwise lets see if this filters closest size is the closest + //available. the closest size is determined by the sum difference + //of the widths and heights + else if( abs(widthIn - tempW) + abs(heightIn - tempH) < abs(widthIn - nearW) + abs(heightIn - nearH) ) + { + nearW = tempW; + nearH = tempH; + + widthOut = nearW; + heightOut = nearH; + mediatypeOut = pmtConfig->subtype; + } + + MyDeleteMediaType(pmtConfig); + + //If we have found an exact match no need to search anymore + if(exactMatch)break; + } + } + } + +} + + +//--------------------------------------------------------------------------------------------------- +static bool setSizeAndSubtype(videoDevice * VD, int attemptWidth, int attemptHeight, GUID mediatype){ + VIDEOINFOHEADER *pVih = reinterpret_cast(VD->pAmMediaType->pbFormat); + + //store current size + int tmpWidth = HEADER(pVih)->biWidth; + int tmpHeight = HEADER(pVih)->biHeight; + AM_MEDIA_TYPE * tmpType = NULL; + + HRESULT hr = VD->streamConf->GetFormat(&tmpType); + if(hr != S_OK)return false; + + //set new size: + //width and height + HEADER(pVih)->biWidth = attemptWidth; + HEADER(pVih)->biHeight = attemptHeight; + + VD->pAmMediaType->formattype = FORMAT_VideoInfo; + VD->pAmMediaType->majortype = MEDIATYPE_Video; + VD->pAmMediaType->subtype = mediatype; + + //buffer size + VD->pAmMediaType->lSampleSize = attemptWidth*attemptHeight*3; + + //set fps if requested + if( VD->requestedFrameTime != -1){ + pVih->AvgTimePerFrame = VD->requestedFrameTime; + } + + //okay lets try new size + hr = VD->streamConf->SetFormat(VD->pAmMediaType); + if(hr == S_OK){ + if( tmpType != NULL )MyDeleteMediaType(tmpType); + return true; + }else{ + VD->streamConf->SetFormat(tmpType); + if( tmpType != NULL )MyDeleteMediaType(tmpType); + } + + return false; +} + +// ---------------------------------------------------------------------- +// Where all the work happens! +// Attempts to build a graph for the specified device +// ---------------------------------------------------------------------- + +int videoInput::start(int deviceID, videoDevice *VD){ + + HRESULT hr = NULL; + VD->myID = deviceID; + VD->setupStarted = true; + CAPTURE_MODE = PIN_CATEGORY_CAPTURE; //Don't worry - it ends up being preview (which is faster) + callbackSetCount = 1; //make sure callback method is not changed after setup called + + if(verbose)printf("SETUP: Setting up device %i\n",deviceID); + + // CREATE THE GRAPH BUILDER // + // Create the filter graph manager and query for interfaces. + hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&VD->pCaptureGraph); + if (FAILED(hr)) // FAILED is a macro that tests the return value + { + if(verbose)printf("ERROR - Could not create the Filter Graph Manager\n"); + return hr; + } + + //FITLER GRAPH MANAGER// + // Create the Filter Graph Manager. + hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,IID_IGraphBuilder, (void**)&VD->pGraph); + if (FAILED(hr)) + { + if(verbose)printf("ERROR - Could not add the graph builder!\n"); + stopDevice(deviceID); + return hr; + } + + //SET THE FILTERGRAPH// + hr = VD->pCaptureGraph->SetFiltergraph(VD->pGraph); + if (FAILED(hr)) + { + if(verbose)printf("ERROR - Could not set filtergraph\n"); + stopDevice(deviceID); + return hr; + } + + //MEDIA CONTROL (START/STOPS STREAM)// + // Using QueryInterface on the graph builder, + // Get the Media Control object. + hr = VD->pGraph->QueryInterface(IID_IMediaControl, (void **)&VD->pControl); + if (FAILED(hr)) + { + if(verbose)printf("ERROR - Could not create the Media Control object\n"); + stopDevice(deviceID); + return hr; + } + + + //FIND VIDEO DEVICE AND ADD TO GRAPH// + //gets the device specified by the second argument. + hr = getDevice(&VD->pVideoInputFilter, deviceID, VD->wDeviceName, VD->nDeviceName); + + if (SUCCEEDED(hr)){ + if(verbose)printf("SETUP: %s\n", VD->nDeviceName); + hr = VD->pGraph->AddFilter(VD->pVideoInputFilter, VD->wDeviceName); + }else{ + if(verbose)printf("ERROR - Could not find specified video device\n"); + stopDevice(deviceID); + return hr; + } + + //LOOK FOR PREVIEW PIN IF THERE IS NONE THEN WE USE CAPTURE PIN AND THEN SMART TEE TO PREVIEW + IAMStreamConfig *streamConfTest = NULL; + hr = VD->pCaptureGraph->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, VD->pVideoInputFilter, IID_IAMStreamConfig, (void **)&streamConfTest); + if(FAILED(hr)){ + if(verbose)printf("SETUP: Couldn't find preview pin using SmartTee\n"); + }else{ + CAPTURE_MODE = PIN_CATEGORY_PREVIEW; + streamConfTest->Release(); + streamConfTest = NULL; + } + + //CROSSBAR (SELECT PHYSICAL INPUT TYPE)// + //my own function that checks to see if the device can support a crossbar and if so it routes it. + //webcams tend not to have a crossbar so this function will also detect a webcams and not apply the crossbar + if(VD->useCrossbar) + { + if(verbose)printf("SETUP: Checking crossbar\n"); + routeCrossbar(&VD->pCaptureGraph, &VD->pVideoInputFilter, VD->connection, CAPTURE_MODE); + } + + + //we do this because webcams don't have a preview mode + hr = VD->pCaptureGraph->FindInterface(&CAPTURE_MODE, &MEDIATYPE_Video, VD->pVideoInputFilter, IID_IAMStreamConfig, (void **)&VD->streamConf); + if(FAILED(hr)){ + if(verbose)printf("ERROR: Couldn't config the stream!\n"); + stopDevice(deviceID); + return hr; + } + + //NOW LETS DEAL WITH GETTING THE RIGHT SIZE + hr = VD->streamConf->GetFormat(&VD->pAmMediaType); + if(FAILED(hr)){ + if(verbose)printf("ERROR: Couldn't getFormat for pAmMediaType!\n"); + stopDevice(deviceID); + return hr; + } + + VIDEOINFOHEADER *pVih = reinterpret_cast(VD->pAmMediaType->pbFormat); + int currentWidth = HEADER(pVih)->biWidth; + int currentHeight = HEADER(pVih)->biHeight; + + bool customSize = VD->tryDiffSize; + bool foundSize = false; + + if(customSize){ + if(verbose) printf("SETUP: Default Format is set to %i by %i \n", currentWidth, currentHeight); + + char guidStr[8]; + for(int i = 0; i < VI_NUM_TYPES; i++){ + + getMediaSubtypeAsString(mediaSubtypes[i], guidStr); + + if(verbose)printf("SETUP: trying format %s @ %i by %i\n", guidStr, VD->tryWidth, VD->tryHeight); + if( setSizeAndSubtype(VD, VD->tryWidth, VD->tryHeight, mediaSubtypes[i]) ){ + VD->setSize(VD->tryWidth, VD->tryHeight); + foundSize = true; + break; + } + } + + //if we didn't find the requested size - lets try and find the closest matching size + if( foundSize == false ){ + if( verbose )printf("SETUP: couldn't find requested size - searching for closest matching size\n"); + + int closestWidth = -1; + int closestHeight = -1; + GUID newMediaSubtype; + + findClosestSizeAndSubtype(VD, VD->tryWidth, VD->tryHeight, closestWidth, closestHeight, newMediaSubtype); + + if( closestWidth != -1 && closestHeight != -1){ + getMediaSubtypeAsString(newMediaSubtype, guidStr); + + if(verbose)printf("SETUP: closest supported size is %s @ %i %i\n", guidStr, closestWidth, closestHeight); + if( setSizeAndSubtype(VD, closestWidth, closestHeight, newMediaSubtype) ){ + VD->setSize(closestWidth, closestHeight); + foundSize = true; + } + } + } + } + + //if we didn't specify a custom size or if we did but couldn't find it lets setup with the default settings + if(customSize == false || foundSize == false){ + if( VD->requestedFrameTime != -1 ){ + pVih->AvgTimePerFrame = VD->requestedFrameTime; + hr = VD->streamConf->SetFormat(VD->pAmMediaType); + } + VD->setSize(currentWidth, currentHeight); + } + + //SAMPLE GRABBER (ALLOWS US TO GRAB THE BUFFER)// + // Create the Sample Grabber. + hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,IID_IBaseFilter, (void**)&VD->pGrabberF); + if (FAILED(hr)){ + if(verbose)printf("Could not Create Sample Grabber - CoCreateInstance()\n"); + stopDevice(deviceID); + return hr; + } + + hr = VD->pGraph->AddFilter(VD->pGrabberF, L"Sample Grabber"); + if (FAILED(hr)){ + if(verbose)printf("Could not add Sample Grabber - AddFilter()\n"); + stopDevice(deviceID); + return hr; + } + + hr = VD->pGrabberF->QueryInterface(IID_ISampleGrabber, (void**)&VD->pGrabber); + if (FAILED(hr)){ + if(verbose)printf("ERROR: Could not query SampleGrabber\n"); + stopDevice(deviceID); + return hr; + } + + + //Set Params - One Shot should be false unless you want to capture just one buffer + hr = VD->pGrabber->SetOneShot(FALSE); + if(bCallback){ + hr = VD->pGrabber->SetBufferSamples(FALSE); + }else{ + hr = VD->pGrabber->SetBufferSamples(TRUE); + } + + if(bCallback){ + //Tell the grabber to use our callback function - 0 is for SampleCB and 1 for BufferCB + //We use SampleCB + hr = VD->pGrabber->SetCallback(VD->sgCallback, 0); + if (FAILED(hr)){ + if(verbose)printf("ERROR: problem setting callback\n"); + stopDevice(deviceID); + return hr; + }else{ + if(verbose)printf("SETUP: Capture callback set\n"); + } + } + + //MEDIA CONVERSION + //Get video properties from the stream's mediatype and apply to the grabber (otherwise we don't get an RGB image) + //zero the media type - lets try this :) - maybe this works? + AM_MEDIA_TYPE mt; + ZeroMemory(&mt,sizeof(AM_MEDIA_TYPE)); + + mt.majortype = MEDIATYPE_Video; + mt.subtype = MEDIASUBTYPE_RGB24; + mt.formattype = FORMAT_VideoInfo; + + //VD->pAmMediaType->subtype = VD->videoType; + hr = VD->pGrabber->SetMediaType(&mt); + + //lets try freeing our stream conf here too + //this will fail if the device is already running + if(VD->streamConf){ + VD->streamConf->Release(); + VD->streamConf = NULL; + }else{ + if(verbose)printf("ERROR: connecting device - prehaps it is already being used?\n"); + stopDevice(deviceID); + return S_FALSE; + } + + + //NULL RENDERER// + //used to give the video stream somewhere to go to. + hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)(&VD->pDestFilter)); + if (FAILED(hr)){ + if(verbose)printf("ERROR: Could not create filter - NullRenderer\n"); + stopDevice(deviceID); + return hr; + } + + hr = VD->pGraph->AddFilter(VD->pDestFilter, L"NullRenderer"); + if (FAILED(hr)){ + if(verbose)printf("ERROR: Could not add filter - NullRenderer\n"); + stopDevice(deviceID); + return hr; + } + + //RENDER STREAM// + //This is where the stream gets put together. + hr = VD->pCaptureGraph->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, VD->pVideoInputFilter, VD->pGrabberF, VD->pDestFilter); + + if (FAILED(hr)){ + if(verbose)printf("ERROR: Could not connect pins - RenderStream()\n"); + stopDevice(deviceID); + return hr; + } + + + //EXP - lets try setting the sync source to null - and make it run as fast as possible + { + IMediaFilter *pMediaFilter = 0; + hr = VD->pGraph->QueryInterface(IID_IMediaFilter, (void**)&pMediaFilter); + if (FAILED(hr)){ + if(verbose)printf("ERROR: Could not get IID_IMediaFilter interface\n"); + }else{ + pMediaFilter->SetSyncSource(NULL); + pMediaFilter->Release(); + } + } + + + //LETS RUN THE STREAM! + hr = VD->pControl->Run(); + + if (FAILED(hr)){ + if(verbose)printf("ERROR: Could not start graph\n"); + stopDevice(deviceID); + return hr; + } + + + //MAKE SURE THE DEVICE IS SENDING VIDEO BEFORE WE FINISH + if(!bCallback){ + + long bufferSize = VD->videoSize; + + while( hr != S_OK){ + hr = VD->pGrabber->GetCurrentBuffer(&bufferSize, (long *)VD->pBuffer); + Sleep(10); + } + + } + + if(verbose)printf("SETUP: Device is setup and ready to capture.\n\n"); + VD->readyToCapture = true; + + //Release filters - seen someone else do this + //looks like it solved the freezes + + //if we release this then we don't have access to the settings + //we release our video input filter but then reconnect with it + //each time we need to use it + VD->pVideoInputFilter->Release(); + VD->pVideoInputFilter = NULL; + + VD->pGrabberF->Release(); + VD->pGrabberF = NULL; + + VD->pDestFilter->Release(); + VD->pDestFilter = NULL; + + return S_OK; +} + + +// ---------------------------------------------------------------------- +// Returns number of good devices +// +// ---------------------------------------------------------------------- + +int videoInput::getDeviceCount(){ + + + ICreateDevEnum *pDevEnum = NULL; + IEnumMoniker *pEnum = NULL; + int deviceCounter = 0; + + HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, + CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, + reinterpret_cast(&pDevEnum)); + + + if (SUCCEEDED(hr)) + { + // Create an enumerator for the video capture category. + hr = pDevEnum->CreateClassEnumerator( + CLSID_VideoInputDeviceCategory, + &pEnum, 0); + + if(hr == S_OK){ + IMoniker *pMoniker = NULL; + while (pEnum->Next(1, &pMoniker, NULL) == S_OK){ + + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, + (void**)(&pPropBag)); + + if (FAILED(hr)){ + pMoniker->Release(); + continue; // Skip this one, maybe the next one will work. + } + + pPropBag->Release(); + pPropBag = NULL; + + pMoniker->Release(); + pMoniker = NULL; + + deviceCounter++; + } + + pEnum->Release(); + pEnum = NULL; + } + + pDevEnum->Release(); + pDevEnum = NULL; + } + return deviceCounter; +} + + +// ---------------------------------------------------------------------- +// Do we need this? +// +// Enumerate all of the video input devices +// Return the filter with a matching friendly name +// ---------------------------------------------------------------------- + +HRESULT videoInput::getDevice(IBaseFilter** gottaFilter, int deviceId, WCHAR * wDeviceName, char * nDeviceName){ + BOOL done = false; + int deviceCounter = 0; + + // Create the System Device Enumerator. + ICreateDevEnum *pSysDevEnum = NULL; + HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum); + if (FAILED(hr)) + { + return hr; + } + + // Obtain a class enumerator for the video input category. + IEnumMoniker *pEnumCat = NULL; + hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0); + + if (hr == S_OK) + { + // Enumerate the monikers. + IMoniker *pMoniker = NULL; + ULONG cFetched; + while ((pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) && (!done)) + { + if(deviceCounter == deviceId) + { + // Bind the first moniker to an object + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); + if (SUCCEEDED(hr)) + { + // To retrieve the filter's friendly name, do the following: + VARIANT varName; + VariantInit(&varName); + hr = pPropBag->Read(L"FriendlyName", &varName, 0); + if (SUCCEEDED(hr)) + { + + //copy the name to nDeviceName & wDeviceName + int count = 0; + while( varName.bstrVal[count] != 0x00 ) { + wDeviceName[count] = varName.bstrVal[count]; + nDeviceName[count] = (char)varName.bstrVal[count]; + count++; + } + + // We found it, so send it back to the caller + hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)gottaFilter); + done = true; + } + VariantClear(&varName); + pPropBag->Release(); + pPropBag = NULL; + pMoniker->Release(); + pMoniker = NULL; + } + } + deviceCounter++; + } + pEnumCat->Release(); + pEnumCat = NULL; + } + pSysDevEnum->Release(); + pSysDevEnum = NULL; + + if (done) { + return hr; // found it, return native error + } else { + return VFW_E_NOT_FOUND; // didn't find it error + } +} + + +// ---------------------------------------------------------------------- +// Show the property pages for a filter +// This is stolen from the DX9 SDK +// ---------------------------------------------------------------------- + +HRESULT videoInput::ShowFilterPropertyPages(IBaseFilter *pFilter){ + + ISpecifyPropertyPages *pProp; + HRESULT hr = pFilter->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pProp); + if (SUCCEEDED(hr)) + { + // Get the filter's name and IUnknown pointer. + FILTER_INFO FilterInfo; + hr = pFilter->QueryFilterInfo(&FilterInfo); + IUnknown *pFilterUnk; + pFilter->QueryInterface(IID_IUnknown, (void **)&pFilterUnk); + + // Show the page. + CAUUID caGUID; + pProp->GetPages(&caGUID); + pProp->Release(); + OleCreatePropertyFrame( + NULL, // Parent window + 0, 0, // Reserved + FilterInfo.achName, // Caption for the dialog box + 1, // Number of objects (just the filter) + &pFilterUnk, // Array of object pointers. + caGUID.cElems, // Number of property pages + caGUID.pElems, // Array of property page CLSIDs + 0, // Locale identifier + 0, NULL // Reserved + ); + + // Clean up. + if(pFilterUnk)pFilterUnk->Release(); + if(FilterInfo.pGraph)FilterInfo.pGraph->Release(); + CoTaskMemFree(caGUID.pElems); + } + return hr; +} + + +// ---------------------------------------------------------------------- +// This code was also brazenly stolen from the DX9 SDK +// Pass it a file name in wszPath, and it will save the filter graph to that file. +// ---------------------------------------------------------------------- + +HRESULT videoInput::SaveGraphFile(IGraphBuilder *pGraph, WCHAR *wszPath) { + const WCHAR wszStreamName[] = L"ActiveMovieGraph"; + HRESULT hr; + IStorage *pStorage = NULL; + + // First, create a document file which will hold the GRF file + hr = StgCreateDocfile( + wszPath, + STGM_CREATE | STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, + 0, &pStorage); + if(FAILED(hr)) + { + return hr; + } + + // Next, create a stream to store. + IStream *pStream; + hr = pStorage->CreateStream( + wszStreamName, + STGM_WRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE, + 0, 0, &pStream); + if (FAILED(hr)) + { + pStorage->Release(); + return hr; + } + + // The IPersistStream converts a stream into a persistent object. + IPersistStream *pPersist = NULL; + pGraph->QueryInterface(IID_IPersistStream, reinterpret_cast(&pPersist)); + hr = pPersist->Save(pStream, TRUE); + pStream->Release(); + pPersist->Release(); + if (SUCCEEDED(hr)) + { + hr = pStorage->Commit(STGC_DEFAULT); + } + pStorage->Release(); + return hr; +} + + +// ---------------------------------------------------------------------- +// For changing the input types +// +// ---------------------------------------------------------------------- + +HRESULT videoInput::routeCrossbar(ICaptureGraphBuilder2 **ppBuild, IBaseFilter **pVidInFilter, int conType, GUID captureMode){ + + //create local ICaptureGraphBuilder2 + ICaptureGraphBuilder2 *pBuild = NULL; + pBuild = *ppBuild; + + //create local IBaseFilter + IBaseFilter *pVidFilter = NULL; + pVidFilter = * pVidInFilter; + + // Search upstream for a crossbar. + IAMCrossbar *pXBar1 = NULL; + HRESULT hr = pBuild->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pVidFilter, + IID_IAMCrossbar, (void**)&pXBar1); + if (SUCCEEDED(hr)) + { + + bool foundDevice = false; + + if(verbose)printf("SETUP: You are not a webcam! Setting Crossbar\n"); + pXBar1->Release(); + + IAMCrossbar *Crossbar; + hr = pBuild->FindInterface(&captureMode, &MEDIATYPE_Interleaved, pVidFilter, IID_IAMCrossbar, (void **)&Crossbar); + + if(hr != NOERROR){ + hr = pBuild->FindInterface(&captureMode, &MEDIATYPE_Video, pVidFilter, IID_IAMCrossbar, (void **)&Crossbar); + } + + LONG lInpin, lOutpin; + hr = Crossbar->get_PinCounts(&lOutpin , &lInpin); + + BOOL IPin=TRUE; LONG pIndex=0 , pRIndex=0 , pType=0; + + while( pIndex < lInpin) + { + hr = Crossbar->get_CrossbarPinInfo( IPin , pIndex , &pRIndex , &pType); + + if( pType == conType){ + if(verbose)printf("SETUP: Found Physical Interface"); + + switch(conType){ + + case PhysConn_Video_Composite: + if(verbose)printf(" - Composite\n"); + break; + case PhysConn_Video_SVideo: + if(verbose)printf(" - S-Video\n"); + break; + case PhysConn_Video_Tuner: + if(verbose)printf(" - Tuner\n"); + break; + case PhysConn_Video_USB: + if(verbose)printf(" - USB\n"); + break; + case PhysConn_Video_1394: + if(verbose)printf(" - Firewire\n"); + break; + } + + foundDevice = true; + break; + } + pIndex++; + + } + + if(foundDevice){ + BOOL OPin=FALSE; LONG pOIndex=0 , pORIndex=0 , pOType=0; + while( pOIndex < lOutpin) + { + hr = Crossbar->get_CrossbarPinInfo( OPin , pOIndex , &pORIndex , &pOType); + if( pOType == PhysConn_Video_VideoDecoder) + break; + } + Crossbar->Route(pOIndex,pIndex); + }else{ + if(verbose)printf("SETUP: Didn't find specified Physical Connection type. Using Defualt. \n"); + } + + //we only free the crossbar when we close or restart the device + //we were getting a crash otherwise + //if(Crossbar)Crossbar->Release(); + //if(Crossbar)Crossbar = NULL; + + if(pXBar1)pXBar1->Release(); + if(pXBar1)pXBar1 = NULL; + + }else{ + if(verbose)printf("SETUP: You are a webcam or snazzy firewire cam! No Crossbar needed\n"); + return hr; + } + + return hr; +} + diff --git a/ThirdParty/videoInput/videoInput.h b/ThirdParty/videoInput/videoInput.h new file mode 100644 index 0000000..0284141 --- /dev/null +++ b/ThirdParty/videoInput/videoInput.h @@ -0,0 +1,385 @@ +#ifndef _VIDEOINPUT +#define _VIDEOINPUT + +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +//THE SOFTWARE. + +////////////////////////////////////////////////////////// +//Written by Theodore Watson - theo.watson@gmail.com // +//Do whatever you want with this code but if you find // +//a bug or make an improvement I would love to know! // +// // +//Warning This code is experimental // +//use at your own risk :) // +////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// +/* Shoutouts + +Thanks to: + + Dillip Kumar Kara for crossbar code. + Zachary Lieberman for getting me into this stuff + and for being so generous with time and code. + The guys at Potion Design for helping me with VC++ + Josh Fisher for being a serious C++ nerd :) + Golan Levin for helping me debug the strangest + and slowest bug in the world! + + And all the people using this library who send in + bugs, suggestions and improvements who keep me working on + the next version - yeah thanks a lot ;) + +*/ +///////////////////////////////////////////////////////// + + + +#include +#include +#include +#include +#include + +//this is for TryEnterCriticalSection +#ifndef _WIN32_WINNT + # define _WIN32_WINNT 0x400 +#endif +#include + + +//Example Usage +/* + //create a videoInput object + videoInput VI; + + //Prints out a list of available devices and returns num of devices found + int numDevices = VI.listDevices(); + + int device1 = 0; //this could be any deviceID that shows up in listDevices + int device2 = 1; //this could be any deviceID that shows up in listDevices + + //if you want to capture at a different frame rate (default is 30) + //specify it here, you are not guaranteed to get this fps though. + //VI.setIdealFramerate(dev, 60); + + //setup the first device - there are a number of options: + + VI.setupDevice(device1); //setup the first device with the default settings + //VI.setupDevice(device1, VI_COMPOSITE); //or setup device with specific connection type + //VI.setupDevice(device1, 320, 240); //or setup device with specified video size + //VI.setupDevice(device1, 320, 240, VI_COMPOSITE); //or setup device with video size and connection type + + //VI.setFormat(device1, VI_NTSC_M); //if your card doesn't remember what format it should be + //call this with the appropriate format listed above + //NOTE: must be called after setupDevice! + + //optionally setup a second (or third, fourth ...) device - same options as above + VI.setupDevice(device2); + + //As requested width and height can not always be accomodated + //make sure to check the size once the device is setup + + int width = VI.getWidth(device1); + int height = VI.getHeight(device1); + int size = VI.getSize(device1); + + unsigned char * yourBuffer1 = new unsigned char[size]; + unsigned char * yourBuffer2 = new unsigned char[size]; + + //to get the data from the device first check if the data is new + if(VI.isFrameNew(device1)){ + VI.getPixels(device1, yourBuffer1, false, false); //fills pixels as a BGR (for openCV) unsigned char array - no flipping + VI.getPixels(device1, yourBuffer2, true, true); //fills pixels as a RGB (for openGL) unsigned char array - flipping! + } + + //same applies to device2 etc + + //to get a settings dialog for the device + VI.showSettingsWindow(device1); + + + //Shut down devices properly + VI.stopDevice(device1); + VI.stopDevice(device2); +*/ + + +////////////////////////////////////// VARS AND DEFS ////////////////////////////////// + + +//STUFF YOU CAN CHANGE + +//change for verbose debug info +static bool verbose = true; + +//if you need VI to use multi threaded com +//#define VI_COM_MULTI_THREADED + +//STUFF YOU DON'T CHANGE + +//videoInput defines +#define VI_VERSION 0.1995 +#define VI_MAX_CAMERAS 20 +#define VI_NUM_TYPES 18 //DON'T TOUCH +#define VI_NUM_FORMATS 18 //DON'T TOUCH + +//defines for setPhyCon - tuner is not as well supported as composite and s-video +#define VI_COMPOSITE 0 +#define VI_S_VIDEO 1 +#define VI_TUNER 2 +#define VI_USB 3 +#define VI_1394 4 + +//defines for formats +#define VI_NTSC_M 0 +#define VI_PAL_B 1 +#define VI_PAL_D 2 +#define VI_PAL_G 3 +#define VI_PAL_H 4 +#define VI_PAL_I 5 +#define VI_PAL_M 6 +#define VI_PAL_N 7 +#define VI_PAL_NC 8 +#define VI_SECAM_B 9 +#define VI_SECAM_D 10 +#define VI_SECAM_G 11 +#define VI_SECAM_H 12 +#define VI_SECAM_K 13 +#define VI_SECAM_K1 14 +#define VI_SECAM_L 15 +#define VI_NTSC_M_J 16 +#define VI_NTSC_433 17 + + +//allows us to directShow classes here with the includes in the cpp +struct ICaptureGraphBuilder2; +struct IGraphBuilder; +struct IBaseFilter; +struct IAMCrossbar; +struct IMediaControl; +struct ISampleGrabber; +struct IMediaEventEx; +struct IAMStreamConfig; +struct _AMMediaType; +class SampleGrabberCallback; +typedef _AMMediaType AM_MEDIA_TYPE; + +//keeps track of how many instances of VI are being used +//don't touch +static int comInitCount = 0; + + +//////////////////////////////////////// VIDEO DEVICE /////////////////////////////////// + +class videoDevice{ + + + public: + + videoDevice(); + void setSize(int w, int h); + void NukeDownstream(IBaseFilter *pBF); + void destroyGraph(); + ~videoDevice(); + + int videoSize; + int width; + int height; + int tryWidth; + int tryHeight; + + ICaptureGraphBuilder2 *pCaptureGraph; // Capture graph builder object + IGraphBuilder *pGraph; // Graph builder object + IMediaControl *pControl; // Media control object + IBaseFilter *pVideoInputFilter; // Video Capture filter + IBaseFilter *pGrabberF; + IBaseFilter * pDestFilter; + IAMStreamConfig *streamConf; + ISampleGrabber * pGrabber; // Grabs frame + AM_MEDIA_TYPE * pAmMediaType; + + IMediaEventEx * pMediaEvent; + + GUID videoType; + long formatType; + + SampleGrabberCallback * sgCallback; + + bool tryDiffSize; + bool useCrossbar; + bool readyToCapture; + bool sizeSet; + bool setupStarted; + bool specificFormat; + bool autoReconnect; + int nFramesForReconnect; + unsigned long nFramesRunning; + int connection; + int storeConn; + int myID; + long requestedFrameTime; //ie fps + + char nDeviceName[255]; + WCHAR wDeviceName[255]; + + unsigned char * pixels; + char * pBuffer; + +}; + + + + +////////////////////////////////////// VIDEO INPUT ///////////////////////////////////// + + + +class videoInput{ + + public: + videoInput(); + ~videoInput(); + + //turns off console messages - default is to print messages + static void setVerbose(bool _verbose); + + //Functions in rough order they should be used. + static int listDevices(bool silent = false); + + //needs to be called after listDevices - otherwise returns NULL + static char * getDeviceName(int deviceID); + + //choose to use callback based capture - or single threaded + void setUseCallback(bool useCallback); + + //call before setupDevice + //directshow will try and get the closest possible framerate to what is requested + void setIdealFramerate(int deviceID, int idealFramerate); + + //some devices will stop delivering frames after a while - this method gives you the option to try and reconnect + //to a device if videoInput detects that a device has stopped delivering frames. + //you MUST CALL isFrameNew every app loop for this to have any effect + void setAutoReconnectOnFreeze(int deviceNumber, bool doReconnect, int numMissedFramesBeforeReconnect); + + //Choose one of these four to setup your device + bool setupDevice(int deviceID); + bool setupDevice(int deviceID, int w, int h); + + //These two are only for capture cards + //USB and Firewire cameras souldn't specify connection + bool setupDevice(int deviceID, int connection); + bool setupDevice(int deviceID, int w, int h, int connection); + + //If you need to you can set your NTSC/PAL/SECAM + //preference here. if it is available it will be used. + //see #defines above for available formats - eg VI_NTSC_M or VI_PAL_B + //should be called after setupDevice + //can be called multiple times + bool setFormat(int deviceNumber, int format); + + //Tells you when a new frame has arrived - you should call this if you have specified setAutoReconnectOnFreeze to true + bool isFrameNew(int deviceID); + + bool isDeviceSetup(int deviceID); + + //Returns the pixels - flipRedAndBlue toggles RGB/BGR flipping - and you can flip the image too + unsigned char * getPixels(int deviceID, bool flipRedAndBlue = true, bool flipImage = false); + + //Or pass in a buffer for getPixels to fill returns true if successful. + bool getPixels(int id, unsigned char * pixels, bool flipRedAndBlue = true, bool flipImage = false); + + //Launches a pop up settings window + //For some reason in GLUT you have to call it twice each time. + void showSettingsWindow(int deviceID); + + //Manual control over settings thanks..... + //These are experimental for now. + bool setVideoSettingFilter(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false); + bool setVideoSettingFilterPct(int deviceID, long Property, float pctValue, long Flags = NULL); + bool getVideoSettingFilter(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long ¤tValue, long &flags, long &defaultValue); + + bool setVideoSettingCamera(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false); + bool setVideoSettingCameraPct(int deviceID, long Property, float pctValue, long Flags = NULL); + bool getVideoSettingCamera(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long ¤tValue, long &flags, long &defaultValue); + + //bool setVideoSettingCam(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false); + + //get width, height and number of pixels + int getWidth(int deviceID); + int getHeight(int deviceID); + int getSize(int deviceID); + + //completely stops and frees a device + void stopDevice(int deviceID); + + //as above but then sets it up with same settings + bool restartDevice(int deviceID); + + //number of devices available + int devicesFound; + + long propBrightness; + long propContrast; + long propHue; + long propSaturation; + long propSharpness; + long propGamma; + long propColorEnable; + long propWhiteBalance; + long propBacklightCompensation; + long propGain; + + long propPan; + long propTilt; + long propRoll; + long propZoom; + long propExposure; + long propIris; + long propFocus; + + + private: + void setPhyCon(int deviceID, int conn); + void setAttemptCaptureSize(int deviceID, int w, int h); + bool setup(int deviceID); + void processPixels(unsigned char * src, unsigned char * dst, int width, int height, bool bRGB, bool bFlip); + int start(int deviceID, videoDevice * VD); + int getDeviceCount(); + void getMediaSubtypeAsString(GUID type, char * typeAsString); + + HRESULT getDevice(IBaseFilter **pSrcFilter, int deviceID, WCHAR * wDeviceName, char * nDeviceName); + static HRESULT ShowFilterPropertyPages(IBaseFilter *pFilter); + HRESULT SaveGraphFile(IGraphBuilder *pGraph, WCHAR *wszPath); + HRESULT routeCrossbar(ICaptureGraphBuilder2 **ppBuild, IBaseFilter **pVidInFilter, int conType, GUID captureMode); + + //don't touch + static bool comInit(); + static bool comUnInit(); + + int connection; + int callbackSetCount; + bool bCallback; + + GUID CAPTURE_MODE; + + //Extra video subtypes + GUID MEDIASUBTYPE_Y800; + GUID MEDIASUBTYPE_Y8; + GUID MEDIASUBTYPE_GREY; + + videoDevice * VDList[VI_MAX_CAMERAS]; + GUID mediaSubtypes[VI_NUM_TYPES]; + long formatTypes[VI_NUM_FORMATS]; + + static void __cdecl basicThread(void * objPtr); + + static char deviceNames[VI_MAX_CAMERAS][255]; + +}; + + #endif diff --git a/ThirdParty/websocket/include/base64.h b/ThirdParty/websocket/include/base64.h new file mode 100644 index 0000000..65d5db8 --- /dev/null +++ b/ThirdParty/websocket/include/base64.h @@ -0,0 +1,4 @@ +#include + +std::string base64_encode(unsigned char const* , unsigned int len); +std::string base64_decode(std::string const& s); diff --git a/ThirdParty/websocket/include/connection.h b/ThirdParty/websocket/include/connection.h new file mode 100644 index 0000000..e37188e --- /dev/null +++ b/ThirdParty/websocket/include/connection.h @@ -0,0 +1,120 @@ +/** + * + * filename: connection.h + * summary: websocket connection + * author: caosiyang + * email: csy3228@gmail.com + * + */ +#ifndef CONNECTION_H +#define CONNECTION_H + +#include "websocket.h" +extern "C" { + #include + #include +} +#include +using namespace std; + + +typedef void(*websocket_cb)(void*); + + +typedef struct { + websocket_cb cb; + void *cbarg; +} ws_cb_unit; + + +typedef struct websocket_connection { + struct bufferevent *bev; + string ws_req_str; + string ws_resp_str; + enum Step step; + uint64_t ntoread; + frame_t *frame; //current frame + ws_cb_unit handshake_cb_unit; + ws_cb_unit frame_recv_cb_unit; + ws_cb_unit write_cb_unit; + ws_cb_unit close_cb_unit; + ws_cb_unit ping_cb_unit; +} ws_conn_t; + + +//callback type +enum CBTYPE { + HANDSHAKE, + FRAME_RECV, + WRITE, + CLOSE, + PING +}; + + +// +// following functions are for library-users +// +//create a websocket connection +ws_conn_t *ws_conn_new(); + + +//destroy a websocket connection +void ws_conn_free(ws_conn_t *conn); + + +//set callback +//MUST set: frame_read_cb, write_cb, close_cb +void ws_conn_setcb(ws_conn_t *conn, enum CBTYPE cbtype, websocket_cb cb, void *cbarg); + + +//websocket serve start +void ws_serve_start(ws_conn_t *conn); + + +//websocket serve exit +void ws_serve_exit(ws_conn_t *conn); + + +//send a frame +int32_t send_a_frame(ws_conn_t *conn, const frame_buffer_t *fb); + + + + +// +// following functions are for internal +// +//accept the websocket request +void accept_websocket_request(ws_conn_t *conn); + + +//respond the websocket request +void respond_websocket_request(ws_conn_t *conn); + + +//receive a frame +void frame_recv_loop(ws_conn_t *conn); + + +//request read callback +void request_read_cb(struct bufferevent *bev, void *ctx); + + +//response write callback +void response_write_cb(struct bufferevent *bev, void *ctx); + + +//frame read callback +void frame_read_cb(struct bufferevent *bev, void *ctx); + + +//websocket write callback +void write_cb(struct bufferevent *bev, void *ctx); + + +//connection close callback +void close_cb(struct bufferevent *bev, short what, void *ctx); + + +#endif diff --git a/ThirdParty/websocket/include/frame.h b/ThirdParty/websocket/include/frame.h new file mode 100644 index 0000000..85dfb64 --- /dev/null +++ b/ThirdParty/websocket/include/frame.h @@ -0,0 +1,68 @@ +/** + * + * filename: frame.h + * summary: + * author: caosiyang + * email: csy3228@gmail.com + * + */ +#ifndef FRAME_H +#define FRAME_H + +#include "tools.h" +#include +using namespace std; + + +//frame buffer +typedef struct FrameBuffer { + char *data; + uint64_t len; +} frame_buffer_t; + + +//frame +typedef struct Frame { + uint8_t fin; + uint8_t opcode; + uint8_t mask; + uint64_t payload_len; + unsigned char masking_key[4]; + char *payload_data; +} frame_t; + + +frame_t *frame_new(); + + +void frame_free(frame_t *frame); + + +bool is_frame_valid(const frame_t *frame); + + +#if 0 +int32_t frame_set(frame_t *frame, + uint8_t fin, + uint8_t opcode, + uint64_t payload_len, + const char *payload_data); +#endif + + +frame_buffer_t *frame_buffer_new(uint8_t fin, + uint8_t opcode, + uint64_t payload_len, + const char *payload_data); + + +frame_buffer_t *frame_buffer_new(const frame_t *frame); + + +void frame_buffer_free(frame_buffer_t *fb); + + +void print_frame_info(const frame_buffer_t *fb); + + +#endif diff --git a/ThirdParty/websocket/include/sha1.h b/ThirdParty/websocket/include/sha1.h new file mode 100644 index 0000000..834622a --- /dev/null +++ b/ThirdParty/websocket/include/sha1.h @@ -0,0 +1,53 @@ +/* sha1.h + +Copyright (c) 2005 Michael D. Leonhard + +http://tamale.net/ + +Copyright (c) 2005 Michael D. Leonhard + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef SHA1_HEADER +typedef unsigned int Uint32; + +class SHA1 +{ + private: + // fields + Uint32 H0, H1, H2, H3, H4; + unsigned char bytes[64]; + int unprocessedBytes; + Uint32 size; + void process(); + public: + SHA1(); + ~SHA1(); + void addBytes( const char* data, int num ); + unsigned char* getDigest(); + // utility methods + static Uint32 lrot( Uint32 x, int bits ); + static void storeBigEndianUint32( unsigned char* byte, Uint32 num ); + static void hexPrinter( unsigned char* c, int l ); +}; + +#define SHA1_HEADER +#endif + diff --git a/ThirdParty/websocket/include/stdint.h b/ThirdParty/websocket/include/stdint.h new file mode 100644 index 0000000..e032ff1 --- /dev/null +++ b/ThirdParty/websocket/include/stdint.h @@ -0,0 +1,232 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#if (_MSC_VER < 1300) && defined(__cplusplus) + extern "C++" { +#endif +# include +#if (_MSC_VER < 1300) && defined(__cplusplus) + } +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/ThirdParty/websocket/include/tools.h b/ThirdParty/websocket/include/tools.h new file mode 100644 index 0000000..442110d --- /dev/null +++ b/ThirdParty/websocket/include/tools.h @@ -0,0 +1,51 @@ +/** + * + * filename: tools.h + * summary: + * author: caosiyang + * email: csy3228@gmail.com + * + */ +#ifndef TOOLS_H +#define TOOLS_H + +#include "stdint.h" + +#include +using namespace std; + + +#define LOG(format, args) fprintf(stdout, format"\n", ##args) + + +inline uint16_t myhtons(uint16_t n) { + return ((n & 0xff00) >> 8) | ((n & 0x00ff) << 8); +} + + +inline uint16_t myntohs(uint16_t n) { + return ((n & 0xff00) >> 8) | ((n & 0x00ff) << 8); +} + + +inline uint32_t myhtonl(uint32_t n) { + return ((n & 0xff000000) >> 24) | ((n & 0x00ff0000) >> 8) | ((n & 0x0000ff00) << 8) | ((n & 0x000000ff) << 24); +} + + +inline uint32_t myntohl(uint32_t n) { + return ((n & 0xff000000) >> 24) | ((n & 0x00ff0000) >> 8) | ((n & 0x0000ff00) << 8) | ((n & 0x000000ff) << 24); +} + + +inline uint64_t myhtonll(uint64_t n) { + return (uint64_t)myhtonl(n >> 32) | ((uint64_t)myhtonl(n) << 32); +} + + +inline uint64_t myntohll(uint64_t n) { + return (uint64_t)myhtonl(n >> 32) | ((uint64_t)myhtonl(n) << 32); +} + + +#endif diff --git a/ThirdParty/websocket/include/websocket.h b/ThirdParty/websocket/include/websocket.h new file mode 100644 index 0000000..203a949 --- /dev/null +++ b/ThirdParty/websocket/include/websocket.h @@ -0,0 +1,85 @@ +/** + * + * filename: websocket.h + * summary: + * author: caosiyang + * email: csy3228@gmail.com + * + */ +#ifndef WEBSOCKET_H +#define WEBSOCKET_H + +#include "tools.h" +#include "frame.h" +#include "sha1.h" +#include "base64.h" +#include +#include +#include +using namespace std; + + +//WebSocket request +typedef struct WebsocketRequest { + string req; + string connection; + string upgrade; + string host; + string origin; + string cookie; + string sec_websocket_key; + string sec_websocket_version; +} ws_req_t; + + +//WebSocket response +typedef struct WebsocketResponse { + string resp; + string date; + string connection; + string server; + string upgrade; + string access_control_allow_origin; + string access_control_allow_credentials; + string sec_websocket_accept; + string access_control_allow_headers; +} ws_resp_t; + + +//steps of receiving a frame +enum Step { + ZERO, //before websocket handshake + ONE, //0-2 bytes, fin, opcode, mask, payload length + TWO, //extended payload length + THREE, //masking-key + FOUR, //payload data + UNKNOWN +}; + + +//parse websocket request +int32_t parse_websocket_request(const char *src, ws_req_t *ws_req); + + +//print websocket request +void print_websocket_request(const ws_req_t *ws_req); + + +//generate websocket response +string generate_websocket_response(const ws_req_t *ws_req); + + +//generate websocket key +string generate_key(const string &key); + + +//parse fin, opcode, mask, payload len +int32_t parse_frame_header(const char *buf, frame_t *frame); + + +//unmask payload-data +int32_t unmask_payload_data(frame_t *frame); +int32_t unmask_payload_data(const char *masking_key, char *payload_data, uint32_t payload_len); + + +#endif diff --git a/ThirdParty/websocket/src/base64.cpp b/ThirdParty/websocket/src/base64.cpp new file mode 100644 index 0000000..aa25878 --- /dev/null +++ b/ThirdParty/websocket/src/base64.cpp @@ -0,0 +1,123 @@ +/* + base64.cpp and base64.h + + Copyright (C) 2004-2008 René Nyffenegger + + This source code is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this source code must not be misrepresented; you must not + claim that you wrote the original source code. If you use this source code + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original source code. + + 3. This notice may not be removed or altered from any source distribution. + + René Nyffenegger rene.nyffenegger@adp-gmbh.ch + +*/ + +#include "base64.h" +#include + +static const std::string base64_chars = +"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +"abcdefghijklmnopqrstuvwxyz" +"0123456789+/"; + + +static inline bool is_base64(unsigned char c) { + return (isalnum(c) || (c == '+') || (c == '/')); +} + +std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { + std::string ret; + int i = 0; + int j = 0; + unsigned char char_array_3[3]; + unsigned char char_array_4[4]; + + while (in_len--) { + char_array_3[i++] = *(bytes_to_encode++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for(i = 0; (i <4) ; i++) + ret += base64_chars[char_array_4[i]]; + i = 0; + } + } + + if (i) + { + for(j = i; j < 3; j++) + char_array_3[j] = '\0'; + + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (j = 0; (j < i + 1); j++) + ret += base64_chars[char_array_4[j]]; + + while((i++ < 3)) + ret += '='; + + } + + return ret; + +} + +std::string base64_decode(std::string const& encoded_string) { + int in_len = encoded_string.size(); + int i = 0; + int j = 0; + int in_ = 0; + unsigned char char_array_4[4], char_array_3[3]; + std::string ret; + + while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { + char_array_4[i++] = encoded_string[in_]; in_++; + if (i ==4) { + for (i = 0; i <4; i++) + char_array_4[i] = base64_chars.find(char_array_4[i]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (i = 0; (i < 3); i++) + ret += char_array_3[i]; + i = 0; + } + } + + if (i) { + for (j = i; j <4; j++) + char_array_4[j] = 0; + + for (j = 0; j <4; j++) + char_array_4[j] = base64_chars.find(char_array_4[j]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; + } + + return ret; +} diff --git a/ThirdParty/websocket/src/connection.cpp b/ThirdParty/websocket/src/connection.cpp new file mode 100644 index 0000000..7ff8722 --- /dev/null +++ b/ThirdParty/websocket/src/connection.cpp @@ -0,0 +1,391 @@ +#include "connection.h" + + +//create a websocket connection +ws_conn_t *ws_conn_new() { + ws_conn_t *conn = new (nothrow) ws_conn_t; + if (conn) { + conn->bev = NULL; + conn->ws_req_str = ""; + conn->ws_resp_str = ""; + conn->step = ZERO; + conn->ntoread = 0; + conn->frame = frame_new(); + conn->handshake_cb_unit.cb = NULL; + conn->handshake_cb_unit.cbarg = NULL; + conn->frame_recv_cb_unit.cb = NULL; + conn->frame_recv_cb_unit.cbarg = NULL; + conn->write_cb_unit.cb = NULL; + conn->write_cb_unit.cbarg = NULL; + conn->close_cb_unit.cb = NULL; + conn->close_cb_unit.cbarg = NULL; + conn->ping_cb_unit.cb = NULL; + conn->ping_cb_unit.cbarg = NULL; + } + return conn; +} + + +//destroy a websocket connection +void ws_conn_free(ws_conn_t *conn) { + if (conn) { + if (conn->frame) { + frame_free(conn->frame); + conn->frame = NULL; + } + delete conn; + } +} + + +//websocket serve start +void ws_serve_start(ws_conn_t *conn) { + if (conn && conn->bev) { + accept_websocket_request(conn); + } else { + ws_serve_exit(conn); + } +} + + +//websocket serve exit +void ws_serve_exit(ws_conn_t *conn) { + if (conn) { + if (conn->close_cb_unit.cb) { + websocket_cb cb = conn->close_cb_unit.cb; + void *cbarg = conn->close_cb_unit.cbarg; + cb(cbarg); + } + } +} + + +//accept the websocket request +void accept_websocket_request(ws_conn_t *conn) { + if (conn && conn->bev) { + //read websocket request + bufferevent_setcb(conn->bev, request_read_cb, response_write_cb, close_cb, conn); + bufferevent_setwatermark(conn->bev, EV_READ, 1, 1); + bufferevent_setwatermark(conn->bev, EV_WRITE, 0, 0); + bufferevent_enable(conn->bev, EV_READ); + } else { + ws_serve_exit(conn); + } +} + + +//respond the websocket request +void respond_websocket_request(ws_conn_t *conn) { + if (conn && conn->bev) { + ws_req_t ws_req; + parse_websocket_request(conn->ws_req_str.c_str(), &ws_req); //parse request + //TODO + //check if it is a websocket request + //if (!valid) { + // ws_serve_exit(conn); + // return; + //} + conn->ws_resp_str = generate_websocket_response(&ws_req); //generate response + if (!conn->ws_resp_str.empty()) { + bufferevent_write(conn->bev, conn->ws_resp_str.c_str(), conn->ws_resp_str.length()); + } else { + ws_serve_exit(conn); + } + } else { + ws_serve_exit(conn); + } +} + + +//request read callback +void request_read_cb(struct bufferevent *bev, void *ctx) { + ws_conn_t *conn = (ws_conn_t*)ctx; + if (conn && conn->bev) { + char c; + bufferevent_read(bev, &c, 1); + conn->ws_req_str += c; + size_t n = conn->ws_req_str.size(); + //TODO + //for security + //if (n > MAX_WS_REQ_LEN) { + // ws_serve_exit(); + //} + + //receive request completely + if (n >= 4 && conn->ws_req_str.substr(n - 4) == "\r\n\r\n") { + bufferevent_disable(conn->bev, EV_READ); //stop reading before a valid handshake + respond_websocket_request(conn); //send websocket response + } + } else { + ws_serve_exit(conn); + } +} + + +//response write callback +void response_write_cb(struct bufferevent *bev, void *ctx) { + ws_conn_t *conn = (ws_conn_t*)ctx; + if (conn && conn->bev) { + if (conn->handshake_cb_unit.cb) { + websocket_cb cb = conn->handshake_cb_unit.cb; + void *cbarg = conn->handshake_cb_unit.cbarg; + cb(cbarg); + } + LOG("%s", conn->ws_req_str.c_str()); + LOG("%s", conn->ws_resp_str.c_str()); + + frame_recv_loop(conn); //frame receive loop + } else { + ws_serve_exit(conn); + } +} + + +//send a frame +inline int32_t send_a_frame(ws_conn_t *conn, const frame_buffer_t *fb) { + return bufferevent_write(conn->bev, fb->data, fb->len) == fb->len ? 0 : -1; +} + + +void frame_recv_loop(ws_conn_t *conn) { + if (conn && conn->bev) { + conn->step = ONE; + conn->ntoread = 2; + bufferevent_setcb(conn->bev, frame_read_cb, write_cb, close_cb, conn); + bufferevent_setwatermark(conn->bev, EV_READ, conn->ntoread, conn->ntoread); + bufferevent_setwatermark(conn->bev, EV_WRITE, 0, 0); + bufferevent_enable(conn->bev, EV_READ); + } else { + ws_serve_exit(conn); + } +} + + +void frame_read_cb(struct bufferevent *bev, void *ctx) { + ws_conn_t *conn = (ws_conn_t*)ctx; + if (!conn || !conn->bev) { + ws_serve_exit(conn); + return; + } + + switch (conn->step) { + case ONE: + { + LOG("---- STEP 1 ----", ""); + char * tmp = new char[conn->ntoread]; + bufferevent_read(bev, tmp, conn->ntoread); + //parse header + if (parse_frame_header(tmp, conn->frame) == 0) { + LOG("FIN = %lu", conn->frame->fin); + LOG("OPCODE = %lu", conn->frame->opcode); + LOG("MASK = %lu", conn->frame->mask); + LOG("PAYLOAD_LEN = %lu", conn->frame->payload_len); + //payload_len is [0, 127] + if (conn->frame->payload_len <= 125) { + conn->step = THREE; + conn->ntoread = 4; + bufferevent_setwatermark(bev, EV_READ, conn->ntoread, conn->ntoread); + } else if (conn->frame->payload_len == 126) { + conn->step = TWO; + conn->ntoread = 2; + bufferevent_setwatermark(bev, EV_READ, conn->ntoread, conn->ntoread); + } else if (conn->frame->payload_len == 127) { + conn->step = TWO; + conn->ntoread = 8; + bufferevent_setwatermark(bev, EV_READ, conn->ntoread, conn->ntoread); + } + } + //TODO + //validate frame header + if (!is_frame_valid(conn->frame)) { + return; + } + delete[] tmp; + break; + } + + case TWO: + { + LOG("---- STEP 2 ----", ""); + char * tmp = new char[conn->ntoread]; + bufferevent_read(bev, tmp, conn->ntoread); + if (conn->frame->payload_len == 126) { + conn->frame->payload_len = ntohs(*(uint16_t*)tmp); + LOG("PAYLOAD_LEN = %lu", conn->frame->payload_len); + } else if (conn->frame->payload_len == 127) { + conn->frame->payload_len = myntohll(*(uint64_t*)tmp); + LOG("PAYLOAD_LEN = %llu", conn->frame->payload_len); + } + conn->step = THREE; + conn->ntoread = 4; + bufferevent_setwatermark(bev, EV_READ, conn->ntoread, conn->ntoread); + delete[] tmp; + break; + } + + case THREE: + { + LOG("---- STEP 3 ----", ""); + char * tmp = new char[conn->ntoread]; + bufferevent_read(bev, tmp, conn->ntoread); + memcpy(conn->frame->masking_key, tmp, conn->ntoread); + if (conn->frame->payload_len > 0) { + conn->step = FOUR; + conn->ntoread = conn->frame->payload_len; + bufferevent_setwatermark(bev, EV_READ, conn->ntoread, conn->ntoread); + } else if (conn->frame->payload_len == 0) { + /*recv a whole frame*/ + if (conn->frame->mask == 0) { + //recv an unmasked frame + } + if (conn->frame->fin == 1 && conn->frame->opcode == 0x8) { + //0x8 denotes a connection close + frame_buffer_t *fb = frame_buffer_new(1, 8, 0, NULL); + send_a_frame(conn, fb); + LOG("send a close frame", ""); + frame_buffer_free(fb); + +#if 0 + if (conn->conn_close_cb_unit.cb) { + websocket_cb cb = conn->conn_close_cb_unit.cb; + void *cbarg = conn->conn_close_cb_unit.cbarg; + cb(cbarg); + } else { + //bufferevent_disable(conn->bev, EV_READ | EV_WRITE); + } +#endif + break; + } else if (conn->frame->fin == 1 && conn->frame->opcode == 0x9) { + //0x9 denotes a ping + //TODO + //make a pong + } else { + //execute custom operation + if (conn->frame_recv_cb_unit.cb) { + websocket_cb cb = conn->frame_recv_cb_unit.cb; + void *cbarg = conn->frame_recv_cb_unit.cbarg; + cb(cbarg); + } + } + + conn->step = ONE; + conn->ntoread = 2; + bufferevent_setwatermark(bev, EV_READ, conn->ntoread, conn->ntoread); + } + delete[] tmp; + break; + } + + case FOUR: + { + LOG("---- STEP 4 ----", ""); + if (conn->frame->payload_len > 0) { + if (conn->frame->payload_data) { + delete[] conn->frame->payload_data; + conn->frame->payload_data = NULL; + } + conn->frame->payload_data = new char[conn->frame->payload_len]; + bufferevent_read(bev, conn->frame->payload_data, conn->frame->payload_len); + unmask_payload_data(conn->frame); + } + + + /*recv a whole frame*/ + if (conn->frame->fin == 1 && conn->frame->opcode == 0x8) { + //0x8 denotes a connection close + frame_buffer_t *fb = frame_buffer_new(1, 8, 0, NULL); + send_a_frame(conn, fb); + LOG("send a close frame", ""); + frame_buffer_free(fb); + +#if 0 + if (conn->conn_close_cb_unit.cb) { + websocket_cb cb = conn->conn_close_cb_unit.cb; + void *cbarg = conn->conn_close_cb_unit.cbarg; + cb(cbarg); + } else { + //bufferevent_disable(conn->bev, EV_READ | EV_WRITE); + } +#endif + break; + } else if (conn->frame->fin == 1 && conn->frame->opcode == 0x9) { + //0x9 denotes a ping + //TODO + //make a pong + } else { + //execute custom operation + if (conn->frame_recv_cb_unit.cb) { + websocket_cb cb = conn->frame_recv_cb_unit.cb; + void *cbarg = conn->frame_recv_cb_unit.cbarg; + cb(cbarg); + } + } + + + if (conn->frame->opcode == 0x1) { //0x1 denotes a text frame + } + if (conn->frame->opcode == 0x2) { //0x1 denotes a binary frame + } + + + conn->step = ONE; + conn->ntoread = 2; + bufferevent_setwatermark(bev, EV_READ, conn->ntoread, conn->ntoread); + break; + } + + default: + LOG("---- STEP UNKNOWN ----", ""); + LOG("exit", ""); + exit(-1); + break; + } + +} + + +void ws_conn_setcb(ws_conn_t *conn, enum CBTYPE cbtype, websocket_cb cb, void *cbarg) { + if (conn) { + switch (cbtype) { + case HANDSHAKE: + conn->handshake_cb_unit.cb = cb; + conn->handshake_cb_unit.cbarg = cbarg; + break; + case FRAME_RECV: + conn->frame_recv_cb_unit.cb = cb; + conn->frame_recv_cb_unit.cbarg = cbarg; + break; + case WRITE: + conn->write_cb_unit.cb = cb; + conn->write_cb_unit.cbarg = cbarg; + break; + case CLOSE: + conn->close_cb_unit.cb = cb; + conn->close_cb_unit.cbarg = cbarg; + break; + case PING: + conn->ping_cb_unit.cb = cb; + conn->ping_cb_unit.cbarg = cbarg; + break; + default: + break; + } + } +} + + +void write_cb(struct bufferevent *bev, void *ctx) { + ws_conn_t *conn = (ws_conn_t*)ctx; + if (conn) { + if (conn->write_cb_unit.cb) { + websocket_cb cb = conn->write_cb_unit.cb; + void *cbarg = conn->write_cb_unit.cbarg; + cb(cbarg); + } + } +} + + +void close_cb(struct bufferevent *bev, short what, void *ctx) { + ws_serve_exit((ws_conn_t*)ctx); +} diff --git a/ThirdParty/websocket/src/frame.cpp b/ThirdParty/websocket/src/frame.cpp new file mode 100644 index 0000000..e7aab88 --- /dev/null +++ b/ThirdParty/websocket/src/frame.cpp @@ -0,0 +1,211 @@ +#include "frame.h" + + +frame_t *frame_new() { + frame_t *frame = new (nothrow) frame_t; + if (frame) { + memset(frame, 0, sizeof(frame_t)); + } + return frame; +} + + +void frame_free(frame_t *frame) { + if (frame) { + if (frame->payload_data) { + delete[] frame->payload_data; + } + delete frame; + } +} + + +bool is_frame_valid(const frame_t *frame) { + if (frame && frame->fin <= 1 && frame->opcode <= 0xf && frame->mask == 1) { + return true; + } + return false; +} + + +#if 0 +int32_t frame_set(frame_t *frame, uint8_t fin, uint8_t opcode, uint64_t payload_len, const char *payload_data) { + if (!frame || fin > 1 || opcode > 0xf) { + return -1; + } + + frame->fin = fin; + frame->opcode = opcode; + frame->mask = 0; + if (payload_data && payload_len > 0) { + frame->payload_len = payload_len; + frame->payload_data = new char[payload_len]; + memcpy(frame->payload_data, payload_data, payload_len); + } else { + frame->payload_len = 0; + frame->payload_data = NULL; + } + return 0; +} +#endif + + +frame_buffer_t *frame_buffer_new(uint8_t fin, uint8_t opcode, uint64_t payload_len, const char *payload_data) { + if (fin > 1 || opcode > 0xf) { + return NULL; + } + + uint8_t mask = 0; //must not mask at server endpoint + char masking_key[4] = {0}; //no need at server endpoint + + char *p = NULL; //buffer + uint64_t len = 0; //buffer length + + unsigned char c1 = 0x00; + unsigned char c2 = 0x00; + c1 = c1 | (fin << 7); //set fin + c1 = c1 | opcode; //set opcode + c2 = c2 | (mask << 7); //set mask + + if (!payload_data || payload_len == 0) { + if (mask == 0) { + p = new char[2]; + *p = c1; + *(p + 1) = c2; + len = 2; + } else { + p = new char[2 + 4]; + *p = c1; + *(p + 1) = c2; + memcpy(p + 2, masking_key, 4); + len = 2 + 4; + } + } else if (payload_data && payload_len <= 125) { + if (mask == 0) { + p = new char[2 + payload_len]; + *p = c1; + *(p + 1) = c2 + payload_len; + memcpy(p + 2, payload_data, payload_len); + len = 2 + payload_len; + } else { + p = new char[2 + 4 + payload_len]; + *p = c1; + *(p + 1) = c2 + payload_len; + memcpy(p + 2, masking_key, 4); + memcpy(p + 6, payload_data, payload_len); + len = 2 + 4 + payload_len; + } + } else if (payload_data && payload_len >= 126 && payload_len <= 65535) { + if (mask == 0) { + p = new char[4 + payload_len]; + *p = c1; + *(p + 1) = c2 + 126; + uint16_t tmplen = myhtons((uint16_t)payload_len); + memcpy(p + 2, &tmplen, 2); + memcpy(p + 4, payload_data, payload_len); + len = 4 + payload_len; + } else { + p = new char[4 + 4 + payload_len]; + *p = c1; + *(p + 1) = c2 + 126; + uint16_t tmplen = myhtons((uint16_t)payload_len); + memcpy(p + 2, &tmplen, 2); + memcpy(p + 4, masking_key, 4); + memcpy(p + 8, payload_data, payload_len); + len = 4 + 4 + payload_len; + } + } else if (payload_data && payload_len >= 65536) { + if (mask == 0) { + p = new char[10 + payload_len]; + *p = c1; + *(p + 1) = c2 + 127; + uint64_t tmplen = myhtonll(payload_len); + memcpy(p + 2, &tmplen, 8); + memcpy(p + 10, payload_data, payload_len); + len = 10 + payload_len; + } else { + p = new char[10 + 4 + payload_len]; + *p = c1; + *(p + 1) = c2 + 127; + uint64_t tmplen = myhtonll(payload_len); + memcpy(p + 2, &tmplen, 8); + memcpy(p + 10, masking_key, 4); + memcpy(p + 14, payload_data, payload_len); + len = 10 + 4 + payload_len; + } + } + + frame_buffer_t *fb = NULL; + if (p && len > 0) { + fb = new (nothrow) frame_buffer_t; + if (fb) { + fb->data = p; + fb->len = len; + } + } + return fb; +} + + +frame_buffer_t *frame_buffer_new(const frame_t *frame) { + if (!frame || frame->fin > 1 || frame->opcode > 0xf || frame->mask > 1) { + return NULL; + } + frame_buffer_t *fb = frame_buffer_new(frame->fin, frame->opcode, frame->payload_len, frame->payload_data); + return fb; +} + + +void frame_buffer_free(frame_buffer_t *fb) { + if (fb) { + if (fb->data) { + delete[] fb->data; + } + delete fb; + } +} + + +void print_frame_info(const frame_buffer_t *fb) { + if (!fb || !fb->data) { + return; + } + LOG("--------------------", ""); + char *p = fb->data; + uint8_t fin = 0, opcode = 0, mask = 0; + uint64_t payload_len = 0; + fin = (*(uint8_t*)p) >> 7; + opcode = (*(uint8_t*)p) & 0x0f; + mask = (*(uint8_t*)(p + 1)) >> 7; + payload_len = (*(uint8_t*)(p + 1)) & 0x7f; + char *tmp = NULL; + if (payload_len == 0) { + } else if (payload_len <= 125) { + tmp = new char[payload_len + 1]; + tmp[payload_len] = 0; + memcpy(tmp, p + 2, payload_len); + } else if (payload_len == 126) { + LOG("126", ""); + payload_len = myntohs(*(uint16_t*)(p + 2)); + tmp = new char[payload_len + 1]; + tmp[payload_len] = 0; + memcpy(tmp, p + 2 + 2, payload_len); + } else if (payload_len == 127) { + LOG("127", ""); + payload_len = myntohll(*(uint64_t*)(p + 2)); + tmp = new char[payload_len + 1]; + tmp[payload_len] = 0; + memcpy(tmp, p + 2 + 8, payload_len); + } + LOG("fin = %lu", fin); + LOG("opcode = %lu", opcode); + LOG("mask = %lu", mask); + LOG("payload_len = %lu", payload_len); + if (tmp) { + LOG("payload = \n%s", tmp); + delete[] tmp; + } else { + LOG("payload = NULL", ""); + } + LOG("--------------------", ""); +} diff --git a/ThirdParty/websocket/src/sha1.cpp b/ThirdParty/websocket/src/sha1.cpp new file mode 100644 index 0000000..3676a43 --- /dev/null +++ b/ThirdParty/websocket/src/sha1.cpp @@ -0,0 +1,209 @@ +/* sha1.cpp + +Copyright (c) 2005 Michael D. Leonhard + +http://tamale.net/ + +Copyright (c) 2005 Michael D. Leonhard + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include +#include +#include +#include + +#include "sha1.h" + +// print out memory in hexadecimal +void SHA1::hexPrinter( unsigned char* c, int l ) +{ + assert( c ); + assert( l > 0 ); + while( l > 0 ) + { + printf( " %02x", *c ); + l--; + c++; + } +} + +// circular left bit rotation. MSB wraps around to LSB +Uint32 SHA1::lrot( Uint32 x, int bits ) +{ + return (x<>(32 - bits)); +}; + +// Save a 32-bit unsigned integer to memory, in big-endian order +void SHA1::storeBigEndianUint32( unsigned char* byte, Uint32 num ) +{ + assert( byte ); + byte[0] = (unsigned char)(num>>24); + byte[1] = (unsigned char)(num>>16); + byte[2] = (unsigned char)(num>>8); + byte[3] = (unsigned char)num; +} + + +// Constructor ******************************************************* +SHA1::SHA1() +{ + // make sure that the data type is the right size + assert( sizeof( Uint32 ) * 5 == 20 ); + + // initialize + H0 = 0x67452301; + H1 = 0xefcdab89; + H2 = 0x98badcfe; + H3 = 0x10325476; + H4 = 0xc3d2e1f0; + unprocessedBytes = 0; + size = 0; +} + +// Destructor ******************************************************** +SHA1::~SHA1() +{ + // erase data + H0 = H1 = H2 = H3 = H4 = 0; + for( int c = 0; c < 64; c++ ) bytes[c] = 0; + unprocessedBytes = size = 0; +} + +// process *********************************************************** +void SHA1::process() +{ + assert( unprocessedBytes == 64 ); + //printf( "process: " ); hexPrinter( bytes, 64 ); printf( "\n" ); + int t; + Uint32 a, b, c, d, e, K, f, W[80]; + // starting values + a = H0; + b = H1; + c = H2; + d = H3; + e = H4; + // copy and expand the message block + for( t = 0; t < 16; t++ ) W[t] = (bytes[t*4] << 24) + +(bytes[t*4 + 1] << 16) + +(bytes[t*4 + 2] << 8) + + bytes[t*4 + 3]; + for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 ); + + /* main loop */ + Uint32 temp; + for( t = 0; t < 80; t++ ) + { + if( t < 20 ) { + K = 0x5a827999; + f = (b & c) | ((b ^ 0xFFFFFFFF) & d);//TODO: try using ~ + } else if( t < 40 ) { + K = 0x6ed9eba1; + f = b ^ c ^ d; + } else if( t < 60 ) { + K = 0x8f1bbcdc; + f = (b & c) | (b & d) | (c & d); + } else { + K = 0xca62c1d6; + f = b ^ c ^ d; + } + temp = lrot(a,5) + f + e + W[t] + K; + e = d; + d = c; + c = lrot(b,30); + b = a; + a = temp; + //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e ); + } + /* add variables */ + H0 += a; + H1 += b; + H2 += c; + H3 += d; + H4 += e; + //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 ); + /* all bytes have been processed */ + unprocessedBytes = 0; +} + +// addBytes ********************************************************** +void SHA1::addBytes( const char* data, int num ) +{ + assert( data ); + assert( num > 0 ); + // add these bytes to the running total + size += num; + // repeat until all data is processed + while( num > 0 ) + { + // number of bytes required to complete block + int needed = 64 - unprocessedBytes; + assert( needed > 0 ); + // number of bytes to copy (use smaller of two) + int toCopy = (num < needed) ? num : needed; + // Copy the bytes + memcpy( bytes + unprocessedBytes, data, toCopy ); + // Bytes have been copied + num -= toCopy; + data += toCopy; + unprocessedBytes += toCopy; + + // there is a full block + if( unprocessedBytes == 64 ) process(); + } +} + +// digest ************************************************************ +unsigned char* SHA1::getDigest() +{ + // save the message size + Uint32 totalBitsL = size << 3; + Uint32 totalBitsH = size >> 29; + // add 0x80 to the message + addBytes( "\x80", 1 ); + + unsigned char footer[64] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + // block has no room for 8-byte filesize, so finish it + if( unprocessedBytes > 56 ) + addBytes( (char*)footer, 64 - unprocessedBytes); + assert( unprocessedBytes <= 56 ); + // how many zeros do we need + int neededZeros = 56 - unprocessedBytes; + // store file size (in bits) in big-endian format + storeBigEndianUint32( footer + neededZeros , totalBitsH ); + storeBigEndianUint32( footer + neededZeros + 4, totalBitsL ); + // finish the final block + addBytes( (char*)footer, neededZeros + 8 ); + // allocate memory for the digest bytes + unsigned char* digest = (unsigned char*)malloc( 20 ); + // copy the digest bytes + storeBigEndianUint32( digest, H0 ); + storeBigEndianUint32( digest + 4, H1 ); + storeBigEndianUint32( digest + 8, H2 ); + storeBigEndianUint32( digest + 12, H3 ); + storeBigEndianUint32( digest + 16, H4 ); + // return the digest + return digest; +} + diff --git a/ThirdParty/websocket/src/websocket.cpp b/ThirdParty/websocket/src/websocket.cpp new file mode 100644 index 0000000..699d9af --- /dev/null +++ b/ThirdParty/websocket/src/websocket.cpp @@ -0,0 +1,153 @@ +#include "websocket.h" + +int32_t parse_websocket_request(const char *s_req, ws_req_t *ws_req) { + if (!s_req || !ws_req) { + return -1; + } + int len = strlen(s_req); + char * tmp = new char[len + 1]; + tmp[len] = 0; + memcpy(tmp, s_req, len); + + char *delim = "\r\n"; + char *p = NULL, *q = NULL; + + p = strtok(tmp, delim); + if (p) { + //printf("%s\n", p); + ws_req->req = p; + while (p = strtok(NULL, delim)) { + //printf("%s\n", p); + if ((q = strstr(p, ":")) != NULL) { + *q = '\0'; + if (_stricmp(p, "Connection") == 0) { + while (*++q == ' '); + ws_req->connection = q; + } + if (_stricmp(p, "Upgrade") == 0) { + while (*++q == ' '); + ws_req->upgrade = q; + } + if (_stricmp(p, "Host") == 0) { + while (*++q == ' '); + ws_req->host = q + 1; + } + if (_stricmp(p, "Origin") == 0) { + while (*++q == ' '); + ws_req->origin = q; + } + if (_stricmp(p, "Cookie") == 0) { + while (*++q == ' '); + ws_req->cookie = q; + } + if (_stricmp(p, "Sec-WebSocket-Key") == 0) { + while (*++q == ' '); + ws_req->sec_websocket_key = q; + } + if (_stricmp(p, "Sec-WebSocket-Version") == 0) { + while (*++q == ' '); + ws_req->sec_websocket_version = q; + } + } + } + } + delete[] tmp; + return 0; +} + + +void print_websocket_request(const ws_req_t *ws_req) { + if (ws_req) { + if (!ws_req->req.empty()) { + fprintf(stdout, "%s\r\n", ws_req->req.c_str()); + } + if (!ws_req->connection.empty()) { + fprintf(stdout, "Connection: %s\r\n", ws_req->connection.c_str()); + } + if (!ws_req->upgrade.empty()) { + fprintf(stdout, "Upgrade: %s\r\n", ws_req->upgrade.c_str()); + } + if (!ws_req->host.empty()) { + fprintf(stdout, "Host: %s\r\n", ws_req->host.c_str()); + } + if (!ws_req->origin.empty()) { + fprintf(stdout, "Origin: %s\r\n", ws_req->origin.c_str()); + } + if (!ws_req->cookie.empty()) { + fprintf(stdout, "Cookie: %s\r\n", ws_req->cookie.c_str()); + } + if (!ws_req->sec_websocket_key.empty()) { + fprintf(stdout, "Sec-WebSocket-Key: %s\r\n", ws_req->sec_websocket_key.c_str()); + } + if (!ws_req->sec_websocket_version.empty()) { + fprintf(stdout, "Sec-WebSocket-Version: %s\r\n", ws_req->sec_websocket_version.c_str()); + } + fprintf(stdout, "\r\n"); + } +} + + +string generate_websocket_response(const ws_req_t *ws_req) { + string resp; + if (ws_req) { + resp += "HTTP/1.1 101 WebSocket Protocol HandShake\r\n"; + resp += "Connection: Upgrade\r\n"; + resp += "Upgrade: WebSocket\r\n"; + resp += "Server: WebChat Demo Server\r\n"; + resp += "Sec-WebSocket-Accept: " + generate_key(ws_req->sec_websocket_key) + "\r\n"; + resp += "\r\n"; + } + return resp; +} + + +string generate_key(const string &key) { + //sha-1 + string tmp = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + unsigned char md[20] = {0}; + SHA1 sha; + sha.addBytes(tmp.c_str(), tmp.length()); + + //base64 encode + unsigned char * digest = sha.getDigest(); + string res = base64_encode(digest, 20); + delete [] digest; + + return res; +} + + +int32_t parse_frame_header(const char *buf, frame_t *frame) { + if (!buf || !frame) { + return -1; + } + unsigned char c1 = *buf; + unsigned char c2 = *(buf + 1); + frame->fin = (c1 >> 7) & 0xff; + frame->opcode = c1 & 0x0f; + frame->mask = (c2 >> 7) & 0xff; + frame->payload_len = c2 & 0x7f; + return 0; +} + + +int32_t unmask_payload_data(frame_t *frame) { + if (frame && frame->payload_data && frame->payload_len > 0) { + for (int32_t i = 0; i < frame->payload_len; ++i) { + *(frame->payload_data + i) = *(frame->payload_data + i) ^ *(frame->masking_key + i % 4); + } + return 0; + } + return -1; +} + + +int32_t unmask_payload_data(const char *masking_key, char *payload_data, uint32_t payload_len) { + if (!masking_key || !payload_data || payload_len == 0) { + return -1; + } + for (int32_t i = 0; i < payload_len; ++i) { + *(payload_data + i) = *(payload_data + i) ^ *(masking_key + i % 4); + } + return 0; +} diff --git a/ThirdParty/wxJSON/include/wx/json_defs.h b/ThirdParty/wxJSON/include/wx/json_defs.h new file mode 100644 index 0000000..1576f3c --- /dev/null +++ b/ThirdParty/wxJSON/include/wx/json_defs.h @@ -0,0 +1,212 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: json_defs.h +// Purpose: shared build defines +// Author: Luciano Cattani +// Created: 2007/10/20 +// RCS-ID: $Id: json_defs.h,v 1.6 2008/03/12 10:48:19 luccat Exp $ +// Copyright: (c) 2007 Luciano Cattani +// Licence: wxWidgets licence +///////////////////////////////////////////////////////////////////////////// + + +#ifndef _WX_JSON_DEFS_H_ +#define _WX_JSON_DEFS_H_ + +// Defines for component version. +// The following symbols should be updated for each new component release +// since some kind of tests, like those of AM_WXCODE_CHECKFOR_COMPONENT_VERSION() +// for "configure" scripts under unix, use them. +#define wxJSON_MAJOR 1 +#define wxJSON_MINOR 2 +#define wxJSON_RELEASE 1 + +// For non-Unix systems (i.e. when building without a configure script), +// users of this component can use the following macro to check if the +// current version is at least major.minor.release +#define wxCHECK_JSON_VERSION(major,minor,release) \ + (wxJSON_MAJOR > (major) || \ + (wxJSON_MAJOR == (major) && wxJSON_MINOR > (minor)) || \ + (wxJSON_MAJOR == (major) && wxJSON_MINOR == (minor) && wxJSON_RELEASE >= (release))) + + +// Defines for shared builds. +// Simple reference for using these macros and for writin components +// which support shared builds: +// +// 1) use the WXDLLIMPEXP_MYCOMP in each class declaration: +// class WXDLLIMPEXP_MYCOMP myCompClass { [...] }; +// +// 2) use the WXDLLIMPEXP_MYCOMP in the declaration of each global function: +// WXDLLIMPEXP_MYCOMP int myGlobalFunc(); +// +// 3) use the WXDLLIMPEXP_DATA_MYCOMP() in the declaration of each global +// variable: +// WXDLLIMPEXP_DATA_MYCOMP(int) myGlobalIntVar; +// +#ifdef WXMAKINGDLL_JSON + #define WXDLLIMPEXP_JSON WXEXPORT + #define WXDLLIMPEXP_DATA_JSON(type) WXEXPORT type +#elif defined(WXUSINGDLL) + #define WXDLLIMPEXP_JSON WXIMPORT + #define WXDLLIMPEXP_DATA_JSON(type) WXIMPORT type +#else // not making nor using DLL + #define WXDLLIMPEXP_JSON + #define WXDLLIMPEXP_DATA_JSON(type) type +#endif + +// the __PRETTY_FUNCTION__ macro expands to the full class's +// member name in the GNU GCC. +// For other compilers we use the standard __wxFUNCTION__ macro +#if !defined( __GNUC__ ) + #define __PRETTY_FUNCTION__ __WXFUNCTION__ +#endif + + + +// define wxJSON_USE_UNICODE if wxWidgets was built with +// unicode support +#if defined( wxJSON_USE_UNICODE ) + #undef wxJSON_USE_UNICODE +#endif +// do not modify the following lines +#if wxUSE_UNICODE == 1 + #define wxJSON_USE_UNICODE +#endif + +// the following macro, if defined, cause the wxJSONValue to store +// pointers to C-strings as pointers to statically allocated +// C-strings. By default this macro is not defined +// #define wxJSON_USE_CSTRING + + +// the following macro, if defined, cause the wxJSONvalue and its +// referenced data structure to store and increment a static +// progressive counter in the ctor. +// this is only usefull for debugging purposes +// #define WXJSON_USE_VALUE_COUNTER + + +// the following macro is used by wxJSON internally and you should not +// modify it. If the platform seems to support 64-bits integers, +// the following lines define the 'wxJSON_64BIT_INT' macro +#if defined( wxLongLong_t ) +#define wxJSON_64BIT_INT +#endif + + +// +// the following macro, if defined, cause the wxJSON library to +// always use 32-bits integers also when the platform seems to +// have native 64-bits support: by default the macro if not defined +// +// #define wxJSON_NO_64BIT_INT +// +#if defined( wxJSON_NO_64BIT_INT ) && defined( wxJSON_64BIT_INT ) +#undef wxJSON_64BIT_INT +#endif + +// +// it seems that some compilers do not define 'long long int' limits +// constants. For example, this is the output of the Borland BCC 5.5 +// compiler when I tried to compile wxJSON with 64-bits integer support: +// Error E2451 ..\src\jsonreader.cpp 1737: Undefined symbol 'LLONG_MAX' +// in function wxJSONReader::Strtoll(const wxString &,__int64 *) +// *** 1 errors in Compile *** +// so, if the constants are not defined, I define them by myself +#if !defined( LLONG_MAX ) + #define LLONG_MAX 9223372036854775807 +#endif + +#if !defined( ULLONG_MAX ) + #define ULLONG_MAX 18446744073709551615 +#endif + +#if !defined( LLONG_MIN ) + #define LLONG_MIN -9223372036854775808 +#endif + + + +// the same applies for all other integer constants +#if !defined( INT_MIN ) + #define INT_MIN -32768 +#endif +#if !defined( INT_MAX ) + #define INT_MAX 32767 +#endif +#if !defined( UINT_MAX ) + #define UINT_MAX 65535 +#endif +#if !defined( LONG_MIN ) + #define LONG_MIN -2147483648 +#endif +#if !defined( LONG_MAX ) + #define LONG_MAX 2147483647 +#endif +#if !defined( ULONG_MAX ) + #define ULONG_MAX 4294967295 +#endif +#if !defined( SHORT_MAX ) + #define SHORT_MAX 32767 +#endif +#if !defined( SHORT_MIN ) + #define SHORT_MIN -32768 +#endif +#if !defined( USHORT_MAX ) + #define USHORT_MAX 65535 +#endif + + + +// +// define the wxJSON_ASSERT() macro to expand to wxASSERT() +// unless the wxJSON_NOABORT_ASSERT is defined +// #define wxJSON_NOABORT_ASSERT +#if defined( wxJSON_NOABORT_ASSERT ) + #define wxJSON_ASSERT( cond ) +#else + #define wxJSON_ASSERT( cond ) wxASSERT( cond ); +#endif + + +// +// the following macros are used by the wxJSONWriter::WriteStringValues() +// when the wxJSONWRITER_SPLIT_STRING flag is set +#define wxJSONWRITER_LAST_COL 50 +#define wxJSONWRITER_SPLIT_COL 75 +#define wxJSONWRITER_MIN_LENGTH 15 +#define wxJSONWRITER_TAB_LENGTH 4 + + +// +// some compilers (i.e. MSVC++) defines their own 'snprintf' function +// so if it is not defined, define it in the following lines +// please note that we cannot use the wxWidget's counterpart 'wxSnprintf' +// because the latter uses 'wxChar' but wxJSON only use 'char' +#if !defined(snprintf) && defined(_MSC_VER) +#define snprintf _snprintf +#endif + + +// +// check if wxWidgets is compiled using --enable-stl in which case +// we have to use different aproaches when declaring the array and +// key/value containers (see the docs: wxJSON internals: array and hash_map +#undef wxJSON_USE_STL +#if defined( wxUSE_STL ) && wxUSE_STL == 1 +#define wxJSON_USE_STL +#endif + +// +// defines the MIN and MAX macro for numeric arguments +// note that the safest way to define such functions is using templates +#ifndef MIN +#define MIN(a,b) a < b ? a : b +#endif +#ifndef MAX +#define MAX(a,b) a > b ? a : b +#endif + +#endif // _WX_JSON_DEFS_H_ + + diff --git a/ThirdParty/wxJSON/include/wx/jsonreader.h b/ThirdParty/wxJSON/include/wx/jsonreader.h new file mode 100644 index 0000000..dd10b8c --- /dev/null +++ b/ThirdParty/wxJSON/include/wx/jsonreader.h @@ -0,0 +1,150 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: jsonreader.h +// Purpose: the parser of JSON text +// Author: Luciano Cattani +// Created: 2007/09/15 +// RCS-ID: $Id: jsonreader.h,v 1.3 2008/03/03 19:05:45 luccat Exp $ +// Copyright: (c) 2007 Luciano Cattani +// Licence: wxWidgets licence +///////////////////////////////////////////////////////////////////////////// + +#if !defined( _WX_JSONREADER_H ) +#define _WX_JSONREADER_H + +#ifdef __GNUG__ + #pragma interface "jsonreader.h" +#endif + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers (this file is usually all you +// need because it includes almost all "standard" wxWidgets headers) +#ifndef WX_PRECOMP + #include + #include + #include +#endif + + +#include "json_defs.h" +#include "jsonval.h" + +// The flags of the parser +enum { + wxJSONREADER_STRICT = 0, + wxJSONREADER_ALLOW_COMMENTS = 1, + wxJSONREADER_STORE_COMMENTS = 2, + wxJSONREADER_CASE = 4, + wxJSONREADER_MISSING = 8, + wxJSONREADER_MULTISTRING = 16, + wxJSONREADER_COMMENTS_AFTER = 32, + wxJSONREADER_NOUTF8_STREAM = 64, + wxJSONREADER_MEMORYBUFF = 128, + + wxJSONREADER_TOLERANT = wxJSONREADER_ALLOW_COMMENTS | wxJSONREADER_CASE | + wxJSONREADER_MISSING | wxJSONREADER_MULTISTRING, + wxJSONREADER_COMMENTS_BEFORE = wxJSONREADER_ALLOW_COMMENTS | wxJSONREADER_STORE_COMMENTS +}; + + +class WXDLLIMPEXP_JSON wxJSONReader +{ +public: + wxJSONReader( int flags = wxJSONREADER_TOLERANT, int maxErrors = 30 ); + virtual ~wxJSONReader(); + + int Parse( const wxString& doc, wxJSONValue* val ); + int Parse( wxInputStream& doc, wxJSONValue* val ); + + int GetDepth() const; + int GetErrorCount() const; + int GetWarningCount() const; + const wxArrayString& GetErrors() const; + const wxArrayString& GetWarnings() const; + + static int UTF8NumBytes( char ch ); + +#if defined( wxJSON_64BIT_INT ) + static bool Strtoll( const wxString& str, wxInt64* i64 ); + static bool Strtoull( const wxString& str, wxUint64* ui64 ); + static bool DoStrto_ll( const wxString& str, wxUint64* ui64, wxChar* sign ); +#endif + +protected: + + int DoRead( wxInputStream& doc, wxJSONValue& val ); + void AddError( const wxString& descr ); + void AddError( const wxString& fmt, const wxString& str ); + void AddError( const wxString& fmt, wxChar ch ); + void AddWarning( int type, const wxString& descr ); + int GetStart( wxInputStream& is ); + int ReadChar( wxInputStream& is ); + int PeekChar( wxInputStream& is ); + void StoreValue( int ch, const wxString& key, wxJSONValue& value, wxJSONValue& parent ); + int SkipWhiteSpace( wxInputStream& is ); + int SkipComment( wxInputStream& is ); + void StoreComment( const wxJSONValue* parent ); + int ReadString( wxInputStream& is, wxJSONValue& val ); + int ReadToken( wxInputStream& is, int ch, wxString& s ); + int ReadValue( wxInputStream& is, int ch, wxJSONValue& val ); + int ReadUES( wxInputStream& is, char* uesBuffer ); + int AppendUES( wxMemoryBuffer& utf8Buff, const char* uesBuffer ); + int NumBytes( char ch ); + int ConvertCharByChar( wxString& s, const wxMemoryBuffer& utf8Buffer ); + int ReadMemoryBuff( wxInputStream& is, wxJSONValue& val ); + + //! Flag that control the parser behaviour, + int m_flags; + + //! Maximum number of errors stored in the error's array + int m_maxErrors; + + //! The current line number (start at 1). + int m_lineNo; + + //! The current column number (start at 1). + int m_colNo; + + //! The current level of object/array annidation (start at ZERO). + int m_level; + + //! The depth level of the read JSON text + int m_depth; + + //! The pointer to the value object that is being read. + wxJSONValue* m_current; + + //! The pointer to the value object that was last stored. + wxJSONValue* m_lastStored; + + //! The pointer to the value object that will be read. + wxJSONValue* m_next; + + //! The comment string read by SkipComment(). + wxString m_comment; + + //! The starting line of the comment string. + int m_commentLine; + + //! The array of error messages. + wxArrayString m_errors; + + //! The array of warning messages. + wxArrayString m_warnings; + + //! The character read by the PeekChar() function (-1 none) + int m_peekChar; + + //! ANSI: do not convert UTF-8 strings + bool m_noUtf8; +}; + + +#endif // not defined _WX_JSONREADER_H + + diff --git a/ThirdParty/wxJSON/include/wx/jsonval.h b/ThirdParty/wxJSON/include/wx/jsonval.h new file mode 100644 index 0000000..7eb5341 --- /dev/null +++ b/ThirdParty/wxJSON/include/wx/jsonval.h @@ -0,0 +1,441 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: jsonval.h +// Purpose: the wxJSONValue class: it holds a JSON value +// Author: Luciano Cattani +// Created: 2007/09/15 +// RCS-ID: $Id: jsonval.h,v 1.4 2008/01/10 21:27:15 luccat Exp $ +// Copyright: (c) 2007 Luciano Cattani +// Licence: wxWidgets licence +///////////////////////////////////////////////////////////////////////////// + +#if !defined( _WX_JSONVAL_H ) +#define _WX_JSONVAL_H + +#ifdef __GNUG__ + #pragma interface "jsonval.h" +#endif + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers (this file is usually all you +// need because it includes almost all "standard" wxWidgets headers) +#ifndef WX_PRECOMP + #include + #include + #include + #include +#endif + + +#include "json_defs.h" + +// forward declarations +class WXDLLIMPEXP_JSON wxJSONReader; +class WXDLLIMPEXP_JSON wxJSONRefData; + +//#if defined( wxJSON_USE_STL ) +// // if compiling on MinGW we use the STL-style declaration of wxWidget's +// // container classes +// class WXDLLIMPEXP_JSON wxJSONValue; +// WX_DECLARE_OBJARRAY( wxJSONValue, wxJSONInternalArray ); +// WX_DECLARE_STRING_HASH_MAP( wxJSONValue, wxJSONInternalMap ); +//#else + class WXDLLIMPEXP_JSON wxJSONInternalMap; + class WXDLLIMPEXP_JSON wxJSONInternalArray; +//#endif + + +//! The type of the value held by the wxJSONRefData class +enum wxJSONType { + wxJSONTYPE_INVALID = 0, /*!< the object is not uninitialized */ + wxJSONTYPE_NULL, /*!< the object contains a NULL value */ + wxJSONTYPE_INT, /*!< the object contains an integer */ + wxJSONTYPE_UINT, /*!< the object contains an unsigned integer */ + wxJSONTYPE_DOUBLE, /*!< the object contains a double */ + wxJSONTYPE_STRING, /*!< the object contains a wxString object */ + wxJSONTYPE_CSTRING, /*!< the object contains a static C-string */ + wxJSONTYPE_BOOL, /*!< the object contains a boolean */ + wxJSONTYPE_ARRAY, /*!< the object contains an array of values */ + wxJSONTYPE_OBJECT, /*!< the object contains a map of keys/values */ + wxJSONTYPE_LONG, /*!< the object contains a 32-bit integer */ + wxJSONTYPE_INT64, /*!< the object contains a 64-bit integer */ + wxJSONTYPE_ULONG, /*!< the object contains an unsigned 32-bit integer */ + wxJSONTYPE_UINT64, /*!< the object contains an unsigned 64-bit integer */ + wxJSONTYPE_SHORT, /*!< the object contains a 16-bit integer */ + wxJSONTYPE_USHORT, /*!< the object contains a 16-bit unsigned integer */ + wxJSONTYPE_MEMORYBUFF /*!< the object contains a binary memory buffer */ +}; + +// the comment position: every value only has one comment position +// althrough comments may be splitted into several lines +enum { + wxJSONVALUE_COMMENT_DEFAULT = 0, + wxJSONVALUE_COMMENT_BEFORE, + wxJSONVALUE_COMMENT_AFTER, + wxJSONVALUE_COMMENT_INLINE, +}; + +/*********************************************************************** + + class wxJSONValue + +***********************************************************************/ + + +// class WXDLLIMPEXP_JSON wxJSONValue : public wxObject +class WXDLLIMPEXP_JSON wxJSONValue +{ + friend class wxJSONReader; + +public: + + // ctors and dtor + wxJSONValue(); + wxJSONValue( wxJSONType type ); + wxJSONValue( int i ); + wxJSONValue( unsigned int i ); + wxJSONValue( short i ); + wxJSONValue( unsigned short i ); + wxJSONValue( long int i ); + wxJSONValue( unsigned long int i ); +#if defined( wxJSON_64BIT_INT) + wxJSONValue( wxInt64 i ); + wxJSONValue( wxUint64 ui ); +#endif + wxJSONValue( bool b ); + wxJSONValue( double d ); + wxJSONValue( const wxChar* str ); // assume static ASCIIZ strings + wxJSONValue( const wxString& str ); + wxJSONValue( const wxMemoryBuffer& buff ); + wxJSONValue( const void* buff, size_t len ); + wxJSONValue( const wxJSONValue& other ); + virtual ~wxJSONValue(); + + // functions for retrieving the value type + wxJSONType GetType() const; + bool IsValid() const; + bool IsNull() const; + bool IsInt() const; + bool IsUInt() const; + bool IsShort() const; + bool IsUShort() const; + bool IsLong() const; + bool IsULong() const; +#if defined( wxJSON_64BIT_INT) + bool IsInt32() const; + bool IsInt64() const; + bool IsUInt32() const; + bool IsUInt64() const; +#endif + bool IsBool() const; + bool IsDouble() const; + bool IsString() const; + bool IsCString() const; + bool IsArray() const; + bool IsObject() const; + bool IsMemoryBuff() const; + + // function for retireving the value as ... + int AsInt() const; + unsigned int AsUInt() const; + short AsShort() const; + unsigned short AsUShort() const; + long int AsLong() const; + unsigned long AsULong() const; + bool AsInt( int& i ) const; + bool AsUInt( unsigned int& ui ) const; + bool AsShort( short int& s ) const; + bool AsUShort( unsigned short& us ) const; + bool AsLong( long int& l ) const; + bool AsULong( unsigned long& ul ) const; +#if defined( wxJSON_64BIT_INT) + wxInt32 AsInt32() const; + wxUint32 AsUInt32() const; + wxInt64 AsInt64() const; + wxUint64 AsUInt64() const; + bool AsInt32( wxInt32& i32 ) const; + bool AsUInt32( wxUint32& ui32 ) const; + bool AsInt64( wxInt64& i64 ) const; + bool AsUInt64( wxUint64& ui64 ) const; +#endif + bool AsBool() const; + double AsDouble() const; + wxString AsString() const; + const wxChar* AsCString() const; + bool AsBool( bool& b ) const; + bool AsDouble( double& d ) const; + bool AsString( wxString& str ) const; + bool AsCString( wxChar* ch ) const; + wxMemoryBuffer AsMemoryBuff() const; + bool AsMemoryBuff( wxMemoryBuffer& buff ) const; + + const wxJSONInternalMap* AsMap() const; + const wxJSONInternalArray* AsArray() const; + + // get members names, size and other info + bool HasMember( unsigned index ) const; + bool HasMember( const wxString& key ) const; + int Size() const; + wxArrayString GetMemberNames() const; + + // appending items, resizing and deleting items + wxJSONValue& Append( const wxJSONValue& value ); + wxJSONValue& Append( bool b ); + wxJSONValue& Append( int i ); + wxJSONValue& Append( unsigned int ui ); + wxJSONValue& Append( short int i ); + wxJSONValue& Append( unsigned short int ui ); + wxJSONValue& Append( long int l ); + wxJSONValue& Append( unsigned long int ul ); +#if defined( wxJSON_64BIT_INT ) + wxJSONValue& Append( wxInt64 i ); + wxJSONValue& Append( wxUint64 ui ); +#endif + wxJSONValue& Append( double d ); + wxJSONValue& Append( const wxChar* str ); + wxJSONValue& Append( const wxString& str ); + wxJSONValue& Append( const wxMemoryBuffer& buff ); + wxJSONValue& Append( const void* buff, size_t len ); + bool Remove( int index ); + bool Remove( const wxString& key ); + void Clear(); + bool Cat( const wxChar* str ); + bool Cat( const wxString& str ); + bool Cat( const wxMemoryBuffer& buff ); + + // retrieve an item + wxJSONValue& Item( unsigned index ); + wxJSONValue& Item( const wxString& key ); + wxJSONValue ItemAt( unsigned index ) const; + wxJSONValue ItemAt( const wxString& key ) const; + + wxJSONValue& operator [] ( unsigned index ); + wxJSONValue& operator [] ( const wxString& key ); + + wxJSONValue& operator = ( int i ); + wxJSONValue& operator = ( unsigned int ui ); + wxJSONValue& operator = ( short int i ); + wxJSONValue& operator = ( unsigned short int ui ); + wxJSONValue& operator = ( long int l ); + wxJSONValue& operator = ( unsigned long int ul ); +#if defined( wxJSON_64BIT_INT ) + wxJSONValue& operator = ( wxInt64 i ); + wxJSONValue& operator = ( wxUint64 ui ); +#endif + wxJSONValue& operator = ( bool b ); + wxJSONValue& operator = ( double d ); + wxJSONValue& operator = ( const wxChar* str ); + wxJSONValue& operator = ( const wxString& str ); + wxJSONValue& operator = ( const wxMemoryBuffer& buff ); + // wxJSONValue& operator = ( const void* buff, size_t len ); cannot be declared + wxJSONValue& operator = ( const wxJSONValue& value ); + + // get the value or a default value + wxJSONValue Get( const wxString& key, const wxJSONValue& defaultValue ) const; + + // comparison function + bool IsSameAs( const wxJSONValue& other ) const; + + // comment-related functions + int AddComment( const wxString& str, int position = wxJSONVALUE_COMMENT_DEFAULT ); + int AddComment( const wxArrayString& comments, int position = wxJSONVALUE_COMMENT_DEFAULT ); + wxString GetComment( int idx = -1 ) const; + int GetCommentPos() const; + int GetCommentCount() const; + void ClearComments(); + const wxArrayString& GetCommentArray() const; + + // debugging functions + wxString GetInfo() const; + wxString Dump( bool deep = false, int mode = 0 ) const; + + //misc functions + wxJSONRefData* GetRefData() const; + wxJSONRefData* SetType( wxJSONType type ); + int GetLineNo() const; + void SetLineNo( int num ); + + // public static functions: mainly used for debugging + static wxString TypeToString( wxJSONType type ); + static wxString MemoryBuffToString( const wxMemoryBuffer& buff, size_t len = -1 ); + static wxString MemoryBuffToString( const void* buff, size_t len, size_t actualLen = -1 ); + static int CompareMemoryBuff( const wxMemoryBuffer& buff1, const wxMemoryBuffer& buff2 ); + static int CompareMemoryBuff( const wxMemoryBuffer& buff1, const void* buff2 ); + static wxMemoryBuffer ArrayToMemoryBuff( const wxJSONValue& value ); + +protected: + wxJSONValue* Find( unsigned index ) const; + wxJSONValue* Find( const wxString& key ) const; + void DeepCopy( const wxJSONValue& other ); + + wxJSONRefData* Init( wxJSONType type ); + wxJSONRefData* COW(); + + // overidden from wxObject + virtual wxJSONRefData* CloneRefData(const wxJSONRefData *data) const; + virtual wxJSONRefData* CreateRefData() const; + + void SetRefData(wxJSONRefData* data); + void Ref(const wxJSONValue& clone); + void UnRef(); + void UnShare(); + void AllocExclusive(); + + //! the referenced data + wxJSONRefData* m_refData; + + + // used for debugging purposes: only in debug builds. +#if defined( WXJSON_USE_VALUE_COUNTER ) + int m_progr; + static int sm_progr; +#endif +}; + + +//#if !defined( wxJSON_USE_STL ) + // if using wxWidget's implementation of container classes we declare + // the OBJARRAY are HASH_MAP _after_ the wxJSONValue is fully known + WX_DECLARE_OBJARRAY( wxJSONValue, wxJSONInternalArray ); + WX_DECLARE_STRING_HASH_MAP_WITH_DECL( wxJSONValue, wxJSONInternalMap, class WXDLLIMPEXP_JSON ); +//#endif + + +/*********************************************************************** + + class wxJSONRefData + +***********************************************************************/ + + + + +//! The actual value held by the wxJSONValue class (internal use) +/*! + Note that this structure is a \b union as in versions prior to 0.4.x + The union just stores primitive types and not complex types which are + stored in separate data members of the wxJSONRefData structure. + + This organization give us more flexibility when retrieving compatible + types such as ints unsigned ints, long and so on. + To know more about the internal structure of the wxJSONValue class + see \ref pg_json_internals. +*/ +union wxJSONValueHolder { + int m_valInt; + unsigned int m_valUInt; + short int m_valShort; + unsigned short m_valUShort; + long int m_valLong; + unsigned long m_valULong; + double m_valDouble; + const wxChar* m_valCString; + bool m_valBool; +#if defined( wxJSON_64BIT_INT ) + wxInt64 m_valInt64; + wxUint64 m_valUInt64; +#endif + }; + +// +// access to the (unsigned) integer value is done through +// the VAL_INT macro which expands to the 'long' integer +// data member of the 'long long' integer if 64-bits integer +// support is enabled +#if defined( wxJSON_64BIT_INT ) + #define VAL_INT m_valInt64 + #define VAL_UINT m_valUInt64 +#else + #define VAL_INT m_valLong + #define VAL_UINT m_valULong +#endif + + + +// class WXDLLIMPEXP_JSON wxJSONRefData : public wxObjectRefData +class WXDLLIMPEXP_JSON wxJSONRefData +{ + // friend class wxJSONReader; + friend class wxJSONValue; + friend class wxJSONWriter; + +public: + + wxJSONRefData(); + virtual ~wxJSONRefData(); + + int GetRefCount() const; + + // there is no need to define copy ctor + + //! the references count + int m_refCount; + + //! The actual type of the value held by this object. + wxJSONType m_type; + + //! The JSON value held by this object. + /*! + This data member contains the JSON data types defined by the + JSON syntax with the exception of the complex objects. + This data member is an union of the primitive types + so that it is simplier to cast them in other compatible types. + */ + wxJSONValueHolder m_value; + + //! The JSON string value. + wxString m_valString; + + //! The JSON array value. + wxJSONInternalArray m_valArray; + + //! The JSON object value. + wxJSONInternalMap m_valMap; + + //! The position of the comment line(s), if any. + /*! + The data member contains one of the following constants: + \li \c wxJSONVALUE_COMMENT_BEFORE + \li \c wxJSONVALUE_COMMENT_AFTER + \li \c wxJSONVALUE_COMMENT_INLINE + */ + int m_commentPos; + + //! The array of comment lines; may be empty. + wxArrayString m_comments; + + //! The line number when this value was read + /*! + This data member is used by the wxJSONReader class and it is + used to store the line number of the JSON text document where + the value appeared. This value is compared to the line number + of a comment line in order to obtain the value which a + comment refersto. + */ + int m_lineNo; + + //! The pointer to the memory buffer object + /*! + Note that despite using reference counting, the \b wxMemoryBuffer is not a + \e copy-on-write structure so the wxJSON library uses some tricks in order to + avoid the side effects of copying / assigning wxMemoryBuffer objects + */ + wxMemoryBuffer* m_memBuff; + + // used for debugging purposes: only in debug builds. +#if defined( WXJSON_USE_VALUE_COUNTER ) + int m_progr; + static int sm_progr; +#endif +}; + + + +#endif // not defined _WX_JSONVAL_H + + diff --git a/ThirdParty/wxJSON/include/wx/jsonwriter.h b/ThirdParty/wxJSON/include/wx/jsonwriter.h new file mode 100644 index 0000000..5705f91 --- /dev/null +++ b/ThirdParty/wxJSON/include/wx/jsonwriter.h @@ -0,0 +1,119 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: jsonwriter.h +// Purpose: the generator of JSON text from a JSON value +// Author: Luciano Cattani +// Created: 2007/09/15 +// RCS-ID: $Id: jsonwriter.h,v 1.4 2008/03/03 19:05:45 luccat Exp $ +// Copyright: (c) 2007 Luciano Cattani +// Licence: wxWidgets licence +///////////////////////////////////////////////////////////////////////////// + +#if !defined( _WX_JSONWRITER_H ) +#define _WX_JSONWRITER_H + +#ifdef __GNUG__ + #pragma interface "jsonwriter.h" +#endif + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers (this file is usually all you +// need because it includes almost all "standard" wxWidgets headers) +#ifndef WX_PRECOMP + #include + #include +#endif + +#include "json_defs.h" +#include "jsonval.h" + +enum { + wxJSONWRITER_NONE = 0, + wxJSONWRITER_STYLED = 1, + wxJSONWRITER_WRITE_COMMENTS = 2, + wxJSONWRITER_COMMENTS_BEFORE = 4, + wxJSONWRITER_COMMENTS_AFTER = 8, + wxJSONWRITER_SPLIT_STRING = 16, + wxJSONWRITER_NO_LINEFEEDS = 32, + wxJSONWRITER_ESCAPE_SOLIDUS = 64, + wxJSONWRITER_MULTILINE_STRING = 128, + wxJSONWRITER_RECOGNIZE_UNSIGNED = 256, + wxJSONWRITER_TAB_INDENT = 512, + wxJSONWRITER_NO_INDENTATION = 1024, + wxJSONWRITER_NOUTF8_STREAM = 2048, + wxJSONWRITER_MEMORYBUFF = 4096 +}; + +// class declaration + +class WXDLLIMPEXP_JSON wxJSONWriter +{ +public: + wxJSONWriter( int style = wxJSONWRITER_STYLED, int indent = 0, int step = 3 ); + ~wxJSONWriter(); + + void Write( const wxJSONValue& value, wxString& str ); + void Write( const wxJSONValue& value, wxOutputStream& os ); + void SetDoubleFmtString( const char* fmt ); + +protected: + + int DoWrite( wxOutputStream& os, const wxJSONValue& value, const wxString* key, bool comma ); + int WriteIndent( wxOutputStream& os ); + int WriteIndent( wxOutputStream& os, int num ); + bool IsSpace( wxChar ch ); + bool IsPunctuation( wxChar ch ); + + int WriteString( wxOutputStream& os, const wxString& str ); + int WriteStringValue( wxOutputStream& os, const wxString& str ); + int WriteNullValue( wxOutputStream& os ); + int WriteIntValue( wxOutputStream& os, const wxJSONValue& v ); + int WriteUIntValue( wxOutputStream& os, const wxJSONValue& v ); + int WriteBoolValue( wxOutputStream& os, const wxJSONValue& v ); + int WriteDoubleValue( wxOutputStream& os, const wxJSONValue& v ); + int WriteMemoryBuff( wxOutputStream& os, const wxMemoryBuffer& buff ); + + int WriteInvalid( wxOutputStream& os ); + int WriteSeparator( wxOutputStream& os ); + + int WriteKey( wxOutputStream& os, const wxString& key ); + int WriteComment( wxOutputStream& os, const wxJSONValue& value, bool indent ); + + int WriteError( const wxString& err ); + +private: + //! The style flag is a combination of wxJSONWRITER_(something) constants. + int m_style; + + //! The initial indentation value, in number of spaces. + int m_indent; + + //! The indentation increment, in number of spaces. + int m_step; + + //! JSON value objects can be nested; this is the level of annidation (used internally). + int m_level; + + // The line number when printing JSON text output (not yet used) + int m_lineNo; + + // The column number when printing JSON text output + int m_colNo; + + // Flag used in ANSI mode that controls UTF-8 conversion + bool m_noUtf8; + + // The format string for printing doubles + char* m_fmt; +}; + + +#endif // not defined _WX_JSONWRITER_H + + + diff --git a/ThirdParty/wxJSON/src/jsonreader.cpp b/ThirdParty/wxJSON/src/jsonreader.cpp new file mode 100644 index 0000000..88c1008 --- /dev/null +++ b/ThirdParty/wxJSON/src/jsonreader.cpp @@ -0,0 +1,2132 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: jsonreader.cpp +// Purpose: the wxJSONReader class: a JSON text parser +// Author: Luciano Cattani +// Created: 2007/10/14 +// RCS-ID: $Id: jsonreader.cpp,v 1.12 2008/03/12 10:48:19 luccat Exp $ +// Copyright: (c) 2007 Luciano Cattani +// Licence: wxWidgets licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ + #pragma implementation "jsonreader.cpp" +#endif + +#include + +#include +#include +#include +#include + + + +/*! \class wxJSONReader + \brief The JSON parser + + The class is a JSON parser which reads a JSON formatted text and stores + values in the \c wxJSONValue structure. + The ctor accepts two parameters: the \e style flag, which controls how + much error-tolerant should the parser be and an integer which is + the maximum number of errors and warnings that have to be reported + (the default is 30). + + If the JSON text document does not contain an open/close JSON character the + function returns an \b invalid value object; in other words, the + wxJSONValue::IsValid() function returns FALSE. + This is the case of a document that is empty or contains only + whitespaces or comments. + If the document contains a starting object/array character immediatly + followed by a closing object/array character + (i.e.: \c {} ) then the function returns an \b empty array or object + JSON value. + This is a valid JSON object of type wxJSONTYPE_OBJECT or wxJSONTYPE_ARRAY + whose wxJSONValue::Size() function returns ZERO. + + \par JSON text + + The wxJSON parser just skips all characters read from the + input JSON text until the start-object '{' or start-array '[' characters + are encontered (see the GetStart() function). + This means that the JSON input text may contain anything + before the first start-object/array character except these two chars themselves + unless they are included in a C/C++ comment. + Comment lines that apear before the first start array/object character, + are non ignored if the parser is constructed with the wxJSONREADER_STORE_COMMENT + flag: they are added to the comment's array of the root JSON value. + + Note that the parsing process stops when the internal DoRead() function + returns. Because that function is recursive, the top-level close-object + '}' or close-array ']' character cause the top-level DoRead() function + to return thus stopping the parsing process regardless the EOF condition. + This means that the JSON input text may contain anything \b after + the top-level close-object/array character. + Here are some examples: + + Returns a wxJSONTYPE_INVALID value (invalid JSON value) + \code + // this text does not contain an open array/object character + \endcode + + Returns a wxJSONTYPE_OBJECT value of Size() = 0 + \code + { + } + \endcode + + Returns a wxJSONTYPE_ARRAY value of Size() = 0 + \code + [ + ] + \endcode + + Text before and after the top-level open/close characters is ignored. + \code + This non-JSON text does not cause the parser to report errors or warnings + { + } + This non-JSON text does not cause the parser to report errors or warnings + \endcode + + + \par Extensions + + The wxJSON parser recognizes all JSON text plus some extensions + that are not part of the JSON syntax but that many other JSON + implementations do recognize. + If the input text contains the following non-JSON text, the parser + reports the situation as \e warnings and not as \e errors unless + the parser object was constructed with the wxJSONREADER_STRICT + flag. In the latter case the wxJSON parser is not tolerant. + + \li C/C++ comments: the parser recognizes C and C++ comments. + Comments can optionally be stored in the value they refer + to and can also be written back to the JSON text document. + To know more about comment storage see \ref wxjson_comments + + \li case tolerance: JSON syntax states that the literals \c null, + \c true and \c false must be lowercase; the wxJSON parser + also recognizes mixed case literals such as, for example, + \b Null or \b FaLSe. A \e warning is emitted. + + \li wrong or missing closing character: wxJSON parser is tolerant + about the object / array closing character. When an open-array + character '[' is encontered, the parser expects the + corresponding close-array character ']'. If the character + encontered is a close-object char '}' a warning is reported. + A warning is also reported if the character is missing when + the end-of-file is reached. + + \li multi-line strings: this feature allows a JSON string type to be + splitted in two or more lines as in the standard C/C++ + languages. The drawback is that this feature is error-prone + and you have to use it with care. + For more info about this topic read \ref wxjson_tutorial_style_split + + Note that you can control how much error-tolerant should the parser be + and also you can specify how many and what extensions are recognized. + See the constructor's parameters for more details. + + \par Unicode vs ANSI + + The parser can read JSON text from two very different kind of objects: + + \li a string object (\b wxString) + \li a stream object (\b wxInputStream) + + When the input is from a string object, the character represented in the + string is platform- and mode- dependant; in other words, characters are + represented differently: in ANSI builds they depend on the charset in use + and in Unicode builds they depend on the platform (UCS-2 on win32, UCS-4 + or UTF-8 on GNU/Linux). + + When the input is from a stream object, the only recognized encoding format + is UTF-8 for both ANSI and Unicode builds. + + \par Example: + + \code + wxJSONValue value; + wxJSONReader reader; + + // open a text file that contains the UTF-8 encoded JSON text + wxFFileInputStream jsonText( _T("filename.utf8"), _T("r")); + + // read the file + int numErrors = reader.Parse( jsonText, &value ); + + if ( numErrors > 0 ) { + ::MessageBox( _T("Error reading the input file")); + } + \endcode + + Starting from version 1.1.0 the wxJSON reader and the writer has changed in + their internal organization. + To know more about ANSI and Unicode mode read \ref wxjson_tutorial_unicode. +*/ + + + +// if you have the debug build of wxWidgets and wxJSON you can see +// trace messages by setting the: +// WXTRACE=traceReader StoreComment +// environment variable +static const wxChar* traceMask = _T("traceReader"); +static const wxChar* storeTraceMask = _T("StoreComment"); + + +//! Ctor +/*! + Construct a JSON parser object with the given parameters. + + JSON parser objects should always be constructed on the stack but + it does not hurt to have a global JSON parser. + + \param flags this paramter controls how much error-tolerant should the + parser be + + \param maxErrors the maximum number of errors (and warnings, too) that are + reported by the parser. When the number of errors reaches this limit, + the parser stops to read the JSON input text and no other error is + reported. + + The \c flag parameter is the combination of ZERO or more of the + following constants OR'ed toghether: + + \li wxJSONREADER_ALLOW_COMMENTS: C/C++ comments are recognized by the + parser; a warning is reported by the parser + \li wxJSONREADER_STORE_COMMENTS: C/C++ comments, if recognized, are + stored in the value they refer to and can be rewritten back to + the JSON text + \li wxJSONREADER_CASE: the parser recognizes mixed-case literal strings + \li wxJSONREADER_MISSING: the parser allows missing or wrong close-object + and close-array characters + \li wxJSONREADER_MULTISTRING: strings may be splitted in two or more + lines + \li wxJSONREADER_COMMENTS_AFTER: if STORE_COMMENTS if defined, the parser + assumes that comment lines apear \b before the value they + refer to unless this constant is specified. In the latter case, + comments apear \b after the value they refer to. + \li wxJSONREADER_NOUTF8_STREAM: suppress UTF-8 conversion when reading a + string value from a stream: the reader assumes that the input stream + is encoded in ANSI format and not in UTF-8; only meaningfull in ANSI + builds, this flag is simply ignored in Unicode builds. + + You can also use the following shortcuts to specify some predefined + flag's combinations: + + \li wxJSONREADER_STRICT: all wxJSON extensions are reported as errors, this + is the same as specifying a ZERO value as \c flags. + \li wxJSONREADER_TOLERANT: this is the same as ALLOW_COMMENTS | CASE | + MISSING | MULTISTRING; all wxJSON extensions are turned on but comments + are not stored in the value objects. + + \par Example: + + The following code fragment construct a JSON parser, turns on all + wxJSON extensions and also stores C/C++ comments in the value object + they refer to. The parser assumes that the comments apear before the + value: + + \code + wxJSONReader reader( wxJSONREADER_TOLERANT | wxJSONREADER_STORE_COMMENTS ); + wxJSONValue root; + int numErrors = reader.Parse( jsonText, &root ); + \endcode +*/ +wxJSONReader::wxJSONReader( int flags, int maxErrors ) +{ + m_flags = flags; + m_maxErrors = maxErrors; + m_noUtf8 = false; +#if !defined( wxJSON_USE_UNICODE ) + // in ANSI builds we can suppress UTF-8 conversion for both the writer and the reader + if ( m_flags & wxJSONREADER_NOUTF8_STREAM ) { + m_noUtf8 = true; + } +#endif + +} + +//! Dtor - does nothing +wxJSONReader::~wxJSONReader() +{ +} + +//! Parse the JSON document. +/*! + The two overloaded versions of the \c Parse() function read a + JSON text stored in a wxString object or in a wxInputStream + object. + + If \c val is a NULL pointer, the function does not store the + values: it can be used as a JSON checker in order to check the + syntax of the document. + Returns the number of \b errors found in the document. + If the returned value is ZERO and the parser was constructed + with the \c wxJSONREADER_STRICT flag, then the parsed document + is \e well-formed and it only contains valid JSON text. + + If the \c wxJSONREADER_TOLERANT flag was used in the parser's + constructor, then a return value of ZERO + does not mean that the document is \e well-formed because it may + contain comments and other extensions that are not fatal for the + wxJSON parser but other parsers may fail to recognize. + You can use the \c GetWarningCount() function to know how many + wxJSON extensions are present in the JSON input text. + + Note that the JSON value object \c val is not cleared by this + function unless its type is of the wrong type. + In other words, if \c val is of type wxJSONTYPE_ARRAY and it already + contains 10 elements and the input document starts with a + '[' (open-array char) then the elements read from the document are + \b appended to the existing ones. + + On the other hand, if the text document starts with a '{' (open-object) char + then this function must change the type of the \c val object to + \c wxJSONTYPE_OBJECT and the old content of 10 array elements will be lost. + + \par Different input types + + The real parsing process in done using UTF-8 streams. If the input is + from a \b wxString object, the Parse function first converts the input string + in a temporary \b wxMemoryInputStream which contains the UTF-8 conversion + of the string itself. + Next, the overloaded Parse function is called. + + @param doc the JSON text that has to be parsed + @param val the wxJSONValue object that contains the parsed text; if NULL the + parser do not store anything but errors and warnings are reported + @return the total number of errors encontered +*/ +int +wxJSONReader:: Parse( const wxString& doc, wxJSONValue* val ) +{ +#if !defined( wxJSON_USE_UNICODE ) + // in ANSI builds input from a string never use UTF-8 conversion + bool noUtf8_bak = m_noUtf8; // save the current setting + m_noUtf8 = true; +#endif + + // convert the string to a UTF-8 / ANSI memory stream and calls overloaded Parse() + char* readBuff = 0; + wxCharBuffer utf8CB = doc.ToUTF8(); // the UTF-8 buffer +#if !defined( wxJSON_USE_UNICODE ) + wxCharBuffer ansiCB( doc.c_str()); // the ANSI buffer + if ( m_noUtf8 ) { + readBuff = ansiCB.data(); + } + else { + readBuff = utf8CB.data(); + } +#else + readBuff = utf8CB.data(); +#endif + + // now construct the temporary memory input stream + size_t len = strlen( readBuff ); + wxMemoryInputStream is( readBuff, len ); + + int numErr = Parse( is, val ); +#if !defined( wxJSON_USE_UNICODE ) + m_noUtf8 = noUtf8_bak; +#endif + return numErr; +} + +//! \overload Parse( const wxString&, wxJSONValue* ) +int +wxJSONReader::Parse( wxInputStream& is, wxJSONValue* val ) +{ + // if val == 0 the 'temp' JSON value will be passed to DoRead() + wxJSONValue temp; + m_level = 0; + m_depth = 0; + m_lineNo = 1; + m_colNo = 1; + m_peekChar = -1; + m_errors.clear(); + m_warnings.clear(); + + // if a wxJSONValue is not passed to the Parse function + // we set the temparary object created on the stack + // I know this will slow down the validation of input + if ( val == 0 ) { + val = &temp; + } + wxASSERT( val ); + + // set the wxJSONValue object's pointers for comment storage + m_next = val; + m_next->SetLineNo( -1 ); + m_lastStored = 0; + m_current = 0; + + int ch = GetStart( is ); + switch ( ch ) { + case '{' : + val->SetType( wxJSONTYPE_OBJECT ); + break; + case '[' : + val->SetType( wxJSONTYPE_ARRAY ); + break; + default : + AddError( _T("Cannot find a start object/array character" )); + return m_errors.size(); + break; + } + + // returning from DoRead() could be for EOF or for + // the closing array-object character + // if -1 is returned, it is as an error because the lack + // of close-object/array characters + // note that the missing close-chars error messages are + // added by the DoRead() function + ch = DoRead( is, *val ); + return m_errors.size(); +} + + +//! Returns the start of the document +/*! + This is the first function called by the Parse() function and it searches + the input stream for the starting character of a JSON text and returns it. + JSON text start with '{' or '['. + If the two starting characters are inside a C/C++ comment, they + are ignored. + Returns the JSON-text start character or -1 on EOF. + + @param is the input stream that contains the JSON text + @return -1 on errors or EOF; one of '{' or '[' +*/ +int +wxJSONReader::GetStart( wxInputStream& is ) +{ + int ch = 0; + do { + switch ( ch ) { + case 0 : + ch = ReadChar( is ); + break; + case '{' : + return ch; + break; + case '[' : + return ch; + break; + case '/' : + ch = SkipComment( is ); + StoreComment( 0 ); + break; + default : + ch = ReadChar( is ); + break; + } + } while ( ch >= 0 ); + return ch; +} + +//! Return a reference to the error message's array. +const wxArrayString& +wxJSONReader::GetErrors() const +{ + return m_errors; +} + +//! Return a reference to the warning message's array. +const wxArrayString& +wxJSONReader::GetWarnings() const +{ + return m_warnings; +} + +//! Return the depth of the JSON input text +/*! + The function returns the number of times the recursive \c DoRead function was + called in the parsing process thus returning the maximum depth of the JSON + input text. +*/ +int +wxJSONReader::GetDepth() const +{ + return m_depth; +} + + + +//! Return the size of the error message's array. +int +wxJSONReader::GetErrorCount() const +{ + return m_errors.size(); +} + +//! Return the size of the warning message's array. +int +wxJSONReader::GetWarningCount() const +{ + return m_warnings.size(); +} + + +//! Read a character from the input JSON document. +/*! + The function returns the next byte from the UTF-8 stream as an INT. + In case of errors or EOF, the function returns -1. + The function also updates the \c m_lineNo and \c m_colNo data + members and converts all CR+LF sequence in LF. + + This function only returns one byte UTF-8 (one code unit) + at a time and not Unicode code points. + The only reason for this function is to process line and column + numbers. + + @param is the input stream that contains the JSON text + @return the next char (one single byte) in the input stream or -1 on error or EOF +*/ +int +wxJSONReader::ReadChar( wxInputStream& is ) +{ + if ( is.Eof()) { + return -1; + } + + unsigned char ch = is.GetC(); + size_t last = is.LastRead(); // returns ZERO if EOF + if ( last == 0 ) { + return -1; + } + + // the function also converts CR in LF. only LF is returned + // in the case of CR+LF + int nextChar; + + if ( ch == '\r' ) { + m_colNo = 1; + nextChar = PeekChar( is ); + if ( nextChar == -1 ) { + return -1; + } + else if ( nextChar == '\n' ) { + ch = is.GetC(); + } + } + if ( ch == '\n' ) { + ++m_lineNo; + m_colNo = 1; + } + else { + ++m_colNo; + } + return (int) ch; +} + + +//! Peek a character from the input JSON document +/*! + This function just calls the \b Peek() function on the stream + and returns it. + + @param is the input stream that contains the JSON text + @return the next char (one single byte) in the input stream or -1 on error or EOF +*/ +int +wxJSONReader::PeekChar( wxInputStream& is ) +{ + int ch = -1; unsigned char c; + if ( !is.Eof()) { + c = is.Peek(); + ch = c; + } + return ch; +} + + +//! Reads the JSON text document (internal use) +/*! + This is a recursive function that is called by \c Parse() + and by the \c DoRead() function itself when a new object / + array character is encontered. + The function returns when a EOF condition is encontered or + when the corresponding close-object / close-array char is encontered. + The function also increments the \c m_level + data member when it is entered and decrements it on return. + It also sets \c m_depth equal to \c m_level if \c m_depth is + less than \c m_level. + + The function is the heart of the wxJSON parser class but it is + also very easy to understand because JSON syntax is very + easy. + + Returns the last close-object/array character read or -1 on EOF. + + @param is the input stream that contains the JSON text + @param parent the JSON value object that is the parent of all subobjects + read by the function until the next close-object/array (for + the top-level \c DoRead function \c parent is the root JSON object) + @return one of close-array or close-object char or -1 on error or EOF +*/ +int +wxJSONReader::DoRead( wxInputStream& is, wxJSONValue& parent ) +{ + ++m_level; + if ( m_depth < m_level ) { + m_depth = m_level; + } + + // 'value' is the wxJSONValue structure that has to be + // read. Data read from the JSON text input is stored + // in the following object. + wxJSONValue value( wxJSONTYPE_INVALID ); + + // sets the pointers to the current, next and last-stored objects + // in order to determine the value to which a comment refers to + m_next = &value; + m_current = &parent; + m_current->SetLineNo( m_lineNo ); + m_lastStored = 0; + + // the 'key' string is stored from 'value' when a ':' is encontered + wxString key; + + // the character read: -1=EOF, 0=to be read + int ch=0; + + do { // we read until ch < 0 + switch ( ch ) { + case 0 : + ch = ReadChar( is ); + break; + case ' ' : + case '\t' : + case '\n' : + case '\r' : + ch = SkipWhiteSpace( is ); + break; + case -1 : // the EOF + break; + case '/' : + ch = SkipComment( is ); + StoreComment( &parent ); + break; + + case '{' : + if ( parent.IsObject() ) { + if ( key.empty() ) { + AddError( _T("\'{\' is not allowed here (\'name\' is missing") ); + } + if ( value.IsValid() ) { + AddError( _T("\'{\' cannot follow a \'value\'") ); + } + } + else if ( parent.IsArray() ) { + if ( value.IsValid() ) { + AddError( _T("\'{\' cannot follow a \'value\' in JSON array") ); + } + } + else { + wxJSON_ASSERT( 0 ); // always fails + } + + // the openobject char cause the DoRead() to be called recursively + value.SetType( wxJSONTYPE_OBJECT ); + ch = DoRead( is, value ); + break; + + case '}' : + if ( !parent.IsObject() ) { + AddWarning( wxJSONREADER_MISSING, + _T("Trying to close an array using the \'}\' (close-object) char" )); + } + // close-object: store the current value, if any + StoreValue( ch, key, value, parent ); + m_current = &parent; + m_next = 0; + m_current->SetLineNo( m_lineNo ); + ch = ReadChar( is ); + return ch; + break; + + case '[' : + if ( parent.IsObject() ) { + if ( key.empty() ) { + AddError( _T("\'[\' is not allowed here (\'name\' is missing") ); + } + if ( value.IsValid() ) { + AddError( _T("\'[\' cannot follow a \'value\' text") ); + } + } + else if ( parent.IsArray()) { + if ( value.IsValid() ) { + AddError( _T("\'[\' cannot follow a \'value\'") ); + } + } + else { + wxJSON_ASSERT( 0 ); // always fails + } + // open-array cause the DoRead() to be called recursively + value.SetType( wxJSONTYPE_ARRAY ); + ch = DoRead( is, value ); + break; + + case ']' : + if ( !parent.IsArray() ) { + // wrong close-array char (should be close-object) + AddWarning( wxJSONREADER_MISSING, + _T("Trying to close an object using the \']\' (close-array) char" )); + } + StoreValue( ch, key, value, parent ); + m_current = &parent; + m_next = 0; + m_current->SetLineNo( m_lineNo ); + return 0; // returning ZERO for reading the next char + break; + + case ',' : + // store the value, if any + StoreValue( ch, key, value, parent ); + key.clear(); + ch = ReadChar( is ); + break; + + case '\"' : + ch = ReadString( is, value ); // read a JSON string type + m_current = &value; + m_next = 0; + break; + + case '\'' : + ch = ReadMemoryBuff( is, value ); // read a memory buffer type + m_current = &value; + m_next = 0; + break; + + case ':' : // key / value separator + m_current = &value; + m_current->SetLineNo( m_lineNo ); + m_next = 0; + if ( !parent.IsObject() ) { + AddError( _T( "\':\' can only used in object's values" )); + } + else if ( !value.IsString() ) { + AddError( _T( "\':\' follows a value which is not of type \'string\'" )); + } + else if ( !key.empty() ) { + AddError( _T( "\':\' not allowed where a \'name\' string was already available" )); + } + else { + // the string in 'value' is set as the 'key' + key = value.AsString(); + value.SetType( wxJSONTYPE_INVALID ); + } + ch = ReadChar( is ); + break; + + default : + // no special char: it is a literal or a number + // errors are checked in the 'ReadValue()' function. + m_current = &value; + m_current->SetLineNo( m_lineNo ); + m_next = 0; + ch = ReadValue( is, ch, value ); + break; + } // end switch + } while ( ch >= 0 ); + + // the DoRead() should return when the close-object/array char is encontered + // if we are here, the EOF condition was encontered so one or more close-something + // characters are missing + if ( parent.IsArray() ) { + AddWarning( wxJSONREADER_MISSING, _T("\']\' missing at end of file")); + } + else if ( parent.IsObject() ) { + AddWarning( wxJSONREADER_MISSING, _T("\'}\' missing at end of file")); + } + else { + wxJSON_ASSERT( 0 ); + } + + // we store the value, as there is a missing close-object/array char + StoreValue( ch, key, value, parent ); + + --m_level; + return ch; +} + +//! Store a value in the parent object. +/*! + The function is called by \c DoRead() when a the comma + or a close-object/array character is encontered and stores the current + value read by the parser in the parent object. + The function checks that \c value is not invalid and that \c key is + not an empty string if \c parent is an object. + + \param ch the character read: a comma or close objecty/array char + \param key the \b key string: must be empty if \c parent is an array + \param value the current JSON value to be stored in \c parent + \param parent the JSON value that is the parent of \c value. + \return none +*/ +void +wxJSONReader::StoreValue( int ch, const wxString& key, wxJSONValue& value, wxJSONValue& parent ) +{ + // if 'ch' == } or ] than value AND key may be empty when a open object/array + // is immediatly followed by a close object/array + // + // if 'ch' == , (comma) value AND key (for TypeMap) cannot be empty + // + wxLogTrace( traceMask, _T("(%s) ch=%d char=%c"), __PRETTY_FUNCTION__, ch, (char) ch); + wxLogTrace( traceMask, _T("(%s) value=%s"), __PRETTY_FUNCTION__, value.AsString().c_str()); + + m_current = 0; + m_next = &value; + m_lastStored = 0; + m_next->SetLineNo( -1 ); + + if ( !value.IsValid() && key.empty() ) { + // OK, if the char read is a close-object or close-array + if ( ch == '}' || ch == ']' ) { + m_lastStored = 0; + wxLogTrace( traceMask, _T("(%s) key and value are empty, returning"), + __PRETTY_FUNCTION__); + } + else { + AddError( _T("key or value is missing for JSON value")); + } + } + else { + // key or value are not empty + if ( parent.IsObject() ) { + if ( !value.IsValid() ) { + AddError( _T("cannot store the value: \'value\' is missing for JSON object type")); + } + else if ( key.empty() ) { + AddError( _T("cannot store the value: \'key\' is missing for JSON object type")); + } + else { + // OK, adding the value to parent key/value map + wxLogTrace( traceMask, _T("(%s) adding value to key:%s"), + __PRETTY_FUNCTION__, key.c_str()); + parent[key] = value; + m_lastStored = &(parent[key]); + m_lastStored->SetLineNo( m_lineNo ); + } + } + else if ( parent.IsArray() ) { + if ( !value.IsValid() ) { + AddError( _T("cannot store the item: \'value\' is missing for JSON array type")); + } + if ( !key.empty() ) { + AddError( _T("cannot store the item: \'key\' (\'%s\') is not permitted in JSON array type"), key); + } + wxLogTrace( traceMask, _T("(%s) appending value to parent array"), + __PRETTY_FUNCTION__ ); + parent.Append( value ); + const wxJSONInternalArray* arr = parent.AsArray(); + wxJSON_ASSERT( arr ); + m_lastStored = &(arr->Last()); + m_lastStored->SetLineNo( m_lineNo ); + } + else { + wxJSON_ASSERT( 0 ); // should never happen + } + } + value.SetType( wxJSONTYPE_INVALID ); + value.ClearComments(); +} + +//! Add a error message to the error's array +/*! + The overloaded versions of this function add an error message to the + error's array stored in \c m_errors. + The error message is formatted as follows: + + \code + Error: line xxx, col xxx - + \endcode + + The \c msg parameter is the description of the error; line's and column's + number are automatically added by the functions. + The \c fmt parameter is a format string that has the same syntax as the \b printf + function. + Note that it is the user's responsability to provide a format string suitable + with the arguments: another string or a character. +*/ +void +wxJSONReader::AddError( const wxString& msg ) +{ + wxString err; + err.Printf( _T("Error: line %d, col %d - %s"), m_lineNo, m_colNo, msg.c_str() ); + + wxLogTrace( traceMask, _T("(%s) %s"), __PRETTY_FUNCTION__, err.c_str()); + + if ( (int) m_errors.size() < m_maxErrors ) { + m_errors.Add( err ); + } + else if ( (int) m_errors.size() == m_maxErrors ) { + m_errors.Add( _T("ERROR: too many error messages - ignoring further errors")); + } + // else if ( m_errors > m_maxErrors ) do nothing, thus ignore the error message +} + +//! \overload AddError( const wxString& ) +void +wxJSONReader::AddError( const wxString& fmt, const wxString& str ) +{ + wxString s; + s.Printf( fmt.c_str(), str.c_str() ); + AddError( s ); +} + +//! \overload AddError( const wxString& ) +void +wxJSONReader::AddError( const wxString& fmt, wxChar c ) +{ + wxString s; + s.Printf( fmt.c_str(), c ); + AddError( s ); +} + +//! Add a warning message to the warning's array +/*! + The warning description is as follows: + \code + Warning: line xxx, col xxx - + \endcode + + Warning messages are generated by the parser when the JSON + text that has been read is not well-formed but the + error is not fatal and the parser recognizes the text + as an extension to the JSON standard (see the parser's ctor + for more info about wxJSON extensions). + + Note that the parser has to be constructed with a flag that + indicates if each individual wxJSON extension is on. + If the warning message is related to an extension that is not + enabled in the parser's \c m_flag data member, this function + calls AddError() and the warning message becomes an error + message. + The \c type parameter is one of the same constants that + specify the parser's extensions. + If type is ZERO than the function always adds a warning +*/ +void +wxJSONReader::AddWarning( int type, const wxString& msg ) +{ + // if 'type' AND 'm_flags' == 1 than the extension is + // ON. Otherwise it is OFF anf the function calls AddError() + if ( type != 0 ) { + if ( ( type & m_flags ) == 0 ) { + AddError( msg ); + return; + } + } + + wxString err; + err.Printf( _T( "Warning: line %d, col %d - %s"), m_lineNo, m_colNo, msg.c_str() ); + + wxLogTrace( traceMask, _T("(%s) %s"), __PRETTY_FUNCTION__, err.c_str()); + if ( (int) m_warnings.size() < m_maxErrors ) { + m_warnings.Add( err ); + } + else if ( (int) m_warnings.size() == m_maxErrors ) { + m_warnings.Add( _T("Error: too many warning messages - ignoring further warnings")); + } + // else do nothing, thus ignore the warning message +} + +//! Skip all whitespaces. +/*! + The function reads characters from the input text + and returns the first non-whitespace character read or -1 + if EOF. + Note that the function does not rely on the \b isspace function + of the C library but checks the space constants: space, TAB and + LF. +*/ +int +wxJSONReader::SkipWhiteSpace( wxInputStream& is ) +{ + // just read one byte at a time and check for whitespaces + int ch; + do { + ch = ReadChar( is ); + if ( ch < 0 ) { + break; + } + } + while ( ch == ' ' || ch == '\n' || ch == '\t' ); + wxLogTrace( traceMask, _T("(%s) end whitespaces line=%d col=%d"), + __PRETTY_FUNCTION__, m_lineNo, m_colNo ); + return ch; +} + +//! Skip a comment +/*! + The function is called by DoRead() when a '/' (slash) character + is read from the input stream assuming that a C/C++ comment is starting. + Returns the first character that follows the comment or + -1 on EOF. + The function also adds a warning message because comments are not + valid JSON text. + The function also stores the comment, if any, in the \c m_comment data + member: it can be used by the DoRead() function if comments have to be + stored in the value they refer to. +*/ +int +wxJSONReader::SkipComment( wxInputStream& is ) +{ + static const wxChar* warn = + _T("Comments may be tolerated in JSON text but they are not part of JSON syntax"); + + // if it is a comment, then a warning is added to the array + // otherwise it is an error: values cannot start with a '/' + // read the char next to the first slash + int ch = ReadChar( is ); + if ( ch < 0 ) { + return -1; + } + + wxLogTrace( storeTraceMask, _T("(%s) start comment line=%d col=%d"), + __PRETTY_FUNCTION__, m_lineNo, m_colNo ); + + // the temporary UTF-8/ANSI buffer that holds the comment string. This will be + // converted to a wxString object using wxString::FromUTF8() or From8BitData() + wxMemoryBuffer utf8Buff; + unsigned char c; + + if ( ch == '/' ) { // C++ comment, read until end-of-line + // C++ comment strings are in UTF-8 format. we store all + // UTF-8 code units until the first LF or CR+LF + AddWarning( wxJSONREADER_ALLOW_COMMENTS, warn ); + m_commentLine = m_lineNo; + utf8Buff.AppendData( "//", 2 ); + + while ( ch >= 0 ) { + if ( ch == '\n' ) { + break; + } + if ( ch == '\r' ) { + ch = PeekChar( is ); + if ( ch == '\n' ) { + ch = ReadChar( is ); + } + break; + } + else { + // store the char in the UTF8 temporary buffer + c = (unsigned char) ch; + utf8Buff.AppendByte( c ); + } + ch = ReadChar( is ); + } + // now convert the temporary UTF-8 buffer + m_comment = wxString::FromUTF8( (const char*) utf8Buff.GetData(), + utf8Buff.GetDataLen()); + } + + // check if a C-style comment + else if ( ch == '*' ) { // C-style comment + AddWarning(wxJSONREADER_ALLOW_COMMENTS, warn ); + m_commentLine = m_lineNo; + utf8Buff.AppendData( "/*", 2 ); + while ( ch >= 0 ) { + // check the END-COMMENT chars ('*/') + if ( ch == '*' ) { + ch = PeekChar( is ); + if ( ch == '/' ) { + ch = ReadChar( is ); // read the '/' char + ch = ReadChar( is ); // read the next char that will be returned + utf8Buff.AppendData( "*/", 2 ); + break; + } + } + // store the char in the UTF8 temporary buffer + c = (unsigned char) ch; + utf8Buff.AppendByte( c ); + ch = ReadChar( is ); + } + // now convert the temporary buffer in a wxString object + if ( m_noUtf8 ) { + m_comment = wxString::From8BitData( (const char*) utf8Buff.GetData(), + utf8Buff.GetDataLen()); + } + else { + m_comment = wxString::FromUTF8( (const char*) utf8Buff.GetData(), + utf8Buff.GetDataLen()); + } + } + + else { // it is not a comment, return the character next the first '/' + AddError( _T( "Strange '/' (did you want to insert a comment?)")); + // we read until end-of-line OR end of C-style comment OR EOF + // because a '/' should be a start comment + while ( ch >= 0 ) { + ch = ReadChar( is ); + if ( ch == '*' && PeekChar( is ) == '/' ) { + break; + } + if ( ch == '\n' ) { + break; + } + } + // read the next char that will be returned + ch = ReadChar( is ); + } + wxLogTrace( traceMask, _T("(%s) end comment line=%d col=%d"), + __PRETTY_FUNCTION__, m_lineNo, m_colNo ); + wxLogTrace( storeTraceMask, _T("(%s) end comment line=%d col=%d"), + __PRETTY_FUNCTION__, m_lineNo, m_colNo ); + wxLogTrace( storeTraceMask, _T("(%s) comment=%s"), + __PRETTY_FUNCTION__, m_comment.c_str()); + return ch; +} + +//! Read a string value +/*! + The function reads a string value from input stream and it is + called by the \c DoRead() function when it enconters the + double quote characters. + The function read all bytes up to the next double quotes + (unless it is escaped) and stores them in a temporary UTF-8 + memory buffer. + Also, the function processes the escaped characters defined + in the JSON syntax. + + Next, the function tries to convert the UTF-8 buffer to a + \b wxString object using the \b wxString::FromUTF8 function. + Depending on the build mode, we can have the following: + \li in Unicode the function always succeeds, provided that the + buffer contains valid UTF-8 code units. + + \li in ANSI builds the conversion may fail because of the presence of + unrepresentable characters in the current locale. In this case, + the default behaviour is to perform a char-by-char conversion; every + char that cannot be represented in the current locale is stored as + \e unicode \e escaped \e sequence + + \li in ANSI builds, if the reader is constructed with the wxJSONREADER_NOUTF8_STREAM + then no conversion takes place and the UTF-8 temporary buffer is simply + \b copied to the \b wxString object + + The string is, finally, stored in the provided wxJSONValue argument + provided that it is empty or it contains a string value. + This is because the parser class recognizes multi-line strings + like the following one: + \code + [ + "This is a very long string value which is splitted into more" + "than one line because it is more human readable" + ] + \endcode + Because of the lack of the value separator (,) the parser + assumes that the string was splitted into several double-quoted + strings. + If the value does not contain a string then an error is + reported. + Splitted strings cause the parser to report a warning. +*/ +int +wxJSONReader::ReadString( wxInputStream& is, wxJSONValue& val ) +{ + // the char last read is the opening qoutes (") + + wxMemoryBuffer utf8Buff; + char ues[8]; // stores a Unicode Escaped Esquence: \uXXXX + + int ch = 0; + while ( ch >= 0 ) { + ch = ReadChar( is ); + unsigned char c = (unsigned char) ch; + if ( ch == '\\' ) { // an escape sequence + ch = ReadChar( is ); + switch ( ch ) { + case -1 : // EOF + break; + case 't' : + utf8Buff.AppendByte( '\t' ); + break; + case 'n' : + utf8Buff.AppendByte( '\n' ); + break; + case 'b' : + utf8Buff.AppendByte( '\b' ); + break; + case 'r' : + utf8Buff.AppendByte( '\r' ); + break; + case '\"' : + utf8Buff.AppendByte( '\"' ); + break; + case '\\' : + utf8Buff.AppendByte( '\\' ); + break; + case '/' : + utf8Buff.AppendByte( '/' ); + break; + case 'f' : + utf8Buff.AppendByte( '\f' ); + break; + case 'u' : + ch = ReadUES( is, ues ); + if ( ch < 0 ) { // if EOF, returns + return ch; + } + // append the escaped character to the UTF8 buffer + AppendUES( utf8Buff, ues ); + // many thanks to Bryan Ashby who discovered this bug + continue; + // break; + default : + AddError( _T( "Unknow escaped character \'\\%c\'"), ch ); + } + } + else { + // we have read a non-escaped character so we have to append it to + // the temporary UTF-8 buffer until the next quote char + if ( ch == '\"' ) { + break; + } + utf8Buff.AppendByte( c ); + } + } + + // if UTF-8 conversion is disabled (ANSI builds only) we just copy the + // bit data to a wxString object + wxString s; + if ( m_noUtf8 ) { + s = wxString::From8BitData( (const char*) utf8Buff.GetData(), utf8Buff.GetDataLen()); + } + else { + // perform UTF-8 conversion + // first we check that the UTF-8 buffer is correct, i.e. it contains valid + // UTF-8 code points. + // this works in both ANSI and Unicode builds. + size_t convLen = wxConvUTF8.ToWChar( 0, // wchar_t destination + 0, // size_t destLenght + (const char*) utf8Buff.GetData(), // char_t source + utf8Buff.GetDataLen()); // size_t sourceLenght + + if ( convLen == wxCONV_FAILED ) { + AddError( _T( "String value: the UTF-8 stream is invalid")); + s.append( _T( "")); + } + else { +#if defined( wxJSON_USE_UNICODE ) + // in Unicode just convert to wxString + s = wxString::FromUTF8( (const char*) utf8Buff.GetData(), utf8Buff.GetDataLen()); +#else + // in ANSI, the conversion may fail and an empty string is returned + // in this case, the reader do a char-by-char conversion storing + // unicode escaped sequences of unrepresentable characters + s = wxString::FromUTF8( (const char*) utf8Buff.GetData(), utf8Buff.GetDataLen()); + if ( s.IsEmpty() ) { + int r = ConvertCharByChar( s, utf8Buff ); // return number of escaped sequences + if ( r > 0 ) { + AddWarning( 0, _T( "The string value contains unrepresentable Unicode characters")); + } + } +#endif + } + } + wxLogTrace( traceMask, _T("(%s) line=%d col=%d"), + __PRETTY_FUNCTION__, m_lineNo, m_colNo ); + wxLogTrace( traceMask, _T("(%s) string read=%s"), + __PRETTY_FUNCTION__, s.c_str() ); + wxLogTrace( traceMask, _T("(%s) value=%s"), + __PRETTY_FUNCTION__, val.AsString().c_str() ); + + // now assign the string to the JSON-value 'value' + // must check that: + // 'value' is empty + // 'value' is a string; concatenate it but emit warning + if ( !val.IsValid() ) { + wxLogTrace( traceMask, _T("(%s) assigning the string to value"), __PRETTY_FUNCTION__ ); + val = s ; + } + else if ( val.IsString() ) { + AddWarning( wxJSONREADER_MULTISTRING, + _T("Multiline strings are not allowed by JSON syntax") ); + wxLogTrace( traceMask, _T("(%s) concatenate the string to value"), __PRETTY_FUNCTION__ ); + val.Cat( s ); + } + else { + AddError( _T( "String value \'%s\' cannot follow another value"), s ); + } + + // store the input text's line number when the string was stored in 'val' + val.SetLineNo( m_lineNo ); + + // read the next char after the closing quotes and returns it + if ( ch >= 0 ) { + ch = ReadChar( is ); + } + return ch; +} + +//! Reads a token string +/*! + This function is called by the ReadValue() when the + first character encontered is not a special char + and it is not a double-quote. + The only possible type is a literal or a number which + all lies in the US-ASCII charset so their UTF-8 encodeing + is the same as US-ASCII. + The function simply reads one byte at a time from the stream + and appends them to a \b wxString object. + Returns the next character read. + + A token cannot include \e unicode \e escaped \e sequences + so this function does not try to interpret such sequences. + + @param is the input stream + @param ch the character read by DoRead + @param s the string object that contains the token read + @return -1 in case of errors or EOF +*/ +int +wxJSONReader::ReadToken( wxInputStream& is, int ch, wxString& s ) +{ + int nextCh = ch; + while ( nextCh >= 0 ) { + switch ( nextCh ) { + case ' ' : + case ',' : + case ':' : + case '[' : + case ']' : + case '{' : + case '}' : + case '\t' : + case '\n' : + case '\r' : + case '\b' : + wxLogTrace( traceMask, _T("(%s) line=%d col=%d"), + __PRETTY_FUNCTION__, m_lineNo, m_colNo ); + wxLogTrace( traceMask, _T("(%s) token read=%s"), + __PRETTY_FUNCTION__, s.c_str() ); + return nextCh; + break; + default : + s.Append( (unsigned char) nextCh, 1 ); + break; + } + // read the next character + nextCh = ReadChar( is ); + } + wxLogTrace( traceMask, _T("(%s) EOF on line=%d col=%d"), + __PRETTY_FUNCTION__, m_lineNo, m_colNo ); + wxLogTrace( traceMask, _T("(%s) EOF - token read=%s"), + __PRETTY_FUNCTION__, s.c_str() ); + return nextCh; +} + +//! Read a value from input stream +/*! + The function is called by DoRead() when it enconters a char that is + not a special char nor a double-quote. + It assumes that the string is a numeric value or a literal + boolean value and stores it in the wxJSONValue object \c val. + + The function also checks that \c val is of type wxJSONTYPE_INVALID otherwise + an error is reported becasue a value cannot follow another value: + maybe a (,) or (:) is missing. + + If the literal starts with a digit, a plus or minus sign, the function + tries to interpret it as a number. The following are tried by the function, + in this order: + + \li if the literal starts with a digit: signed integer, then unsigned integer + and finally double conversion is tried + \li if the literal starts with a minus sign: signed integer, then double + conversion is tried + \li if the literal starts with plus sign: unsigned integer + then double conversion is tried + + Returns the next character or -1 on EOF. +*/ +int +wxJSONReader::ReadValue( wxInputStream& is, int ch, wxJSONValue& val ) +{ + wxString s; + int nextCh = ReadToken( is, ch, s ); + wxLogTrace( traceMask, _T("(%s) value=%s"), + __PRETTY_FUNCTION__, val.AsString().c_str() ); + + if ( val.IsValid() ) { + AddError( _T( "Value \'%s\' cannot follow a value: \',\' or \':\' missing?"), s ); + return nextCh; + } + + // variables used for converting numeric values + bool r; double d; +#if defined( wxJSON_64BIT_INT ) + wxInt64 i64; + wxUint64 ui64; +#else + unsigned long int ul; long int l; +#endif + + // first try the literal strings lowercase and nocase + if ( s == _T("null") ) { + val.SetType( wxJSONTYPE_NULL ); + wxLogTrace( traceMask, _T("(%s) value = NULL"), __PRETTY_FUNCTION__ ); + return nextCh; + } + else if ( s.CmpNoCase( _T( "null" )) == 0 ) { + wxLogTrace( traceMask, _T("(%s) value = NULL"), __PRETTY_FUNCTION__ ); + AddWarning( wxJSONREADER_CASE, _T( "the \'null\' literal must be lowercase" )); + val.SetType( wxJSONTYPE_NULL ); + return nextCh; + } + else if ( s == _T("true") ) { + wxLogTrace( traceMask, _T("(%s) value = TRUE"), __PRETTY_FUNCTION__ ); + val = true; + return nextCh; + } + else if ( s.CmpNoCase( _T( "true" )) == 0 ) { + wxLogTrace( traceMask, _T("(%s) value = TRUE"), __PRETTY_FUNCTION__ ); + AddWarning( wxJSONREADER_CASE, _T( "the \'true\' literal must be lowercase" )); + val = true; + return nextCh; + } + else if ( s == _T("false") ) { + wxLogTrace( traceMask, _T("(%s) value = FALSE"), __PRETTY_FUNCTION__ ); + val = false; + return nextCh; + } + else if ( s.CmpNoCase( _T( "false" )) == 0 ) { + wxLogTrace( traceMask, _T("(%s) value = FALSE"), __PRETTY_FUNCTION__ ); + AddWarning( wxJSONREADER_CASE, _T( "the \'false\' literal must be lowercase" )); + val = false; + return nextCh; + } + + + // try to convert to a number if the token starts with a digit, a plus or a minus + // sign. The function first states what type of conversion are tested: + // 1. first signed integer (not if 'ch' == '+') + // 2. unsigned integer (not if 'ch' == '-') + // 3. finally double + bool tSigned = true, tUnsigned = true, tDouble = true; + switch ( ch ) { + case '0' : + case '1' : + case '2' : + case '3' : + case '4' : + case '5' : + case '6' : + case '7' : + case '8' : + case '9' : + // first try a signed integer, then a unsigned integer, then a double + break; + + case '+' : + // the plus sign forces a unsigned integer + tSigned = false; + break; + + case '-' : + // try signed and double + tUnsigned = false; + break; + default : + AddError( _T( "Literal \'%s\' is incorrect (did you forget quotes?)"), s ); + return nextCh; + } + + if ( tSigned ) { + #if defined( wxJSON_64BIT_INT) + r = Strtoll( s, &i64 ); + wxLogTrace( traceMask, _T("(%s) convert to wxInt64 result=%d"), + __PRETTY_FUNCTION__, r ); + if ( r ) { + // store the value + val = i64; + return nextCh; + } + #else + r = s.ToLong( &l ); + wxLogTrace( traceMask, _T("(%s) convert to int result=%d"), + __PRETTY_FUNCTION__, r ); + if ( r ) { + // store the value + val = (int) l; + return nextCh; + } + #endif + } + + if ( tUnsigned ) { + #if defined( wxJSON_64BIT_INT) + r = Strtoull( s, &ui64 ); + wxLogTrace( traceMask, _T("(%s) convert to wxUint64 result=%d"), + __PRETTY_FUNCTION__, r ); + if ( r ) { + // store the value + val = ui64; + return nextCh; + } + #else + r = s.ToULong( &ul ); + wxLogTrace( traceMask, _T("(%s) convert to int result=%d"), + __PRETTY_FUNCTION__, r ); + if ( r ) { + // store the value + val = (unsigned int) ul; + return nextCh; + } + #endif + } + + if ( tDouble ) { + r = s.ToDouble( &d ); + wxLogTrace( traceMask, _T("(%s) convert to double result=%d"), + __PRETTY_FUNCTION__, r ); + if ( r ) { + // store the value + val = d; + return nextCh; + } + } + + + // the value is not syntactically correct + AddError( _T( "Literal \'%s\' is incorrect (did you forget quotes?)"), s ); + return nextCh; + return nextCh; +} + + +//! Read a 4-hex-digit unicode character. +/*! + The function is called by ReadString() when the \b \\u sequence is + encontered; the sequence introduces a control character in the form: + \code + \uXXXX + \endcode + where XXXX is a four-digit hex code.. + The function reads four chars from the input UTF8 stream by calling ReadChar() + four times: if EOF is encontered before reading four chars, -1 is + also returned and no sequence interpretation is performed. + The function stores the 4 hexadecimal digits in the \c uesBuffer parameter. + + Returns the character after the hex sequence or -1 if EOF. + + \b NOTICE: although the JSON syntax states that only control characters + are represented in this way, the wxJSON library reads and recognizes all + unicode characters in the BMP. +*/ +int +wxJSONReader::ReadUES( wxInputStream& is, char* uesBuffer ) +{ + int ch; + for ( int i = 0; i < 4; i++ ) { + ch = ReadChar( is ); + if ( ch < 0 ) { + return ch; + } + uesBuffer[i] = (unsigned char) ch; + } + uesBuffer[4] = 0; // makes a ASCIIZ string + + return 0; +} + + +//! The function appends a Unice Escaped Sequence to the temporary UTF8 buffer +/*! + This function is called by \c ReadString() when a \e unicode \e escaped + \e sequence is read from the input text as for example: + + \code + \u0001 + \endcode + + which represents a control character. + The \c uesBuffer parameter contains the 4 hexadecimal digits that are + read from \c ReadUES. + + The function tries to convert the 4 hex digits in a \b wchar_t character + which is appended to the memory buffer \c utf8Buff after converting it + to UTF-8. + + If the conversion from hexadecimal fails, the function does not + store the character in the UTF-8 buffer and an error is reported. + The function is the same in ANSI and Unicode. + Returns -1 if the buffer does not contain valid hex digits. + sequence. On success returns ZERO. + + @param utf8Buff the UTF-8 buffer to which the control char is written + @param uesBuffer the four-hex-digits read from the input text + @return ZERO on success, -1 if the four-hex-digit buffer cannot be converted +*/ +int +wxJSONReader::AppendUES( wxMemoryBuffer& utf8Buff, const char* uesBuffer ) +{ + unsigned long l; + int r = sscanf( uesBuffer, "%lx", &l ); // r is the assigned items + if ( r != 1 ) { + AddError( _T( "Invalid Unicode Escaped Sequence")); + return -1; + } + wxLogTrace( traceMask, _T("(%s) unicode sequence=%s code=%ld"), + __PRETTY_FUNCTION__, uesBuffer, l ); + + wchar_t ch = (wchar_t) l; + char buffer[16]; + size_t len = wxConvUTF8.FromWChar( buffer, 10, &ch, 1 ); + + // seems that the wxMBConv classes always appends a NULL byte to + // the converted buffer + //if ( len > 1 ) { + // len = len - 1; + //} + utf8Buff.AppendData( buffer, len ); + + // sould never fail + wxASSERT( len != wxCONV_FAILED ); + return 0; +} + +//! Store the comment string in the value it refers to. +/*! + The function searches a suitable value object for storing the + comment line that was read by the parser and temporarly + stored in \c m_comment. + The function searches the three values pointed to by: + \li \c m_next + \li \c m_current + \li \c m_lastStored + + The value that the comment refers to is: + + \li if the comment is on the same line as one of the values, the comment + refer to that value and it is stored as \b inline. + \li otherwise, if the comment flag is wxJSONREADER_COMMENTS_BEFORE, the comment lines + are stored in the value pointed to by \c m_next + \li otherwise, if the comment flag is wxJSONREADER_COMMENTS_AFTER, the comment lines + are stored in the value pointed to by \c m_current or m_latStored + + Note that the comment line is only stored if the wxJSONREADER_STORE_COMMENTS + flag was used when the parser object was constructed; otherwise, the + function does nothing and immediatly returns. + Also note that if the comment line has to be stored but the + function cannot find a suitable value to add the comment line to, + an error is reported (note: not a warning but an error). +*/ +void +wxJSONReader::StoreComment( const wxJSONValue* parent ) +{ + wxLogTrace( storeTraceMask, _T("(%s) m_comment=%s"), __PRETTY_FUNCTION__, m_comment.c_str()); + wxLogTrace( storeTraceMask, _T("(%s) m_flags=%d m_commentLine=%d"), + __PRETTY_FUNCTION__, m_flags, m_commentLine ); + wxLogTrace( storeTraceMask, _T("(%s) m_current=%p"), __PRETTY_FUNCTION__, m_current ); + wxLogTrace( storeTraceMask, _T("(%s) m_next=%p"), __PRETTY_FUNCTION__, m_next ); + wxLogTrace( storeTraceMask, _T("(%s) m_lastStored=%p"), __PRETTY_FUNCTION__, m_lastStored ); + + // first check if the 'store comment' bit is on + if ( (m_flags & wxJSONREADER_STORE_COMMENTS) == 0 ) { + m_comment.clear(); + return; + } + + // check if the comment is on the same line of one of the + // 'current', 'next' or 'lastStored' value + if ( m_current != 0 ) { + wxLogTrace( storeTraceMask, _T("(%s) m_current->lineNo=%d"), + __PRETTY_FUNCTION__, m_current->GetLineNo() ); + if ( m_current->GetLineNo() == m_commentLine ) { + wxLogTrace( storeTraceMask, _T("(%s) comment added to \'m_current\' INLINE"), + __PRETTY_FUNCTION__ ); + m_current->AddComment( m_comment, wxJSONVALUE_COMMENT_INLINE ); + m_comment.clear(); + return; + } + } + if ( m_next != 0 ) { + wxLogTrace( storeTraceMask, _T("(%s) m_next->lineNo=%d"), + __PRETTY_FUNCTION__, m_next->GetLineNo() ); + if ( m_next->GetLineNo() == m_commentLine ) { + wxLogTrace( storeTraceMask, _T("(%s) comment added to \'m_next\' INLINE"), + __PRETTY_FUNCTION__ ); + m_next->AddComment( m_comment, wxJSONVALUE_COMMENT_INLINE ); + m_comment.clear(); + return; + } + } + if ( m_lastStored != 0 ) { + wxLogTrace( storeTraceMask, _T("(%s) m_lastStored->lineNo=%d"), + __PRETTY_FUNCTION__, m_lastStored->GetLineNo() ); + if ( m_lastStored->GetLineNo() == m_commentLine ) { + wxLogTrace( storeTraceMask, _T("(%s) comment added to \'m_lastStored\' INLINE"), + __PRETTY_FUNCTION__ ); + m_lastStored->AddComment( m_comment, wxJSONVALUE_COMMENT_INLINE ); + m_comment.clear(); + return; + } + } + + // if comment is BEFORE, store the comment in the 'm_next' + // or 'm_current' value + // if comment is AFTER, store the comment in the 'm_lastStored' + // or 'm_current' value + + if ( m_flags & wxJSONREADER_COMMENTS_AFTER ) { // comment AFTER + if ( m_current ) { + if ( m_current == parent || !m_current->IsValid()) { + AddError( _T("Cannot find a value for storing the comment (flag AFTER)")); + } + else { + wxLogTrace( storeTraceMask, _T("(%s) comment added to m_current (AFTER)"), + __PRETTY_FUNCTION__ ); + m_current->AddComment( m_comment, wxJSONVALUE_COMMENT_AFTER ); + } + } + else if ( m_lastStored ) { + wxLogTrace( storeTraceMask, _T("(%s) comment added to m_lastStored (AFTER)"), + __PRETTY_FUNCTION__ ); + m_lastStored->AddComment( m_comment, wxJSONVALUE_COMMENT_AFTER ); + } + else { + wxLogTrace( storeTraceMask, + _T("(%s) cannot find a value for storing the AFTER comment"), __PRETTY_FUNCTION__ ); + AddError(_T("Cannot find a value for storing the comment (flag AFTER)")); + } + } + else { // comment BEFORE can only be added to the 'next' value + if ( m_next ) { + wxLogTrace( storeTraceMask, _T("(%s) comment added to m_next (BEFORE)"), + __PRETTY_FUNCTION__ ); + m_next->AddComment( m_comment, wxJSONVALUE_COMMENT_BEFORE ); + } + else { + // cannot find a value for storing the comment + AddError(_T("Cannot find a value for storing the comment (flag BEFORE)")); + } + } + m_comment.clear(); +} + + +//! Return the number of bytes that make a character in stream input +/*! + This function returns the number of bytes that represent a unicode + code point in various encoding. + For example, if the input stream is UTF-32 the function returns 4. + Because the only recognized format for streams is UTF-8 the function + just calls UTF8NumBytes() and returns. + The function is, actually, not used at all. + +*/ +int +wxJSONReader::NumBytes( char ch ) +{ + int n = UTF8NumBytes( ch ); + return n; +} + +//! Compute the number of bytes that makes a UTF-8 encoded wide character. +/*! + The function counts the number of '1' bit in the character \c ch and + returns it. + The UTF-8 encoding specifies the number of bytes needed by a wide character + by coding it in the first byte. See below. + + Note that if the character does not contain a valid UTF-8 encoding + the function returns -1. + +\code + UCS-4 range (hex.) UTF-8 octet sequence (binary) + ------------------- ----------------------------- + 0000 0000-0000 007F 0xxxxxxx + 0000 0080-0000 07FF 110xxxxx 10xxxxxx + 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx + 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx +\endcode +*/ +int +wxJSONReader::UTF8NumBytes( char ch ) +{ + int num = 0; // the counter of '1' bits + for ( int i = 0; i < 8; i++ ) { + if ( (ch & 0x80) == 0 ) { + break; + } + ++num; + ch = ch << 1; + } + + // note that if the char contains more than six '1' bits it is not + // a valid UTF-8 encoded character + if ( num > 6 ) { + num = -1; + } + else if ( num == 0 ) { + num = 1; + } + return num; +} + +//! Convert a UTF-8 memory buffer one char at a time +/*! + This function is used in ANSI mode when input from a stream is in UTF-8 + format and the UTF-8 buffer read cannot be converted to the locale + wxString object. + The function performs a char-by-char conversion of the buffer and appends + every representable character to the string \c s. + Characters that cannot be represented are stored as \e unicode \e escaped + \e sequences in the form: + \code + \uXXXX + \endcode + where XXXX is a for-hex-digits Unicode code point. + The function returns the number of characters that cannot be represented + in the current locale. +*/ +int +wxJSONReader::ConvertCharByChar( wxString& s, const wxMemoryBuffer& utf8Buffer ) +{ + size_t len = utf8Buffer.GetDataLen(); + char* buff = (char*) utf8Buffer.GetData(); + char* buffEnd = buff + len; + + int result = 0; + char temp[16]; // the UTF-8 code-point + + while ( buff < buffEnd ) { + temp[0] = *buff; // the first UTF-8 code-unit + // compute the number of code-untis that make one UTF-8 code-point + int numBytes = NumBytes( *buff ); + ++buff; + for ( int i = 1; i < numBytes; i++ ) { + if ( buff >= buffEnd ) { + break; + } + temp[i] = *buff; // the first UTF-8 code-unit + ++buff; + } + //if ( buff >= buffEnd ) { + // break; + //} + // now convert 'temp' to a wide-character + wchar_t dst[10]; + size_t outLength = wxConvUTF8.ToWChar( dst, 10, temp, numBytes ); + + // now convert the wide char to a locale dependent character + // len = wxConvLocal.FromWChar( temp, 16, dst, outLength ); + // len = wxConviso8859_1.FromWChar( temp, 16, dst, outLength ); + len = wxConvLibc.FromWChar( temp, 16, dst, outLength ); + if ( len == wxCONV_FAILED ) { + ++result; + wxString t; + t.Printf( _T( "\\u%04X"), (int) dst[0] ); + s.Append( t ); + } + else { + s.Append( temp[0], 1 ); + } + } // end while + return result; +} + +//! Read a memory buffer type +/*! + This function is called by DoRead() when the single-quote character is + encontered which starts a \e memory \e buffer type. + This type is a \b wxJSON extension so the function emits a warning + when such a type encontered. + If the reader is constructed without the \c wxJSONREADER_MEMORYBUFF flag + then the warning becomes an error. + To know more about this JSON syntax extension read \ref wxjson_tutorial_memorybuff + + @param is the input stream + @param val the JSON value that will hold the memory buffer value + @return the last char read or -1 in case of EOF +*/ + +//union byte +//{ +// unsigned char c[2]; +// short int b; +//}; + +int +wxJSONReader::ReadMemoryBuff( wxInputStream& is, wxJSONValue& val ) +{ + static const wxChar* membuffError = _T("the \'memory buffer\' type contains %d invalid digits" ); + + AddWarning( wxJSONREADER_MEMORYBUFF, _T( "the \'memory buffer\' type is not valid JSON text" )); + + wxMemoryBuffer buff; + int ch = 0; int errors = 0; + unsigned char byte = 0; + while ( ch >= 0 ) { + ch = ReadChar( is ); + if ( ch < 0 ) { + break; + } + if ( ch == '\'' ) { + break; + } + // the conversion is done two chars at a time + unsigned char c1 = (unsigned char) ch; + ch = ReadChar( is ); + if ( ch < 0 ) { + break; + } + unsigned char c2 = (unsigned char) ch; + c1 -= '0'; + c2 -= '0'; + if ( c1 > 9 ) { + c1 -= 7; + } + if ( c2 > 9 ) { + c2 -= 7; + } + if ( c1 > 15 ) { + ++errors; + } + else if ( c2 > 15 ) { + ++errors; + } + else { + byte = (c1 * 16) + c2; + buff.AppendByte( byte ); + } + } // end while + + if ( errors > 0 ) { + wxString err; + err.Printf( membuffError, errors ); + AddError( err ); + } + + + // now assign the memory buffer object to the JSON-value 'value' + // must check that: + // 'value' is invalid OR + // 'value' is a memory buffer; concatenate it + if ( !val.IsValid() ) { + wxLogTrace( traceMask, _T("(%s) assigning the memory buffer to value"), __PRETTY_FUNCTION__ ); + val = buff ; + } + else if ( val.IsMemoryBuff() ) { + wxLogTrace( traceMask, _T("(%s) concatenate memory buffer to value"), __PRETTY_FUNCTION__ ); + val.Cat( buff ); + } + else { + AddError( _T( "Memory buffer value cannot follow another value") ); + } + + // store the input text's line number when the string was stored in 'val' + val.SetLineNo( m_lineNo ); + + // read the next char after the closing quotes and returns it + if ( ch >= 0 ) { + ch = ReadChar( is ); + } + return ch; +} + + + + +#if defined( wxJSON_64BIT_INT ) +//! Converts a decimal string to a 64-bit signed integer +/*! + This function implements a simple variant + of the \b strtoll C-library function. + I needed this implementation because the wxString::To(U)LongLong + function does not work on my system: + + \li GNU/Linux Fedora Core 6 + \li GCC version 4.1.1 + \li libc.so.6 + + The wxWidgets library (actually I have installed version 2.8.7) + relies on \b strtoll in order to do the conversion from a string + to a long long integer but, in fact, it does not work because + the 'wxHAS_STRTOLL' macro is not defined on my system. + The problem only affects the Unicode builds while it seems + that the wxString::To(U)LongLong function works in ANSI builds. + + Note that this implementation is not a complete substitute of the + strtoll function because it only converts decimal strings (only base + 10 is implemented). + + @param str the string that contains the decimal literal + @param i64 the pointer to long long which holds the converted value + + @return TRUE if the conversion succeeds +*/ +bool +wxJSONReader::Strtoll( const wxString& str, wxInt64* i64 ) +{ + wxChar sign = ' '; + wxUint64 ui64; + bool r = DoStrto_ll( str, &ui64, &sign ); + + // check overflow for signed long long + switch ( sign ) { + case '-' : + if ( ui64 > (wxUint64) LLONG_MAX + 1 ) { + r = false; + } + else { + *i64 = (wxInt64) (ui64 * -1); + } + break; + + // case '+' : + default : + if ( ui64 > LLONG_MAX ) { + r = false; + } + else { + *i64 = (wxInt64) ui64; + } + break; + } + return r; +} + + +//! Converts a decimal string to a 64-bit unsigned integer. +/*! + Similar to \c Strtoll but for unsigned integers +*/ +bool +wxJSONReader::Strtoull( const wxString& str, wxUint64* ui64 ) +{ + wxChar sign = ' '; + bool r = DoStrto_ll( str, ui64, &sign ); + if ( sign == '-' ) { + r = false; + } + return r; +} + +//! Perform the actual conversion from a string to a 64-bit integer +/*! + This function is called internally by the \c Strtoll and \c Strtoull functions + and it does the actual conversion. + The function is also able to check numeric overflow. + + @param str the string that has to be converted + @param ui64 the pointer to a unsigned long long that holds the converted value + @param sign the pointer to a wxChar character that will get the sign of the literal string, if any + @return TRUE if the conversion succeeds +*/ +bool +wxJSONReader::DoStrto_ll( const wxString& str, wxUint64* ui64, wxChar* sign ) +{ + // the conversion is done by multiplying the individual digits + // in reverse order to the corresponding power of 10 + // + // 10's power: 987654321.9876543210 + // + // LLONG_MAX: 9223372036854775807 + // LLONG_MIN: -9223372036854775808 + // ULLONG_MAX: 18446744073709551615 + // + // the function does not take into account the sign: only a + // unsigned long long int is returned + + int maxDigits = 20; // 20 + 1 (for the sign) + + wxUint64 power10[] = { + wxULL(1), + wxULL(10), + wxULL(100), + wxULL(1000), + wxULL(10000), + wxULL(100000), + wxULL(1000000), + wxULL(10000000), + wxULL(100000000), + wxULL(1000000000), + wxULL(10000000000), + wxULL(100000000000), + wxULL(1000000000000), + wxULL(10000000000000), + wxULL(100000000000000), + wxULL(1000000000000000), + wxULL(10000000000000000), + wxULL(100000000000000000), + wxULL(1000000000000000000), + wxULL(10000000000000000000) + }; + + + wxUint64 temp1 = wxULL(0); // the temporary converted integer + + int strLen = str.length(); + if ( strLen == 0 ) { + // an empty string is converted to a ZERO value: the function succeeds + *ui64 = wxLL(0); + return true; + } + + int index = 0; + wxChar ch = str[0]; + if ( ch == '+' || ch == '-' ) { + *sign = ch; + ++index; + ++maxDigits; + } + + if ( strLen > maxDigits ) { + return false; + } + + // check the overflow: check the string length and the individual digits + // of the string; the overflow is checked for unsigned long long + if ( strLen == maxDigits ) { + wxString uLongMax( _T("18446744073709551615")); + int j = 0; + for ( int i = index; i < strLen - 1; i++ ) { + ch = str[i]; + if ( ch < '0' || ch > '9' ) { + return false; + } + if ( ch > uLongMax[j] ) { + return false; + } + if ( ch < uLongMax[j] ) { + break; + } + ++j; + } + } + + // get the digits in the reverse order and multiply them by the + // corresponding power of 10 + int exponent = 0; + for ( int i = strLen - 1; i >= index; i-- ) { + wxChar ch = str[i]; + if ( ch < '0' || ch > '9' ) { + return false; + } + ch = ch - '0'; + // compute the new temporary value + temp1 += ch * power10[exponent]; + ++exponent; + } + *ui64 = temp1; + return true; +} + +#endif // defined( wxJSON_64BIT_INT ) + +/* +{ +} +*/ + + + diff --git a/ThirdParty/wxJSON/src/jsonval.cpp b/ThirdParty/wxJSON/src/jsonval.cpp new file mode 100644 index 0000000..85f053b --- /dev/null +++ b/ThirdParty/wxJSON/src/jsonval.cpp @@ -0,0 +1,3561 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: jsonval.cpp +// Purpose: the wxJSON class that holds a JSON value +// Author: Luciano Cattani +// Created: 2007/10/01 +// RCS-ID: $Id: jsonval.cpp,v 1.12 2008/03/06 10:25:18 luccat Exp $ +// Copyright: (c) 2007 Luciano Cattani +// Licence: wxWidgets licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ + #pragma implementation "jsonval.cpp" +#endif + + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#include +#include +#include + +#include + + +WX_DEFINE_OBJARRAY( wxJSONInternalArray ); + + +// the trace mask used in wxLogTrace() function +// static const wxChar* traceMask = _T("jsonval"); +static const wxChar* traceMask = _T("jsonval"); +static const wxChar* compareTraceMask = _T("sameas"); +static const wxChar* cowTraceMask = _T("traceCOW" ); + + + +/******************************************************************* + + class wxJSONRefData + +*******************************************************************/ + + +/*! \class wxJSONRefData + \brief The reference counted JSON value data (internal use). + + Starting from version 0.4, the JSON value class use the reference + counting tecnique (also know as \e copy-on-write) described in the + \b wxWidgets documentation in order to speed up processing. + The class is used internally by the wxJSONValue class which does + all processing. + To know more about COW see \ref json_internals_cow +*/ + +#if defined( WXJSON_USE_VALUE_COUNTER ) + // The progressive counter (used for debugging only) + int wxJSONRefData::sm_progr = 1; +#endif + +//! Constructor. +wxJSONRefData::wxJSONRefData() +{ + m_lineNo = -1; + m_refCount = 1; + m_memBuff = 0; + +#if defined( WXJSON_USE_VALUE_COUNTER ) + m_progr = sm_progr; + ++sm_progr; + wxLogTrace( traceMask, _T("(%s) JSON refData ctor progr=%d"), + __PRETTY_FUNCTION__, m_progr); +#endif +} + +// Dtor +wxJSONRefData::~wxJSONRefData() +{ + if ( m_memBuff ) { + delete m_memBuff; + } +} + +// Return the number of objects that reference this data. +int +wxJSONRefData::GetRefCount() const +{ + return m_refCount; +} + + +/******************************************************************* + + class wxJSONValue + +*******************************************************************/ + + +/*! \class wxJSONValue + \brief The JSON value class implementation. + +This class holds a JSON value which may be of variuos types (see the +wxJSONType constants for a description of the types). +To know more about the internal representation of JSON values see +\ref pg_json_internals. + +Starting from version 0.5 the wxJSON library supports 64-bits integers on +platforms that have native support for very large integers. +Note that the integer type is still stored as a generic wxJSONTYPE_(U)INT +constant regardless the size of the value but the JSON value class defines +functions in order to let the user know if an integer value fits in 16, 32 +or 64 bit integer. +To know more about 64-bits integer support see \ref json_internals_integer + +Storing values in a JSON value object of this class is very simple. +The following is an example: +\code + wxJSONValue v( _T( "A string")); // store a string value in the object + wxString s = v.AsString(); // get the string value + + v = 12; // now 'v' contains an integer value + int i = v.AsInt(); // get the integer +\endcode + + \par The C-string JSON value object + + The wxJSONValue(const wxChar*) ctor allows you to create a JSON value + object that contains a string value which is stored as a + \e pointer-to-static-string. + Beware that this ctor DOES NOT copy the string: it only stores the + pointer in a data member and the pointed-to buffer is not deleted + by the dtor. + If the string is not static you have to use the wxJSONValue(const wxString&) + constructor. + + Also note that this does NOT mean that the value stored in this JSON + object cannot change: you can assign whatever other value you want, + an integer, a double or an array of values. + What I intended is that the pointed-to string must exist for the lifetime + of the wxJSONValue object. + The following code is perfectly legal: + \code + wxJSONvalue aString( "this is a static string" ); + aString = 10; + \endcode + To know more about this topic see \ref json_internals_cstring. + + Starting from version 1.3 the class can hold binary memory buffers + as an extension to the JSON syntax. Memory buffers are stored as + \b wxMemoryBuffer objects which contain binary data. The class + uses reference counting for the copy and assignment operation but + it is not a \e copy-on-write structure. + To know more about memory buffers read \ref wxjson_tutorial_memorybuff + + \sa the \ref wxjson_tutorial. +*/ + + +#if defined( WXJSON_USE_VALUE_COUNTER ) + // The progressive counter (used for debugging only) + int wxJSONValue::sm_progr = 1; +#endif + +//! Constructors. +/*! + The overloaded constructors allow the user to construct a JSON value + object that holds the specified value and type of value. + The default ctor construct a valid JSON object that constains a \b null + value. + + If you want to create an \b invalid JSON value object you have to use the + \c wxJSONValue( wxJSONTYPE_INVALID ) ctor. + Note that this object is not a valid JSON value - to know more about this + topic see the SetType() function. + + To create an empty array or key/value map use the following: + \code + wxJSONvalue v1( wxJSONTYPE_ARRAY ); + wxJSONvalue v2( wxJSONTYPE_OBJECT ); + \endcode +*/ +wxJSONValue::wxJSONValue() +{ + m_refData = 0; + Init( wxJSONTYPE_NULL ); +} + +//! Initialize the JSON value class. +/*! + The function is called by the ctors and allocates a new instance of + the wxJSONRefData class and sets the type of the JSON value. + Note that only the type is set, not the value. + Also note that this function may be called from other memberfunctions + if the \c m_refData data member is NULL. +*/ +wxJSONRefData* +wxJSONValue::Init( wxJSONType type ) +{ + wxJSONRefData* data = GetRefData(); + if ( data != 0 ) { + UnRef(); + } + + // we allocate a new instance of the referenced data + data = new wxJSONRefData(); + wxJSON_ASSERT( data ); + + // in release builds we do not have ASSERT so we check 'data' before + // using it + if ( data ) { + data->m_type = type; + data->m_commentPos = wxJSONVALUE_COMMENT_BEFORE; + } + SetRefData( data ); + +#if defined( WXJSON_USE_VALUE_COUNTER ) + m_progr = sm_progr; + ++sm_progr; + wxLogTrace( cowTraceMask, _T("(%s) Init a new object progr=%d"), + __PRETTY_FUNCTION__, m_progr ); +#endif + return data; +} + + +//! \overload wxJSONValue() +wxJSONValue::wxJSONValue( wxJSONType type ) +{ + m_refData = 0; + Init( type ); +} + +//! \overload wxJSONValue() +wxJSONValue::wxJSONValue( int i ) +{ + m_refData = 0; + wxJSONRefData* data = Init( wxJSONTYPE_INT ); + wxJSON_ASSERT( data ); + if ( data != 0 ) { + // the 'VAL_INT' macro expands to 'm_valLong' or 'm_valInt64' depending + // on 64-bits integer support being enabled on not + data->m_value.VAL_INT = i; + } +} + + +//! \overload wxJSONValue() +wxJSONValue::wxJSONValue( unsigned int ui ) +{ + m_refData = 0; + wxJSONRefData* data = Init( wxJSONTYPE_UINT ); + wxJSON_ASSERT( data ); + if ( data != 0 ) { + // the 'VAL_UINT' macro expands to 'm_valULong' or 'm_valUInt64' depending + // on 64-bits integer support being enabled on not + data->m_value.VAL_UINT = ui; + } +} + +//! \overload wxJSONValue() +wxJSONValue::wxJSONValue( short int i ) +{ + m_refData = 0; + wxJSONRefData* data = Init( wxJSONTYPE_INT ); + wxJSON_ASSERT( data ); + if ( data != 0 ) { + // the 'VAL_INT' macro expands to 'm_valLong' or 'm_valInt64' depending + // on 64-bits integer support being enabled on not + data->m_value.VAL_INT = i; + } +} + + +//! \overload wxJSONValue() +wxJSONValue::wxJSONValue( unsigned short ui ) +{ + m_refData = 0; + wxJSONRefData* data = Init( wxJSONTYPE_UINT ); + wxJSON_ASSERT( data ); + if ( data != 0 ) { + // the 'VAL_UINT' macro expands to 'm_valULong' or 'm_valUInt64' depending + // on 64-bits integer support being enabled on not + data->m_value.VAL_UINT = ui; + } +} + +//! \overload wxJSONValue() +wxJSONValue::wxJSONValue( bool b ) +{ + m_refData = 0; + wxJSONRefData* data = Init( wxJSONTYPE_BOOL ); + wxJSON_ASSERT( data ); + if ( data != 0 ) { + data->m_value.m_valBool = b; + } +} + +//! \overload wxJSONValue() +wxJSONValue::wxJSONValue( double d ) +{ + m_refData = 0; + wxJSONRefData* data = Init( wxJSONTYPE_DOUBLE ); + wxJSON_ASSERT( data ); + if ( data != 0 ) { + data->m_value.m_valDouble = d; + } +} + +//! \overload wxJSONValue() +wxJSONValue::wxJSONValue( const wxChar* str ) +{ + m_refData = 0; + wxJSONRefData* data = Init( wxJSONTYPE_CSTRING ); + wxJSON_ASSERT( data ); + if ( data != 0 ) { + #if !defined( WXJSON_USE_CSTRING ) + data->m_type = wxJSONTYPE_STRING; + data->m_valString.assign( str ); + #else + data->m_value.m_valCString = str; + #endif + } +} + +//! \overload wxJSONValue() +wxJSONValue::wxJSONValue( const wxString& str ) +{ + m_refData = 0; + wxJSONRefData* data = Init( wxJSONTYPE_STRING ); + wxJSON_ASSERT( data ); + if ( data != 0 ) { + data->m_valString.assign( str ); + } +} + +//! \overload wxJSONValue() +wxJSONValue::wxJSONValue( long int l ) +{ + m_refData = 0; + wxJSONRefData* data = Init( wxJSONTYPE_INT ); + wxJSON_ASSERT( data ); + if ( data != 0 ) { + data->m_value.VAL_INT = l; + } +} + +//! \overload wxJSONValue() +wxJSONValue::wxJSONValue( unsigned long int ul ) +{ + m_refData = 0; + wxJSONRefData* data = Init( wxJSONTYPE_UINT ); + wxJSON_ASSERT( data ); + if ( data != 0 ) { + data->m_value.VAL_UINT = ul; + } +} + +//! Construct a JSON value object of type \e memory \e buffer +/*! + Note that this ctor makes a deep copy of \c buff so changes made + to the original buffer does not reflect to the buffer stored in this + JSON value. +*/ +wxJSONValue::wxJSONValue( const wxMemoryBuffer& buff ) +{ + m_refData = 0; + wxJSONRefData* data = Init( wxJSONTYPE_MEMORYBUFF ); + wxJSON_ASSERT( data ); + if ( data != 0 ) { + data->m_memBuff = new wxMemoryBuffer(); + const void* ptr = buff.GetData(); + size_t buffLen = buff.GetDataLen(); + if ( buffLen > 0 ) { + data->m_memBuff->AppendData( ptr, buffLen ); + } + } +} + +//! Construct a JSON value object of type \e memory \e buffer +/*! + Note that this ctor makes a deep copy of \c buff so changes made + to the original buffer does not reflect to the buffer stored in this + JSON value. +*/ +wxJSONValue::wxJSONValue( const void* buff, size_t len ) +{ + m_refData = 0; + wxJSONRefData* data = Init( wxJSONTYPE_MEMORYBUFF ); + wxJSON_ASSERT( data ); + if ( data != 0 && len > 0 ) { + data->m_memBuff = new wxMemoryBuffer(); + data->m_memBuff->AppendData( buff, len ); + } +} + +//! Copy constructor +/*! + The function copies the content of \c other in this + object. + Note that the JSON value object is not really copied; + the function calls Ref() in order to increment + the reference count of the \c wxJSONRefData structure. +*/ +wxJSONValue::wxJSONValue( const wxJSONValue& other ) +{ + m_refData = 0; + Ref( other ); + + // the progressive counter of the ctor is not copied from + // the other wxJSONValue object: only data is shared, the + // progressive counter is not shared because this object + // is a copy of 'other' and it has its own progressive +#if defined( WXJSON_USE_VALUE_COUNTER ) + m_progr = sm_progr; + ++sm_progr; + wxLogTrace( cowTraceMask, _T("(%s) Copy ctor - progr=%d other progr=%d"), + __PRETTY_FUNCTION__, m_progr, other.m_progr ); +#endif +} + + +//! Dtor - calls UnRef(). +wxJSONValue::~wxJSONValue() +{ + UnRef(); +} + + +// functions for retreiving the value type: they are all 'const' + + +//! Return the type of the value stored in the object. +/*! + This function is the only one that does not ASSERT that the + \c m_refData data member is not NULL. + In fact, if the JSON value object does not contain a pointer + to a wxJSONRefData structure, the function returns the + wxJSONTYPE_INVALID constant which represent an invalid JSON value object. + Also note that the pointer to the referenced data structure + should NEVER be NULL. + + \par Integer types + + Integers are stored internally in a \b signed/unsigned \b long \b int + or, on platforms that support 64-bits integers, in a + \b wx(U)Int64 data type. + When constructed, it is assigned a generic integer type that only + depends on the sign: wxJSON_(U)INT regardless the size of the + stored value. + + This function can be used to know the actual size requirement + of the stored value and how it can be retrieved. The value + returned by this function is: + + - for signed integers: + - \b wxJSONTYPE_SHORT if the value is between SHORT_MIN and SHORT_MAX + - \b wxJSONTYPE_LONG if the value is between LONG_MIN and LONG_MAX + and greater than SHORT_MAX and less than SHORT_MIN + - \b wxJSONTYPE_INT64 if the value is greater than LONG_MAX and + less than LONG_MIN + + - for unsigned integers: + - \b wxJSONTYPE_USHORT if the value is between 0 and USHORT_MAX + - \b wxJSONTYPE_ULONG if the value is between 0 and ULONG_MAX + and greater than USHORT_MAX + - \b wxJSONTYPE_UINT64 if the value is greater than ULONG_MAX + + Note that this function never returns the wxJSONTYPE_(U)INT constant + because the \b int data type may have the same width as SHORT or LONG + depending on the platform. + This does not mean that you cannot use \b int as the return value: if + you use \b wxWidgets to develop application in only one platform, you + can use \b int because you know the size of the data type. + Otherwise, if is preferable to always use \b long instead of \b int. + + Also note that the class defines the \c IsInt() memberfunction which + works fine regardless the actual width of the \b int data type. + This function returns TRUE if the stored value fits in a \b int data + type whatever its size is on the current platform (16 or 32-bits). + + \sa SetType IsInt +*/ +wxJSONType +wxJSONValue::GetType() const +{ + wxJSONRefData* data = GetRefData(); + wxJSONType type = wxJSONTYPE_INVALID; + if ( data ) { + type = data->m_type; + + // for integers and unsigned ints check the storage requirements + // note that ints are stored as 'long' or as 'long long' + switch ( type ) { + case wxJSONTYPE_INT : + // check if the integer fits in a SHORT INT + if ( data->m_value.VAL_INT >= SHORT_MIN && + data->m_value.VAL_INT <= SHORT_MAX ) { + type = wxJSONTYPE_SHORT; + } + // check if the value fits in LONG INT + else if ( data->m_value.VAL_INT >= LONG_MIN + && data->m_value.VAL_INT <= LONG_MAX ) { + type = wxJSONTYPE_LONG; + } + else { + type = wxJSONTYPE_INT64; + } + break; + + case wxJSONTYPE_UINT : + if ( data->m_value.VAL_UINT <= USHORT_MAX ) { + type = wxJSONTYPE_USHORT; + } + else if ( data->m_value.VAL_UINT <= ULONG_MAX ) { + type = wxJSONTYPE_ULONG; + } + else { + type = wxJSONTYPE_UINT64; + } + break; + + default : + break; + } + } + return type; +} + + +//! Return TRUE if the type of the value is wxJSONTYPE_NULL. +bool +wxJSONValue::IsNull() const +{ + wxJSONType type = GetType(); + bool r = false; + if ( type == wxJSONTYPE_NULL ) { + r = true; + } + return r; +} + + +//! Return TRUE if the value stored is valid +/*! + The function returns TRUE if the wxJSONValue object was correctly + initialized - that is it contains a valid value. + A JSON object is valid if its type is not equal to wxJSONTYPE_INVALID. + Please note that the default ctor of wxJSONValue constructs a \b valid + JSON object of type \b null. + To create an invalid object you have to use; + \code + wxJSONValue v( wxJSONTYPE_INVALID ); + \endcode +*/ +bool +wxJSONValue::IsValid() const +{ + wxJSONType type = GetType(); + bool r = false; + if ( type != wxJSONTYPE_INVALID ) { + r = true; + } + return r; +} + +//! Return TRUE if the type of the value stored is integer. +/*! + This function returns TRUE if the stored value is of + type signed integer and the numeric value fits in a + \b int data type. + In other words, the function returns TRUE if the \c wxJSONRefData::m_type + data member is of type \c wxJSONTYPE_INT and: + + \code + INT_MIN <= m_value <= INT_MAX + \endcode + + Note that if you are developing cross-platform applications you should never + use \b int as the integer data type but \b long for 32-bits integers and + \b short for 16-bits integers. + This is because the \b int data type may have different width on different + platforms. + Regardless the widht of the data type (16 or 32 bits), the function returns + the correct result because it relies on the INT_MAX and INT_MIN macros. + + \sa \ref json_internals_integer +*/ +bool +wxJSONValue::IsInt() const +{ + wxJSONType type = GetType(); + bool r = false; + // if the type is SHORT the value fits into an INT, too + if ( type == wxJSONTYPE_SHORT ) { + r = true; + } + else if ( type == wxJSONTYPE_LONG ) { + // in case of LONG, check if the bit width is the same + if ( INT_MAX == LONG_MAX ) { + r = true; + } + } + return r; +} + +//! Return TRUE if the type of the value stored is 16-bit integer. +/*! + This function returns TRUE if the stored value is of + type signed integer and the numeric value fits in a + \b short \b int data type (16-bit integer). + In other words, the function returns TRUE if the \c wxJSONRefData::m_type + data member is of type \c wxJSONTYPE_INT and: + + \code + SHORT_MIN <= m_value <= SHORT_MAX + \endcode + + \sa \ref json_internals_integer +*/ +bool +wxJSONValue::IsShort() const +{ + wxJSONType type = GetType(); + bool r = false; + if ( type == wxJSONTYPE_SHORT ) { + r = true; + } + return r; +} + +//! Return TRUE if the type of the value stored is a unsigned int. +/*! + This function returns TRUE if the stored value is of + type unsigned integer and the numeric value fits int a + \b int data type. + In other words, the function returns TRUE if the \c wxJSONRefData::m_type + data member is of type \c wxJSONTYPE_UINT and: + + \code + 0 <= m_value <= UINT_MAX + \endcode + + Note that if you are developing cross-platform applications you should never + use \b unsigned \b int as the integer data type but \b unsigned \b long for + 32-bits integers and \b unsigned \b short for 16-bits integers. + This is because the \b unsigned \b int data type may have different width + on different platforms. + Regardless the widht of the data type (16 or 32 bits), the function returns + the correct result because it relies on the UINT_MAX macro. + + + \sa \ref json_internals_integer +*/ +bool +wxJSONValue::IsUInt() const +{ + wxJSONType type = GetType(); + bool r = false; + if ( type == wxJSONTYPE_USHORT ) { + r = true; + } + else if ( type == wxJSONTYPE_ULONG ) { + if ( INT_MAX == LONG_MAX ) { + r = true; + } + } + return r; +} + +//! Return TRUE if the type of the value stored is a unsigned short. +/*! + This function returns TRUE if the stored value is of + type unsigned integer and the numeric value fits in a + \b unsigned \b short \b int data type. + In other words, the function returns TRUE if the \c wxJSONRefData::m_type + data member is of type \c wxJSONTYPE_UINT and: + + \code + 0 <= m_value <= USHORT_MAX + \endcode + + \sa \ref json_internals_integer +*/ +bool +wxJSONValue::IsUShort() const +{ + wxJSONType type = GetType(); + bool r = false; + if ( type == wxJSONTYPE_USHORT ) { + r = true; + } + return r; +} + + +//! Return TRUE if the stored value is an integer which fits in a long int +/*! + This function returns TRUE if the stored value is of + type signed LONG integer and the numeric value fits int a + \b long \b int data type. + In other words, the function returns TRUE if the \c wxJSONRefData::m_type + data member is of type \c wxJSONTYPE_INT and: + + \code + LONG_MIN <= m_value <= LONG_MAX + \endcode + + \sa \ref json_internals_integer +*/ +bool +wxJSONValue::IsLong() const +{ + wxJSONType type = GetType(); + bool r = false; + if ( type == wxJSONTYPE_LONG || type == wxJSONTYPE_SHORT ) { + r = true; + } + return r; +} + +//! Return TRUE if the stored value is an integer which fits in a unsigned long int +/*! + This function returns TRUE if the stored value is of + type unsigned LONG integer and the numeric value fits int a + \b unsigned \b long \b int data type. + In other words, the function returns TRUE if the \c wxJSONRefData::m_type + data member is of type \c wxJSONTYPE_UINT and: + + \code + 0 <= m_value <= ULONG_MAX + \endcode + + \sa \ref json_internals_integer +*/ +bool +wxJSONValue::IsULong() const +{ + wxJSONType type = GetType(); + bool r = false; + if ( type == wxJSONTYPE_ULONG || type == wxJSONTYPE_USHORT ) { + r = true; + } + return r; +} + + + +//! Return TRUE if the type of the value stored is a boolean. +bool +wxJSONValue::IsBool() const +{ + wxJSONType type = GetType(); + bool r = false; + if ( type == wxJSONTYPE_BOOL ) { + r = true; + } + return r; +} + +//! Return TRUE if the type of the value stored is a double. +bool +wxJSONValue::IsDouble() const +{ + wxJSONType type = GetType(); + bool r = false; + if ( type == wxJSONTYPE_DOUBLE ) { + r = true; + } + return r; +} + +//! Return TRUE if the type of the value stored is a wxString object. +bool +wxJSONValue::IsString() const +{ + wxJSONType type = GetType(); + bool r = false; + if ( type == wxJSONTYPE_STRING ) { + r = true; + } + return r; +} + +//! Return TRUE if the type of the value stored is a pointer to a static C string. +/*! + This function returns TRUE if, and only if the stored value is a + pointer to a static C-string and the C-string storage is enabled in + the wxJSON library. + By default, C-string storage is not enabled in the library so this + function always returns FALSE. + To know more about C-strings read \ref json_internals_cstring +*/ +bool +wxJSONValue::IsCString() const +{ + wxJSONType type = GetType(); + bool r = false; + if ( type == wxJSONTYPE_CSTRING ) { + r = true; + } + return r; +} + +//! Return TRUE if the type of the value stored is an array type. +bool +wxJSONValue::IsArray() const +{ + wxJSONType type = GetType(); + bool r = false; + if ( type == wxJSONTYPE_ARRAY ) { + r = true; + } + return r; +} + +//! Return TRUE if the type of this value is a key/value map. +bool +wxJSONValue::IsObject() const +{ + wxJSONType type = GetType(); + bool r = false; + if ( type == wxJSONTYPE_OBJECT ) { + r = true; + } + return r; +} + +//! Return TRUE if the type of this value is a binary memory buffer. +bool +wxJSONValue::IsMemoryBuff() const +{ + wxJSONType type = GetType(); + bool r = false; + if ( type == wxJSONTYPE_MEMORYBUFF ) { + r = true; + } + return r; +} + + + +// get the stored value; all these functions are 'const' + +//! Return the stored value as an integer. +/*! + The function returns the stored value as an integer. + Note that the function does not check that the type of the + value is actually an integer and it just returns the content + of the wxJSONValueHolder union. + However, in debug builds, the function ASSERTs that the + type of the stored value \c IsInt(). + + \sa \ref json_internals_integer + \sa \ref wxjson_tutorial_get +*/ +int +wxJSONValue::AsInt() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + int i = (int) data->m_value.VAL_INT; + + wxJSON_ASSERT( IsInt()); + return i; +} + +//! Return the stored value as a boolean. +/*! + The function returns the stored value as a boolean. + Note that the function does not check that the type of the + value is actually a boolean and it just returns the content + of the wxJSONValueHolder union. + However, in debug builds, the function ASSERTs that the + type of the stored value is wxJSONTYPE_BOOL. + + \sa \ref wxjson_tutorial_get +*/ +bool +wxJSONValue::AsBool() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + wxJSON_ASSERT( data->m_type == wxJSONTYPE_BOOL ); + return data->m_value.m_valBool; +} + +//! Return the stored value as a double. +/*! + The function returns the stored value as a double. + Note that the function does not check that the type of the + value is actually a double and it just returns the content + of the wxJSONValueHolder union as if it was a double. + However, in debug builds, the function ASSERTs that the + type of the stored value \c IsDouble(). + + \sa \ref wxjson_tutorial_get +*/ +double +wxJSONValue::AsDouble() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + double d = data->m_value.m_valDouble; + wxJSON_ASSERT( IsDouble()); + return d; +} + + +//! Return the stored value as a wxWidget's string. +/*! + The function returns a string representation of the value + stored in the JSON object. + All value types are converted to a string by this function + and returned as a string: + + \li For integer the string is the string representation of + the numerical value in decimal notation; the function uses the + \b wxString::Printf() function for the conversion + + \li for doubles, the value is converted to a string using the + \b wxString::Printf("%.10g") function; the format string specifies + a precision of ten decimal digits and suppress trailing ZEROes + + \li for booleans the string returned is: \b true or \b false. + + \li if the value is a NULL value the \b null literal string is returned. + + \li if the value is of type wxJSONTYPE_INVALID, the literal string \b <invalid> + is returned. Note that this is NOT a valid JSON text. + + \li if the value is of type wxJSONTYPE_MEMORYBUFF the string returned contains the + hexadecimal digits of the first 5 bytes preceeded by the length of the buffer, + enclosed in parenthesis + + If the value is an array or map, the returned string is the number of + elements is the array/object enclosed in the JSON special characters that + identifies the array/object. Example: + + \code + [0] // an empty array + {12} // an object of 12 elements + \endcode + + \sa \ref wxjson_tutorial_get +*/ +wxString +wxJSONValue::AsString() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + wxString s; + int size = Size(); + switch ( data->m_type ) { + case wxJSONTYPE_STRING : + s.assign( data->m_valString); + break; + case wxJSONTYPE_CSTRING : + s.assign( data->m_value.m_valCString); + break; + case wxJSONTYPE_INT : + #if defined( wxJSON_64BIT_INT ) + s.Printf( _T("%") wxT(wxLongLongFmtSpec) _T("i"), + data->m_value.m_valInt64 ); + #else + s.Printf( _T("%ld"), data->m_value.m_valLong ); + #endif + break; + case wxJSONTYPE_UINT : + #if defined( wxJSON_64BIT_INT ) + s.Printf( _T("%") wxT(wxLongLongFmtSpec) _T("u"), + data->m_value.m_valUInt64 ); + #else + s.Printf( _T("%lu"), data->m_value.m_valULong ); + #endif + break; + case wxJSONTYPE_DOUBLE : + s.Printf( _T("%.10g"), data->m_value.m_valDouble ); + break; + case wxJSONTYPE_BOOL : + s.assign( ( data->m_value.m_valBool ? + _T("true") : _T("false") )); + break; + case wxJSONTYPE_NULL : + s.assign( _T( "null")); + break; + case wxJSONTYPE_INVALID : + s.assign( _T( "")); + break; + case wxJSONTYPE_ARRAY : + s.Printf( _T("[%d]"), size ); + break; + case wxJSONTYPE_OBJECT : + s.Printf( _T("{%d}"), size ); + break; + case wxJSONTYPE_MEMORYBUFF : + s = MemoryBuffToString( *(data->m_memBuff), 5 ); + break; + default : + s.assign( _T( "wxJSONValue::AsString(): Unknown JSON type \'")); + s.append( TypeToString( data->m_type )); + s.append( _T( "\'" )); + wxFAIL_MSG( s ); + break; + } + return s; +} + +//! Return the stored value as a pointer to a static C string. +/*! + If the type of the value is stored as a C-string data type the + function just returns that pointer. + If the stored value is a wxString object, the function returns the + pointer returned by the \b wxString::c_str() function. + If the stored value is of all other JSON types, the functions returns a NULL pointer. + + Note that in versions prior to 0.5, the + function returned a NULL pointer also if the value is a \c wxString object. + + \sa \ref json_internals_cstring + \sa \ref wxjson_tutorial_get + +*/ +const wxChar* +wxJSONValue::AsCString() const +{ + const wxChar* s = 0; + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + switch ( data->m_type ) { + case wxJSONTYPE_CSTRING : + s = data->m_value.m_valCString; + break; + case wxJSONTYPE_STRING : + s = data->m_valString.c_str(); + break; + default : + break; + } + return s; +} + + +//! Return the stored value as a unsigned int. +/*! + The function returns the stored value as a unsigned integer. + Note that the function does not check that the type of the + value is actually a unsigned integer and it just returns the content + of the wxJSONValueHolder union. + However, in debug builds, the function ASSERTs that the + type of the stored value is wxJSONTYPE_UINT. + + \sa \ref json_internals_integer + \sa \ref wxjson_tutorial_get +*/ +unsigned int +wxJSONValue::AsUInt() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + unsigned int ui = (unsigned) data->m_value.VAL_UINT; + + wxJSON_ASSERT( IsUInt()); + return ui; +} + + +//! Returns the value as a long integer +/*! + The function returns the stored value as a long integer. + Note that the function does not check that the type of the + value is actually a long integer and it just returns the content + of the wxJSONValueHolder union. + However, in debug builds, the function ASSERTs that the + type of the stored value \c IsLong(). + + \sa \ref json_internals_integer + \sa \ref wxjson_tutorial_get +*/ +long int +wxJSONValue::AsLong() const +{ + long int l; + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + l = (long) data->m_value.VAL_INT; + + wxJSON_ASSERT( IsLong()); + return l; +} + +//! Returns the value as a unsigned long integer +/*! + The function returns the stored value as a unsigned long integer. + Note that the function does not check that the type of the + value is actually a unsigned long integer and it just returns the content + of the wxJSONValueHolder union. + However, in debug builds, the function ASSERTs that the + type of the stored value \c IsLong(). + + \sa \ref json_internals_integer + \sa \ref wxjson_tutorial_get +*/ +unsigned long int +wxJSONValue::AsULong() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + unsigned long int ul = (unsigned long) data->m_value.VAL_UINT; + + wxJSON_ASSERT( IsULong()); // expands only in debug builds + return ul; +} + + +//! Returns the value as a short integer +/*! + The function returns the stored value as a short integer. + Note that the function does not check that the type of the + value is actually a short integer and it just returns the content + of the wxJSONValueHolder union. + However, in debug builds, the function ASSERTs that the + type of the stored value \c IsShort(). + + \sa \ref json_internals_integer + \sa \ref wxjson_tutorial_get +*/ +short int +wxJSONValue::AsShort() const +{ + short int i; + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + i = (short) data->m_value.VAL_INT; + + wxJSON_ASSERT( IsShort()); + return i; +} + +//! Returns the value as a unsigned short integer +/*! + The function returns the stored value as a unsigned short integer. + Note that the function does not check that the type of the + value is actually a unsigned short and it just returns the content + of the wxJSONValueHolder union. + However, in debug builds, the function ASSERTs that the + type of the stored value \c IsUShort(). + + \sa \ref json_internals_integer + \sa \ref wxjson_tutorial_get +*/ +unsigned short +wxJSONValue::AsUShort() const +{ + unsigned short ui; + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + ui = (unsigned short) data->m_value.VAL_UINT; + + wxJSON_ASSERT( IsUShort()); + return ui; +} + + + +//! Stores the value of this object in the provided argument +/*! + The functions of the form \c AsXxxxxx(T&) are the same as the \c AsXxxxxxx() + but store the value in the provided argument and return TRUE if the value of + this object is of the correct type. + By using these functions you can get the value and test if the JSON value is + of the expected type in only one step. + For example: + \code + int i; wxJSONValue v(10); + if ( !v.AsInt( i )) { + cout << "Error: value is not of the expected type"; + } + \endcode + This is the same as: + \code + int i; wxJSONValue v(10); + if ( v.IsInt() { + i = v.AsInt(); + } + else { + cout << "Error: value is not of the expected type"; + } + \endcode + Thanks to \b catalin who has suggested this new feature. +*/ +bool +wxJSONValue::AsInt( int& i ) const +{ + bool r = false; + if ( IsInt() ) { + i = AsInt(); + r = true; + } + return r; +} + +bool +wxJSONValue::AsUInt( unsigned int& ui ) const +{ + bool r = false; + if ( IsUInt() ) { + ui = AsUInt(); + r = true; + } + return r; +} + +bool +wxJSONValue::AsShort( short int& s ) const +{ + bool r = false; + if ( IsShort() ) { + s = AsShort(); + r = true; + } + return r; +} + +bool +wxJSONValue::AsUShort( unsigned short& us ) const +{ + bool r = false; + if ( IsUShort() ) { + us = AsUShort(); + r = true; + } + return r; +} + +bool +wxJSONValue::AsLong( long int& l ) const +{ + bool r = false; + if ( IsLong() ) { + l = AsLong(); + r = true; + } + return r; +} + +bool +wxJSONValue::AsULong( unsigned long& ul ) const +{ + bool r = false; + if ( IsULong() ) { + ul = AsULong(); + r = true; + } + return r; +} + + +bool +wxJSONValue::AsBool( bool& b ) const +{ + bool r = false; + if ( IsBool() ) { + b = AsBool(); + r = true; + } + return r; +} + +bool +wxJSONValue::AsDouble( double& d ) const +{ + bool r = false; + if ( IsDouble() ) { + d = AsDouble(); + r = true; + } + return r; +} + +//! Return this string value in the provided argument +/*! + This function is different from \c AsString because the latter always returns + a string also when this object does not contain a string. In that case, a string + representation of this value is returned. + This function, instead, returns TRUE only if this object contains a string, that is + only if \c IsString() returns TRUE. + Also note that the string value is only stored in \c str if this object actually + contains a \b string or \b c-string value. + \c str will never contain a string representation of other types. +*/ +bool +wxJSONValue::AsString( wxString& str ) const +{ + bool r = IsString(); + if ( r ) { + str = AsString(); + } + return r; +} + +bool +wxJSONValue::AsCString( wxChar* ch ) const +{ + bool r = IsCString(); + if ( r ) { + ch = (wxChar*) AsCString(); + } + return r; +} + +//! Returns the value as a memory buffer +/*! + The function returns the \e memory \e buffer object stored in + this JSON object. + Note that as of wxWidgets 2.8 and 2.9 the \b wxMemoryBuffer object uses + reference counting when copying the actual buffer but the class itself + is not a \e copy-on-write structure so changes made to one buffer affects + all other copies made from it. + This means that if you make a change to the returned copy of the memory + buffer, the change affects also the memory buffer stored in this JSON value. + + If this JSON object does not contain a \e wxJSONTYPE_MEMORYBUFF type + the function returns an empty memory buffer object. + An empty memory buffer is also returned if this JSON + type contains a valid, empty memory buffer. + You have to use the IsMemoryBuff() function to known the type of the + JSON value contained in this object, or the overloaded version of + this function. +*/ +wxMemoryBuffer +wxJSONValue::AsMemoryBuff() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + wxMemoryBuffer buff; + if ( data->m_memBuff ) { + buff = *(data->m_memBuff); + } + + wxJSON_ASSERT( IsMemoryBuff()); + return buff; +} + + +//! Returns the value as a memory buffer +/*! + The function returns the \e memory \e buffer object stored in + this JSON object. + Note that as of wxWidgets 2.8 and 2.9 the \b wxMemoryBuffer object uses + reference counting when copying the actual buffer but the class itself + is not a \e copy-on-write structure so changes made to one buffer affects + all other copies made from it. + This means that if you make a change to the returned copy of the memory + buffer, the change affects also the memory buffer stored in this JSON value. + + If this JSON object does not contain a \e wxJSONTYPE_MEMORYBUFF type + the function returns an empty memory buffer object. + An empty memory buffer is also returned if this JSON + type contains a valid, empty memory buffer. + You have to use the IsMemoryBuff() function to known the type of the + JSON value contained in this object, or the overloaded version of + this function. +*/ +bool +wxJSONValue::AsMemoryBuff( wxMemoryBuffer& buff ) const +{ + bool r = IsMemoryBuff(); + if ( r ) { + buff = AsMemoryBuff(); + } + return r; +} + + +// internal use + +//! Return the stored value as a map object. +/*! + This function is for testing and debugging purposes and you shold never use it. + To retreive values from an array or map JSON object use the \c Item() or ItemAt() + memberfunctions or the subscript operator. + If the stored value is not a map type, returns a NULL pointer. +*/ +const wxJSONInternalMap* +wxJSONValue::AsMap() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + const wxJSONInternalMap* v = 0; + if ( data->m_type == wxJSONTYPE_OBJECT ) { + v = &( data->m_valMap ); + } + return v; +} + +//! Return the stored value as an array object. +/*! + This function is for testing and debugging purposes and you shold never use it. + To retreive values from an array or map JSON object use the \c Item() or ItemAt() + memberfunctions or the subscript operator. + If the stored value is not an array type, returns a NULL pointer. +*/ +const wxJSONInternalArray* +wxJSONValue::AsArray() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + const wxJSONInternalArray* v = 0; + if ( data->m_type == wxJSONTYPE_ARRAY ) { + v = &( data->m_valArray ); + } + return v; +} + +// retrieve the members and other info + + +//! Return TRUE if the object contains an element at the specified index. +/*! + If the stoerd value is not an array or a map, the function returns FALSE. +*/ +bool +wxJSONValue::HasMember( unsigned index ) const +{ + bool r = false; + int size = Size(); + if ( index < (unsigned) size ) { + r = true; + } + return r; +} + +//! Return TRUE if the object contains an element at the specified key. +/*! + If the stored value is not a key/map map, the function returns FALSE. +*/ +bool +wxJSONValue::HasMember( const wxString& key ) const +{ + bool r = false; + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + if ( data && data->m_type == wxJSONTYPE_OBJECT ) { + wxJSONInternalMap::iterator it = data->m_valMap.find( key ); + if ( it != data->m_valMap.end() ) { + r = true; + } + } + return r; +} + +//! Return the size of the array or map stored in this value. +/*! + Note that both the array and the key/value map may have a size of + ZERO elements. + If the stored value is not an array nor a key/value hashmap, the + function returns -1. +*/ +int +wxJSONValue::Size() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + int size = -1; + if ( data->m_type == wxJSONTYPE_ARRAY ) { + size = (int) data->m_valArray.GetCount(); + } + if ( data->m_type == wxJSONTYPE_OBJECT ) { + size = (int) data->m_valMap.size(); + } + return size; +} + +//! Return the array of keys of this JSON object. +/*! + If the stored value is a key/value map, the function returns an + array of strings containing the \e key of all elements. + Note that the returned array may be empty if the map has ZERO + elements. + An empty string array is also returned if the stored value is + not a key/value map. + Also note that in debug builds, the function wxJSON_ASSERTs that the + type of the stored object is wxJSONTYPE_OBJECT. +*/ +wxArrayString +wxJSONValue::GetMemberNames() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + wxJSON_ASSERT( data->m_type == wxJSONTYPE_OBJECT ); + + wxArrayString arr; + if ( data->m_type == wxJSONTYPE_OBJECT ) { + wxJSONInternalMap::iterator it; + for ( it = data->m_valMap.begin(); it != data->m_valMap.end(); it++ ) { + arr.Add( it->first ); + } + } + return arr; +} + + +// appending items, resizing and deleting items +// NOTE: these functions are not 'const' so we have to call +// the COW() function before accessing data + +//! Append the specified value in the array. +/*! + The function appends the value specified in the parameter to the array + contained in this object. + If this object does not contain an array type, the actual content is + deleted, a new array type is created and the JSON value \c value is + appended to the newly created array. + Returns a reference to the appended object. +*/ +wxJSONValue& +wxJSONValue::Append( const wxJSONValue& value ) +{ + wxJSONRefData* data = COW(); + wxJSON_ASSERT( data ); + if ( data->m_type != wxJSONTYPE_ARRAY ) { + // we have to change the type of the actual object to the array type + SetType( wxJSONTYPE_ARRAY ); + } + // we add the wxJSONValue object to the wxObjArray: note that the + // array makes a copy of the JSON-value object by calling its + // copy ctor thus using reference count + data->m_valArray.Add( value ); + wxJSONValue& v = data->m_valArray.Last(); + return v; +} + + +//! \overload Append( const wxJSONValue& ) +wxJSONValue& +wxJSONValue::Append( int i ) +{ + wxJSONValue v( i ); + wxJSONValue& r = Append( v ); + return r; +} + +//! \overload Append( const wxJSONValue& ) +wxJSONValue& +wxJSONValue::Append( short int i ) +{ + wxJSONValue v( i ); + wxJSONValue& r = Append( v ); + return r; +} + +//! \overload Append( const wxJSONValue& ) +wxJSONValue& +wxJSONValue::Append( long int l ) +{ + wxJSONValue v( l ); + wxJSONValue& r = Append( v ); + return r; +} + +//! \overload Append( const wxJSONValue& ) +wxJSONValue& +wxJSONValue::Append( bool b ) +{ + wxJSONValue v( b ); + wxJSONValue& r = Append( v ); + return r; +} + +//! \overload Append( const wxJSONValue& ) +wxJSONValue& +wxJSONValue::Append( unsigned int ui ) +{ + wxJSONValue v( ui ); + wxJSONValue& r = Append( v ); + return r; +} + +//! \overload Append( const wxJSONValue& ) +wxJSONValue& +wxJSONValue::Append( unsigned short ui ) +{ + wxJSONValue v( ui ); + wxJSONValue& r = Append( v ); + return r; +} + +//! \overload Append( const wxJSONValue& ) +wxJSONValue& +wxJSONValue::Append( unsigned long ul ) +{ + wxJSONValue v( ul ); + wxJSONValue& r = Append( v ); + return r; +} + +//! \overload Append( const wxJSONValue& ) +wxJSONValue& +wxJSONValue::Append( double d ) +{ + wxJSONValue v( d ); + wxJSONValue& r = Append( v ); + return r; +} + +//! \overload Append( const wxJSONValue& ) +wxJSONValue& +wxJSONValue::Append( const wxChar* str ) +{ + wxJSONValue v( str ); + wxJSONValue& r = Append( v ); + return r; +} + +//! \overload Append( const wxJSONValue& ) +wxJSONValue& +wxJSONValue::Append( const wxString& str ) +{ + wxJSONValue v( str ); + wxJSONValue& r = Append( v ); + return r; +} + +//! \overload Append( const wxJSONValue& ) +wxJSONValue& +wxJSONValue::Append( const wxMemoryBuffer& buff ) +{ + wxJSONValue v( buff ); + wxJSONValue& r = Append( v ); + return r; +} + +//! \overload Append( const wxJSONValue& ) +wxJSONValue& +wxJSONValue::Append( const void* buff, size_t len ) +{ + wxJSONValue v( buff, len ); + wxJSONValue& r = Append( v ); + return r; +} + + +//! Concatenate a string to this string object. +/*! + The function concatenates \c str to the string contained + in this object and returns TRUE if the operation is succefull. + If the value stored in this value is not a string object + the function does nothing and returns FALSE. + Note that in order to be successfull, the value must contain + a \b wxString object and not a pointer to C-string. +*/ +bool +wxJSONValue::Cat( const wxString& str ) +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + bool r = false; + if ( data->m_type == wxJSONTYPE_STRING ) { + wxJSONRefData* data = COW(); + wxJSON_ASSERT( data ); + data->m_valString.append( str ); + r = true; + } + return r; +} + +//! Concatenate a memory buffer to this memory buffer object. +/*! + The function concatenates \c buff to the \b wxMemoryBuffer object contained + in this object and returns TRUE if the operation is succefull. + If the value stored in this value is not a memory buffer object + the function does nothing and returns FALSE. +*/ +bool +wxJSONValue::Cat( const wxMemoryBuffer& buff ) +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + bool r = false; + if ( data->m_type == wxJSONTYPE_MEMORYBUFF ) { + wxJSONRefData* data = COW(); + wxJSON_ASSERT( data ); + data->m_memBuff->AppendData( buff.GetData(), buff.GetDataLen()); + r = true; + } + return r; +} + + +//! \overload Cat( const wxString& ) +bool +wxJSONValue::Cat( const wxChar* str ) +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + bool r = false; + if ( data->m_type == wxJSONTYPE_STRING ) { + wxJSONRefData* data = COW(); + wxJSON_ASSERT( data ); + data->m_valString.append( str ); + r = true; + } + return r; +} + + +//! Remove the item at the specified index or key. +/*! + The function removes the item at index \c index or at the specified + key in the array or map. + If this object does not contain an array (for a index parameter) or a map + (for a key parameter), the function does nothing and returns FALSE. + If the element does not exist, FALSE is returned. +*/ +bool +wxJSONValue::Remove( int index ) +{ + wxJSONRefData* data = COW(); + wxJSON_ASSERT( data ); + + bool r = false; + if ( data->m_type == wxJSONTYPE_ARRAY ) { + data->m_valArray.RemoveAt( index ); + r = true; + } + return r; +} + + +//! \overload Remove( int ) +bool +wxJSONValue::Remove( const wxString& key ) +{ + wxJSONRefData* data = COW(); + wxJSON_ASSERT( data ); + + bool r = false; + if ( data->m_type == wxJSONTYPE_OBJECT ) { + wxJSONInternalMap::size_type count = data->m_valMap.erase( key ); + if ( count > 0 ) { + r = true; + } + } + return r; +} + + +//! Clear the object value. +/*! + This function causes the object to be empty. + The function simply calls UnRef() making this object to become + invalid and set its type to wxJSONTYPE_INVALID. +*/ +void +wxJSONValue::Clear() +{ + UnRef(); + SetType( wxJSONTYPE_INVALID ); +} + +// retrieve an item + +//! Return the item at the specified index. +/*! + The function returns a reference to the object at the specified + index. + If the element does not exist, the array is enlarged to \c index + 1 + elements and a reference to the last element will be returned. + New elements will contain NULL values. + If this object does not contain an array, the old value is + replaced by an array object which will be enlarged to the needed + dimension. +*/ +wxJSONValue& +wxJSONValue::Item( unsigned index ) +{ + wxJSONRefData* data = COW(); + wxJSON_ASSERT( data ); + + if ( data->m_type != wxJSONTYPE_ARRAY ) { + data = SetType( wxJSONTYPE_ARRAY ); + } + int size = Size(); + wxJSON_ASSERT( size >= 0 ); + // if the desired element does not yet exist, we create as many + // elements as needed; the new values will be 'null' values + if ( index >= (unsigned) size ) { + wxJSONValue v( wxJSONTYPE_NULL); + int missing = index - size + 1; + data->m_valArray.Add( v, missing ); + } + return data->m_valArray.Item( index ); +} + +//! Return the item at the specified key. +/*! + The function returns a reference to the object in the map + that has the specified key. + If \c key does not exist, a new NULL value is created with + the provided key and a reference to it is returned. + If this object does not contain a map, the old value is + replaced by a map object. +*/ +wxJSONValue& +wxJSONValue::Item( const wxString& key ) +{ + wxLogTrace( traceMask, _T("(%s) searched key=\'%s\'"), __PRETTY_FUNCTION__, key.c_str()); + wxLogTrace( traceMask, _T("(%s) actual object: %s"), __PRETTY_FUNCTION__, GetInfo().c_str()); + + wxJSONRefData* data = COW(); + wxJSON_ASSERT( data ); + + if ( data->m_type != wxJSONTYPE_OBJECT ) { + // deletes the contained value; + data = SetType( wxJSONTYPE_OBJECT ); + return data->m_valMap[key]; + } + wxLogTrace( traceMask, _T("(%s) searching key \'%s' in the actual object"), + __PRETTY_FUNCTION__, key.c_str() ); + return data->m_valMap[key]; +} + + +//! Return the item at the specified index. +/*! + The function returns a copy of the object at the specified + index. + If the element does not exist, the function returns an \b invalid value. +*/ +wxJSONValue +wxJSONValue::ItemAt( unsigned index ) const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + wxJSONValue v( wxJSONTYPE_INVALID ); + if ( data->m_type == wxJSONTYPE_ARRAY ) { + int size = Size(); + wxJSON_ASSERT( size >= 0 ); + if ( index < (unsigned) size ) { + v = data->m_valArray.Item( index ); + } + } + return v; +} + +//! Return the item at the specified key. +/*! + The function returns a copy of the object in the map + that has the specified key. + If \c key does not exist, an \b invalid value is returned. +*/ +wxJSONValue +wxJSONValue::ItemAt( const wxString& key ) const +{ + wxLogTrace( traceMask, _T("(%s) searched key=\'%s\'"), __PRETTY_FUNCTION__, key.c_str()); + wxLogTrace( traceMask, _T("(%s) actual object: %s"), __PRETTY_FUNCTION__, GetInfo().c_str()); + + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + wxJSONValue v( wxJSONTYPE_INVALID ); + if ( data->m_type == wxJSONTYPE_OBJECT ) { + wxJSONInternalMap::const_iterator it = data->m_valMap.find( key ); + if ( it != data->m_valMap.end() ) { + v = it->second; + } + } + return v; +} + + +//! Return the item at the specified index. +/*! + The function returns a reference to the object at the specified + index. + If the element does not exist, the array is enlarged to \c index + 1 + elements and a reference to the last element will be returned. + New elements will contain NULL values. + If this object does not contain an array, the old value is + replaced by an array object. +*/ +wxJSONValue& +wxJSONValue::operator [] ( unsigned index ) +{ + wxJSONValue& v = Item( index ); + return v; +} + +//! Return the item at the specified key. +/*! + The function returns a reference to the object in the map + that has the specified key. + If \c key does not exist, a new NULL value is created with + the provided key and a reference to it is returned. + If this object does not contain a map, the old value is + replaced by a map object. +*/ +wxJSONValue& +wxJSONValue::operator [] ( const wxString& key ) +{ + wxJSONValue& v = Item( key ); + return v; +} + +// +// assignment operators +// note that reference counting is only used if the original +// value is a wxJSONValue object +// in all other cases, the operator= function deletes the old +// content and assigns the new one + + +//! Assign the specified value to this object replacing the old value. +/*! + The assignment operator assigns to this object the value specified in the + right operand of the assignment operator. + Note that the old value is deleted but not the other data members + in the wxJSONRefData structure. + This is particularly usefull for the parser class which stores + comment lines in a temporary wxJSONvalue object that is of type + wxJSONTYPE_INVALID. + As comment lines may apear before the value they refer to, comments + are stored in a value that is not yet being read. + when the value is read, it is assigned to the temporary JSON value + object without deleting the comment lines. +*/ +wxJSONValue& +wxJSONValue::operator = ( int i ) +{ + wxJSONRefData* data = SetType( wxJSONTYPE_INT ); + data->m_value.VAL_INT = i; + return *this; +} + + +//! \overload operator = (int) +wxJSONValue& +wxJSONValue::operator = ( bool b ) +{ + wxJSONRefData* data = SetType( wxJSONTYPE_BOOL ); + data->m_value.m_valBool = b; + return *this; +} + +//! \overload operator = (int) +wxJSONValue& +wxJSONValue::operator = ( unsigned int ui ) +{ + wxJSONRefData* data = SetType( wxJSONTYPE_UINT ); + data->m_value.VAL_UINT = ui; + return *this; +} + +//! \overload operator = (int) +wxJSONValue& +wxJSONValue::operator = ( long l ) +{ + wxJSONRefData* data = SetType( wxJSONTYPE_INT ); + data->m_value.VAL_INT = l; + return *this; +} + +//! \overload operator = (int) +wxJSONValue& +wxJSONValue::operator = ( unsigned long ul ) +{ + wxJSONRefData* data = SetType( wxJSONTYPE_UINT ); + data->m_value.VAL_UINT = ul; + return *this; +} + + +//! \overload operator = (int) +wxJSONValue& +wxJSONValue::operator = ( short i ) +{ + wxJSONRefData* data = SetType( wxJSONTYPE_INT ); + data->m_value.VAL_INT = i; + return *this; +} + + +//! \overload operator = (int) +wxJSONValue& +wxJSONValue::operator = ( unsigned short ui ) +{ + wxJSONRefData* data = SetType( wxJSONTYPE_UINT ); + data->m_value.VAL_UINT = ui; + return *this; +} + +//! \overload operator = (int) +wxJSONValue& +wxJSONValue::operator = ( double d ) +{ + wxJSONRefData* data = SetType( wxJSONTYPE_DOUBLE ); + data->m_value.m_valDouble = d; + return *this; +} + + +//! \overload operator = (int) +wxJSONValue& +wxJSONValue::operator = ( const wxChar* str ) +{ + wxJSONRefData* data = SetType( wxJSONTYPE_CSTRING ); + data->m_value.m_valCString = str; +#if !defined( WXJSON_USE_CSTRING ) + data->m_type = wxJSONTYPE_STRING; + data->m_valString.assign( str ); +#endif + return *this; +} + +//! \overload operator = (int) +wxJSONValue& +wxJSONValue::operator = ( const wxString& str ) +{ + wxJSONRefData* data = SetType( wxJSONTYPE_STRING ); + data->m_valString.assign( str ); + return *this; +} + + +//! Assigns to this object a memory buffer type +/*! + As with the ctor, this function makes a deep copy of the + memory buffer \c buff so changes made to the original buffer + does not reflect to the memory buffer stored in this JSON value. +*/ +wxJSONValue& +wxJSONValue::operator = ( const wxMemoryBuffer& buff ) +{ + wxJSONRefData* data = SetType( wxJSONTYPE_MEMORYBUFF ); + data->m_memBuff = new wxMemoryBuffer(); + const void* ptr = buff.GetData(); + size_t len = buff.GetDataLen(); + if ( data->m_memBuff && len ) { + data->m_memBuff->AppendData( ptr, len ); + } + return *this; +} + + +//! Assignment operator using reference counting. +/*! + Unlike all other assignment operators, this one makes a + swallow copy of the other JSON value object. + The function calls \c Ref() to get a shared referenced + data. + \sa \ref json_internals_cow +*/ +wxJSONValue& +wxJSONValue::operator = ( const wxJSONValue& other ) +{ + Ref( other ); + return *this; +} + + +// finding elements + + +//! Return a value or a default value. +/*! + This function returns a copy of the value object for the specified key. + If the key is not found, a copy of \c defaultValue is returned. + Note that the returned values are not real copy of the \c key or the + default values because \e copy-on-write is used by this class. + However, you have to treat them as real copies; in other words, if you + change the values of the returned object your changes does not reflect + in the otiginal value. + Example: + \code + wxJSONValue defaultValue( 0 ); + wxJSONvalue v1; + v1["key"] = 100; // 'v1["key"]' contains the integer 100 + + // 'v2' contains 100 but it is a swallow copy of 'v1["key"]' + wxJSONValue v2 = v1.Get( "key", defaultValue ); + + // 'v1["key"]' still contains 100 + v2 = 200; + + // if you want your change to be reflected in the 'v1' object + // you have to assign it + v1["key"] = v2; + \endcode +*/ +wxJSONValue +wxJSONValue::Get( const wxString& key, const wxJSONValue& defaultValue ) const +{ + // NOTE: this function does many wxJSONValue copies. + // so implementing COW is a good thing + + // this is the first copy (the default value) + wxJSONValue v( defaultValue ); + + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + if ( data->m_type == wxJSONTYPE_OBJECT ) { + wxJSONInternalMap::iterator it = data->m_valMap.find( key ); + if ( it != data->m_valMap.end() ) { + v = it->second; + } + } + return v; +} + + +// protected functions + +//! Find an element +/*! + The function returns a pointer to the element at index \c index + or a NULL pointer if \c index does not exist. + A NULL pointer is also returned if the object does not contain an + array nor a key/value map. +*/ +wxJSONValue* +wxJSONValue::Find( unsigned index ) const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + wxJSONValue* vp = 0; + + if ( data->m_type == wxJSONTYPE_ARRAY ) { + size_t size = data->m_valArray.GetCount(); + if ( index < size ) { + vp = &(data->m_valArray.Item( index )); + } + } + return vp; +} + +//! Find an element +/*! + The function returns a pointer to the element with key \c key + or a NULL pointer if \c key does not exist. + A NULL pointer is also returned if the object does not contain a + key/value map. +*/ +wxJSONValue* +wxJSONValue::Find( const wxString& key ) const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + wxJSONValue* vp = 0; + + if ( data->m_type == wxJSONTYPE_OBJECT ) { + wxJSONInternalMap::iterator it = data->m_valMap.find( key ); + if ( it != data->m_valMap.end() ) { + vp = &(it->second); + } + } + return vp; +} + + + +//! Return a string description of the type +/*! + This static function is only usefull for debugging purposes and + should not be used by users of this class. + It simply returns a string representation of the JSON value + type stored in a object. + For example, if \c type is wxJSONTYPE_INT the function returns the + string "wxJSONTYPE_INT". + If \c type is out of range, an empty string is returned (should + never happen). +*/ +wxString +wxJSONValue::TypeToString( wxJSONType type ) +{ + static const wxChar* str[] = { + _T( "wxJSONTYPE_INVALID" ), // 0 + _T( "wxJSONTYPE_NULL" ), // 1 + _T( "wxJSONTYPE_INT" ), // 2 + _T( "wxJSONTYPE_UINT" ), // 3 + _T( "wxJSONTYPE_DOUBLE" ), // 4 + _T( "wxJSONTYPE_STRING" ), // 5 + _T( "wxJSONTYPE_CSTRING" ), // 6 + _T( "wxJSONTYPE_BOOL" ), // 7 + _T( "wxJSONTYPE_ARRAY" ), // 8 + _T( "wxJSONTYPE_OBJECT" ), // 9 + _T( "wxJSONTYPE_LONG" ), // 10 + _T( "wxJSONTYPE_INT64" ), // 11 + _T( "wxJSONTYPE_ULONG" ), // 12 + _T( "wxJSONTYPE_UINT64" ), // 13 + _T( "wxJSONTYPE_SHORT" ), // 14 + _T( "wxJSONTYPE_USHORT" ), // 15 + _T( "wxJSONTYPE_MEMORYBUFF" ), // 16 + }; + + wxString s; + int idx = (int) type; + if ( idx >= 0 && idx < 17 ) { + s = str[idx]; + } + return s; +} + +//! Returns informations about the object +/*! + The function is only usefull for debugging purposes and will probably + be dropped in future versions. + Returns a string that contains info about the object such as: + + \li the type of the object + \li the size + \li the progressive counter + \li the pointer to referenced data + \li the progressive counter of referenced data + \li the number of share of referenced data + +The \c deep parameter is used to specify if the function will be called +recursively in order to dump sub-items. If the parameter is TRUE than a +deep dump is executed. + +The \c indent is the initial indentation: it is incremented by 3 every +time the Dump() function is called recursively. +*/ +wxString +wxJSONValue::Dump( bool deep, int indent ) const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + wxJSONType type = GetType(); + + wxString s; + if ( indent > 0 ) { + s.append( indent, ' ' ); + } + + wxString s1; + wxString s2; +#if defined( WXJSON_USE_VALUE_COUNTER ) + s1.Printf( _T("Object: Progr=%d Type=%s Size=%d comments=%d\n"), + m_progr, + TypeToString( type ).c_str(), + Size(), + data->m_comments.GetCount() ); + s2.Printf(_T(" : RefData=%p Progr=%d Num shares=%d\n"), + data, data->m_progr, data->GetRefCount() ); +#else + s1.Printf( _T("Object: Type=%s Size=%d comments=%d\n"), + TypeToString( type ).c_str(), + Size(), + data->m_comments.GetCount() ); + s2.Printf(_T(" : RefData=%p Num shares=%d\n"), + data, data->GetRefCount() ); +#endif + s.append( s1 ); + if ( indent > 0 ) { + s.append( indent, ' ' ); + } + s.append( s2 ); + + wxString sub; + + // if we have to do a deep dump, we call the Dump() function for + // every sub-item + if ( deep ) { + indent += 3; + const wxJSONInternalMap* map; + int size;; + wxJSONInternalMap::const_iterator it; + switch ( type ) { + case wxJSONTYPE_OBJECT : + map = AsMap(); + size = Size(); + for ( it = map->begin(); it != map->end(); ++it ) { + const wxJSONValue& v = it->second; + sub = v.Dump( true, indent ); + s.append( sub ); + } + break; + case wxJSONTYPE_ARRAY : + size = Size(); + for ( int i = 0; i < size; i++ ) { + const wxJSONValue* v = Find( i ); + wxJSON_ASSERT( v ); + sub = v->Dump( true, indent ); + s.append( sub ); + } + break; + default : + break; + } + } + return s; +} + +//! Returns informations about the object +/*! + The function is only usefull for debugging purposes and will probably + be dropped in future versions. + You should not rely on this function to exist in future versions. +*/ +wxString +wxJSONValue::GetInfo() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + wxString s; +#if defined( WXJSON_USE_VALUE_CONTER ) + s.Printf( _T("Object: Progr=%d Type=%s Size=%d comments=%d\n"), + (int)data->m_progr, + wxJSONValue::TypeToString( data->m_type ).c_str(), + (int)Size(), + (int)data->m_comments.GetCount() ); +#else + s.Printf( _T("Object: Type=%s Size=%d comments=%d\n"), + wxJSONValue::TypeToString( data->m_type ).c_str(), + (int)Size(), (int)data->m_comments.GetCount() ); +#endif + if ( data->m_type == wxJSONTYPE_OBJECT ) { + wxArrayString arr = GetMemberNames(); + for ( unsigned int i = 0; i < arr.size(); i++ ) { + s.append( _T(" Member name: ")); + s.append( arr[i] ); + s.append( _T("\n") ); + } + } + return s; +} + +//! The comparison function +/*! + This function returns TRUE if this object looks like \c other. + Note that this class does not define a comparison operator + (the classical \b operator== function) because the notion + of \b equal for JSON values objects is not applicable. + The comment strings array are not compared: JSON value objects + are \b the \b same if they contains the same values, regardless the + comment's strings. + + Note that the function does not return the element that cause the + comparison to return FALSE. There is not a good structure to + tell this information. + If you need it for debugging purposes, you have to turn on the + \b sameas tracing feature by setting the WXTRACE environment + variable (you need a debug version of the application): + + \code + export WXTRACE=sameas // for unix systems that use bash + \endcode + + Note that if the two JSON value objects share the same referenced + data, the function immediatly returns TRUE without doing a deep + comparison which is, sure, useless. + For further info see \ref json_internals_compare. +*/ +bool +wxJSONValue::IsSameAs( const wxJSONValue& other ) const +{ + // this is a recursive function: it calls itself + // for every 'value' object in an array or map + bool r = false; + + // some variables used in the switch statement + int size; + wxJSONInternalMap::const_iterator it; + + // get the referenced data for the two objects + wxJSONRefData* data = GetRefData(); + wxJSONRefData* otherData = other.GetRefData(); + + if ( data == otherData ) { + wxLogTrace( compareTraceMask, _T("(%s) objects share the same referenced data - r=TRUE"), + __PRETTY_FUNCTION__ ); + return true; + } + + + // if the type does not match the function compares the values if + // they are of compatible types such as INT, UINT and DOUBLE + if ( data->m_type != otherData->m_type ) { + // if the types are not compatible, returns false + // otherwise compares the compatible types: INT, UINT and DOUBLE + double val; + switch ( data->m_type ) { + case wxJSONTYPE_INT : + if ( otherData->m_type == wxJSONTYPE_UINT ) { + // compare the bits and returns true if value is between 0 and LLONG_MAX + if ( (data->m_value.VAL_UINT <= LLONG_MAX ) && + (data->m_value.VAL_UINT == otherData->m_value.VAL_UINT)) + { + r = true; + } + } + else if ( otherData->m_type == wxJSONTYPE_DOUBLE ) { + val = data->m_value.VAL_INT; + if ( val == otherData->m_value.m_valDouble ) { + r = true; + } + } + else { + r = false; + } + break; + case wxJSONTYPE_UINT : + if ( otherData->m_type == wxJSONTYPE_INT ) { + // compare the bits and returns true if value is between 0 and LLONG_MAX + if ( (data->m_value.VAL_UINT <= LLONG_MAX ) && + (data->m_value.VAL_UINT == otherData->m_value.VAL_UINT)) + { + r = true; + } + } + else if ( otherData->m_type == wxJSONTYPE_DOUBLE ) { + val = data->m_value.VAL_UINT; + if ( val == otherData->m_value.m_valDouble ) { + r = true; + } + } + else { + r = false; + } + break; + case wxJSONTYPE_DOUBLE : + if ( otherData->m_type == wxJSONTYPE_INT ) { + val = otherData->m_value.VAL_INT; + if ( val == data->m_value.m_valDouble ) { + r = true; + } + } + else if ( otherData->m_type == wxJSONTYPE_UINT ) { + val = otherData->m_value.VAL_UINT; + if ( val == data->m_value.m_valDouble ) { + r = true; + } + } + else { + r = false; + } + break; + default: + r = false; + break; + } + return r; + } + + // the two objects have the same 'm_type' + + // for comparing wxJSONTYPE_CSTRING we use two temporary wxString + // objects: this is to avoid using strcmp() and wcscmp() which + // may not be available on all platforms + wxString s1, s2; + r = true; + int r1; + + switch ( data->m_type ) { + case wxJSONTYPE_INVALID : + case wxJSONTYPE_NULL : + // there is no need to compare the values + break; + case wxJSONTYPE_INT : + if ( data->m_value.VAL_INT != otherData->m_value.VAL_INT ) { + r = false; + } + break; + case wxJSONTYPE_UINT : + if ( data->m_value.VAL_UINT != otherData->m_value.VAL_UINT ) { + r = false; + } + break; + case wxJSONTYPE_DOUBLE : + if ( data->m_value.m_valDouble != otherData->m_value.m_valDouble ) { + r = false; + } + break; + case wxJSONTYPE_CSTRING : + s1 = wxString( data->m_value.m_valCString ); + s2 = wxString( otherData->m_value.m_valCString ); + if ( s1 != s2 ) { + r = false; + } + break; + case wxJSONTYPE_BOOL : + if ( data->m_value.m_valBool != otherData->m_value.m_valBool ) { + r = false; + } + break; + case wxJSONTYPE_STRING : + if ( data->m_valString != otherData->m_valString ) { + r = false; + } + break; + case wxJSONTYPE_MEMORYBUFF : + // we cannot simply use the operator ==; we need a deep comparison + r1 = CompareMemoryBuff( *(data->m_memBuff), *(otherData->m_memBuff)); + if ( r1 != 0 ) { + r = false; + } + break; + case wxJSONTYPE_ARRAY : + size = Size(); + wxLogTrace( compareTraceMask, _T("(%s) Comparing an array object - size=%d"), + __PRETTY_FUNCTION__, size ); + + if ( size != other.Size() ) { + wxLogTrace( compareTraceMask, _T("(%s) Sizes does not match"), + __PRETTY_FUNCTION__ ); + return false; + } + // compares every element in this object with the element of + // the same index in the 'other' object + for ( int i = 0; i < size; i++ ) { + wxLogTrace( compareTraceMask, _T("(%s) Comparing array element=%d"), + __PRETTY_FUNCTION__, i ); + wxJSONValue v1 = ItemAt( i ); + wxJSONValue v2 = other.ItemAt( i ); + + if ( !v1.IsSameAs( v2 )) { + return false; + } + } + break; + case wxJSONTYPE_OBJECT : + size = Size(); + wxLogTrace( compareTraceMask, _T("(%s) Comparing a map obejct - size=%d"), + __PRETTY_FUNCTION__, size ); + + if ( size != other.Size() ) { + wxLogTrace( compareTraceMask, _T("(%s) Comparison failed - sizes does not match"), + __PRETTY_FUNCTION__ ); + return false; + } + // for every key calls itself on the value found in + // the other object. if 'key' does no exist, returns FALSE + for ( it = data->m_valMap.begin(); it != data->m_valMap.end(); it++ ) { + wxString key = it->first; + wxLogTrace( compareTraceMask, _T("(%s) Comparing map object - key=%s"), + __PRETTY_FUNCTION__, key.c_str() ); + wxJSONValue otherVal = other.ItemAt( key ); + bool isSame = it->second.IsSameAs( otherVal ); + if ( !isSame ) { + wxLogTrace( compareTraceMask, _T("(%s) Comparison failed for the last object"), + __PRETTY_FUNCTION__ ); + return false; + } + } + break; + default : + // should never happen + wxFAIL_MSG( _T("wxJSONValue::IsSameAs() unexpected wxJSONType")); + break; + } + return r; +} + +//! Add a comment to this JSON value object. +/*! + The function adds a comment string to this JSON value object and returns + the total number of comment strings belonging to this value. + Note that the comment string must be a valid C/C++ comment because the + wxJSONWriter does not modify it. + In other words, a C++ comment string must start with '//' and must end with + a new-line character. If the final LF char is missing, the + automatically adds it. + You can also add C-style comments which must be enclosed in the usual + C-comment characters. + For C-style comments, the function does not try to append the final comment + characters but allows trailing whitespaces and new-line chars. + The \c position parameter is one of: + + \li wxJSONVALUE_COMMENT_BEFORE: the comment will be written before the value + \li wxJSONVALUE_COMMENT_INLINE: the comment will be written on the same line + \li wxJSONVALUE_COMMENT_AFTER: the comment will be written after the value + \li wxJSONVALUE_COMMENT_DEFAULT: the old value of comment's position is not + changed; if no comments were added to the value object this is the + same as wxJSONVALUE_COMMENT_BEFORE. + + To know more about comment's storage see \ref json_comment_add + +*/ +int +wxJSONValue::AddComment( const wxString& str, int position ) +{ + wxJSONRefData* data = COW(); + wxJSON_ASSERT( data ); + + wxLogTrace( traceMask, _T("(%s) comment=%s"), __PRETTY_FUNCTION__, str.c_str() ); + int r = -1; + int len = str.length(); + if ( len < 2 ) { + wxLogTrace( traceMask, _T(" error: len < 2") ); + return -1; + } + if ( str[0] != '/' ) { + wxLogTrace( traceMask, _T(" error: does not start with\'/\'") ); + return -1; + } + if ( str[1] == '/' ) { // a C++ comment: check that it ends with '\n' + wxLogTrace( traceMask, _T(" C++ comment" )); + if ( str.GetChar(len - 1) != '\n' ) { + wxString temp( str ); + temp.append( 1, '\n' ); + data->m_comments.Add( temp ); + wxLogTrace( traceMask, _T(" C++ comment: LF added") ); + } + else { + data->m_comments.Add( str ); + } + r = data->m_comments.size(); + } + else if ( str[1] == '*' ) { // a C-style comment: check that it ends with '*/' + wxLogTrace( traceMask, _T(" C-style comment") ); + int lastPos = len - 1; + wxChar ch = str.GetChar( lastPos ); + // skip leading whitespaces + while ( ch == ' ' || ch == '\n' || ch == '\t' ) { + --lastPos; + ch = str.GetChar( lastPos ); + } + if ( str.GetChar( lastPos ) == '/' && str.GetChar( lastPos - 1 ) == '*' ) { + data->m_comments.Add( str ); + r = data->m_comments.size(); + } + } + else { + wxLogTrace( traceMask, _T(" error: is not a valid comment string") ); + r = -1; + } + // if the comment was stored, store the position + if ( r >= 0 && position != wxJSONVALUE_COMMENT_DEFAULT ) { + data->m_commentPos = position; + } + return r; +} + +//! Add one or more comments to this JSON value object. +/*! + The function adds the strings contained in \c comments to the comment's + string array of this value object by calling the AddComment( const wxString&,int) + function for every string in the \c comment array. + Returns the number of strings correctly added. +*/ +int +wxJSONValue::AddComment( const wxArrayString& comments, int position ) +{ + int siz = comments.GetCount(); int r = 0; + for ( int i = 0; i < siz; i++ ) { + int r2 = AddComment( comments[i], position ); + if ( r2 >= 0 ) { + ++r; + } + } + return r; +} + +//! Return a comment string. +/*! + The function returns the comment string at index \c idx. + If \c idx is out of range, an empty string is returned. + If \c idx is equal to -1, then the function returns a string + that contains all comment's strings stored in the array. +*/ +wxString +wxJSONValue::GetComment( int idx ) const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + wxString s; + int size = data->m_comments.GetCount(); + if ( idx < 0 ) { + for ( int i = 0; i < size; i++ ) { + s.append( data->m_comments[i] ); + } + } + else if ( idx < size ) { + s = data->m_comments[idx]; + } + return s; +} + +//! Return the number of comment strings. +int +wxJSONValue::GetCommentCount() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + int d = data->m_comments.GetCount(); + wxLogTrace( traceMask, _T("(%s) comment count=%d"), __PRETTY_FUNCTION__, d ); + return d; +} + +//! Return the comment position. +int +wxJSONValue::GetCommentPos() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + return data->m_commentPos; +} + +//! Get the comment string's array. +const wxArrayString& +wxJSONValue::GetCommentArray() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + + return data->m_comments; +} + +//! Clear all comment strings +void +wxJSONValue::ClearComments() +{ + wxJSONRefData* data = COW(); + wxJSON_ASSERT( data ); + + data->m_comments.clear(); +} + + +//! Set the type of the stored value. +/*! + The function sets the type of the stored value as specified in + the provided argument. + If the actual type is equal to \c type, nothing happens and this + JSON value object retains the original type and value. + If the type differs, however, the original type and value are + lost. + + The function just sets the type of the object and not the + value itself. + If the object does not have a data structure it is allocated + using the CreateRefData() function unless the type to be set + is wxJSONTYPE_INVALID. In this case and if a data structure is + not yet allocated, it is not allocated. + + If the object already contains a data structure it is not deleted + but the type is changed in the original data structure. + Complex values in the old structure are cleared. + The \c type argument can be one of the following: + + \li wxJSONTYPE_INVALID: an empty (not initialized) JSON value + \li wxJSONTYPE_NULL: a NULL value + \li wxJSONTYPE_INT: an integer value + \li wxJSONTYPE_UINT: an unsigned integer + \li wxJSONTYPE_DOUBLE: a double precision number + \li wxJSONTYPE_BOOL: a boolean + \li wxJSONTYPE_CSTRING: a C string + \li wxJSONTYPE_STRING: a wxString object + \li wxJSONTYPE_ARRAY: an array of wxJSONValue objects + \li wxJSONTYPE_OBJECT: a hashmap of key/value pairs where \e value is a wxJSONValue object + \li wxJSONTYPE_LONG: a 32-bits integer value + \li wxJSONTYPE_ULONG: an unsigned 32-bits integer + \li wxJSONTYPE_INT64: a 64-bits integer value + \li wxJSONTYPE_UINT64: an unsigned 64-bits integer + \li wxJSONTYPE_SHORT: a signed short integer + \li wxJSONTYPE_USHORT: an unsigned short integer + \li wxJSONTYPE_MEMORYBUFF: a binary memory buffer + + The integer storage depends on the platform: for platforms that support 64-bits + integers, integers are always stored as 64-bits integers. + On platforms that do not support 64-bits integers, ints are stored as \b long \b int. + To know more about the internal representation of integers, read + \ref json_internals_integer. + + Note that there is no need to set a type for the object in order to assign + a value to it. + In other words, if you want to construct a JSON value which holds an integer + value of 10, just use the specific constructor: + \code + wxJSONValue value( 10 ); + \endcode + which sets the integer type and also the numeric value. + Moreover, there is no need to set the type for none of the handled types, + not only for primitive types but for complex types, too. + For example, if you want to construct an array of JSON values, just use + the default ctor and call the Append() member function which will append the + first element to the array and will set the array type: + \code + wxJSONValue value; + value.Append( "a string" ); + \endcode + \sa GetType +*/ +wxJSONRefData* +wxJSONValue::SetType( wxJSONType type ) +{ + wxJSONRefData* data = GetRefData(); + wxJSONType oldType = GetType(); + + // check that type is within the allowed range + wxJSON_ASSERT((type >= wxJSONTYPE_INVALID) && (type <= wxJSONTYPE_MEMORYBUFF)); + if ( (type < wxJSONTYPE_INVALID) || (type > wxJSONTYPE_MEMORYBUFF) ) { + type = wxJSONTYPE_INVALID; + } + + // the function unshares the referenced data but does not delete the + // structure. This is because the wxJSON reader stores comments + // that apear before the value in a temporary value of type wxJSONTYPE_INVALID + // which is invalid and, next, it stores the JSON value in the same + // wxJSONValue object. + // If we would delete the structure using 'Unref()' we loose the + // comments + data = COW(); + + // do nothing if the actual type is the same as 'type' + if ( type == oldType ) { + return data; + } + + // change the type of the referened structure + // NOTE: integer types are always stored as the generic integer types + if ( type == wxJSONTYPE_LONG || type == wxJSONTYPE_INT64 || type == wxJSONTYPE_SHORT ) { + type = wxJSONTYPE_INT; + } + if ( type == wxJSONTYPE_ULONG || type == wxJSONTYPE_UINT64 || type == wxJSONTYPE_USHORT ) { + type = wxJSONTYPE_UINT; + } + + wxJSON_ASSERT( data ); + data->m_type = type; + + // clears complex objects of the old type + switch ( oldType ) { + case wxJSONTYPE_STRING: + data->m_valString.clear(); + break; + case wxJSONTYPE_ARRAY: + data->m_valArray.Clear(); + break; + case wxJSONTYPE_OBJECT: + data->m_valMap.clear(); + break; + case wxJSONTYPE_MEMORYBUFF: + // we first have to delete the actual memory buffer, if any + if ( data->m_memBuff ) { + delete data->m_memBuff; + data->m_memBuff = 0; + } + break; + default : + // there is not need to clear primitive types + break; + } + + // if the WXJSON_USE_CSTRING macro is not defined, the class forces + // C-string to be stored as wxString objects +#if !defined( WXJSON_USE_CSTRING ) + if ( data->m_type == wxJSONTYPE_CSTRING ) { + data->m_type = wxJSONTYPE_STRING; + } +#endif + return data; +} + +//! Return the line number of this JSON value object +/*! + The line number of a JSON value object is set to -1 when the + object is constructed. + The line number is set by the parser class, wxJSONReader, when + a JSON text is read from a stream or a string. + it is used when reading a comment line: comment lines that apear + on the same line as a value are considered \b inline comments of + the value. +*/ +int +wxJSONValue::GetLineNo() const +{ + // return ZERO if there is not a referenced data structure + int n = 0; + wxJSONRefData* data = GetRefData(); + if ( data != 0 ) { + n = data->m_lineNo; + } + return n; +} + +//! Set the line number of this JSON value object. +void +wxJSONValue::SetLineNo( int num ) +{ + wxJSONRefData* data = COW(); + wxJSON_ASSERT( data ); + data->m_lineNo = num; +} + +//! Set the pointer to the referenced data. +void +wxJSONValue::SetRefData(wxJSONRefData* data) +{ + m_refData = data; +} + +//! Increments the referenced data counter. +void +wxJSONValue::Ref(const wxJSONValue& clone) +{ + // nothing to be done + if (m_refData == clone.m_refData) + return; + + // delete reference to old data + UnRef(); + + // reference new data + if ( clone.m_refData ) { + m_refData = clone.m_refData; + ++(m_refData->m_refCount); + } +} + +//! Unreferences the shared data +/*! + The function decrements the number of shares in wxJSONRefData::m_refCount + and if it is ZERO, deletes the referenced data. + It is called by the destructor and by the copy-on-write functions. +*/ +void +wxJSONValue::UnRef() +{ + if ( m_refData ) { + wxASSERT_MSG( m_refData->m_refCount > 0, _T("invalid ref data count") ); + + if ( --m_refData->m_refCount == 0 ) { + delete m_refData; + m_refData = NULL; + } + } +} + +//! Makes an exclusive copy of shared data +void +wxJSONValue::UnShare() +{ + AllocExclusive(); +} + + +//! Do a deep copy of the other object. +/*! + This function allocates a new ref-data structure and copies it + from the object \c other. +*/ +void +wxJSONValue::DeepCopy( const wxJSONValue& other ) +{ + UnRef(); + wxJSONRefData* data = CloneRefData( other.m_refData ); + SetRefData( data ); +} + +//! Return the pointer to the referenced data structure. +wxJSONRefData* +wxJSONValue::GetRefData() const +{ + wxJSONRefData* data = m_refData; + return data; +} + + +//! Make a copy of the referenced data. +/*! + The function allocates a new instance of the wxJSONRefData + structure, copies the content of \c other and returns the pointer + to the newly created structure. + This function is called by the wxObject::UnRef() function + when a non-const member function is called on multiple + referenced data. +*/ +wxJSONRefData* +wxJSONValue::CloneRefData( const wxJSONRefData* otherData ) const +{ + wxJSON_ASSERT( otherData ); + + // make a static cast to pointer-to-wxJSONRefData + const wxJSONRefData* other = otherData; + + // allocate a new instance of wxJSONRefData using the default + // ctor; we cannot use the copy ctor of a wxJSONRefData + wxJSONRefData* data = new wxJSONRefData(); + + // copy the referenced data structure's data members + data->m_type = other->m_type; + data->m_value = other->m_value; + data->m_commentPos = other->m_commentPos; + data->m_comments = other->m_comments; + data->m_lineNo = other->m_lineNo; + data->m_valString = other->m_valString; + data->m_valArray = other->m_valArray; + data->m_valMap = other->m_valMap; + + // if the data contains a wxMemoryBuffer object, then we have + // to make a deep copy of the buffer by allocating a new one because + // wxMemoryBuffer is not a copy-on-write structure + if ( other->m_memBuff ) { + data->m_memBuff = new wxMemoryBuffer(); + const void* ptr = data->m_memBuff->GetData(); + size_t len = data->m_memBuff->GetDataLen(); + if ( data->m_memBuff && len ) { + data->m_memBuff->AppendData( ptr, len ); + } + } + + wxLogTrace( cowTraceMask, _T("(%s) CloneRefData() PROGR: other=%d data=%d"), + __PRETTY_FUNCTION__, other->GetRefCount(), data->GetRefCount() ); + + return data; +} + +//! Create a new data structure +/*! + The function allocates a new instance of the wxJSONRefData + structure and returns its pointer. + The type of the JSON value is set to wxJSONTYPE_INVALID (= + a not initialized value). +*/ +wxJSONRefData* +wxJSONValue::CreateRefData() const +{ + wxJSONRefData* data = new wxJSONRefData(); + data->m_type = wxJSONTYPE_INVALID; + return data; +} + + + +//! Make sure the referenced data is unique +/*! + This function is called by all non-const member functions and makes + sure that the referenced data is unique by calling \b UnShare() + If the referenced data is shared acrosss other wxJSONValue instances, + the \c UnShare() function makes a private copy of the shared data. +*/ +wxJSONRefData* +wxJSONValue::COW() +{ + wxJSONRefData* data = GetRefData(); + wxLogTrace( cowTraceMask, _T("(%s) COW() START data=%p data->m_count=%d"), + __PRETTY_FUNCTION__, data, data->GetRefCount()); + UnShare(); + data = GetRefData(); + wxLogTrace( cowTraceMask, _T("(%s) COW() END data=%p data->m_count=%d"), + __PRETTY_FUNCTION__, data, data->GetRefCount()); + return GetRefData(); +} + +//! Makes a private copy of the referenced data +void +wxJSONValue::AllocExclusive() +{ + if ( !m_refData ) { + m_refData = CreateRefData(); + } + else if ( m_refData->GetRefCount() > 1 ) { + // note that ref is not going to be destroyed in this case + const wxJSONRefData* ref = m_refData; + UnRef(); + + // ... so we can still access it + m_refData = CloneRefData(ref); + } + //else: ref count is 1, we are exclusive owners of m_refData anyhow + + wxASSERT_MSG( m_refData && m_refData->GetRefCount() == 1, + _T("wxObject::AllocExclusive() failed.") ); +} + +//! Convert memory buffer object to a string representation. +/*/ + The fucntion returns a string representation of the data contained in the + memory buffer object \c buff. + The string is conposed of two hexadecimal digits for every byte contained + in the memory buffer; bytes are separated by a space character. + The string starts with the actual lenght of the data enclosed in parenthesis. + The string will contain \c len bytes if \c len is less than the length + of the actual data in \c buff. + Note that the (len) printed in the output referes to the length of the buffer + which may be greater than the length that has to be printed. + + \b Example: + This is an example of printing a memory buffer object that contains 10 bytes: + \code + 0x80974653 (10) 00 01 02 03 04 05 06 07 08 09 + \endcode +*/ +wxString +wxJSONValue::MemoryBuffToString( const wxMemoryBuffer& buff, size_t len ) +{ + size_t buffLen = buff.GetDataLen(); + void* ptr = buff.GetData(); + wxString s = MemoryBuffToString( ptr, MIN( buffLen, len ), buffLen ); + return s; +} + + +//! Convert a binary memory buffer to a string representation. +/*/ + The function returns a string representation of the data contained in the + binary memory buffer pointed to by \c buff for \c len bytes. + The string is composed of two hexadecimal digits for every byte contained + in the memory buffer; bytes are separated by a space character. + The string starts with pointer to binary data followed by the lenght of the + data enclosed in parenthesis. + + \b Example: + This is an example of printing ten bytes from a memory buffer: + \code + 0x80974653 (10) 00 01 02 03 04 05 06 07 08 09 + \endcode + + @param buff the pointer to the memory buffer data + @len the length of the data that has to be printed + @actualLen the real lenght of the memory buffer that has to be printed + just afetr the pointer; may be greater than \c len. If this parameter + is -1 then it is equal to \c len +*/ +wxString +wxJSONValue::MemoryBuffToString( const void* buff, size_t len, size_t actualLen ) +{ + wxString s; + size_t buffLen = actualLen; + if (buffLen == (size_t) -1 ) { + buffLen = len; + } + s.Printf( _T("%p (%u) "), buff, buffLen ); + unsigned char* ptr = (unsigned char*) buff; + for ( unsigned int i = 0; i < len; i++ ) { + unsigned char c = *ptr; + ++ptr; + // now convert the character + char c1 = c / 16; + char c2 = c % 16; + c1 += '0'; + c2 += '0'; + if ( c1 > '9' ) { + c1 += 7; + } + if ( c2 > '9' ) { + c2 += 7; + } + s.Append( c1, 1 ); + s.Append( c2, 1 ); + s.Append( ' ', 1 ); // a space separates the bytes + } + return s; +} + +//! Compares two memory buffer objects +/*! + The function is the counterpart of the comparison operator == for two wxMemoryBuffer + objects. + You may noticed that the wxMemoryBuffer class does not define comparison operators so + if you write a code snippset like the following: + \code + wxMemoryBuffer b1; + wxMemoryBuffer b2; + b1.AppendData( "1234567890", 10 ); + b2.AppendData( "1234567890", 10 ); + bool r = b1 == b2; + \endcode + + you may expect that \b r is TRUE, because both objects contain the same data. + This is not true. The result you get is FALSE because the default comparison operator + is used, which just compares the data members of the class. + The data member is the pointer to the allocated memory that contains the data and + they are not equal. + This function uses the (fast) \b memcmp function to compare the actual data + contained in the nenory buffer objects thus doing a deep comparison. + The function returns the return value of \b memcmp: + + the memcmp() function returns an integer less than, equal to, or + greater than zero if the first n bytes of \c buff1 is found, respectively, to + be less than, to match, or be greater than the first n bytes of \c buff2. +*/ +int +wxJSONValue::CompareMemoryBuff( const wxMemoryBuffer& buff1, const wxMemoryBuffer& buff2 ) +{ + int r; + size_t buff1Len = buff1.GetDataLen(); + size_t buff2Len = buff2.GetDataLen(); + if ( buff1Len > buff2Len ) { + r = 1; + } + else if ( buff1Len < buff2Len ) { + r = -1; + } + else { + r = memcmp( buff1.GetData(), buff2.GetData(), buff1Len ); + } + return r; +} + +//! Compares a memory buffer object and a memory buffer +/*! + The function compares the data contained in a memory buffer object with a + memory buffer. + This function uses the (fast) \b memcmp function to compare the actual data + contained in the nenory buffer object thus doing a deep comparison. + The function returns the return value of \b memcmp: + + The memcmp() function returns an integer less than, equal to, or + greater than zero if the first n bytes of \c buff1 is found, respectively, to + be less than, to match, or be greater than the first n bytes of \c buff2. +*/ +int +wxJSONValue::CompareMemoryBuff( const wxMemoryBuffer& buff1, const void* buff2 ) +{ + int r; + size_t buff1Len = buff1.GetDataLen(); + r = memcmp( buff1.GetData(), buff2, buff1Len ); + return r; +} + + +//! Converts an array of INTs to a memory buffer +/*! + This static function converts an array of INTs stored in a wxJSONvalue object + into a memory buffer object. + The wxJSONvalue object passed as parameter must be of type ARRAY and must contain + INT types whose values are between 0 and 255. + + Every element of the array si converted to a BYTE value and appended to the returned + wxMemoryBuffer object. The following rules apply in the conversion: + \li if \c value is not an ARRAY type, an empty memory buffer is returned + \li if the \c value array contains elements of type other than INT, those + elements are ignored + \li if the \c value array contains elements of type INT which value is outside the + range 0..255, those elements are ignored + \li if the \c value array contains only ignored elements an empty wxMemoryBuffer + object is returned. + + This function can be used to get a memory buffer object from valid JSON text. + Please note that the wxJSONReader cannot know which array of INTs represent a binary + memory buffer unless you use the \b wxJSON \e memory \e buffer extension in the writer and + in the reader. +*/ +wxMemoryBuffer +wxJSONValue::ArrayToMemoryBuff( const wxJSONValue& value ) +{ + wxMemoryBuffer buff; + if ( value.IsArray() ) { + int len = value.Size(); + for ( int i = 0; i < len; i++ ) { + short int byte; unsigned char c; + // we do not use opertaor [] because it is not const + // bool r = value[i].AsShort( byte ); + bool r = value.ItemAt(i).AsShort( byte ); + if ( r && ( byte >= 0 && byte <= 255 ) ) { + c = (unsigned char) byte; + buff.AppendByte( c ); + } + } + } + return buff; +} + + +/************************************************************************* + + 64-bits integer support + +*************************************************************************/ + +#if defined( wxJSON_64BIT_INT) + + +//! \overload wxJSONValue() +wxJSONValue::wxJSONValue( wxInt64 i ) +{ + m_refData = 0; + wxJSONRefData* data = Init( wxJSONTYPE_INT ); + wxJSON_ASSERT( data ); + if ( data != 0 ) { + data->m_value.VAL_INT = i; + } +} + +//! \overload wxJSONValue() +wxJSONValue::wxJSONValue( wxUint64 ui ) +{ + m_refData = 0; + wxJSONRefData* data = Init( wxJSONTYPE_UINT ); + wxJSON_ASSERT( data ); + if ( data != 0 ) { + data->m_value.VAL_UINT = ui; + } +} + +//! Return TRUE if the stored value is a 32-bits integer +/*! + This function is only available on 64-bits platforms and returns + TRUE if, and only if, the stored value is of type \b wxJSONTYPE_INT + and the numeric value fits in a 32-bits signed integer. + The function just calls IsLong() and returns the value returned by + that function. + The use of this function is deprecated: use \c IsLong() instead +*/ +bool +wxJSONValue::IsInt32() const +{ + bool r = IsLong(); + return r; +} + +//! Return TRUE if the stored value is a unsigned 32-bits integer +/*! + This function is only available on 64-bits platforms and returns + TRUE if, and only if, the stored value is of type \b wxJSONTYPE_UINT + and the numeric value fits in a 32-bits unsigned integer. + The function just calls IsULong() and returns the value returned by + that function. + The use of this function is deprecated: use \c IsULong() instead +*/ +bool +wxJSONValue::IsUInt32() const +{ + bool r = IsULong(); + return r; +} + + +//! Return TRUE if the stored value is integer. +/*! + This function returns TRUE if the stored value is of + type signed integer. + In other words, the function returns TRUE if the \c wxJSONRefData::m_type + data member is of type \c wxJSONTYPE_INT + The function is only available if 64-bits integer support is enabled. + + \sa \ref json_internals_integer +*/ +bool +wxJSONValue::IsInt64() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + bool r = false; + if ( data->m_type == wxJSONTYPE_INT ) { + r = true; + } + return r; +} + + +//! Return TRUE if the stored value is a unsigned integer +/*! + This function returns TRUE if the stored value is of + type unsigned integer. + In other words, the function returns TRUE if the \c wxJSONRefData::m_type + data member is of type \c wxJSONTYPE_UINT. + The function is only available if 64-bits integer support is enabled. + + \sa \ref json_internals_integer +*/ +bool +wxJSONValue::IsUInt64() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + bool r = false; + if ( data->m_type == wxJSONTYPE_UINT ) { + r = true; + } + return r; +} + +//! Returns the low-order 32 bits of the value as an integer +/*! + This function is only available on 64-bits platforms and returns + the low-order 32-bits of the integer stored in the JSON value. + Note that all integer types are stored as \b wx(U)Int64 data types by + the JSON value class and that the function does not check that the + numeric value fits in a 32-bit integer. + The function just calls AsLong() and casts the value in a wxInt32 data + type + + \sa \ref wxjson_tutorial_get +*/ +wxInt32 +wxJSONValue::AsInt32() const +{ + wxInt32 i; + i = (wxInt32) AsLong(); + return i; +} + +//! Returns the low-order 32 bits of the value as an unsigned integer +/*! + This function is only available on 64-bits platforms and returns + the low-order 32-bits of the integer stored in the JSON value. + Note that all integer types are stored as \b wx(U)Int64 data types by + the JSON value class and that the function does not check that the + numeric value fits in a 32-bit integer. + The function just calls AsULong() and casts the value in a wxUInt32 data + type + + \sa \ref wxjson_tutorial_get +*/ +wxUint32 +wxJSONValue::AsUInt32() const +{ + wxUint32 ui; + ui = (wxUint32) AsULong(); + return ui; +} + + +//! Return the numeric value as a 64-bit integer. +/*! + This function is only available on 64-bits platforms and returns + the numeric value as a 64-bit integer. + + Note that the function does not check that the type of the + value is actually an integer and it just returns the content + of the wxJSONValueHolder union. + However, in debug builds, the function ASSERTs that the + type of the stored value is wxJSONTYPE_INT. + + \sa \ref json_internals_integer + \sa \ref wxjson_tutorial_get +*/ +wxInt64 +wxJSONValue::AsInt64() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + wxInt64 i64 = data->m_value.m_valInt64; + + wxJSON_ASSERT( IsInt64()); // exapnds only in debug builds + return i64; +} + +//! Return the numeric value as a 64-bit unsigned integer. +/*! + This function is only available on 64-bits platforms and returns + the numeric value as a 64-bit unsigned integer. + + Note that the function does not check that the type of the + value is actually an integer and it just returns the content + of the wxJSONValueHolder union. + However, in debug builds, the function wxJSON_ASSERTs that the + type of the stored value is wxJSONTYPE_UINT. + + \sa \ref json_internals_integer + \sa \ref wxjson_tutorial_get +*/ +wxUint64 +wxJSONValue::AsUInt64() const +{ + wxJSONRefData* data = GetRefData(); + wxJSON_ASSERT( data ); + wxUint64 ui64 = data->m_value.m_valUInt64; + + wxJSON_ASSERT( IsUInt64()); // exapnds only in debug builds + return ui64; +} + +bool +wxJSONValue::AsInt32( wxInt32& i32 ) const +{ + bool r = IsInt32(); + if ( r ) { + i32 = AsInt32(); + } + return r; +} + +bool +wxJSONValue::AsUInt32( wxUint32& ui32 ) const +{ + bool r = IsUInt32(); + if ( r ) { + ui32 = AsUInt32(); + } + return r; +} + +bool +wxJSONValue::AsInt64( wxInt64& i64 ) const +{ + bool r = IsInt64(); + if ( r ) { + i64 = AsInt64(); + } + return r; +} + +bool +wxJSONValue::AsUInt64( wxUint64& ui64 ) const +{ + bool r = IsUInt64(); + if ( r ) { + ui64 = AsUInt64(); + } + return r; +} + +//! \overload Append( const wxJSONValue& ) +wxJSONValue& +wxJSONValue::Append( wxInt64 i ) +{ + wxJSONValue v( i ); + wxJSONValue& r = Append( v ); + return r; +} + +//! \overload Append( const wxJSONValue& ) +wxJSONValue& +wxJSONValue::Append( wxUint64 ui ) +{ + wxJSONValue v( ui ); + wxJSONValue& r = Append( v ); + return r; +} + + +//! \overload operator = (int) +wxJSONValue& +wxJSONValue::operator = ( wxInt64 i ) +{ + wxJSONRefData* data = SetType( wxJSONTYPE_INT ); + data->m_value.VAL_INT = i; + return *this; +} + +//! \overload operator = (int) +wxJSONValue& +wxJSONValue::operator = ( wxUint64 ui ) +{ + wxJSONRefData* data = SetType( wxJSONTYPE_UINT ); + data->m_value.VAL_UINT = ui; + return *this; +} + + +#endif // defined( wxJSON_64BIT_INT ) + + + + +/* +{ +} +*/ + diff --git a/ThirdParty/wxJSON/src/jsonwriter.cpp b/ThirdParty/wxJSON/src/jsonwriter.cpp new file mode 100644 index 0000000..37def98 --- /dev/null +++ b/ThirdParty/wxJSON/src/jsonwriter.cpp @@ -0,0 +1,1274 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: jsonwriter.cpp +// Purpose: the wxJSONWriter class: a JSON text generator +// Author: Luciano Cattani +// Created: 2007/10/12 +// RCS-ID: $Id: jsonwriter.cpp,v 1.6 2008/03/03 19:05:47 luccat Exp $ +// Copyright: (c) 2007 Luciano Cattani +// Licence: wxWidgets licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ + #pragma implementation "jsonwriter.cpp" +#endif + + +#include + +#include +#include +#include +#include + +static const wxChar* writerTraceMask = _T("traceWriter"); + +/*! \class wxJSONWriter + \brief The JSON document writer + + This class is a JSON document writer and it is used to write a + wxJSONValue object to an output stream or to a string object. + The ctor accepts some parameters which can be used to + change the style of the output. + The default output is in human-readable format that uses a three-space + indentation for object / array sub-items and separates every + value with a linefeed character. + + + \par Examples + + Using the default writer constructor + + \code + // construct the JSON value object and add values to it + wxJSONValue root; + root["key1"] = "some value"; + ... + + // construct the string that will contain the JSON text + wxString str; + + // construct a JSON writer: use the default writer's settings + wxJSONWriter writer; + + // call the writer's Write() memberfunction + writer.Write( root, str ); + \endcode + + + To write a JSON value object using a four-spaces indentation and forcing all + comment strings to apear before the value they refer to, use the following code: + \code + wxJSONWriter writer( wxJSONWRITER_STYLED | // want a styled output + wxJSONWRITER_WRITE_COMMENTS | // want comments in the document + wxJSONWRITER_COMMENTS_BEFORE, // force comments before value + 0, // initial indentation + 4); // indentation step + writer.Write( value, document ); + \endcode + + The following code construct a JSON writer that produces the most compact + text output but it is hard to read by humans: + + \code + wxJSONWriter writer( wxJSONWRITER_NONE ); + writer.Write( value, document ); + \endcode + + + \par The two types of output objects + + You can write JSON text to two different kind of objects: + + \li a string object (\b wxString) + \li a stream object (\b wxOutputStream) + + When writing to a string object, the output is platform- and mode-dependent. + In ANSI builds, the JSON text output in the string object will + contain one-byte characters: the actual characters represented is + locale dependent. + In Unicode builds, the JSON text output in the string contains + wide characters which encoding format is platform dependent: UCS-2 in + Windows, UCS-4 in GNU/Linux. + Starting from wxWidgets version 2.9 the internal encoding for Unicode + builds in linux/unix systems is UTF-8. + + When writing to a stream object, the JSON text output is always + encoded in UTF-8 in both ANSI and Unicode builds. + In ANSI builds the user may want to suppress UTF-8 encoding so + that the JSON text can be stored in ANSI format. + Note that this is not valid JSON text unless all characters written + to the JSON text document are in the US-ASCII character ser (0x00..0x7F). + To know more read \ref wxjson_tutorial_unicode_ansi + + \par Efficiency + + In versions up to 1.0 the JSON writer wrote every character to the + output object (the string or the stream). + This is very inefficient becuase the writer converted each char to + UTF-8 when writing to streams but we have to note that only string values + have to be actually converted. + Special JSON characters, numbers and literals do not need the conversion + because they lay in the US-ASCII plane (0x00-0x7F) + and no conversion is needed as the UTF-8 encoding is the same as US-ASCII. + + For more info about the unicode topic see \ref wxjson_tutorial_unicode. + + \par The problem of writing doubles + + You can customize the ouput of doubles by specifing the format string + that has to be used by the JSON writer class. To know more about this issue + read \ref wxjson_tutorial_write_doubles +*/ + +//! Ctor. +/*! + Construct the JSON writer object with the specified parameters. + Note that if \c styled is FALSE the indentation is totally suppressed + and the values of the other two parameters are simply ignored. + + \param indent the initial indentation in number of spaces. Default is ZERO. + If you specify the wxJSONWRITER_TAB_INDENT flag for the \e style, + this value referes to the number of TABs in the initial indentation + + \param step the indentation increment for new objects/arrays in number of spaces + (default is 3). + This value is ignored if you specify the wxJSONWRITER_TAB_INDENT flag for + the \e style: the indentation increment is only one TAB character. + + \param style this is a combination of the following constants OR'ed togheter: + \li wxJSONWRITER_NONE: no indentation is performed and no LF character is + written between values. + This style produces strict JSON text but it is hard to read by humans + \li wxJSONWRITER_STYLED: output is human-readable: values are separated by + LF characters and sub-items are indented. + This style produces strict JSON text that is easy to read by humans. + \li wxJSONWRITER_WRITE_COMMENTS: this flag force the writer to write C/C++ + comment strings, if any. The comments will be written in their original position. + C/C++ comments may not be recognized by other JSON implementations because + they are not strict JSON text. + \li wxJSONWRITER_COMMENTS_BEFORE: this flag force the writer to write C/C++ comments + always before the value they refer to. + In order for this style to take effect, you also have to specify the + wxJSONWRITER_WRITE_COMMENTS flag. + \li wxJSONWRITER_COMMENTS_AFTER: this flag force the writer to write C/C++ comments + always after the value they refer to. + In order for this style to take effect, you also have to specify the + wxJSONWRITER_WRITE_COMMENTS flag. + \li wxJSONWRITER_SPLIT_STRINGS: this flag cause the writer to split strings + in more than one line if they are too long. + \li wxJSONWRITER_NO_LINEFEEDS: this flag cause the JSON writer to not add + newlines between values. It is ignored if wxJSONWRITER_STYLED is not set. + This style produces strict JSON text. + \li wxJSONWRITER_ESCAPE_SOLIDUS: the solidus character (/) should only be + escaped if the JSON text is meant for embedding in HTML. + Unlike in older 0.x versions, it is disabled by default and this flag cause + the solidus char to be escaped. + This style produces strict JSON text. + \li wxJSONWRITER_MULTILINE_STRING:this is a multiline-string mode where newlines + and tabs are not escaped. This is not strict JSON, but it helps immensely when + manually editing json files with multiline strings + \li wxJSONWRITER_RECOGNIZE_UNSIGNED: this flag cause the JSON writer to prepend + a plus sign (+) to unsigned integer values. This is used by the wxJSON reader to + force the integer to be stored in an \b unsigned \b int. Note that this + feature may be incompatible with other JSON implementations. + \li wxJSONWRITER_TAB_INDENT: this flag cause the indentation of sub-objects / arrays + to be done using a TAB character instead of SPACES. + In order for this style to take effect, you also have to specify the + wxJSONWRITER_STYLED flag. + This style produces strict JSON text. + \li wxJSONWRITER_NO_INDENTATION: this flag cause the JSON writer to not add + indentation. It is ignored if wxJSONWRITER_STYLED is not set. + This style produces strict JSON text. + \li wxJSONWRITER_NOUTF8_STREAM: suppress UTF-8 conversion when writing string + values to the stream thus producing ANSI text output; only meaningfull in + ANSI builds, this flag is simply ignored in Unicode builds. + \li wxJSONWRITER_MEMORYBUFF: + + + Note that for the style wxJSONWRITER_NONE the JSON text output is a bit + different from that of old 0.x versions although it is syntactically equal. + If you rely on the old JSON output formatting read the following page + \ref wxjson_tutorial_style_none. + To know more about the writer's styles see \ref wxjson_tutorial_style +*/ +wxJSONWriter::wxJSONWriter( int style, int indent, int step ) +{ + m_indent = indent; + m_step = step; + m_style = style; + m_noUtf8 = false; + if ( m_style == wxJSONWRITER_NONE ) { + m_indent = 0; + m_step = 0; + } + // set the default format string for doubles as + // 10 significant digits and suppress trailing ZEROes + SetDoubleFmtString( "%.10g") ; + +#if !defined( wxJSON_USE_UNICODE ) + // in ANSI builds we can suppress UTF-8 conversion for both the writer and the reader + if ( m_style == wxJSONWRITER_NOUTF8_STREAM ) { + m_noUtf8 = true; + } +#endif +} + +//! Dtor - does nothing +wxJSONWriter::~wxJSONWriter() +{ +} + +//! Write the JSONvalue object to a JSON text. +/*! + The two overloaded versions of this function let the user choose + the output object which can be: + + \li a string object (\b wxString) + \li a stream object ( \b wxOutputStream) + + The two types of output object are very different because the + text outputted is encoded in different formats depending on the + build mode. + When writing to a string object, the JSON text output is encoded + differently depending on the build mode and the platform. + Writing to a stream always produce UTF-8 encoded text. + To know more about this topic read \ref wxjson_tutorial_unicode. + + Also note that the Write() function does not return a status code. + If you are writing to a string, you do not have to warry about this + issue: no errors can occur when writing to strings. + On the other hand, wehn writing to a stream there could be errors + in the write operation. + If an error occurs, the \c Write(9 function immediatly returns + without trying further output operations. + You have to check the status of the stream by calling the stream's + memberfunctions. Example: + + \code + // construct the JSON value object and add values to it + wxJSONValue root; + root["key1"] = "some value"; + + // write to a stream + wxMemoryOutputStream mem; + wxJSONWriter writer; + writer.Write( root, mem ); + wxStreamError err = mem.GetLastError(); + if ( err != wxSTREAM_NO_ERROR ) { + MessageBox( _T("ERROR: cannot write the JSON text output")); + } +\endcode +*/ +void +wxJSONWriter::Write( const wxJSONValue& value, wxString& str ) +{ +#if !defined( wxJSON_USE_UNICODE ) + // in ANSI builds output to a string never use UTF-8 conversion + bool noUtf8_bak = m_noUtf8; // save the current setting + m_noUtf8 = true; +#endif + + wxMemoryOutputStream os; + Write( value, os ); + + // get the address of the buffer + wxFileOffset len = os.GetLength(); + wxStreamBuffer* osBuff = os.GetOutputStreamBuffer(); + void* buffStart = osBuff->GetBufferStart(); + + if ( m_noUtf8 ) { + str = wxString::From8BitData( (const char*) buffStart, len ); + } + else { + str = wxString::FromUTF8( (const char*) buffStart, len ); + } +#if !defined( wxJSON_USE_UNICODE ) + m_noUtf8 = noUtf8_bak; // restore the old setting +#endif +} + +//! \overload Write( const wxJSONValue&, wxString& ) +void +wxJSONWriter::Write( const wxJSONValue& value, wxOutputStream& os ) +{ + m_level = 0; + DoWrite( os, value, 0, false ); +} + +//! Set the format string for double values. +/*! + This function sets the format string used for printing double values. + Double values are outputted to JSON text using the \b snprintf function + with a default format string of: + \code + %.10g + \endcode + which prints doubles with a precision of 10 decimal digits and suppressing + trailing ZEROes. + + Note that the parameter is a pointer to \b char and not to \b wxChar. This + is because the JSON writer always procudes UTF-8 encoded text and decimal + digits in UTF-8 are made of only one UTF-8 code-unit (1 byte). +*/ +void +wxJSONWriter::SetDoubleFmtString( const char* fmt ) +{ + m_fmt = (char*) fmt; +} + + + +//! Perform the real write operation. +/*! + This is a recursive function that gets the type of the \c value object and + calls several protected functions depending on the type: + + \li \c WriteNullvalue for type NULL + \li \c WriteStringValue() for STRING and CSTRING types + \li \c WriteIntValue for INT types + \li \c WriteUIntValue for UINT types + \li \c WriteBoolValue for BOOL types + \li \c WriteDoubleValue for DOUBLE types + \li \c WriteMemoryBuff for MEMORYBUFF types + + If the value is an array or key/value map (types ARRAY and OBJECT), the function + iterates through all JSON value object in the array/map and calls itself for every + item in the container. +*/ +int +wxJSONWriter::DoWrite( wxOutputStream& os, const wxJSONValue& value, const wxString* key, bool comma ) +{ + // note that this function is recursive + + // some variables that cannot be allocated in the switch statement + const wxJSONInternalMap* map = 0; + int size; + m_colNo = 1; m_lineNo = 1; + // determine the comment position; it is one of: + // + // wxJSONVALUE_COMMENT_BEFORE + // wxJSONVALUE_COMMENT_AFTER + // wxJSONVALUE_COMMENT_INLINE + // + // or -1 if comments have not to be written + int commentPos = -1; + if ( value.GetCommentCount() > 0 && (m_style & wxJSONWRITER_WRITE_COMMENTS)) { + commentPos = value.GetCommentPos(); + if ( ( m_style & wxJSONWRITER_COMMENTS_BEFORE) != 0 ) { + commentPos = wxJSONVALUE_COMMENT_BEFORE; + } + else if ( (m_style & wxJSONWRITER_COMMENTS_AFTER) != 0 ) { + commentPos = wxJSONVALUE_COMMENT_AFTER; + } + } + + int lastChar = 0; // check if WriteComment() writes the last LF char + + // first write the comment if it is BEFORE + if ( commentPos == wxJSONVALUE_COMMENT_BEFORE ) { + lastChar = WriteComment( os, value, true ); + if ( lastChar < 0 ) { + return lastChar; + } + else if ( lastChar != '\n' ) { + WriteSeparator( os ); + } + } + + lastChar = WriteIndent( os ); + if ( lastChar < 0 ) { + return lastChar; + } + + // now write the key if it is not NULL + if ( key ) { + lastChar = WriteKey( os, *key ); + } + if ( lastChar < 0 ) { + return lastChar; + } + + // now write the value + wxJSONInternalMap::const_iterator it; // declare the map object + long int count = 0; + + wxJSONType t = value.GetType(); + switch ( t ) { + case wxJSONTYPE_INVALID : + WriteInvalid( os ); + wxFAIL_MSG( _T("wxJSONWriter::WriteEmpty() cannot be called (not a valid JSON text")); + break; + + case wxJSONTYPE_INT : + case wxJSONTYPE_SHORT : + case wxJSONTYPE_LONG : + case wxJSONTYPE_INT64 : + lastChar = WriteIntValue( os, value ); + break; + + case wxJSONTYPE_UINT : + case wxJSONTYPE_USHORT : + case wxJSONTYPE_ULONG : + case wxJSONTYPE_UINT64 : + lastChar = WriteUIntValue( os, value ); + break; + + case wxJSONTYPE_NULL : + lastChar = WriteNullValue( os ); + break; + case wxJSONTYPE_BOOL : + lastChar = WriteBoolValue( os, value ); + break; + + case wxJSONTYPE_DOUBLE : + lastChar = WriteDoubleValue( os, value ); + break; + + case wxJSONTYPE_STRING : + case wxJSONTYPE_CSTRING : + lastChar = WriteStringValue( os, value.AsString()); + break; + + case wxJSONTYPE_MEMORYBUFF : + lastChar = WriteMemoryBuff( os, value.AsMemoryBuff()); + break; + + case wxJSONTYPE_ARRAY : + ++m_level; + os.PutC( '[' ); + // the inline comment for objects and arrays are printed in the open char + if ( commentPos == wxJSONVALUE_COMMENT_INLINE ) { + commentPos = -1; // we have already written the comment + lastChar = WriteComment( os, value, false ); + if ( lastChar < 0 ) { + return lastChar; + } + if ( lastChar != '\n' ) { + lastChar = WriteSeparator( os ); + } + } + else { // comment is not to be printed inline, so write a LF + lastChar = WriteSeparator( os ); + if ( lastChar < 0 ) { + return lastChar; + } + } + + // now iterate through all sub-items and call DoWrite() recursively + size = value.Size(); + for ( int i = 0; i < size; i++ ) { + bool comma = false; + if ( i < size - 1 ) { + comma = true; + } + wxJSONValue v = value.ItemAt( i ); + lastChar = DoWrite( os, v, 0, comma ); + if ( lastChar < 0 ) { + return lastChar; + } + + } + --m_level; + lastChar = WriteIndent( os ); + if ( lastChar < 0 ) { + return lastChar; + } + os.PutC( ']' ); + break; + + case wxJSONTYPE_OBJECT : + ++m_level; + + os.PutC( '{' ); + // the inline comment for objects and arrays are printed in the open char + if ( commentPos == wxJSONVALUE_COMMENT_INLINE ) { + commentPos = -1; // we have already written the comment + lastChar = WriteComment( os, value, false ); + if ( lastChar < 0 ) { + return lastChar; + } + if ( lastChar != '\n' ) { + WriteSeparator( os ); + } + } + else { + lastChar = WriteSeparator( os ); + } + + map = value.AsMap(); + size = value.Size(); + count = 0; + for ( it = map->begin(); it != map->end(); ++it ) { + // get the key and the value + wxString key = it->first; + const wxJSONValue& v = it->second; + bool comma = false; + if ( count < size - 1 ) { + comma = true; + } + lastChar = DoWrite( os, v, &key, comma ); + if ( lastChar < 0 ) { + return lastChar; + } + count++; + } + --m_level; + lastChar = WriteIndent( os ); + if ( lastChar < 0 ) { + return lastChar; + } + os.PutC( '}' ); + break; + + default : + // a not yet defined wxJSONType: we FAIL + wxFAIL_MSG( _T("wxJSONWriter::DoWrite() undefined wxJSONType type")); + break; + } + + // writes the comma character before the inline comment + if ( comma ) { + os.PutC( ',' ); + } + + if ( commentPos == wxJSONVALUE_COMMENT_INLINE ) { + lastChar = WriteComment( os, value, false ); + if ( lastChar < 0 ) { + return lastChar; + } + } + else if ( commentPos == wxJSONVALUE_COMMENT_AFTER ) { + WriteSeparator( os ); + lastChar = WriteComment( os, value, true ); + if ( lastChar < 0 ) { + return lastChar; + } + } + if ( lastChar != '\n' ) { + lastChar = WriteSeparator( os ); + } + return lastChar; +} + + +//! Write the comment strings, if any. +int +wxJSONWriter::WriteComment( wxOutputStream& os, const wxJSONValue& value, bool indent ) +{ + // the function returns the last character written which should be + // a LF char or -1 in case of errors + // if nothing is written, returns ZERO + int lastChar = 0; + + // only write comments if the style include the WRITE_COMMENTS flag + if ( (m_style & wxJSONWRITER_WRITE_COMMENTS ) == 0 ) { + return lastChar; + } + + const wxArrayString cmt = value.GetCommentArray(); + int cmtSize = cmt.GetCount(); + for ( int i = 0; i < cmtSize; i++ ) { + if ( indent ) { + WriteIndent( os ); + } + else { + os.PutC( '\t' ); + } + WriteString( os, cmt[i]); + lastChar = cmt[i].Last(); + if ( lastChar != '\n' ) { + os.PutC( '\n' ); + lastChar = '\n'; + } + } + return lastChar; +} + +//! Writes the indentation to the JSON text. +/*! + The two functions write the indentation as \e spaces in the JSON output + text. When called with a int parameter, the function + writes the specified number of spaces. + If no parameter is given, the function computes the number of spaces + using the following formula: + If the wxJSONWRITER_TAB_INDENT flag is used in the writer's cnstructor, + the function calls WriteTabIndent(). + + The function also checks that wxJSONWRITER_STYLED is set and the + wxJSONWRITER_NO_INDENTATION is not set. +*/ +int +wxJSONWriter::WriteIndent( wxOutputStream& os ) +{ + int lastChar = WriteIndent( os, m_level ); + return lastChar; +} + +//! Write the specified number of indentation (spaces or tabs) +/*! + The function is called by WriteIndent() and other writer's functions. + It writes the indentation as specified in the \c num parameter which is + the actual \b level of annidation. + The function checks if wxJSONWRITER_STYLED is set: if not, no indentation + is performed. + Also, the function checks if wxJSONWRITER_TAB_INDENT is set: if it is, + indentation is done by writing \b num TAB characters otherwise, + it is performed by writing a number of spaces computed as: + \code + numSpaces = m_indent + ( m_step * num ) + \endcode + +*/ +int +wxJSONWriter::WriteIndent( wxOutputStream& os, int num ) +{ + int lastChar = 0; + if ( !(m_style & wxJSONWRITER_STYLED) || (m_style & wxJSONWRITER_NO_INDENTATION)) { + return lastChar; + } + + int numChars = m_indent + ( m_step * num ); + char c = ' '; + if ( m_style & wxJSONWRITER_TAB_INDENT ) { + c = '\t'; + numChars = num; + } + + for ( int i = 0; i < numChars; i++ ) { + os.PutC( c ); + if ( os.GetLastError() != wxSTREAM_NO_ERROR ) { + return -1; + } + + } + return c; +} + + +//! Write the provided string to the output object. +/*! + The function writes the string \c str to the output object that + was specified in the wxJSONWriter::Write() function. + The function may split strings in two or more lines if the + string contains LF characters if the \c m_style data member contains + the wxJSONWRITER_SPLIT_STRING flag. + + The function does not actually write the string: for every character + in the provided string the function calls WriteChar() which does + the actual character output. + + The function returns ZERO on success or -1 in case of errors. +*/ +int +wxJSONWriter::WriteStringValue( wxOutputStream& os, const wxString& str ) +{ + // JSON values of type STRING are written by converting the whole string + // to UTF-8 and then copying the UTF-8 buffer to the 'os' stream + // one byte at a time and processing them + os.PutC( '\"' ); // open quotes + + // the buffer that has to be written is either UTF-8 or ANSI c_str() depending + // on the 'm_noUtf8' flag + char* writeBuff = 0; + wxCharBuffer utf8CB = str.ToUTF8(); // the UTF-8 buffer +#if !defined( wxJSON_USE_UNICODE ) + wxCharBuffer ansiCB( str.c_str()); // the ANSI buffer + if ( m_noUtf8 ) { + writeBuff = ansiCB.data(); + } + else { + writeBuff = utf8CB.data(); + } +#else + writeBuff = utf8CB.data(); +#endif + + // NOTE: in ANSI builds UTF-8 conversion may fail (see samples/test5.cpp, + // test 7.3) although I do not know why + if ( writeBuff == 0 ) { + const char* err = ""; + os.Write( err, strlen( err )); + return 0; + } + size_t len = strlen( writeBuff ); + int lastChar = 0; + + // store the column at which the string starts + // splitting strings only happen if the string starts within + // column wxJSONWRITER_LAST_COL (default 50) + // see 'include/wx/json_defs.h' for the defines + int tempCol = m_colNo; + + // now write the UTF8 buffer processing the bytes + size_t i; + for ( i = 0; i < len; i++ ) { + bool shouldEscape = false; + unsigned char ch = *writeBuff; + ++writeBuff; // point to the next byte + + // the escaped character + char escCh = 0; + + // for every character we have to check if it is a character that + // needs to be escaped: note that characters that should be escaped + // may be not if some writer's flags are specified + switch ( ch ) { + case '\"' : // quotes + shouldEscape = true; + escCh = '\"'; + break; + case '\\' : // reverse solidus + shouldEscape = true; + escCh = '\\'; + break; + case '/' : // solidus + shouldEscape = true; + escCh = '/'; + break; + case '\b' : // backspace + shouldEscape = true; + escCh = 'b'; + break; + case '\f' : // formfeed + shouldEscape = true; + escCh = 'f'; + break; + case '\n' : // newline + shouldEscape = true; + escCh = 'n'; + break; + case '\r' : // carriage-return + shouldEscape = true; + escCh = 'r'; + break; + case '\t' : // horizontal tab + shouldEscape = true; + escCh = 't'; + break; + default : + shouldEscape = false; + break; + } // end switch + + + // if the character is a control character that is not identified by a + // lowercase letter, we should escape it + if ( !shouldEscape && ch < 32 ) { + char b[8]; + snprintf( b, 8, "\\u%04X", (int) ch ); + os.Write( b, 6 ); + if ( os.GetLastError() != wxSTREAM_NO_ERROR ) { + return -1; + } + } + + // the char is not a control character + else { + // some characters that should be escaped are not escaped + // if the writer was constructed with some flags + if ( shouldEscape && !( m_style & wxJSONWRITER_ESCAPE_SOLIDUS) ) { + if ( ch == '/' ) { + shouldEscape = false; + } + } + if ( shouldEscape && (m_style & wxJSONWRITER_MULTILINE_STRING)) { + if ( ch == '\n' || ch == '\t' ) { + shouldEscape = false; + } + } + + + // now write the character prepended by ESC if it should be escaped + if ( shouldEscape ) { + os.PutC( '\\' ); + os.PutC( escCh ); + if ( os.GetLastError() != wxSTREAM_NO_ERROR ) { + return -1; + } + } + else { + // a normal char or a UTF-8 units: write the character + os.PutC( ch ); + if ( os.GetLastError() != wxSTREAM_NO_ERROR ) { + return -1; + } + } + } + + // check if SPLIT_STRING flag is set and if the string has to + // be splitted + if ( (m_style & wxJSONWRITER_STYLED) && (m_style & wxJSONWRITER_SPLIT_STRING)) { + // split the string if the character written is LF + if ( ch == '\n' ) { + // close quotes and CR + os.Write( "\"\n", 2 ); + lastChar = WriteIndent( os, m_level + 2 ); // write indentation + os.PutC( '\"' ); // reopen quotes + if ( lastChar < 0 ) { + return lastChar; + } + } + // split the string only if there is at least wxJSONWRITER_MIN_LENGTH + // character to write and the character written is a punctuation or space + // BUG: the following does not work because the columns are not counted + else if ( (m_colNo >= wxJSONWRITER_SPLIT_COL) + && (tempCol <= wxJSONWRITER_LAST_COL )) { + if ( IsSpace( ch ) || IsPunctuation( ch )) { + if ( len - i > wxJSONWRITER_MIN_LENGTH ) { + // close quotes and CR + os.Write( "\"\n", 2 ); + lastChar = WriteIndent( os, m_level + 2 ); // write indentation + os.PutC( '\"' ); // reopen quotes + if ( lastChar < 0 ) { + return lastChar; + } + } + } + } + } + } // end for + os.PutC( '\"' ); // close quotes + return 0; +} + + + +//! Write a generic string +/*! + The function writes the wxString object \c str to the output object. + The string is written as is; you cannot use it to write JSON strings + to the output text. + The function converts the string \c str to UTF-8 and writes the buffer.. +*/ +int +wxJSONWriter::WriteString( wxOutputStream& os, const wxString& str ) +{ + wxLogTrace( writerTraceMask, _T("(%s) string to write=%s"), + __PRETTY_FUNCTION__, str.c_str() ); + int lastChar = 0; + char* writeBuff = 0; + + // the buffer that has to be written is either UTF-8 or ANSI c_str() depending + // on the 'm_noUtf8' flag + wxCharBuffer utf8CB = str.ToUTF8(); // the UTF-8 buffer +#if !defined( wxJSON_USE_UNICODE ) + wxCharBuffer ansiCB( str.c_str()); // the ANSI buffer + + if ( m_noUtf8 ) { + writeBuff = ansiCB.data(); + } + else { + writeBuff = utf8CB.data(); + } +#else + writeBuff = utf8CB.data(); +#endif + + // NOTE: in ANSI builds UTF-8 conversion may fail (see samples/test5.cpp, + // test 7.3) although I do not know why + if ( writeBuff == 0 ) { + const char* err = ""; + os.Write( err, strlen( err )); + return 0; + } + size_t len = strlen( writeBuff ); + + os.Write( writeBuff, len ); + if ( os.GetLastError() != wxSTREAM_NO_ERROR ) { + return -1; + } + + wxLogTrace( writerTraceMask, _T("(%s) result=%d"), + __PRETTY_FUNCTION__, lastChar ); + return lastChar; +} + +//! Write the NULL JSON value to the output stream. +/*! + The function writes the \b null literal string to the output stream. +*/ +int +wxJSONWriter::WriteNullValue( wxOutputStream& os ) +{ + os.Write( "null", 4 ); + if ( os.GetLastError() != wxSTREAM_NO_ERROR ) { + return -1; + } + return 0; +} + + +//! Writes a value of type INT. +/*! + This function is called for every value objects of INT type. + This function uses the \n snprintf function to get the US-ASCII + representation of the integer and simply copy it to the output stream. + Returns -1 on stream errors or ZERO if no errors. +*/ +int +wxJSONWriter::WriteIntValue( wxOutputStream& os, const wxJSONValue& value ) +{ + int r = 0; + char buffer[32]; // need to store 64-bits integers (max 20 digits) + size_t len; + + wxJSONRefData* data = value.GetRefData(); + wxASSERT( data ); + +#if defined( wxJSON_64BIT_INT ) + #if wxCHECK_VERSION(2, 9, 0 ) || !defined( wxJSON_USE_UNICODE ) + // this is fine for wxW 2.9 and for wxW 2.8 ANSI + snprintf( buffer, 32, "%" wxLongLongFmtSpec "d", + data->m_value.m_valInt64 ); + #else + // this is for wxW 2.8 Unicode: in order to use the cross-platform + // format specifier, we use the wxString's sprintf() function and then + // convert to UTF-8 before writing to the stream + wxString s; + s.Printf( _T("%") wxLongLongFmtSpec _T("d"), + data->m_value.m_valInt64 ); + wxCharBuffer cb = s.ToUTF8(); + const char* cbData = cb.data(); + len = strlen( cbData ); + wxASSERT( len < 32 ); + memcpy( buffer, cbData, len ); + buffer[len] = 0; + #endif +#else + snprintf( buffer, 32, "%ld", data->m_value.m_valLong ); +#endif + len = strlen( buffer ); + os.Write( buffer, len ); + if ( os.GetLastError() != wxSTREAM_NO_ERROR ) { + r = -1; + } + return r; +} + +//! Writes a value of type UNSIGNED INT. +/*! + This function is called for every value objects of UINT type. + This function uses the \n snprintf function to get the US-ASCII + representation of the integer and simply copy it to the output stream. + The function prepends a \b plus \b sign if the \c wxJSONWRITER_RECOGNIZE_UNSIGNED + flag is set in the \c m_flags data member. + Returns -1 on stream errors or ZERO if no errors. +*/ +int +wxJSONWriter::WriteUIntValue( wxOutputStream& os, const wxJSONValue& value ) +{ + int r = 0; size_t len; + + // prepend a plus sign if the style specifies that unsigned integers + // have to be recognized by the JSON reader + if ( m_style & wxJSONWRITER_RECOGNIZE_UNSIGNED ) { + os.PutC( '+' ); + } + + char buffer[32]; // need to store 64-bits integers (max 20 digits) + wxJSONRefData* data = value.GetRefData(); + wxASSERT( data ); + +#if defined( wxJSON_64BIT_INT ) + #if wxCHECK_VERSION(2, 9, 0 ) || !defined( wxJSON_USE_UNICODE ) + // this is fine for wxW 2.9 and for wxW 2.8 ANSI + snprintf( buffer, 32, "%" wxLongLongFmtSpec "u", + data->m_value.m_valUInt64 ); + #else + // this is for wxW 2.8 Unicode: in order to use the cross-platform + // format specifier, we use the wxString's sprintf() function and then + // convert to UTF-8 before writing to the stream + wxString s; + s.Printf( _T("%") wxLongLongFmtSpec _T("u"), + data->m_value.m_valInt64 ); + wxCharBuffer cb = s.ToUTF8(); + const char* cbData = cb.data(); + len = strlen( cbData ); + wxASSERT( len < 32 ); + memcpy( buffer, cbData, len ); + buffer[len] = 0; + #endif +#else + snprintf( buffer, 32, "%lu", data->m_value.m_valULong ); +#endif + len = strlen( buffer ); + os.Write( buffer, len ); + if ( os.GetLastError() != wxSTREAM_NO_ERROR ) { + r = -1; + } + return r; +} + +//! Writes a value of type DOUBLE. +/*! + This function is called for every value objects of DOUBLE type. + This function uses the \n snprintf function to get the US-ASCII + representation of the integer and simply copy it to the output stream. + Returns -1 on stream errors or ZERO if no errors. + + Note that writing a double to a decimal ASCII representation could + lay to unexpected results depending on the format string used in the + conversion. + See SetDoubleFmtString for details. +*/ +int +wxJSONWriter::WriteDoubleValue( wxOutputStream& os, const wxJSONValue& value ) +{ + int r = 0; + + char buffer[32]; + wxJSONRefData* data = value.GetRefData(); + wxASSERT( data ); + snprintf( buffer, 32, m_fmt, data->m_value.m_valDouble ); + size_t len = strlen( buffer ); + os.Write( buffer, len ); + if ( os.GetLastError() != wxSTREAM_NO_ERROR ) { + r = -1; + } + return r; +} + +//! Writes a value of type BOOL. +/*! + This function is called for every value objects of BOOL type. + This function prints the literals \b true or \b false depending on the + value in \c value. + Returns -1 on stream errors or ZERO if no errors. +*/ +int +wxJSONWriter::WriteBoolValue( wxOutputStream& os, const wxJSONValue& value ) +{ + int r = 0; + const char* f = "false"; const char* t = "true"; + wxJSONRefData* data = value.GetRefData(); + wxASSERT( data ); + + const char* c = f; // defaults to FALSE + + if ( data->m_value.m_valBool ) { + c = t; + } + + size_t len = strlen( c ); + os.Write( c, len ); + if ( os.GetLastError() != wxSTREAM_NO_ERROR ) { + r = -1; + } + return r; +} + + + + +//! Write the key of a key/value element to the output stream. +int +wxJSONWriter::WriteKey( wxOutputStream& os, const wxString& key ) +{ + wxLogTrace( writerTraceMask, _T("(%s) key write=%s"), + __PRETTY_FUNCTION__, key.c_str() ); + + int lastChar = WriteStringValue( os, key ); + os.Write( " : ", 3 ); + return lastChar; +} + +//! Write the invalid JSON value to the output stream. +/*! + An invalid wxJSONValue is a value that was not initialized and it is + an error. You should never write invalid values to JSON text because + the output is not valid JSON text. + Note that the NULL value is a legal JSON text and it is written: + \code + null + \endcode + + This function writes a non-JSON text to the output stream: + \code + + \endcode + In debug mode, the function always fails with an wxFAIL_MSG failure. +*/ +int +wxJSONWriter::WriteInvalid( wxOutputStream& os ) +{ + wxFAIL_MSG( _T("wxJSONWriter::WriteInvalid() cannot be called (not a valid JSON text")); + int lastChar = 0; + os.Write( "", 9 ); + return lastChar; +} + +//! Write a JSON value of type \e memory \e buffer +/*! + The type wxJSONTYPE_MEMORYBUFF is a \b wxJSON extension that is not correctly read by + other JSON implementations. + By default, the function writes such a type as an array of INTs as follows: + \code + [ 0,32,45,255,6,...] + \endcode + If the writer object was constructed using the \c wxJSONWRITER_MEMORYBUFF flag, then + the output is much more compact and recognized by the \b wxJSON reader as a memory buffer + type: + \code + '00203FFF06..' + \endcode + +*/ +int +wxJSONWriter::WriteMemoryBuff( wxOutputStream& os, const wxMemoryBuffer& buff ) +{ +#define MAX_BYTES_PER_ROW 20 + char str[16]; + + // if STYLED and SPLIT_STRING flags are set, the function writes 20 bytes on every row + // the following is the counter of bytes written. + // the string is splitted only for the special meory buffer type, not for array of INTs + int bytesWritten = 0; + bool splitString = false; + if ( (m_style & wxJSONWRITER_STYLED) && + (m_style & wxJSONWRITER_SPLIT_STRING)) { + splitString = true; + } + + size_t buffLen = buff.GetDataLen(); + unsigned char* ptr = (unsigned char*) buff.GetData(); + wxASSERT( ptr ); + char openChar = '\''; + char closeChar = '\''; + bool asArray = false; + + if ( (m_style & wxJSONWRITER_MEMORYBUFF ) == 0 ) { + // if the special flag is not specified, write as an array of INTs + openChar = '['; + closeChar = ']'; + asArray = true; + } + // write the open character + os.PutC( openChar ); + + for ( size_t i = 0; i < buffLen; i++ ) { + unsigned char c = *ptr; + ++ptr; + + if ( asArray ) { + snprintf( str, 14, "%d", c ); + size_t len = strlen( str ); + wxASSERT( len <= 3 ); + wxASSERT( len >= 1 ); + str[len] = ','; + // do not write the comma char for the last element + if ( i < buffLen - 1 ) { + ++len; + } + os.Write( str, len ); + if ( os.GetLastError() != wxSTREAM_NO_ERROR ) { + return -1; + } + } + else { + // now convert the byte in two hex digits + char c1 = c / 16; + char c2 = c % 16; + c1 += '0'; + c2 += '0'; + if ( c1 > '9' ) { + c1 += 7; + } + if ( c2 > '9' ) { + c2 += 7; + } + os.PutC( c1 ); + os.PutC( c2 ); + if ( os.GetLastError() != wxSTREAM_NO_ERROR ) { + return -1; + } + if ( splitString ) { + ++bytesWritten; + } + + if (( bytesWritten >= MAX_BYTES_PER_ROW ) && ((buffLen - i ) >= 5 )) { + // split the string if we wrote 20 bytes, but only is we have to + // write at least 5 bytes + os.Write( "\'\n", 2 ); + int lastChar = WriteIndent( os, m_level + 2 ); // write indentation + os.PutC( '\'' ); // reopen quotes + if ( lastChar < 0 ) { + return lastChar; + } + bytesWritten = 0; + } + } + } + + // write the close character + os.PutC( closeChar ); + return closeChar; +} + + +//! Writes the separator between values +/*! + The function is called when a value has been written to the JSON + text output and it writes the separator character: LF. + The LF char is actually written only if the wxJSONWRITER_STYLED flag + is specified and wxJSONWRITER_NO_LINEFEEDS is not set. + + Returns the last character written which is LF itself or -1 in case + of errors. Note that LF is returned even if the character is not + actually written. +*/ +int +wxJSONWriter::WriteSeparator( wxOutputStream& os ) +{ + int lastChar = '\n'; + if ( (m_style & wxJSONWRITER_STYLED) && !(m_style & wxJSONWRITER_NO_LINEFEEDS )) { + os.PutC( '\n' ); + } + return lastChar; +} + +//! Returns TRUE if the character is a space character. +bool +wxJSONWriter::IsSpace( wxChar ch ) +{ + bool r = false; + switch ( ch ) { + case ' ' : + case '\t' : + case '\r' : + case '\f' : + case '\n' : + r = true; + break; + default : + break; + } + return r; +} + +//! Returns TRUE if the character if a puctuation character +bool +wxJSONWriter::IsPunctuation( wxChar ch ) +{ + bool r = false; + switch ( ch ) { + case '.' : + case ',' : + case ';' : + case ':' : + case '!' : + case '?' : + r = true; + break; + default : + break; + } + return r; +} + + +/* +{ +} +*/ + + diff --git a/ThirdParty/wxTranslationHelper/CMakeLists.txt b/ThirdParty/wxTranslationHelper/CMakeLists.txt new file mode 100644 index 0000000..4a641b2 --- /dev/null +++ b/ThirdParty/wxTranslationHelper/CMakeLists.txt @@ -0,0 +1,22 @@ +# +# Stuff the average programmer needs to change +# +set(SRCS + wxTranslationHelper.cpp +) +set(HFILES + wxTranslationHelper.h +) +set(INCLUDE_DIRECTORIES ${BASE_INCLUDE_DIRECTORIES}) +set(LIBRARY_NAME wxTranslationHelper) +if(WIN32) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};${wxWidgets_DEFINITIONS};/D_LIB) +endif(WIN32) +set(SRCS ${SRCS} ${HFILES}) + +add_definitions(${PREPROCESSOR_DEFINITIONS}) +include_directories(${INCLUDE_DIRECTORIES}) + +add_library(${LIBRARY_NAME} STATIC ${SRCS}) + +target_link_libraries(${LIBRARY_NAME} ${wxWidgets_LIBRARIES}) diff --git a/ThirdParty/wxTranslationHelper/Win/wxTranslationHelper.vcxproj b/ThirdParty/wxTranslationHelper/Win/wxTranslationHelper.vcxproj new file mode 100644 index 0000000..404fc23 --- /dev/null +++ b/ThirdParty/wxTranslationHelper/Win/wxTranslationHelper.vcxproj @@ -0,0 +1,129 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {F2E960FE-1817-3D7D-A503-16BD29FA5B15} + 10.0.16299.0 + Win32Proj + x64 + wxTranslationHelper + NoUpgrade + + + + StaticLibrary + Unicode + v141 + + + StaticLibrary + Unicode + v141 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + F:\IT-Dim\trunk\ThirdParty\wxTranslationHelper\Win\Debug\ + wxTranslationHelper.dir\Debug\ + wxTranslationHelper + .lib + F:\IT-Dim\trunk\ThirdParty\wxTranslationHelper\Win\Release\ + wxTranslationHelper.dir\Release\ + wxTranslationHelper + .lib + + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;%(AdditionalIncludeDirectories) + Debug/ + EnableFastChecks + CompileAsCpp + ProgramDatabase + 4996 + Sync + Disabled + true + Disabled + NotUsing + MultiThreadedDebugDLL + true + Level3 + WIN32;_WINDOWS;__WXDEBUG__=1;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_LIB;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions) + $(IntDir) + + + WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_LIB;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions) + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;%(AdditionalIncludeDirectories) + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + %(AdditionalOptions) /machine:x64 + + + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;%(AdditionalIncludeDirectories) + Release/ + CompileAsCpp + 4996 + Sync + AnySuitable + true + MaxSpeed + NotUsing + MultiThreadedDLL + true + Level3 + WIN32;_WINDOWS;NDEBUG;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;__WXDEBUG__=1;_LIB;CMAKE_INTDIR="Release";%(PreprocessorDefinitions) + $(IntDir) + + + + + WIN32;_WINDOWS;NDEBUG;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;__WXDEBUG__=1;_LIB;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions) + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;%(AdditionalIncludeDirectories) + + + F:\IT-Dim\wxWidgets\lib\vc_x64_dll\mswu;F:\IT-Dim\wxWidgets\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\include;F:\IT-Dim\trunk\ThirdParty\build\..\..\ThirdParty\GLEW\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + %(AdditionalOptions) /machine:x64 + + + + + + + + + + + + \ No newline at end of file diff --git a/ThirdParty/wxTranslationHelper/Win/wxTranslationHelper.vcxproj.filters b/ThirdParty/wxTranslationHelper/Win/wxTranslationHelper.vcxproj.filters new file mode 100644 index 0000000..20d762e --- /dev/null +++ b/ThirdParty/wxTranslationHelper/Win/wxTranslationHelper.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + Source Files + + + + + Header Files + + + + + {51D244FA-C21C-3174-8217-FDB3769212C0} + + + {A07A887B-0B8A-3ED7-BD7F-43C26975F88D} + + + diff --git a/ThirdParty/wxTranslationHelper/wxTranslationHelper.cpp b/ThirdParty/wxTranslationHelper/wxTranslationHelper.cpp new file mode 100644 index 0000000..8ee0bdc --- /dev/null +++ b/ThirdParty/wxTranslationHelper/wxTranslationHelper.cpp @@ -0,0 +1,191 @@ +#include "stdwx.h" +#include "wxTranslationHelper.h" + +wxTranslationHelper::wxTranslationHelper(const wxString & search_path, + bool use_native_config) +: m_SearchPath(search_path), m_ConfigPath(wxEmptyString), +m_Locale(NULL), m_UseNativeConfig(use_native_config) +{ + if(search_path.IsEmpty()) + { + m_SearchPath = wxPathOnly(wxTheApp->argv[0]); + } +} + +wxTranslationHelper::~wxTranslationHelper() +{ + Save(); + if(m_Locale) + { + wxDELETE(m_Locale); + } +} + +wxLocale * wxTranslationHelper::GetLocale() +{ + return m_Locale; +} + +const wxString & wxTranslationHelper::GetSearchPath() +{ + return m_SearchPath; +} + +void wxTranslationHelper::SetSearchPath(wxString & value) +{ + m_SearchPath = value; + if(m_SearchPath.IsEmpty()) + { + m_SearchPath = wxPathOnly(wxTheApp->argv[0]); + } +} + +const wxString & wxTranslationHelper::GetConfigPath() +{ + return m_ConfigPath; +} + +void wxTranslationHelper::SetConfigPath(wxString & value) +{ + m_ConfigPath = value; +} + +bool wxTranslationHelper::Load() +{ + wxConfigBase * config; + if(m_UseNativeConfig) + { + config = new wxConfig(wxTheApp->GetAppName()); + } + else + { + config = new wxFileConfig(wxTheApp->GetAppName(), wxEmptyString, m_ConfigPath); + } + long language; + config->SetPath(wxT("wxTranslation")); + if(!config->Read(wxT("wxTranslationLanguage"), + &language, wxLANGUAGE_UNKNOWN)) + { + language = wxLANGUAGE_UNKNOWN; + } + delete config; + if(language == wxLANGUAGE_UNKNOWN) + { + return false; + } + wxArrayString names; + wxArrayLong identifiers; + GetInstalledLanguages(names, identifiers); + for(size_t i = 0; i < identifiers.Count(); i++) + { + if(identifiers[i] == language) + { + if(m_Locale) wxDELETE(m_Locale); + m_Locale = new wxLocale; + m_Locale->Init(identifiers[i]); + m_Locale->AddCatalogLookupPathPrefix(m_SearchPath); + m_Locale->AddCatalog(wxTheApp->GetAppName()); + return true; + } + } + return false; +} + +void wxTranslationHelper::Save(bool bReset) +{ + wxConfigBase * config; + if(m_UseNativeConfig) + { + config = new wxConfig(wxTheApp->GetAppName()); + } + else + { + config = new wxFileConfig(wxTheApp->GetAppName(), wxEmptyString, m_ConfigPath); + } + long language = wxLANGUAGE_UNKNOWN; + if(!bReset) + { + if(m_Locale) + { + language = m_Locale->GetLanguage(); + } + } + config->DeleteEntry(wxT("wxTranslation")); + config->SetPath(wxT("wxTranslation")); + config->Write(wxT("wxTranslationLanguage"), language); + config->Flush(); + delete config; +} + +void wxTranslationHelper::GetInstalledLanguages(wxArrayString & names, + wxArrayLong & identifiers) +{ + names.Clear(); + identifiers.Clear(); + wxString filename; + const wxLanguageInfo * langinfo; + wxString name = wxLocale::GetLanguageName(wxLANGUAGE_DEFAULT); + if(!name.IsEmpty()) + { + names.Add(_("Default")); + identifiers.Add(wxLANGUAGE_DEFAULT); + } + if(!wxDir::Exists(m_SearchPath)) + { + wxLogTrace(_("Directory %s DOES NOT EXIST !!!"), + m_SearchPath.GetData()); + return; + } + wxDir dir(m_SearchPath); + for(bool cont = dir.GetFirst(&filename, +#ifdef __WXMSW__ + wxT("*.*"), +#else + wxT("*"), +#endif + wxDIR_DEFAULT); + cont; cont = dir.GetNext(&filename)) + { + langinfo = wxLocale::FindLanguageInfo(filename); + if(langinfo != NULL) + { + wxLogTrace(_("SEARCHING FOR %s"), + wxString(dir.GetName()+wxFileName::GetPathSeparator()+ + filename+wxFileName::GetPathSeparator()+ + wxTheApp->GetAppName()+wxT(".mo")).GetData()); + if(wxFileExists(dir.GetName()+wxFileName::GetPathSeparator()+ + filename+wxFileName::GetPathSeparator()+ + wxTheApp->GetAppName()+wxT(".mo"))) + { + names.Add(langinfo->Description); + identifiers.Add(langinfo->Language); + } + } + } +} + +bool wxTranslationHelper::AskUserForLanguage(wxArrayString & names, + wxArrayLong & identifiers) +{ + wxCHECK_MSG(names.Count() == identifiers.Count(), false, + _("Array of language names and identifiers should have the same size.")); + long index = wxGetSingleChoiceIndex(_("Select the language"), + _("Language"), names); + if(index != -1) + { + if(m_Locale) + { + wxDELETE(m_Locale); + } + m_Locale = new wxLocale; + m_Locale->Init(identifiers[index]); + m_Locale->AddCatalogLookupPathPrefix(m_SearchPath); + wxLogTrace(_("wxTranslationHelper: Path Prefix = \"%s\""), + m_SearchPath.GetData()); + m_Locale->AddCatalog(wxTheApp->GetAppName()); + wxLogTrace(_("wxTranslationHelper: Catalog Name = \"%s\""), + wxTheApp->GetAppName().GetData()); + return true; + } + return false; +} diff --git a/ThirdParty/wxTranslationHelper/wxTranslationHelper.h b/ThirdParty/wxTranslationHelper/wxTranslationHelper.h new file mode 100644 index 0000000..c12b3e0 --- /dev/null +++ b/ThirdParty/wxTranslationHelper/wxTranslationHelper.h @@ -0,0 +1,26 @@ +#ifndef _WX_TRANSLATION_HELPER_H +#define _WX_TRANSLATION_HELPER_H + +class wxTranslationHelper +{ + wxString m_SearchPath; + wxString m_ConfigPath; + wxLocale * m_Locale; + bool m_UseNativeConfig; +public: + wxTranslationHelper(const wxString & search_path, bool use_native_config = true); + ~wxTranslationHelper(); + wxLocale * GetLocale(); + void GetInstalledLanguages(wxArrayString & names, wxArrayLong & identifiers); + bool AskUserForLanguage(wxArrayString & names, wxArrayLong & identifiers); + bool Load(); + void Save(bool bReset = false); + + const wxString & GetSearchPath(); + void SetSearchPath(wxString & value); + + const wxString & GetConfigPath(); + void SetConfigPath(wxString &); +}; + +#endif diff --git a/ThirdParty/wxXS/include/wx/wxxmlserializer/Defs.h b/ThirdParty/wxXS/include/wx/wxxmlserializer/Defs.h new file mode 100644 index 0000000..ba7e271 --- /dev/null +++ b/ThirdParty/wxXS/include/wx/wxxmlserializer/Defs.h @@ -0,0 +1,21 @@ +#ifndef _XSDEFS_H +#define _XSDEFS_H + +#ifdef USING_SOURCE_XS + #define WXDLLIMPEXP_XS + #define WXDLLIMPEXP_DATA_XS(type) type +#elif defined( LIB_USINGDLL ) + #define WXDLLIMPEXP_XS + #define WXDLLIMPEXP_DATA_XS(type) +#elif defined( WXMAKINGDLL_WXXS ) + #define WXDLLIMPEXP_XS WXEXPORT + #define WXDLLIMPEXP_DATA_XS(type) WXEXPORT type +#elif defined(WXUSINGDLL) + #define WXDLLIMPEXP_XS WXIMPORT + #define WXDLLIMPEXP_DATA_XS(type) WXIMPORT type +#else // not making nor using DLL + #define WXDLLIMPEXP_XS + #define WXDLLIMPEXP_DATA_XS(type) type +#endif + +#endif//_XSDEFS_H diff --git a/ThirdParty/wxXS/include/wx/wxxmlserializer/PropertyIO.h b/ThirdParty/wxXS/include/wx/wxxmlserializer/PropertyIO.h new file mode 100644 index 0000000..dc81e01 --- /dev/null +++ b/ThirdParty/wxXS/include/wx/wxxmlserializer/PropertyIO.h @@ -0,0 +1,313 @@ +/*************************************************************** + * Name: PropertyIO.cpp + * Purpose: Declares data types I/O and conversion functions + * Author: Michal Bližňák (michal.bliznak@tiscali.cz) + * Created: 2007-10-28 + * Copyright: Michal Bližňák + * License: wxWidgets license (www.wxwidgets.org) + * Notes: + **************************************************************/ + +#ifndef _XSPROPERTYIO_H +#define _XSPROPERTYIO_H + +#ifndef WX_PRECOMP + #include +#endif + +#include +#include +#include +#include + +#include + +class WXDLLIMPEXP_XS xsProperty; +class WXDLLIMPEXP_XS xsSerializable; + +WX_DECLARE_OBJARRAY_WITH_DECL(wxRealPoint, RealPointArray, class WXDLLIMPEXP_XS); +WX_DECLARE_LIST_WITH_DECL(wxRealPoint, RealPointList, class WXDLLIMPEXP_XS); + +WX_DEFINE_USER_EXPORTED_ARRAY_CHAR(char, CharArray, class WXDLLIMPEXP_XS); +WX_DEFINE_USER_EXPORTED_ARRAY_INT(int, IntArray, class WXDLLIMPEXP_XS); +WX_DEFINE_USER_EXPORTED_ARRAY_LONG(long, LongArray, class WXDLLIMPEXP_XS); +WX_DEFINE_USER_EXPORTED_ARRAY_DOUBLE(double, DoubleArray, class WXDLLIMPEXP_XS); + +WX_DECLARE_STRING_HASH_MAP_WITH_DECL(wxString, StringMap, class WXDLLIMPEXP_XS); + +/*! + * \brief Base class encapsulating a property I/O handler. The class is used by + * the xsSerializable class and is responsiblefor reading and writing of an XML node + * containing property information. Each supported property (data) type should have + * its own I/O handler class. Moreover, all derived classes must provide public functions + * 'static wxString classname::ToString(datatype value)' and 'static datatype classname:: + * FromString( const wxString& value )' responsible for conversion between datatype and + * and its string representation (these functions are used internally by class virtual functions. + */ +class WXDLLIMPEXP_XS xsPropertyIO : public wxObject +{ +public: + DECLARE_DYNAMIC_CLASS(xsProperty); + + /*! \brief Constructor. */ + xsPropertyIO(){;} + /*! \brief Destructor. */ + virtual ~xsPropertyIO(){;} + + /*! + * \brief Read content of the property XML node and store it to given property object. + * \param property Pointer to the target property object + * \param source Pointer to the source XML node + */ + virtual void Read(xsProperty *property, wxXmlNode *source){wxUnusedVar(property);wxUnusedVar(source);} + /*! + * \brief Write content of given property object to target XML node. + * \param property Pointer to the source property object + * \param target Pointer to the target XML node + */ + virtual void Write(xsProperty *property, wxXmlNode *target){wxUnusedVar(property);wxUnusedVar(target);} + /*! + * \brief Get textual representation of current property value. + * \param property Pointer to the source property object + * \return Textual representation of property's value + */ + virtual wxString GetValueStr(xsProperty *property){wxUnusedVar(property);return wxT("");} + /*! + * \brief Set value defined by its textual representation to given property. + * \param property Pointer to the target property object + * \param valstr Textual representation of given value + */ + virtual void SetValueStr(xsProperty *property, const wxString& valstr){wxUnusedVar(property); wxUnusedVar(valstr);} + + /*! + * \brief Create new XML node of given name and value and assign it to the given + * parent XML node. + * \param parent Pointer to parent XML node + * \param name Name of new XML node + * \param value Content of new XML node + * \param type Type of new XML (content) node + */ + static wxXmlNode* AddPropertyNode(wxXmlNode* parent, const wxString& name, const wxString& value, wxXmlNodeType type = wxXML_TEXT_NODE ); + +protected: + + /*! + * \brief Append info about the source property to given XML node. + * \param source Pointer to the source property + * \param target Pointer to modified XML node + */ + void AppendPropertyType(xsProperty *source, wxXmlNode *target); +}; + +/*! + * \brief Macro suitable for declaration of new property I/O handler + * \param datatype Property's data type + * \param name Handler class name + */ +#define XS_DECLARE_IO_HANDLER(datatype, name) \ +class name : public xsPropertyIO \ +{ \ +public: \ + DECLARE_DYNAMIC_CLASS(name); \ + name(){;} \ + virtual ~name(){;} \ +\ + virtual void Read(xsProperty *property, wxXmlNode *source); \ + virtual void Write(xsProperty *property, wxXmlNode *target); \ + virtual wxString GetValueStr(xsProperty *property); \ + virtual void SetValueStr(xsProperty *property, const wxString& valstr); \ + static wxString ToString(const datatype& value); \ + static datatype FromString(const wxString& value); \ +}; \ + + /*! + * \brief Macro suitable for declaration of exported new property I/O handler + * \param datatype Property's data type + * \param name Handler class name + * \param decoration Class decoration + */ +#define XS_DECLARE_EXPORTED_IO_HANDLER(datatype, name, decoration) \ +class decoration name : public xsPropertyIO \ +{ \ +public: \ + DECLARE_DYNAMIC_CLASS(name); \ + name(){;} \ + virtual ~name(){;} \ +\ + virtual void Read(xsProperty *property, wxXmlNode *source); \ + virtual void Write(xsProperty *property, wxXmlNode *target); \ + virtual wxString GetValueStr(xsProperty *property); \ + virtual void SetValueStr(xsProperty *property, const wxString& valstr); \ + static wxString ToString(const datatype& value); \ + static datatype FromString(const wxString& value); \ +}; \ + + /*! + * \brief Macro suitable for implementation of new property I/O handler + * \param datatype Property's data type + * \param name Handler class name + */ +#define XS_DEFINE_IO_HANDLER(datatype, name) \ +IMPLEMENT_DYNAMIC_CLASS(name, xsPropertyIO); \ +\ +void name::Read(xsProperty *property, wxXmlNode *source) \ +{ \ + datatype value = FromString(source->GetNodeContent()); \ + *((datatype*)property->m_pSourceVariable) = value; \ +} \ +\ +void name::Write(xsProperty *property, wxXmlNode *target) \ +{ \ + wxString val = ToString(*((datatype*)property->m_pSourceVariable)); \ +\ + if(val != property->m_sDefaultValueStr) \ + { \ + wxXmlNode *newNode = AddPropertyNode(target, wxT("property"), val); \ + AppendPropertyType(property, newNode); \ + } \ +} \ +\ +wxString name::GetValueStr(xsProperty *property) \ +{ \ + return ToString(*((datatype*)property->m_pSourceVariable)); \ +} \ +\ +void name::SetValueStr(xsProperty *property, const wxString& valstr) \ +{ \ + datatype value = FromString(valstr); \ + *((datatype*)property->m_pSourceVariable) = value; \ +} \ + +/*! + * \brief Property class encapsulating I/O functions used by 'wxString' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(wxString, xsStringPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'wxChar' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(wxChar, xsCharPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'long' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(long, xsLongPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'int' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(int, xsIntPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'bool' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(bool, xsBoolPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'double' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(double, xsDoublePropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'float' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(float, xsFloatPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'wxPoint' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(wxPoint, xsPointPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'wxSize' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(wxSize, xsSizePropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'wxRealPoint' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(wxRealPoint, xsRealPointPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'wxColour' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(wxColour, xsColourPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'wxPen' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(wxPen, xsPenPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'wxBrush' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(wxBrush, xsBrushPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'wxFont' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(wxFont, xsFontPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'wxArrayString' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(wxArrayString, xsArrayStringPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'CharArray' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(CharArray, xsArrayCharPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'IntArray' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(IntArray, xsArrayIntPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'LongArray' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(LongArray, xsArrayLongPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'DoubleArray' properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(DoubleArray, xsArrayDoublePropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'RealPointArray' (array of + * integer values) properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(RealPointArray, xsArrayRealPointPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'ListRealPoint' (list of + * wxRealPoint objects) properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(RealPointList, xsListRealPointPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'serializabledynamic' (xsSerializable + * dynamic class objects which are created during the deserialization process) properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(xsSerializable, xsDynObjPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'serializabledynamicnocreate' (already + * existing xsSerializable dynamic class objects) properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(xsSerializable, xsDynNCObjPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'serializablestatic' (static + * xsSerializable class objects) properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(xsSerializable, xsStaticObjPropIO, WXDLLIMPEXP_XS); + +/*! + * \brief Property class encapsulating I/O functions used by 'mapstring' (string hash map) properties. + */ +XS_DECLARE_EXPORTED_IO_HANDLER(StringMap, xsMapStringPropIO, WXDLLIMPEXP_XS); + +WX_DECLARE_HASH_MAP( wxString, xsPropertyIO*, wxStringHash, wxStringEqual, PropertyIOMap ); + +#endif //_XSPROPERTYIO_H diff --git a/ThirdParty/wxXS/include/wx/wxxmlserializer/XmlSerializer.h b/ThirdParty/wxXS/include/wx/wxxmlserializer/XmlSerializer.h new file mode 100644 index 0000000..4c61c97 --- /dev/null +++ b/ThirdParty/wxXS/include/wx/wxxmlserializer/XmlSerializer.h @@ -0,0 +1,1063 @@ +/*************************************************************** + * Name: XmlSerializer.h + * Purpose: Defines XML serializer and related classes + * Author: Michal Bližňák (michal.bliznak@tiscali.cz) + * Created: 2007-08-28 + * Copyright: Michal Bližňák + * License: wxWidgets license (www.wxwidgets.org) + * Notes: + **************************************************************/ + +#ifndef _XSXMLSERIALIZE_H +#define _XSXMLSERIALIZE_H + +#ifndef WX_PRECOMP + #include +#endif + +#include + +#include +#include + +#define xsWITH_ROOT true +#define xsWITHOUT_ROOT false + +#define xsRECURSIVE true +#define xsNORECURSIVE false + +/*! \brief Macro creates new serialized STRING property */ +#define XS_SERIALIZE_STRING(x, name) XS_SERIALIZE_PROPERTY(x, wxT("string"), name); +/*! \brief Macro creates new serialized STRING property with defined default value */ +#define XS_SERIALIZE_STRING_EX(x, name, def) XS_SERIALIZE_PROPERTY_EX(x, wxT("string"), name, def); +/*! \brief Macro creates new serialized STRING property */ +#define XS_SERIALIZE_CHAR(x, name) XS_SERIALIZE_PROPERTY(x, wxT("char"), name); +/*! \brief Macro creates new serialized STRING property with defined default value */ +#define XS_SERIALIZE_CHAR_EX(x, name, def) XS_SERIALIZE_PROPERTY_EX(x, wxT("char"), name, def); +/*! \brief Macro creates new serialized LONG property */ +#define XS_SERIALIZE_LONG(x, name) XS_SERIALIZE_PROPERTY(x, wxT("long"), name); +/*! \brief Macro creates new serialized LONG property with defined default value */ +#define XS_SERIALIZE_LONG_EX(x, name, def) XS_SERIALIZE_PROPERTY_EX(x, wxT("long"), name, xsLongPropIO::ToString(def)); +/*! \brief Macro creates new serialized DOUBLE property */ +#define XS_SERIALIZE_DOUBLE(x, name) XS_SERIALIZE_PROPERTY(x, wxT("double"), name); +/*! \brief Macro creates new serialized DOUBLE property with defined default value */ +#define XS_SERIALIZE_DOUBLE_EX(x, name, def) XS_SERIALIZE_PROPERTY_EX(x, wxT("double"), name, xsDoublePropIO::ToString(def)); +/*! \brief Macro creates new serialized INT property */ +#define XS_SERIALIZE_INT(x, name) XS_SERIALIZE_PROPERTY(x, wxT("int"), name); +/*! \brief Macro creates new serialized INT property with defined default value */ +#define XS_SERIALIZE_INT_EX(x, name, def) XS_SERIALIZE_PROPERTY_EX(x, wxT("int"), name, xsIntPropIO::ToString(def)); +/*! \brief Macro creates new serialized FLOAT property */ +#define XS_SERIALIZE_FLOAT(x, name) XS_SERIALIZE_PROPERTY(x, wxT("float"), name); +/*! \brief Macro creates new serialized FLOAT property with defined default value */ +#define XS_SERIALIZE_FLOAT_EX(x, name, def) XS_SERIALIZE_PROPERTY_EX(x, wxT("float"), name, xsFloatPropIO::ToString(def)); + +/*! \brief Macro creates new serialized BOOL property */ +#define XS_SERIALIZE_BOOL(x, name) XS_SERIALIZE_PROPERTY(x, wxT("bool"), name); +/*! \brief Macro creates new serialized BOOL property with defined default value */ +#define XS_SERIALIZE_BOOL_EX(x, name, def) XS_SERIALIZE_PROPERTY_EX(x, wxT("bool"), name, xsBoolPropIO::ToString(def)); + +/*! \brief Macro creates new serialized wxPoint property */ +#define XS_SERIALIZE_POINT(x, name) XS_SERIALIZE_PROPERTY(x, wxT("point"), name); +/*! \brief Macro creates new serialized wxPoint property with defined default value */ +#define XS_SERIALIZE_POINT_EX(x, name, def) XS_SERIALIZE_PROPERTY_EX(x, wxT("point"), name, xsPointPropIO::ToString(def)); +/*! \brief Macro creates new serialized wxRealPoint property */ +#define XS_SERIALIZE_REALPOINT(x, name) XS_SERIALIZE_PROPERTY(x, wxT("realpoint"), name); +/*! \brief Macro creates new serialized wxRealPoint property with defined default value */ +#define XS_SERIALIZE_REALPOINT_EX(x, name, def) XS_SERIALIZE_PROPERTY_EX(x, wxT("realpoint"), name, xsRealPointPropIO::ToString(def)); +/*! \brief Macro creates new serialized wxSize property */ +#define XS_SERIALIZE_SIZE(x, name) XS_SERIALIZE_PROPERTY(x, wxT("size"), name); +/*! \brief Macro creates new serialized wxSize property with defined default value */ +#define XS_SERIALIZE_SIZE_EX(x, name, def) XS_SERIALIZE_PROPERTY_EX(x, wxT("size"), name, xsSizePropIO::ToString(def)); + +/*! \brief Macro creates new serialized wxColour property */ +#define XS_SERIALIZE_COLOUR(x, name) XS_SERIALIZE_PROPERTY(x, wxT("colour"), name); +/*! \brief Macro creates new serialized wxColour property with defined default value */ +#define XS_SERIALIZE_COLOUR_EX(x, name, def) XS_SERIALIZE_PROPERTY_EX(x, wxT("colour"), name, xsColourPropIO::ToString(def)); +/*! \brief Macro creates new serialized wxPen property */ +#define XS_SERIALIZE_PEN(x, name) XS_SERIALIZE_PROPERTY(x, wxT("pen"), name); +/*! \brief Macro creates new serialized wxPen property with defined default value */ +#define XS_SERIALIZE_PEN_EX(x, name, def) XS_SERIALIZE_PROPERTY_EX(x, wxT("pen"), name, xsPenPropIO::ToString(def)); +/*! \brief Macro creates new serialized wxBrush property */ +#define XS_SERIALIZE_BRUSH(x, name) XS_SERIALIZE_PROPERTY(x, wxT("brush"), name); +/*! \brief Macro creates new serialized wxBrush property with defined default value */ +#define XS_SERIALIZE_BRUSH_EX(x, name, def) XS_SERIALIZE_PROPERTY_EX(x, wxT("brush"), name, xsBrushPropIO::ToString(def)); +/*! \brief Macro creates new serialized wxFont property */ +#define XS_SERIALIZE_FONT(x, name) XS_SERIALIZE_PROPERTY(x, wxT("font"), name); +/*! \brief Macro creates new serialized wxFont property with defined default value */ +#define XS_SERIALIZE_FONT_EX(x, name, def) XS_SERIALIZE_PROPERTY_EX(x, wxT("font"), name, xsFontPropIO::ToString(def)); + +/*! \brief Macro creates new serialized property (type 'array of strings (wxArrayString)') */ +#define XS_SERIALIZE_ARRAYSTRING(x, name) XS_SERIALIZE_PROPERTY(x, wxT("arraystring"), name); +/*! \brief Macro creates new serialized property (type 'array of chars (CharArray)') */ +#define XS_SERIALIZE_ARRAYCHAR(x, name) XS_SERIALIZE_PROPERTY(x, wxT("arraychar"), name); +/*! \brief Macro creates new serialized property (type 'array of ints (IntArray)') */ +#define XS_SERIALIZE_ARRAYINT(x, name) XS_SERIALIZE_PROPERTY(x, wxT("arrayint"), name); +/*! \brief Macro creates new serialized property (type 'array of longs (LongArray)') */ +#define XS_SERIALIZE_ARRAYLONG(x, name) XS_SERIALIZE_PROPERTY(x, wxT("arraylong"), name); +/*! \brief Macro creates new serialized property (type 'array of doubles (DoubleArray)') */ +#define XS_SERIALIZE_ARRAYDOUBLE(x, name) XS_SERIALIZE_PROPERTY(x, wxT("arraydouble"), name); +/*! \brief Macro creates new serialized property (type 'array of wxRealPoint objects') */ +#define XS_SERIALIZE_ARRAYREALPOINT(x, name) XS_SERIALIZE_PROPERTY(x, wxT("arrayrealpoint"), name); +/*! \brief Macro creates new serialized property (type 'list of wxRealPoint objects') */ +#define XS_SERIALIZE_LISTREALPOINT(x, name) XS_SERIALIZE_PROPERTY(x, wxT("listrealpoint"), name); + +/*! \brief Macro creates new serialized property (type 'string hash map (StringMap)') */ +#define XS_SERIALIZE_MAPSTRING(x, name) XS_SERIALIZE_PROPERTY(x, wxT("mapstring"), name); + +/*! \brief Macro creates new serialized property encapsulating a dynamic serializable object */ +#define XS_SERIALIZE_DYNAMIC_OBJECT(x, name) XS_SERIALIZE_PROPERTY(x, wxT("serializabledynamic"), name); +/*! \brief Macro creates new serialized property encapsulating a dynamic serializable object */ +#define XS_SERIALIZE_DYNAMIC_OBJECT_NO_CREATE(x, name) XS_SERIALIZE_PROPERTY(x, wxT("serializabledynamicnocreate"), name); +/*! \brief Macro creates new serialized property encapsulating a static serializable object */ +#define XS_SERIALIZE_STATIC_OBJECT(x, name) XS_SERIALIZE_PROPERTY(x, wxT("serializablestatic"), name); + +/*! \brief Macro creates new serialized property of given type */ +#define XS_SERIALIZE_PROPERTY(x, type, name) AddProperty(new xsProperty(&x, type, name)); +/*! \brief Macro creates new serialized property of given type with defined dafult value */ +#define XS_SERIALIZE_PROPERTY_EX(x, type, name, def) AddProperty(new xsProperty(&x, type, name, def)); + +/*! \brief Macro creates new serialized property and automaticaly determines its type (if supported) */ +#define XS_SERIALIZE(x, name) AddProperty(new xsProperty(&x, name)); +/*! \brief Macro creates new serialized property with defined dafult value and automaticaly determines its type (if supported)*/ +#define XS_SERIALIZE_EX(x, name, def) AddProperty(new xsProperty(&x, name, def)); + +/*! \brief Macro registers new IO handler for specified data type (handler class must exist) */ +#define XS_REGISTER_IO_HANDLER(type, class) wxXmlSerializer::m_mapPropertyIOHandlers[type] = new class(); + + +/*! \brief Enable RTTI (the same as DECLARE_DYNAMIC_CLASS) and declare xsSerializable::Clone() function */ +#define XS_DECLARE_CLONABLE_CLASS(name) \ +public: \ + DECLARE_DYNAMIC_CLASS(name) \ + virtual wxObject* Clone(); \ + +/*! \brief Enable RTTI (the same as IMPLEMENT_DYNAMIC_CLASS) and implement xsSerializable::Clone() function */ +#define XS_IMPLEMENT_CLONABLE_CLASS(name, base) \ + IMPLEMENT_DYNAMIC_CLASS(name, base) \ + wxObject* name::Clone() \ + { \ + if( m_fClone ) return new name(*this); \ + else \ + return NULL; \ + } \ + + +class WXDLLIMPEXP_XS xsProperty; +class WXDLLIMPEXP_XS xsSerializable; +class WXDLLIMPEXP_XS wxXmlSerializer; + +WX_DECLARE_LIST_WITH_DECL(xsProperty, PropertyList, class WXDLLIMPEXP_XS); +WX_DECLARE_LIST_WITH_DECL(xsSerializable, SerializableList, class WXDLLIMPEXP_XS); + +WX_DECLARE_HASH_MAP( long, xsSerializable*, wxIntegerHash, wxIntegerEqual, IDMap ); + +/*! + * \brief Base class encapsulating object which can be serialized/deserialized to/from + * XML file (disk file or any stream). This class acts as a data container for properties + * (xsProperty class objects) encapsulating serialized class data members. + * + * Class data members which should be serialized must be marked by appropriate macro defined + * in wxXmlSerializer.h header file (it is recommended to mark desired data members in the class constructor). + * + * Instances of this class can be arranged into a list/d-ary tree hierarchy so it can behave like + * powerfull data container. All chained serializable class objects can be handled by class + * member functions or by member functions of wxXmlSerializer class object which should be + * used as their manager (recommended way). + * + * Another built-in (optional) functionality is class instaces' cloning. User can use + * XS_DECLARE_CLONABLE_CLASS and XS_IMPLEMENT_CLONABLE_CLASS macros instead of classic + * DECLARE_DYNAMIC_CLASS and IMPLEMENT_DYNAMIC_CLASS macros which lead to definition of + * xsSerializable::Clone() virtual function used for cloning of current class instance + * via its copy constructor (user must define it manually). Virtual xsSerializble::Clone() + * function is also used by the wxXmlSerializer::CopyItems() function (used by the + * wxXmlSerializer copy constructor). + */ +class WXDLLIMPEXP_XS xsSerializable : public wxObject +{ +public: + friend class wxXmlSerializer; + + XS_DECLARE_CLONABLE_CLASS(xsSerializable); + + enum SEARCHMODE + { + /*! \brief Depth-First-Search algorithm */ + searchDFS, + /*! \brief Breadth-First-Search algorithm */ + searchBFS + }; + + /*! \brief Constructor. */ + xsSerializable(); + /*! \brief Copy constructor. */ + xsSerializable(const xsSerializable& obj); + /*! \brief Destructor. */ + ~xsSerializable(); + + // public functions + + /*! + * \brief Get serializable parent object. + * \return Pointer to serializable parent object if exists, otherwise NULL + */ + inline xsSerializable* GetParent() { return m_pParentItem; } + /*! + * \brief Get parent data manager (instance of wxXmlSerializer). + * \return Pointer to parent data manager if set, otherwise NULL + */ + inline wxXmlSerializer* GetParentManager() { return m_pParentManager; } + /*! + * \brief Get first serializable child object. + * \return Pointer to child object if exists, otherwise NULL + */ + xsSerializable* GetFirstChild(); + /*! + * \brief Get first serializable child object of given type. + * \param type Child object type (can be NULL for any type) + * \return Pointer to child object if exists, otherwise NULL + */ + xsSerializable* GetFirstChild(wxClassInfo *type); + /*! + * \brief Get last serializable child object. + * \return Pointer to child object if exists, otherwise NULL + */ + xsSerializable* GetLastChild(); + /*! + * \brief Get last serializable child object of given type. + * \param type Child object type (can be NULL for any type) + * \return Pointer to child object if exists, otherwise NULL + */ + xsSerializable* GetLastChild(wxClassInfo *type); + /*! + * \brief Get next serializable sibbling object. + * \return Pointer to sibbling object if exists, otherwise NULL + */ + xsSerializable* GetSibbling(); + /*! + * \brief Get next serializable sibbling object of given type. + * \param type Child object type (can be NULL for any type) + * \return Pointer to sibbling object if exists, otherwise NULL + */ + xsSerializable* GetSibbling(wxClassInfo *type); + /*! + * \brief Get child item with given ID if exists. + * \param id ID of searched child item + * \param recursive If TRUE then the child shape will be searched recursivelly + * \return Pointer to first child with given ID if pressent, otherwise NULL + */ + xsSerializable* GetChild(long id, bool recursive = xsNORECURSIVE); + + /*! + * \brief Function finds out whether this serializable item has some children. + * \return TRUE if the parent shape has children, otherwise FALSE + */ + inline bool HasChildren() const { return !m_lstChildItems.IsEmpty(); } + /*! + * \brief Get list of children (serializable objects) of this object. + * \return Reference to a list with child serializable objects (can be empty) + */ + inline SerializableList& GetChildrenList() { return m_lstChildItems; } + /*! + * \brief Get children of given type. + * \param type Child object type (if NULL then all children are returned) + * \param list Reference to a list where all found child objects will be appended + */ + void GetChildren(wxClassInfo *type, SerializableList& list); + /*! + * \brief Get all children of given type recursively (i.e. children of children of .... ). + * \param type Get only children of given type (if NULL then all children are returned) + * \param list Reference to a list where all found child objects will be appended + * \param mode Search mode. User can choose Depth-First-Search or Breadth-First-Search algorithm (BFS is default) + * \sa SEARCHMODE + */ + void GetChildrenRecursively(wxClassInfo *type, SerializableList& list, SEARCHMODE mode = searchBFS); + /*! + * \brief Get pointer to list node containing first serializable child object. + */ + inline SerializableList::compatibility_iterator GetFirstChildNode() const { return m_lstChildItems.GetFirst(); } + /*! + * \brief Get pointer to list node containing last serializable child object. + */ + inline SerializableList::compatibility_iterator GetLastChildNode() const { return m_lstChildItems.GetLast(); } + + /*! + * \brief Set serializable parent object. + * \param parent Pointer to parent object + */ + inline void SetParent(xsSerializable* parent) { m_pParentItem = parent; } + /*! + * \brief Set parent data manager. + * \param parent Pointer to parent data manager + */ + inline void SetParentManager(wxXmlSerializer* parent) { m_pParentManager = parent; } + /*! + * \brief Add serializable child object to this object. + * \param child Pointer to added child object (must NOT be NULL) + * \return Pointer to to the added child object + */ + xsSerializable* AddChild(xsSerializable* child); + /*! + * \brief Insert serializable child object to this object at given position. + * \param pos Zero-based position + * \param child Pointer to added child object (must NOT be NULL) + * \return Pointer to to the added child object + */ + xsSerializable* InsertChild(size_t pos, xsSerializable* child); + /*! + * \brief Assign this object as a child to given parent object. + * \param parent Pointer to new parent object (must NOT be NULL) + */ + void Reparent(xsSerializable* parent); + + /*! + * \brief Set ID of this object. Can be used for further objects' handling by + * wxXmlSerializer class (default ID value is -1). This functions should NOT + * be used directly; it is called by wxXmlSerializer object in the case that this + * serializable object is attached to another one (or directly to root node of wxXmlSerializer) by + * wxXmlSerializer::AddItem() member function. + */ + void SetId(long id); + /*! + * \brief Get object ID. + * \return ID value or -1 if the ID hasn't been set yet + */ + inline long GetId() const { return m_nId; } + + /*! + * \brief Create new 'object' XML node and serialize all marked class data members (properties) into it. + * \param node Pointer to parent XML node + * \return Pointer to modified parent XML node + */ + wxXmlNode* SerializeObject(wxXmlNode* node); + /*! + * \brief Deserialize marked class data members (properties) from appropriate fields of given + * parent 'object' XML node. + * \param node Pointer to parent 'object' XML node + */ + void DeserializeObject(wxXmlNode* node); + + /*! + * \brief Add new property to the property list. + * \param property Pointer to added property object + * \sa xsProperty + */ + void AddProperty(xsProperty* property); + /** + * \brief Remove given property from the property list. + * \param property Pointer to existing property. + * \sa xsProperty, GetProperty() + */ + void RemoveProperty(xsProperty *property); + /*! + * \brief Get serialized property of given name. + * \return Pointer to the property object if exists, otherwise NULL + * \sa xsProperty + */ + xsProperty* GetProperty(const wxString& field); + /*! + * \brief Get reference to properties list. + * \sa xsProperty + */ + inline PropertyList& GetProperties() { return m_lstProperties; } + + /*! + * \brief Enable/disable serialization of given property. + * \param field Property name + * \param enab TRUE if the property should be serialized, otherwise FALSE + */ + void EnablePropertySerialization(const wxString& field, bool enab); + /*! + * \brief Returns information whether the given property is serialized or not. + * \param field Name of examined property + */ + bool IsPropertySerialized(const wxString& field); + /*! + * \brief Enable/disable object serialization. + * \param enab TRUE if the object should be serialized, otherwise FALSE + */ + inline void EnableSerialization(bool enab) { m_fSerialize = enab; } + /*! + * \brief Returns information whether the object can be serialized or not. + */ + inline bool IsSerialized() const { return m_fSerialize; } + /*! + * \brief Enable/disable object cloning. + * \param enab TRUE if the object can be cloned, otherwise FALSE + */ + inline void EnableCloning(bool enab) { m_fClone = enab; } + /*! + * \brief Returns information whether the object can be cloned or not. + */ + inline bool IsCloningEnabled() const { return m_fClone; } + + // overloaded operators + /*! + * \brief Add serializable child object to this object. + * \param child Pointer to added child object (should NOT be NULL) + * \return Pointer to added object + */ + xsSerializable* operator<<(xsSerializable *child); + +protected: + // protected data members + /*! \brief List of serialized properties */ + PropertyList m_lstProperties; + /*! \brief List of child objects */ + SerializableList m_lstChildItems; + + /*! \brief Pointer to parent serializable object */ + xsSerializable *m_pParentItem; + /*! \brief Pointer to parent data manager */ + wxXmlSerializer *m_pParentManager; + + /*! \brief Object serialization flag */ + bool m_fSerialize; + /*! \brief Object cloning flag */ + bool m_fClone; + + /** + * \brief Initialize new child object. + * \param child Pointer to new child object + */ + void InitChild(xsSerializable *child); + + // protected virtual functions + /*! + * \brief Serialize stored properties to the given XML node. The serialization + * routine is automatically called by the framework and cares about serialization + * of all defined properties. + * + * Note that default implementation automatically serializes all class data members + * marked by appropriate macros. If some non-standard class member should be serialized as well, + * the source code of derived function implementation can be as in following example. + * + * \param node Pointer to XML node where the property nodes will be appended to + * + * Example code: + * \code + * wxXmlNode* DerivedFrom_xsSerializable::Serialize(wxXmlNode* node) + * { + * if(node) + * { + * // call base class's serialization routine + * node = xsSeralizable::Serialize(node); + * + * // serialize custom property + * xsPropertyIO::AddPropertyNode(node, wxT("some_property_field_name"), wxT("string_repr_of_its_value")); + * } + * // return updated node + * return node; + * } + * \endcode + */ + virtual wxXmlNode* Serialize(wxXmlNode* node); + /*! + * \brief Deserialize object properties from the given XML node. The + * routine is automatically called by the framework and cares about deserialization + * of all defined properties. + * + * Note that default implementation automatically deserializes all class data members + * marked by appropriate macros. If some non-standard class member should be deserialized as well, + * the source code of derived function implementation can be as in following example. + * + * \param node Pointer to a source XML node containig the property nodes + * + * Example code: + * \code + * void DerivedFrom_xsSerializable::Deserialize(wxXmlNode* node) + * { + * // call base class's deserialization rountine (if necessary...) + * xsSerializable::Deserialize(node); + * + * // iterate through all custom property nodes + * wxXmlNode *propNode = node->GetChildren(); + * while(propNode) + * { + * if(propNode->GetName() == wxT("some_property_field_name")) + * { + * // read the node content and convert it to a proper data type + * } + * propNode = propNode->GetNext(); + * } + * } + * \endcode + */ + virtual void Deserialize(wxXmlNode* node); + +private: + /*! \brief Object ID */ + long m_nId; +}; + +/*! + * \brief Class encapsulates a serializable objects' manager which is responsible + * for handling stored serializable objects and their serialization/deserialization + * from/to XML files or streams. + * + * Stored objects can be arranged into a list or d-ary tree structure so this class + * can be used as a container for various application data. Also created XML files + * (root node) can be marked with given version and owner name, so it is possible to + * control a version of saved document. + * + * wxXmlSerializer class contains one instance of xsSerializable object created in the + * class constructor (can be set later via member functions as well). This serializable + * object called 'root object' holds all other inserted serializable objects (in case of + * tree structure it is a topmost tree node, in case of list structure all list items are + * its children). These child object can be handled via xsSerializable and wxXmlSerializer + * classes' member functions. + * + * Another built-in (optional) functionality is class instaces' cloning. User can use + * XS_DECLARE_CLONABLE_CLASS and XS_IMPLEMENT_CLONABLE_CLASS macros instead of classic + * DECLARE_DYNAMIC_CLASS and IMPLEMENT_DYNAMIC_CLASS macros which lead to definition of + * wxXmlSerializer::Clone() virtual function used for cloning of current class instance + * via its copy constructor (user must define it manually). + */ +class WXDLLIMPEXP_XS wxXmlSerializer : public wxObject +{ +public: + XS_DECLARE_CLONABLE_CLASS(wxXmlSerializer); + + /*! \brief Constructor. */ + wxXmlSerializer(); + /*! + * \brief User constructor. + * \param owner Owner name + * \param root Name of root node + * \param version File version + */ + wxXmlSerializer(const wxString& owner, const wxString& root, const wxString& version); + /*! \brief Copy constructor. */ + wxXmlSerializer(const wxXmlSerializer &obj); + /*! \brief Destructor. */ + virtual ~wxXmlSerializer(); + + // public member data accessors + /*! + * \brief Set owner name. + * \param name Owner name + */ + inline void SetSerializerOwner(const wxString& name) { m_sOwner = name; } + /*! + * \brief Set root name. + * \param name Root name + */ + inline void SetSerializerRootName(const wxString& name) { m_sRootName = name; } + /*! + * \brief Set file version. + * \param name File version + */ + inline void SetSerializerVersion(const wxString& name) { m_sVersion = name; } + /*! \brief Get owner name. */ + inline const wxString& GetSerializerOwner() const { return m_sOwner; } + /*! \brief Get name of root node. */ + inline const wxString& GetSerializerRootName() const { return m_sRootName; } + /*! \brief Get file version. */ + inline const wxString& GetSerializerVersion() const { return m_sVersion; } + /*! \brief Get the library version. */ + inline const wxString& GetLibraryVersion() const { return m_sLibraryVersion; } + + // public functions + /*! \brief Get pointer to root serializable object. */ + inline xsSerializable* GetRootItem() const { return m_pRoot; } + /*! + * \brief Get serializable object with given ID. + * \param id Object ID + * \return Pointer to serializable object if exists, otherwise NULL + */ + xsSerializable* GetItem(long id); + /*! + * \brief Get items of given class type. + * \param type Class type + * \param list List with matching serializable objects + * \param mode Search mode + * \sa xsSerializable::SEARCHMODE + */ + void GetItems(wxClassInfo* type, SerializableList& list, xsSerializable::SEARCHMODE mode = xsSerializable::searchBFS); + /*! + * \brief Check whether given object is included in the serializer. + * \param object Pointer to checked object + * \return True if the object is included in the serializer, otherwise False + */ + bool Contains(xsSerializable *object) const; + /*! + * \brief Check whether any object of given type is included in the serializer. + * \param type Pointer to class info + * \return True if at least one object of given type is included in the serializer, otherwise False + */ + bool Contains(wxClassInfo *type); + + /*! + * \brief Set root item. + * \param root Pointer to root item + */ + void SetRootItem(xsSerializable* root, bool bDeleteCurrentRoot = true); + + /*! + * \brief Replace current stored data with a content stored in given source manager. + * + * For proper functionality all stored data items derived from the xsSerializable class + * MUST implement virtual function xsSerializable::Clone() as well as the copy + * constructor. For more details see the xsSerializable::Clone() function documentation. + * \param src Reference to the source data manager + */ + void CopyItems(const wxXmlSerializer& src); + /*! + * \brief Add serializable object to the serializer. + * \param parentId ID of parent serializable object + * \param item Added serializable object + * \return Pointer to added item + */ + xsSerializable* AddItem(long parentId, xsSerializable* item); + /*! + * \brief Add serializable object to the serializer. + * \param parent Pointer to parent serializable object (if NULL then the object + * is added directly to the root item) + * \param item Added serializable object + * \return Pointer to added item + */ + xsSerializable* AddItem(xsSerializable* parent, xsSerializable* item); + /*! + * \brief Remove serializable object from the serializer (object will be destroyed). + * \param id Object ID + */ + void RemoveItem(long id); + /*! + * \brief Remove serializable object from the serializer (object will be destroyed). + * \param item Pointer to removed object + */ + void RemoveItem(xsSerializable* item); + /*! \brief Remove and destroy all stored serializable objects*/ + void RemoveAll(); + /*! + * \brief Enable/disable object cloning. + * \param enab TRUE if the object can be cloned, otherwise FALSE + */ + inline void EnableCloning(bool enab) { m_fClone = enab; } + /*! + * \brief Returns information whether the object can be cloned or not. + */ + inline bool IsCloned() const { return m_fClone; } + + /*! + * \brief Serialize stored objects to given file. + * \param file Full path to output file + * \param withroot If TRUE then the root item's properties are serialized as well + * \return TRUE on success, otherwise FALSE + */ + virtual bool SerializeToXml(const wxString& file, bool withroot = false); + /*! + * \brief Serialize stored objects to given stream. + * \param outstream Output stream + * \param withroot If TRUE then the root item's properties are serialized as well + * \return TRUE on success, otherwise FALSE + */ + virtual bool SerializeToXml(wxOutputStream& outstream, bool withroot = false); + /*! + * \brief Deserialize objects from given file. + * \param file Full path to input file + * \return TRUE on success, otherwise FALSE + */ + virtual bool DeserializeFromXml(const wxString& file); + /*! + * \brief Deserialize objects from given stream. + * \param instream Input stream + * \return TRUE on success, otherwise FALSE + */ + virtual bool DeserializeFromXml(wxInputStream& instream); + + /*! + * \brief Serialize child objects of given parent object (parent object can be optionaly + * serialized as well) to given XML node. The function can be overriden if necessary. + * \param parent Pointer to parent serializable object + * \param node Pointer to output XML node + * \param withparent TRUE if the parent object should be serialized as well + */ + virtual void SerializeObjects(xsSerializable* parent, wxXmlNode* node, bool withparent); + /*! + * \brief Deserialize child objects of given parent object from given XML node. + * The function can be overriden if necessary. + * \param parent Pointer to parent serializable object + * \param node Pointer to input XML node + */ + virtual void DeserializeObjects(xsSerializable* parent, wxXmlNode* node); + + /*! + * \brief Get the lowest free object ID + */ + long GetNewId(); + /*! + * \brief Find out whether given object ID is already used. + * \param id Object ID + * \return TRUE if the object ID is used, otherwise FALSE + */ + bool IsIdUsed(long id); + /*! + * \brief Get number of occurences of given ID. + * \param id Object ID + * \return Number of ID's occurences + */ + int GetIDCount(long id); + /*! + * \brief Get map of used IDs. + * \return Reference to map where all used IDs are stored + */ + IDMap& GetUsedIDs() { return m_mapUsedIDs; } + + /*! \brief Initialize all standard property IO handlers */ + void InitializeAllIOHandlers(); + /*! \brief Clear all initialized property IO handlers */ + void ClearIOHandlers(); + /*! + * \brief Get property I/O handler for given datatype. + * \param datatype String ID of data type + * \return Pointer to I/O handler suitable for given data type if exists, otherwise NULL + */ + inline static xsPropertyIO* GetPropertyIOHandler(const wxString& datatype) { return m_mapPropertyIOHandlers[datatype]; } + + /*! \brief Map of property IO handlers */ + static PropertyIOMap m_mapPropertyIOHandlers; + + // overloaded operators + /*! + * \brief Add serializable object to the serializer's root. + * \param obj Pointer to serializable object + */ + void operator<< (xsSerializable *obj) { if( obj ) this->AddItem( (xsSerializable*)NULL, obj); } + +protected: + // protected data members + /*! \brief Owner name */ + wxString m_sOwner; + /*! \brief Root node name */ + wxString m_sRootName; + /*! \brief File version */ + wxString m_sVersion; + + /*! \brief Pointer to root object */ + xsSerializable* m_pRoot; + + /*! \brief Object cloning flag */ + bool m_fClone; + + /*! \brief Map storing information which ID is already used */ + IDMap m_mapUsedIDs; + +private: + // private data members + //int m_nCounter; + static int m_nRefCounter; + static wxString m_sLibraryVersion; + + // private functions + /*! \brief Auxiliary function */ + xsSerializable* _GetItem(long id, xsSerializable* parent); + /*! \brief Auxiliary function */ + bool _Contains(xsSerializable *object, xsSerializable* parent) const; +}; + +/*! + * \brief Class encapsulates a property stored in a list included inside a parent serializable + * object (class xsSerializable) which is serialized/deserialized to/from XML file. The + * property object type is defined by a string name and is processed by parent xsSerializable class object. + * + * Allowed property data types (keywords) are: 'long', 'double', 'bool', 'string', 'point', 'size', + * 'realpoint', 'colour', 'brush', 'pen', 'font', 'arraystring', 'arrayrealpoint', 'listrealpoint', + * 'serializabledynamic' and 'serializablestatic'. Only properties of these data types are recognized + * and processed by parent serializable object. + */ +class WXDLLIMPEXP_XS xsProperty : public wxObject +{ +public: + DECLARE_DYNAMIC_CLASS(xsProperty); + + /*! \brief Default constructor */ + xsProperty() + { + m_pSourceVariable = NULL; + m_sDataType = wxT("Undefined"); + m_sFieldName = wxT("Undefined"); + m_sDefaultValueStr = wxT(""); + m_fSerialize = false; + } + + /*! + * \brief Constructor + * \param src Pointer to serialized object + * \param type String value describing data type of serialized object + * \param field Property name used in XML files and for property handling + * \param def String representation of default poperty value + */ + xsProperty(void* src, const wxString& type, const wxString& field, const wxString& def = wxT("")) + { + m_pSourceVariable = src; + m_sDataType = type; + m_sFieldName = field; + m_sDefaultValueStr = def; + m_fSerialize = true; + } + + /*! \brief Constructor for BOOL property. */ + xsProperty(bool* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("bool")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + /*! \brief Constructor for BOOL property with defined default value. */ + xsProperty(bool* src, const wxString& field, bool def) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("bool")), m_sDefaultValueStr(xsBoolPropIO::ToString(def)), m_fSerialize(true) {;} + + /*! \brief Constructor for LONG property. */ + xsProperty(long* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("long")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + /*! \brief Constructor for LONG property with defined default value. */ + xsProperty(long* src, const wxString& field, long def) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("long")), m_sDefaultValueStr(xsLongPropIO::ToString(def)), m_fSerialize(true) {;} + + /*! \brief Constructor for INT property. */ + xsProperty(int* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("int")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + /*! \brief Constructor for INT property with defined default value. */ + xsProperty(int* src, const wxString& field, int def) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("int")), m_sDefaultValueStr(xsIntPropIO::ToString(def)), m_fSerialize(true) {;} + + /*! \brief Constructor for DOUBLE property. */ + xsProperty(double* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("double")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + /*! \brief Constructor for DOUBLE property with defined default value. */ + xsProperty(double* src, const wxString& field, double def) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("double")), m_sDefaultValueStr(xsDoublePropIO::ToString(def)), m_fSerialize(true) {;} + + /*! \brief Constructor for FLOAT property. */ + xsProperty(float* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("float")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + /*! \brief Constructor for FLOAT property with defined default value. */ + xsProperty(float* src, const wxString& field, float def) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("float")), m_sDefaultValueStr(xsFloatPropIO::ToString(def)), m_fSerialize(true) {;} + + /*! \brief Constructor for wxString property. */ + xsProperty(wxString* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("string")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + /*! \brief Constructor for wxString property with defined default value. */ + xsProperty(wxString* src, const wxString& field, const wxString& def) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("string")), m_sDefaultValueStr(def), m_fSerialize(true) {;} + + /*! \brief Constructor for wxChar property. */ + xsProperty(wxChar* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("char")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + /*! \brief Constructor for wxChar property with defined default value. */ + xsProperty(wxChar* src, const wxString& field, wxChar def) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("char")), m_sDefaultValueStr(xsCharPropIO::ToString(def)), m_fSerialize(true) {;} + + /*! \brief Constructor for wxPoint property. */ + xsProperty(wxPoint* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("point")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + /*! \brief Constructor for wxPoint property with defined default value. */ + xsProperty(wxPoint* src, const wxString& field, const wxPoint& def) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("point")), m_sDefaultValueStr(xsPointPropIO::ToString(def)), m_fSerialize(true) {;} + + /*! \brief Constructor for wxRealPoint property. */ + xsProperty(wxRealPoint* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("realpoint")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + /*! \brief Constructor for wxRealPoint property with defined default value. */ + xsProperty(wxRealPoint* src, const wxString& field, const wxRealPoint& def) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("realpoint")), m_sDefaultValueStr(xsRealPointPropIO::ToString(def)), m_fSerialize(true) {;} + + /*! \brief Constructor for wxSize property. */ + xsProperty(wxSize* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("size")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + /*! \brief Constructor for wxSize property with defined default value. */ + xsProperty(wxSize* src, const wxString& field, const wxSize& def) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("size")), m_sDefaultValueStr(xsSizePropIO::ToString(def)), m_fSerialize(true) {;} + + /*! \brief Constructor for wxBrush property. */ + xsProperty(wxBrush* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("brush")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + /*! \brief Constructor for wxBrush property with defined default value. */ + xsProperty(wxBrush* src, const wxString& field, const wxBrush& def) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("brush")), m_sDefaultValueStr(xsBrushPropIO::ToString(def)), m_fSerialize(true) {;} + + /*! \brief Constructor for wxPen property. */ + xsProperty(wxPen* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("pen")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + /*! \brief Constructor for wxPen property with defined default value. */ + xsProperty(wxPen* src, const wxString& field, const wxPen& def) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("pen")), m_sDefaultValueStr(xsPenPropIO::ToString(def)), m_fSerialize(true) {;} + + /*! \brief Constructor for wxFont property. */ + xsProperty(wxFont* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("font")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + /*! \brief Constructor for wxFont property with defined default value. */ + xsProperty(wxFont* src, const wxString& field, const wxFont& def) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("font")), m_sDefaultValueStr(xsFontPropIO::ToString(def)), m_fSerialize(true) {;} + + /*! \brief Constructor for wxColour property. */ + xsProperty(wxColour* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("colour")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + /*! \brief Constructor for wxColour property with defined default value. */ + xsProperty(wxColour* src, const wxString& field, const wxColour& def) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("colour")), m_sDefaultValueStr(xsColourPropIO::ToString(def)), m_fSerialize(true) {;} + + /*! \brief Constructor for wxArrayString property. */ + xsProperty(wxArrayString* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("arraystring")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + + /*! \brief Constructor for CharArray property. */ + xsProperty(CharArray* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("arraychar")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + + /*! \brief Constructor for IntArray property. */ + xsProperty(IntArray* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("arrayint")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + + /*! \brief Constructor for LongArray property. */ + xsProperty(LongArray* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("arraylong")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + + /*! \brief Constructor for DoubleArray property. */ + xsProperty(DoubleArray* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("arraydoubles")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + + /*! \brief Constructor for RealPointArray property. */ + xsProperty(RealPointArray* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("arrayrealpoint")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + + /*! \brief Constructor for RealPointList property. */ + xsProperty(RealPointList* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("listrealpoint")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + + /*! \brief Constructor for StringMap property. */ + xsProperty(StringMap* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("mapstring")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + + /*! \brief Constructor for static serializable property. */ + xsProperty(xsSerializable* src, const wxString& field) : m_pSourceVariable((void*)src), m_sFieldName(field), m_sDataType(wxT("serializablestatic")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + + /*! \brief Constructor for dynamic serializable property. */ + xsProperty(xsSerializable** src, const wxString& field) : m_pSourceVariable((void**)src), m_sFieldName(field), m_sDataType(wxT("serializabledynamic")), m_sDefaultValueStr(wxT("")), m_fSerialize(true) {;} + + /*! \brief Copy constructor. */ + xsProperty(const xsProperty& obj) : wxObject( obj ), m_pSourceVariable(obj.m_pSourceVariable), m_sFieldName(obj.m_sFieldName), m_sDataType(obj.m_sDataType), m_sDefaultValueStr(obj.m_sDefaultValueStr), m_fSerialize(obj.m_fSerialize) {;} + + ~xsProperty(){;} + + // public functions + /** + * \brief Get textual representation of the property's value. + * \return Textual representation of current value + */ + wxString ToString() + { + xsPropertyIO *pIO = wxXmlSerializer::m_mapPropertyIOHandlers[m_sDataType]; + if(pIO) return pIO->GetValueStr(this); + else + return wxEmptyString; + } + + /** + * \brief Set value defined by its textual representation. + * \param val Textual representation of given value + */ + void FromString(const wxString& val) + { + xsPropertyIO *pIO = wxXmlSerializer::m_mapPropertyIOHandlers[m_sDataType]; + if(pIO) return pIO->SetValueStr(this, val); + } + + /** + * \brief Get reference to managed data member as BOOL. + * \return Reference to managed data member + */ + inline bool& AsBool() { wxASSERT(m_sDataType == wxT("bool")); return *(bool*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as INT. + * \return Reference to managed data member + */ + inline int& AsInt() { wxASSERT(m_sDataType == wxT("int")); return *(int*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as LONG. + * \return Reference to managed data member + */ + inline long& AsLong() { wxASSERT(m_sDataType == wxT("long")); return *(long*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as FLOAT. + * \return Reference to managed data member + */ + inline float& AsFloat() { wxASSERT(m_sDataType == wxT("float")); return *(float*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as DOUBLE. + * \return Reference to managed data member + */ + inline double& AsDouble() { wxASSERT(m_sDataType == wxT("double")); return *(double*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as wxChar. + * \return Reference to managed data member + */ + inline wxChar& AsChar() { wxASSERT(m_sDataType == wxT("char")); return *(wxChar*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as wxString. + * \return Reference to managed data member + */ + inline wxString& AsString() { wxASSERT(m_sDataType == wxT("string")); return *(wxString*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as wxSize. + * \return Reference to managed data member + */ + inline wxSize& AsSize() { wxASSERT(m_sDataType == wxT("size")); return *(wxSize*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as wxPoint. + * \return Reference to managed data member + */ + inline wxPoint& AsPoint() { wxASSERT(m_sDataType == wxT("point")); return *(wxPoint*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as wxRealPoint. + * \return Reference to managed data member + */ + inline wxRealPoint& AsRealPoint() { wxASSERT(m_sDataType == wxT("realpoint")); return *(wxRealPoint*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as wxBrush. + * \return Reference to managed data member + */ + inline wxBrush& AsBrush() { wxASSERT(m_sDataType == wxT("brush")); return *(wxBrush*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as wxPen. + * \return Reference to managed data member + */ + inline wxPen& AsPen() { wxASSERT(m_sDataType == wxT("pen")); return *(wxPen*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as wxFont. + * \return Reference to managed data member + */ + inline wxFont& AsFont() { wxASSERT(m_sDataType == wxT("font")); return *(wxFont*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as wxColour. + * \return Reference to managed data member + */ + inline wxColour& AsColour() { wxASSERT(m_sDataType == wxT("colour")); return *(wxColour*)m_pSourceVariable; } + + /** + * \brief Get reference to managed data member as wxArrayString. + * \return Reference to managed data member + */ + inline wxArrayString& AsStringArray() { wxASSERT(m_sDataType == wxT("arraystring")); return *(wxArrayString*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as CharArray. + * \return Reference to managed data member + */ + inline CharArray& AsCharArray() { wxASSERT(m_sDataType == wxT("arraychar")); return *(CharArray*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as IntArray. + * \return Reference to managed data member + */ + inline IntArray& AsIntArray() { wxASSERT(m_sDataType == wxT("arrayint")); return *(IntArray*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as LongArray. + * \return Reference to managed data member + */ + inline LongArray& AsLongArray() { wxASSERT(m_sDataType == wxT("arraylong")); return *(LongArray*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as DoubleArray. + * \return Reference to managed data member + */ + inline DoubleArray& AsDoubleArray() { wxASSERT(m_sDataType == wxT("arraydouble")); return *(DoubleArray*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as RealPointArray. + * \return Reference to managed data member + */ + inline RealPointArray& AsRealPointArray() { wxASSERT(m_sDataType == wxT("arrayrealpoint")); return *(RealPointArray*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as RealPointList. + * \return Reference to managed data member + */ + inline RealPointList& AsRealPointList() { wxASSERT(m_sDataType == wxT("listrealpoint")); return *(RealPointList*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as StringMap. + * \return Reference to managed data member + */ + inline StringMap& AsStringMap() { wxASSERT(m_sDataType == wxT("mapstring")); return *(StringMap*)m_pSourceVariable; } + + /** + * \brief Get reference to managed data member as serializable static object. + * \return Reference to managed data member + */ + inline xsSerializable& AsSerializableStatic() { wxASSERT(m_sDataType == wxT("serializablestatic")); return *(xsSerializable*)m_pSourceVariable; } + /** + * \brief Get reference to managed data member as serializable dynamic object. + * \return Reference to managed data member + */ + inline xsSerializable& AsSerializableDynamic() { wxASSERT(m_sDataType == wxT("serializabledynamic")); return **(xsSerializable**)m_pSourceVariable; } + + // public data members + /*! \brief General (void) pointer to serialized object encapsulated by the property */ + void* m_pSourceVariable; + /*! \brief Field (property) name */ + wxString m_sFieldName; + /*! \brief Data type */ + wxString m_sDataType; + /*! \brief String representation of property's default value */ + wxString m_sDefaultValueStr; + /*! \brief Flag used for enabling/disabling of property serialization */ + bool m_fSerialize; +}; + +#endif //_XSXMLSERIALIZE_H diff --git a/ThirdParty/wxXS/src/PropertyIO.cpp b/ThirdParty/wxXS/src/PropertyIO.cpp new file mode 100644 index 0000000..96c8c85 --- /dev/null +++ b/ThirdParty/wxXS/src/PropertyIO.cpp @@ -0,0 +1,1209 @@ +/*************************************************************** + * Name: PropertyIO.cpp + * Purpose: Implements data types I/O and conversion functions + * Author: Michal Bližňák (michal.bliznak@tiscali.cz) + * Created: 2007-10-28 + * Copyright: Michal Bliňák + * License: wxWidgets license (www.wxwidgets.org) + * Notes: + **************************************************************/ + +#include "wx_pch.h" + +#ifdef _DEBUG_MSVC +#define new DEBUG_NEW +#endif + +#include "wx/wxxmlserializer/PropertyIO.h" +#include "wx/wxxmlserializer/XmlSerializer.h" + +#include +#include +#include + +using namespace std; + +WX_DEFINE_EXPORTED_OBJARRAY(RealPointArray); +WX_DEFINE_EXPORTED_LIST(RealPointList); + +///////////////////////////////////////////////////////////////////////////////////// +// xsPropertyIO class /////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC_CLASS(xsPropertyIO, wxObject); + +wxXmlNode* xsPropertyIO::AddPropertyNode(wxXmlNode* parent, const wxString& name, const wxString& value, wxXmlNodeType type) +{ + if(parent) + { + wxXmlNode* child = new wxXmlNode(wxXML_ELEMENT_NODE, name); + child->AddChild(new wxXmlNode(type, wxT(""), value)); + parent->AddChild(child); + return child; + } + return NULL; +} + +void xsPropertyIO::AppendPropertyType(xsProperty *source, wxXmlNode *target) +{ + target->AddAttribute(wxT("name"), source->m_sFieldName); + target->AddAttribute(wxT("type"), source->m_sDataType); +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsStringPropIO class ///////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_DEFINE_IO_HANDLER(wxString, xsStringPropIO); + +wxString xsStringPropIO::ToString(const wxString& value) +{ + return value; +} + +wxString xsStringPropIO::FromString(const wxString& value) +{ + return value; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsCharPropIO class /////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_DEFINE_IO_HANDLER(wxChar, xsCharPropIO); + +wxString xsCharPropIO::ToString(const wxChar& value) +{ + return wxString::Format(wxT("%c"), value); +} + +wxChar xsCharPropIO::FromString(const wxString& value) +{ + return value.GetChar(0); +} + + +///////////////////////////////////////////////////////////////////////////////////// +// xsLongPropIO class /////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_DEFINE_IO_HANDLER(long, xsLongPropIO); + +wxString xsLongPropIO::ToString(const long& value) +{ + return wxString::Format(wxT("%ld"), value); +} + +long xsLongPropIO::FromString(const wxString& value) +{ + long num = 0; + if(!value.IsEmpty()) + { + value.ToLong(&num); + } + return num; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsIntPropIO class //////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_DEFINE_IO_HANDLER(int, xsIntPropIO); + +wxString xsIntPropIO::ToString(const int& value) +{ + return wxString::Format(wxT("%d"), value); +} + +int xsIntPropIO::FromString(const wxString& value) +{ + long num = 0; + if(!value.IsEmpty()) + { + value.ToLong(&num); + } + return (int)num; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsBoolPropIO class /////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_DEFINE_IO_HANDLER(bool, xsBoolPropIO); + +wxString xsBoolPropIO::ToString(const bool& value) +{ + return wxString::Format(wxT("%d"), value); +} + +bool xsBoolPropIO::FromString(const wxString& value) +{ + long num = 0; + if(!value.IsEmpty()) + { + value.ToLong(&num); + } + return (num == 1); +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsDoublePropIO class ///////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_DEFINE_IO_HANDLER(double, xsDoublePropIO); + +wxString xsDoublePropIO::ToString(const double& value) +{ + wxString sVal; + + if( wxIsNaN(value) ) + { + sVal = wxT("NAN"); + } + else if( wxFinite(value) == 0 ) + { + sVal = wxT("INF"); + } + else + { + // use '.' decimal point character + sVal= wxString::Format(wxT("%lf"), value); + sVal.Replace(wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER), wxT(".")); + } + + return sVal; +} + +double xsDoublePropIO::FromString(const wxString& value) +{ + double num = 0; + + if(!value.IsEmpty()) + { + if( value == wxT("NAN") ) + { + num = numeric_limits::quiet_NaN(); + } + else if( value == wxT("INF") ) + { + num = numeric_limits::infinity(); + } + else + { + // decimal point character used in wxXS is strictly '.'... + value.ToCDouble(&num); + } + } + + return num; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsFloatPropIO class ////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_DEFINE_IO_HANDLER(float, xsFloatPropIO); + +wxString xsFloatPropIO::ToString(const float& value) +{ + wxString sVal; + if( wxIsNaN(value) ) + { + sVal = wxT("NAN"); + } + else if( wxFinite(value) == 0 ) + { + sVal = wxT("INF"); + } + else + { + sVal = wxString::Format(wxT("%f"), value); + sVal.Replace(wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER), wxT(".")); + } + + return sVal; +} + +float xsFloatPropIO::FromString(const wxString& value) +{ + double num = 0; + + if(!value.IsEmpty()) + { + if( value == wxT("NAN") ) + { + num = numeric_limits::quiet_NaN(); + } + else if( value == wxT("INF") ) + { + num = numeric_limits::infinity(); + } + else + { + // decimal point character used in wxXS is strictly '.'... + value.ToCDouble(&num); + } + } + + return (float)num; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsPointPropIO class ////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_DEFINE_IO_HANDLER(wxPoint, xsPointPropIO); + +wxString xsPointPropIO::ToString(const wxPoint& value) +{ + return wxString::Format(wxT("%d,%d"), value.x, value.y); +} + +wxPoint xsPointPropIO::FromString(const wxString& value) +{ + wxPoint pt; + + //long x, y; + + if(!value.IsEmpty()) + { + wxSscanf( value, wxT("%d,%d"), &pt.x, &pt.y ); + +// wxStringTokenizer tokens(value, wxT(","), wxTOKEN_STRTOK); +// +// tokens.GetNextToken().ToLong(&x); +// tokens.GetNextToken().ToLong(&y); +// pt.x = x; +// pt.y = y; + } + + return pt; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsSizePropIO class /////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_DEFINE_IO_HANDLER(wxSize, xsSizePropIO); + +wxString xsSizePropIO::ToString(const wxSize& value) +{ + return wxString::Format(wxT("%d,%d"), value.x, value.y); +} + +wxSize xsSizePropIO::FromString(const wxString& value) +{ + wxPoint pt = xsPointPropIO::FromString(value); + return wxSize(pt.x, pt.y); +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsRealPointPropIO class ////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_DEFINE_IO_HANDLER(wxRealPoint, xsRealPointPropIO); + +wxString xsRealPointPropIO::ToString(const wxRealPoint& value) +{ + return wxString::Format(wxT("%s,%s"), xsDoublePropIO::ToString(value.x).c_str(), xsDoublePropIO::ToString(value.y).c_str()); +} + +wxRealPoint xsRealPointPropIO::FromString(const wxString& value) +{ + wxRealPoint pt; + + if(!value.IsEmpty()) + { + wxStringTokenizer tokens(value, wxT(","), wxTOKEN_STRTOK); + + pt.x = xsDoublePropIO::FromString(tokens.GetNextToken()); + pt.y = xsDoublePropIO::FromString(tokens.GetNextToken()); + } + + return pt; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsColourPropIO class ///////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_DEFINE_IO_HANDLER(wxColour, xsColourPropIO); + +wxString xsColourPropIO::ToString(const wxColour& value) +{ + return wxString::Format(wxT("%d,%d,%d,%d"), value.Red(), value.Green(), value.Blue(), value.Alpha()); +} + +wxColour xsColourPropIO::FromString(const wxString& value) +{ + int nRed = 0; + int nGreen = 0; + int nBlue = 0; + int nAlpha = 0; + + if(!value.IsEmpty()) + { + if( wxSscanf( value, wxT("%d,%d,%d,%d"), &nRed, &nGreen, &nBlue, &nAlpha ) == 3 ) nAlpha = 255; + } + + return wxColour(nRed, nGreen, nBlue, nAlpha); +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsPenPropIO class //////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_DEFINE_IO_HANDLER(wxPen, xsPenPropIO); + +wxString xsPenPropIO::ToString(const wxPen& value) +{ + return wxString::Format(wxT("%s %d %d"), xsColourPropIO::ToString(value.GetColour()).c_str(), value.GetWidth(), value.GetStyle()); +} + +wxPen xsPenPropIO::FromString(const wxString& value) +{ + wxPen pen; + + wxStringTokenizer tokens(value, wxT(" "), wxTOKEN_STRTOK); + pen.SetColour(xsColourPropIO::FromString(tokens.GetNextToken())); + pen.SetWidth(xsLongPropIO::FromString(tokens.GetNextToken())); + pen.SetStyle(xsLongPropIO::FromString(tokens.GetNextToken())); + + return pen; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsBrushPropIO class ////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_DEFINE_IO_HANDLER(wxBrush, xsBrushPropIO); + +wxString xsBrushPropIO::ToString(const wxBrush& value) +{ + return wxString::Format(wxT("%s %d"), xsColourPropIO::ToString(value.GetColour()).c_str(), value.GetStyle()); +} + +wxBrush xsBrushPropIO::FromString(const wxString& value) +{ + wxBrush brush; + + wxStringTokenizer tokens(value, wxT(" "), wxTOKEN_STRTOK); + brush.SetColour(xsColourPropIO::FromString(tokens.GetNextToken())); + brush.SetStyle(xsLongPropIO::FromString(tokens.GetNextToken())); + + return brush; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsFontPropIO class /////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_DEFINE_IO_HANDLER(wxFont, xsFontPropIO); + +wxString xsFontPropIO::ToString(const wxFont& value) +{ + return value.GetNativeFontInfoUserDesc(); +} + +wxFont xsFontPropIO::FromString(const wxString& value) +{ + wxFont font; + + if( !font.SetNativeFontInfoUserDesc(value) ) + { + return *wxSWISS_FONT; + } + else + return font; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsArrayStringPropIO class //////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC_CLASS(xsArrayStringPropIO, xsPropertyIO); + +void xsArrayStringPropIO::Read(xsProperty *property, wxXmlNode *source) +{ + ((wxArrayString*)property->m_pSourceVariable)->Clear(); + + wxXmlNode *listNode = source->GetChildren(); + while(listNode) + { + if(listNode->GetName() == wxT("item")) + { + ((wxArrayString*)property->m_pSourceVariable)->Add(listNode->GetNodeContent()); + } + + listNode = listNode->GetNext(); + } +} + +void xsArrayStringPropIO::Write(xsProperty *property, wxXmlNode *target) +{ + wxArrayString& array = *((wxArrayString*)property->m_pSourceVariable); + + size_t cnt = array.GetCount(); + if(cnt > 0) + { + wxXmlNode *newNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("property")); + for(size_t i = 0; i < cnt; i++) + { + AddPropertyNode(newNode, wxT("item"), array[i]); + } + + target->AddChild(newNode); + AppendPropertyType(property, newNode); + } +} + +wxString xsArrayStringPropIO::GetValueStr(xsProperty *property) +{ + return ToString(*((wxArrayString*)property->m_pSourceVariable)); +} + +void xsArrayStringPropIO::SetValueStr(xsProperty *property, const wxString& valstr) +{ + *((wxArrayString*)property->m_pSourceVariable) = FromString(valstr); +} + +wxString xsArrayStringPropIO::ToString(const wxArrayString& value) +{ + wxString out; + + for( size_t i = 0; i < value.GetCount(); i++) + { + out << value[i]; + if( i < value.GetCount()-1 ) out << wxT("|"); + } + + return out; +} + +wxArrayString xsArrayStringPropIO::FromString(const wxString& value) +{ + wxArrayString arrData; + + wxStringTokenizer tokens( value, wxT("|") ); + while( tokens.HasMoreTokens() ) + { + arrData.Add( tokens.GetNextToken() ); + } + + return arrData; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsArrayIntPropIO class //////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC_CLASS(xsArrayIntPropIO, xsPropertyIO); + +void xsArrayIntPropIO::Read(xsProperty *property, wxXmlNode *source) +{ + ((IntArray*)property->m_pSourceVariable)->Clear(); + + wxXmlNode *listNode = source->GetChildren(); + while(listNode) + { + if(listNode->GetName() == wxT("item")) + { + ((IntArray*)property->m_pSourceVariable)->Add(xsIntPropIO::FromString(listNode->GetNodeContent())); + } + + listNode = listNode->GetNext(); + } +} + +void xsArrayIntPropIO::Write(xsProperty *property, wxXmlNode *target) +{ + IntArray& array = *((IntArray*)property->m_pSourceVariable); + + size_t cnt = array.GetCount(); + if(cnt > 0) + { + wxXmlNode *newNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("property")); + for(size_t i = 0; i < cnt; i++) + { + AddPropertyNode(newNode, wxT("item"), xsIntPropIO::ToString(array[i])); + } + + target->AddChild(newNode); + AppendPropertyType(property, newNode); + } +} + +wxString xsArrayIntPropIO::GetValueStr(xsProperty *property) +{ + return ToString(*((IntArray*)property->m_pSourceVariable)); +} + +void xsArrayIntPropIO::SetValueStr(xsProperty *property, const wxString& valstr) +{ + *((IntArray*)property->m_pSourceVariable) = FromString(valstr); +} + +wxString xsArrayIntPropIO::ToString(const IntArray& value) +{ + wxString out; + + for( size_t i = 0; i < value.GetCount(); i++) + { + out << xsIntPropIO::ToString(value[i]); + if( i < value.GetCount()-1 ) out << wxT("|"); + } + + return out; +} + +IntArray xsArrayIntPropIO::FromString(const wxString& value) +{ + IntArray arrData; + + wxStringTokenizer tokens( value, wxT("|") ); + while( tokens.HasMoreTokens() ) + { + arrData.Add( xsIntPropIO::FromString( tokens.GetNextToken() ) ); + } + + return arrData; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsArrayLongPropIO class //////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC_CLASS(xsArrayLongPropIO, xsPropertyIO); + +void xsArrayLongPropIO::Read(xsProperty *property, wxXmlNode *source) +{ + ((LongArray*)property->m_pSourceVariable)->Clear(); + + wxXmlNode *listNode = source->GetChildren(); + while(listNode) + { + if(listNode->GetName() == wxT("item")) + { + ((LongArray*)property->m_pSourceVariable)->Add(xsLongPropIO::FromString(listNode->GetNodeContent())); + } + + listNode = listNode->GetNext(); + } +} + +void xsArrayLongPropIO::Write(xsProperty *property, wxXmlNode *target) +{ + LongArray& array = *((LongArray*)property->m_pSourceVariable); + + size_t cnt = array.GetCount(); + if(cnt > 0) + { + wxXmlNode *newNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("property")); + for(size_t i = 0; i < cnt; i++) + { + AddPropertyNode(newNode, wxT("item"), xsLongPropIO::ToString(array[i])); + } + + target->AddChild(newNode); + AppendPropertyType(property, newNode); + } +} + +wxString xsArrayLongPropIO::GetValueStr(xsProperty *property) +{ + return ToString(*((LongArray*)property->m_pSourceVariable)); +} + +void xsArrayLongPropIO::SetValueStr(xsProperty *property, const wxString& valstr) +{ + *((LongArray*)property->m_pSourceVariable) = FromString(valstr); +} + +wxString xsArrayLongPropIO::ToString(const LongArray& value) +{ + wxString out; + + for( size_t i = 0; i < value.GetCount(); i++) + { + out << xsLongPropIO::ToString(value[i]); + if( i < value.GetCount()-1 ) out << wxT("|"); + } + + return out; +} + +LongArray xsArrayLongPropIO::FromString(const wxString& value) +{ + LongArray arrData; + + wxStringTokenizer tokens( value, wxT("|") ); + while( tokens.HasMoreTokens() ) + { + arrData.Add( xsLongPropIO::FromString( tokens.GetNextToken() ) ); + } + + return arrData; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsArrayDoublePropIO class //////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC_CLASS(xsArrayDoublePropIO, xsPropertyIO); + +void xsArrayDoublePropIO::Read(xsProperty *property, wxXmlNode *source) +{ + ((DoubleArray*)property->m_pSourceVariable)->Clear(); + + wxXmlNode *listNode = source->GetChildren(); + while(listNode) + { + if(listNode->GetName() == wxT("item")) + { + ((DoubleArray*)property->m_pSourceVariable)->Add(xsDoublePropIO::FromString(listNode->GetNodeContent())); + } + + listNode = listNode->GetNext(); + } +} + +void xsArrayDoublePropIO::Write(xsProperty *property, wxXmlNode *target) +{ + DoubleArray& array = *((DoubleArray*)property->m_pSourceVariable); + + size_t cnt = array.GetCount(); + if(cnt > 0) + { + wxXmlNode *newNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("property")); + for(size_t i = 0; i < cnt; i++) + { + AddPropertyNode(newNode, wxT("item"), xsDoublePropIO::ToString(array[i])); + } + + target->AddChild(newNode); + AppendPropertyType(property, newNode); + } +} + +wxString xsArrayDoublePropIO::GetValueStr(xsProperty *property) +{ + return ToString(*((DoubleArray*)property->m_pSourceVariable)); +} + +void xsArrayDoublePropIO::SetValueStr(xsProperty *property, const wxString& valstr) +{ + *((DoubleArray*)property->m_pSourceVariable) = FromString(valstr); +} + +wxString xsArrayDoublePropIO::ToString(const DoubleArray& value) +{ + wxString out; + + for( size_t i = 0; i < value.GetCount(); i++) + { + out << xsDoublePropIO::ToString(value[i]); + if( i < value.GetCount()-1 ) out << wxT("|"); + } + + return out; +} + +DoubleArray xsArrayDoublePropIO::FromString(const wxString& value) +{ + DoubleArray arrData; + + wxStringTokenizer tokens( value, wxT("|") ); + while( tokens.HasMoreTokens() ) + { + arrData.Add( xsDoublePropIO::FromString( tokens.GetNextToken() ) ); + } + + return arrData; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsArrayCharPropIO class //////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC_CLASS(xsArrayCharPropIO, xsPropertyIO); + +void xsArrayCharPropIO::Read(xsProperty *property, wxXmlNode *source) +{ + ((CharArray*)property->m_pSourceVariable)->Clear(); + + wxXmlNode *listNode = source->GetChildren(); + while(listNode) + { + if(listNode->GetName() == wxT("item")) + { + ((CharArray*)property->m_pSourceVariable)->Add(xsCharPropIO::FromString(listNode->GetNodeContent())); + } + + listNode = listNode->GetNext(); + } +} + +void xsArrayCharPropIO::Write(xsProperty *property, wxXmlNode *target) +{ + CharArray& array = *((CharArray*)property->m_pSourceVariable); + + size_t cnt = array.GetCount(); + if(cnt > 0) + { + wxXmlNode *newNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("property")); + for(size_t i = 0; i < cnt; i++) + { + AddPropertyNode(newNode, wxT("item"), xsCharPropIO::ToString(array[i])); + } + + target->AddChild(newNode); + AppendPropertyType(property, newNode); + } +} + +wxString xsArrayCharPropIO::GetValueStr(xsProperty *property) +{ + return ToString(*((CharArray*)property->m_pSourceVariable)); +} + +void xsArrayCharPropIO::SetValueStr(xsProperty *property, const wxString& valstr) +{ + *((CharArray*)property->m_pSourceVariable) = FromString(valstr); +} + +wxString xsArrayCharPropIO::ToString(const CharArray& value) +{ + wxString out; + + for( size_t i = 0; i < value.GetCount(); i++) + { + out << xsCharPropIO::ToString(value[i]); + if( i < value.GetCount()-1 ) out << wxT("|"); + } + + return out; +} + +CharArray xsArrayCharPropIO::FromString(const wxString& value) +{ + CharArray arrData; + + wxStringTokenizer tokens( value, wxT("|") ); + while( tokens.HasMoreTokens() ) + { + arrData.Add( xsCharPropIO::FromString( tokens.GetNextToken() ) ); + } + + return arrData; +} + + + +///////////////////////////////////////////////////////////////////////////////////// +// xsArrayRealPointPropIO class ///////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC_CLASS(xsArrayRealPointPropIO, xsPropertyIO); + +void xsArrayRealPointPropIO::Read(xsProperty *property, wxXmlNode *source) +{ + ((RealPointArray*)property->m_pSourceVariable)->Clear(); + + wxXmlNode *listNode = source->GetChildren(); + while(listNode) + { + if(listNode->GetName() == wxT("item")) + { + ((RealPointArray*)property->m_pSourceVariable)->Add(xsRealPointPropIO::FromString(listNode->GetNodeContent())); + } + + listNode = listNode->GetNext(); + } +} + +void xsArrayRealPointPropIO::Write(xsProperty *property, wxXmlNode *target) +{ + RealPointArray& array = *((RealPointArray*)property->m_pSourceVariable); + + size_t cnt = array.GetCount(); + if(cnt > 0) + { + wxXmlNode *newNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("property")); + for(size_t i = 0; i < cnt; i++) + { + AddPropertyNode(newNode, wxT("item"), xsRealPointPropIO::ToString(array[i])); + } + + target->AddChild(newNode); + AppendPropertyType(property, newNode); + } +} + +wxString xsArrayRealPointPropIO::GetValueStr(xsProperty *property) +{ + return ToString(*((RealPointArray*)property->m_pSourceVariable)); +} + +void xsArrayRealPointPropIO::SetValueStr(xsProperty *property, const wxString& valstr) +{ + *((RealPointArray*)property->m_pSourceVariable) = FromString(valstr); +} + +wxString xsArrayRealPointPropIO::ToString(const RealPointArray& value) +{ + wxString out; + + for( size_t i = 0; i < value.GetCount(); i++) + { + out << xsRealPointPropIO::ToString(value[i]); + if( i < value.GetCount()-1 ) out << wxT("|"); + } + + return out; +} + +RealPointArray xsArrayRealPointPropIO::FromString(const wxString& value) +{ + RealPointArray arrData; + + wxStringTokenizer tokens( value, wxT("|") ); + while( tokens.HasMoreTokens() ) + { + arrData.Add( xsRealPointPropIO::FromString( tokens.GetNextToken() ) ); + } + + return arrData; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsListRealPointPropIO class ////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC_CLASS(xsListRealPointPropIO, xsPropertyIO); + +void xsListRealPointPropIO::Read(xsProperty *property, wxXmlNode *source) +{ + RealPointList *list = (RealPointList*)property->m_pSourceVariable; + + // clear previous list content + bool fDelState = list->GetDeleteContents(); + + list->DeleteContents(true); + list->Clear(); + list->DeleteContents(fDelState); + + wxXmlNode *listNode = source->GetChildren(); + while(listNode) + { + if(listNode->GetName() == wxT("item")) + { + list->Append(new wxRealPoint(xsRealPointPropIO::FromString(listNode->GetNodeContent()))); + } + + listNode = listNode->GetNext(); + } +} + +void xsListRealPointPropIO::Write(xsProperty *property, wxXmlNode *target) +{ + RealPointList *list = (RealPointList*)property->m_pSourceVariable; + + if( !list->IsEmpty() ) + { + wxXmlNode *newNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("property")); + RealPointList::compatibility_iterator listNode = list->GetFirst(); + while(listNode) + { + AddPropertyNode(newNode, wxT("item"), xsRealPointPropIO::ToString(*(wxRealPoint*)listNode->GetData())); + listNode = listNode->GetNext(); + } + + target->AddChild(newNode); + AppendPropertyType(property, newNode); + } +} + +wxString xsListRealPointPropIO::GetValueStr(xsProperty *property) +{ + return ToString(*((RealPointList*)property->m_pSourceVariable)); +} + +void xsListRealPointPropIO::SetValueStr(xsProperty *property, const wxString& valstr) +{ + *((RealPointList*)property->m_pSourceVariable) = FromString(valstr); +} + +wxString xsListRealPointPropIO::ToString(const RealPointList& value) +{ + wxString out; + + RealPointList::compatibility_iterator node = value.GetFirst(); + while( node ) + { + out << xsRealPointPropIO::ToString(*(wxRealPoint*)node->GetData()); + if( node != value.GetLast() ) out << wxT("|"); + + node = node->GetNext(); + } + + return out; +} + +RealPointList xsListRealPointPropIO::FromString(const wxString& value) +{ + RealPointList lstData; + + wxStringTokenizer tokens( value, wxT("|") ); + while( tokens.HasMoreTokens() ) + { + lstData.Append( new wxRealPoint(xsRealPointPropIO::FromString( tokens.GetNextToken() )) ); + } + + return lstData; +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsDynObjPropIO class ///////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC_CLASS(xsDynObjPropIO, xsPropertyIO); + +void xsDynObjPropIO::Read(xsProperty *property, wxXmlNode *source) +{ + wxXmlNode *objectNode = source->GetChildren(); + + if( objectNode && (objectNode->GetName() == wxT("object")) ) + { + *(xsSerializable**)(property->m_pSourceVariable) = (xsSerializable*)wxCreateDynamicObject(objectNode->GetAttribute(wxT("type"), wxT(""))); + + xsSerializable* object = *(xsSerializable**)(property->m_pSourceVariable); + if(object) + { + object->DeserializeObject(objectNode); + } + } +} + +void xsDynObjPropIO::Write(xsProperty *property, wxXmlNode *target) +{ + xsSerializable* object = *(xsSerializable**)(property->m_pSourceVariable); + + if( object && object->IsKindOf(CLASSINFO(xsSerializable))) + { + wxXmlNode *newNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("property")); + newNode->AddChild(object->SerializeObject(NULL)); + + target->AddChild(newNode); + AppendPropertyType(property, newNode); + } +} + +wxString xsDynObjPropIO::GetValueStr(xsProperty *property) +{ + return ToString(**(xsSerializable**)(property->m_pSourceVariable)); +} + +void xsDynObjPropIO::SetValueStr(xsProperty *property, const wxString& valstr) +{ + **((xsSerializable**)property->m_pSourceVariable) = FromString(valstr); +} + +wxString xsDynObjPropIO::ToString(const xsSerializable& value) +{ + return wxString::Format(wxT("Dynamic object at address 0x%x"), &value); +} + +xsSerializable xsDynObjPropIO::FromString(const wxString& value) +{ + wxUnusedVar( value ); + + return xsSerializable(); +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsDynNCObjPropIO class /////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC_CLASS(xsDynNCObjPropIO, xsPropertyIO); + +void xsDynNCObjPropIO::Read(xsProperty *property, wxXmlNode *source) +{ + wxXmlNode *objectNode = source->GetChildren(); + + if( objectNode && (objectNode->GetName() == wxT("object")) ) + { + xsSerializable* object = *(xsSerializable**)(property->m_pSourceVariable); + if(object) + { + object->DeserializeObject(objectNode); + } + } +} + +void xsDynNCObjPropIO::Write(xsProperty *property, wxXmlNode *target) +{ + xsSerializable* object = *(xsSerializable**)(property->m_pSourceVariable); + + if( object && object->IsKindOf(CLASSINFO(xsSerializable))) + { + wxXmlNode *newNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("property")); + newNode->AddChild(object->SerializeObject(NULL)); + + target->AddChild(newNode); + AppendPropertyType(property, newNode); + } +} + +wxString xsDynNCObjPropIO::GetValueStr(xsProperty *property) +{ + return ToString(**(xsSerializable**)(property->m_pSourceVariable)); +} + +void xsDynNCObjPropIO::SetValueStr(xsProperty *property, const wxString& valstr) +{ + **((xsSerializable**)property->m_pSourceVariable) = FromString(valstr); +} + +wxString xsDynNCObjPropIO::ToString(const xsSerializable& value) +{ + return wxString::Format(wxT("Dynamic object at address 0x%x"), &value); +} + +xsSerializable xsDynNCObjPropIO::FromString(const wxString& value) +{ + wxUnusedVar( value ); + + return xsSerializable(); +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsStaticObjPropIO class ////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC_CLASS(xsStaticObjPropIO, xsPropertyIO); + +void xsStaticObjPropIO::Read(xsProperty *property, wxXmlNode *source) +{ + wxXmlNode *objectNode = source->GetChildren(); + + if( objectNode && (objectNode->GetName() == wxT("object")) ) + { + (*((xsSerializable*)property->m_pSourceVariable)).DeserializeObject(objectNode); + } +} + +void xsStaticObjPropIO::Write(xsProperty *property, wxXmlNode *target) +{ + wxXmlNode *newNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("property")); + newNode->AddChild((*((xsSerializable*)property->m_pSourceVariable)).SerializeObject(NULL)); + + target->AddChild(newNode); + AppendPropertyType(property, newNode); +} + +wxString xsStaticObjPropIO::GetValueStr(xsProperty *property) +{ + return ToString(*(xsSerializable*)property->m_pSourceVariable); +} + +void xsStaticObjPropIO::SetValueStr(xsProperty *property, const wxString& valstr) +{ + *((xsSerializable*)property->m_pSourceVariable) = FromString(valstr); +} + +wxString xsStaticObjPropIO::ToString(const xsSerializable& value) +{ + return wxString::Format(wxT("Static object at address 0x%x"), &value); +} + +xsSerializable xsStaticObjPropIO::FromString(const wxString& value) +{ + wxUnusedVar( value ); + + return xsSerializable(); +} + +///////////////////////////////////////////////////////////////////////////////////// +// xsMapStringPropIO class //////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC_CLASS(xsMapStringPropIO, xsPropertyIO); + +void xsMapStringPropIO::Read(xsProperty *property, wxXmlNode *source) +{ + ((StringMap*)property->m_pSourceVariable)->clear(); + + wxXmlNode *listNode = source->GetChildren(); + while(listNode) + { + if(listNode->GetName() == wxT("item")) + { + (*(StringMap*)property->m_pSourceVariable)[listNode->GetAttribute( wxT("key"), wxT("undef_key") )] = listNode->GetNodeContent(); + } + + listNode = listNode->GetNext(); + } +} + +void xsMapStringPropIO::Write(xsProperty *property, wxXmlNode *target) +{ + StringMap& map = *((StringMap*)property->m_pSourceVariable); + + if( !map.empty() ) + { + wxXmlNode *pXmlNode, *newNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("property")); + StringMap::iterator it; + + for( it = map.begin(); it != map.end(); ++it ) + { + wxString key = it->first, value = it->second; + pXmlNode = AddPropertyNode(newNode, wxT("item"), it->second); + pXmlNode->AddAttribute(wxT("key"), it->first); + } + + target->AddChild(newNode); + AppendPropertyType(property, newNode); + } +} + +wxString xsMapStringPropIO::GetValueStr(xsProperty *property) +{ + return ToString(*((StringMap*)property->m_pSourceVariable)); +} + +void xsMapStringPropIO::SetValueStr(xsProperty *property, const wxString& valstr) +{ + *((StringMap*)property->m_pSourceVariable) = FromString(valstr); +} + +wxString xsMapStringPropIO::ToString(const StringMap& value) +{ + wxString out; + + StringMap::const_iterator it; + + for( it = value.begin(); it != value.end(); ++it ) + { + if( it != value.begin() ) out << wxT("|"); + out << it->first << wxT("->") << it->second; + } + + return out; +} + +StringMap xsMapStringPropIO::FromString(const wxString& value) +{ + StringMap mapData; + + wxString token; + wxStringTokenizer tokens( value, wxT("|") ); + while( tokens.HasMoreTokens() ) + { + token = tokens.GetNextToken(); + token.Replace(wxT("->"), wxT("|")); + mapData[token.BeforeFirst(wxT('|'))] = token.AfterFirst(wxT('|')); + } + + return mapData; +} + diff --git a/ThirdParty/wxXS/src/XmlSerializer.cpp b/ThirdParty/wxXS/src/XmlSerializer.cpp new file mode 100644 index 0000000..33264e9 --- /dev/null +++ b/ThirdParty/wxXS/src/XmlSerializer.cpp @@ -0,0 +1,974 @@ +/*************************************************************** + * Name: XmlSerializer.cpp + * Purpose: Implements XML serializer and related classes + * Author: Michal Bližňák (michal.bliznak@tiscali.cz) + * Created: 2007-08-28 + * Copyright: Michal Bližňák + * License: wxWidgets license (www.wxwidgets.org) + * Notes: + **************************************************************/ + +#include "wx_pch.h" + +#ifdef _DEBUG_MSVC +#define new DEBUG_NEW +#endif + +#include "wx/wxxmlserializer/XmlSerializer.h" + +#include +#include +#include + +WX_DEFINE_EXPORTED_LIST(PropertyList); +WX_DEFINE_EXPORTED_LIST(SerializableList); + +// static members +PropertyIOMap wxXmlSerializer::m_mapPropertyIOHandlers; +int wxXmlSerializer::m_nRefCounter = 0; +wxString wxXmlSerializer::m_sLibraryVersion = wxT("1.3.1 beta"); + +///////////////////////////////////////////////////////////////////////////////////// +// xsProperty class ///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC_CLASS(xsProperty, wxObject); + +///////////////////////////////////////////////////////////////////////////////////// +// xsSerializable class ///////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_IMPLEMENT_CLONABLE_CLASS(xsSerializable, wxObject); + +// constructor and destructor /////////////////////////////////////////////////////// + +xsSerializable::xsSerializable() +{ + m_pParentManager = NULL; + m_pParentItem = NULL; + m_fSerialize = true; + m_fClone = true; + m_nId = -1; + + XS_SERIALIZE(m_nId, wxT("id")); +} + +xsSerializable::xsSerializable(const xsSerializable& obj) +: wxObject(obj) +{ + m_pParentManager = NULL; + m_pParentItem = NULL; + m_fSerialize = obj.m_fSerialize; + m_fClone = obj.m_fClone; + m_nId = obj.m_nId; + + XS_SERIALIZE(m_nId, wxT("id")); + + // copy serialized children as well + SerializableList::compatibility_iterator node = obj.GetFirstChildNode(); + while( node ) + { + if( node->GetData()->IsSerialized() ) AddChild( (xsSerializable*)node->GetData()->Clone() ); + node = node->GetNext(); + } +} + +xsSerializable::~xsSerializable() +{ + if( m_pParentManager ) + { + m_pParentManager->GetUsedIDs().erase( m_nId ); + } + + m_lstProperties.DeleteContents(true); + m_lstProperties.Clear(); + + m_lstChildItems.DeleteContents(true); + m_lstChildItems.Clear(); +} + +// public functions ///////////////////////////////////////////////////////////////// + +void xsSerializable::SetId(long id) +{ + m_nId = id; + + if( m_pParentManager ) m_pParentManager->GetUsedIDs()[id] = this; +} + +xsSerializable* xsSerializable::AddChild(xsSerializable* child) +{ + wxASSERT(child); + + if( child ) + { + InitChild( child ); + + m_lstChildItems.Append(child); + } + + return child; +} + +xsSerializable* xsSerializable::InsertChild(size_t pos, xsSerializable* child) +{ + wxASSERT(child); + + if( child ) + { + InitChild( child ); + + m_lstChildItems.Insert(pos, child); + } + + return child; +} + +void xsSerializable::Reparent(xsSerializable* parent) +{ + if(m_pParentItem) + { + m_pParentItem->m_lstChildItems.DeleteObject(this); + } + + if(parent) + { + parent->AddChild(this); + } + else + m_pParentItem = NULL; +} + +xsSerializable* xsSerializable::GetFirstChild() +{ + SerializableList::compatibility_iterator node = m_lstChildItems.GetFirst(); + if( node )return node->GetData(); + else + return NULL; +} + +xsSerializable* xsSerializable::GetFirstChild(wxClassInfo *type) +{ + SerializableList::compatibility_iterator node = m_lstChildItems.GetFirst(); + while( node ) + { + if( node->GetData()->IsKindOf( type ) ) return node->GetData(); + node = node->GetNext(); + } + return NULL; +} + +xsSerializable* xsSerializable::GetLastChild() +{ + SerializableList::compatibility_iterator node = m_lstChildItems.GetLast(); + if( node )return node->GetData(); + else + return NULL; +} + +xsSerializable* xsSerializable::GetLastChild(wxClassInfo *type) +{ + SerializableList::compatibility_iterator node = m_lstChildItems.GetLast(); + while( node ) + { + if( node->GetData()->IsKindOf( type ) ) return node->GetData(); + node = node->GetPrevious(); + } + return NULL; +} + +xsSerializable* xsSerializable::GetSibbling() +{ + wxASSERT( m_pParentItem ); + + if( m_pParentItem ) + { + SerializableList::compatibility_iterator node = m_pParentItem->GetChildrenList().Find( this ); + if( node ) + { + if( node->GetNext() ) return node->GetNext()->GetData(); + } + } + + return NULL; +} + +xsSerializable* xsSerializable::GetSibbling(wxClassInfo *type) +{ + wxASSERT( m_pParentItem ); + + if( m_pParentItem ) + { + SerializableList::compatibility_iterator node = m_pParentItem->GetChildrenList().Find( this ); + while( node ) + { + node = node->GetNext(); + + if( node && (node->GetData()->IsKindOf( type ) ) ) return node->GetData(); + } + } + + return NULL; +} + + +xsSerializable* xsSerializable::GetChild(long id, bool recursive) +{ + SerializableList lstChildren; + SerializableList::compatibility_iterator node; + + if( recursive ) + { + GetChildrenRecursively( CLASSINFO(xsSerializable), lstChildren ); + node = lstChildren.GetFirst(); + } + else + node = m_lstChildItems.GetFirst(); + + while(node) + { + if( node->GetData()->GetId() == id) return node->GetData(); + node = node->GetNext(); + } + + return NULL; +} + +void xsSerializable::GetChildren(wxClassInfo *type, SerializableList& list) +{ + xsSerializable *pChild; + + SerializableList::compatibility_iterator node = m_lstChildItems.GetFirst(); + while(node) + { + pChild = node->GetData(); + + if( !type || pChild->IsKindOf(type) ) list.Append(pChild); + + node = node->GetNext(); + } +} + +void xsSerializable::GetChildrenRecursively(wxClassInfo *type, SerializableList& list, SEARCHMODE mode) +{ + xsSerializable *pChild; + + SerializableList::compatibility_iterator node = m_lstChildItems.GetFirst(); + while(node) + { + pChild = node->GetData(); + if( !type || pChild->IsKindOf(type) ) list.Append(pChild); + if( mode == searchDFS ) pChild->GetChildrenRecursively(type, list); + + node = node->GetNext(); + } + + if( mode == searchBFS ) + { + node = m_lstChildItems.GetFirst(); + while(node) + { + node->GetData()->GetChildrenRecursively(type, list); + node = node->GetNext(); + } + } +} + +void xsSerializable::AddProperty(xsProperty* property) +{ + if(property) + { + if(!GetProperty(property->m_sFieldName)) + { + m_lstProperties.Append(property); + } + } +} + +void xsSerializable::RemoveProperty(xsProperty* property) +{ + if( property ) + { + m_lstProperties.DeleteObject( property ); + delete property; + } +} + +xsProperty* xsSerializable::GetProperty(const wxString& field) +{ + PropertyList::compatibility_iterator node = m_lstProperties.GetFirst(); + while(node) + { + if(node->GetData()->m_sFieldName == field)return node->GetData(); + node = node->GetNext(); + } + return NULL; +} + +void xsSerializable::EnablePropertySerialization(const wxString& field, bool enab) +{ + xsProperty* property = GetProperty(field); + if(property) + { + property->m_fSerialize = enab; + } +} + +bool xsSerializable::IsPropertySerialized(const wxString& field) +{ + xsProperty* property = GetProperty(field); + if(property) + { + return property->m_fSerialize; + } + return false; +} + +wxXmlNode* xsSerializable::SerializeObject(wxXmlNode* node) +{ + if(!node || (node->GetName() != wxT("object"))) + { + node = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("object")); + node->AddAttribute(new wxXmlAttribute(wxT("type"), this->GetClassInfo()->GetClassName())); + } + + if(node) return this->Serialize(node); + else + return NULL; +} + +void xsSerializable::DeserializeObject(wxXmlNode* node) +{ + if(node && (node->GetName()==wxT("object"))) + { + this->Deserialize(node); + } +} + +// overloaded operators ///////////////////////////////////////////////////////////// + +xsSerializable* xsSerializable::operator<<( xsSerializable *child ) +{ + if( child && (child != this ) ) + { + return this->AddChild( child ); + } + else + return this; +} + +// protected functions ////////////////////////////////////////////////////////////// + +wxXmlNode* xsSerializable::Serialize(wxXmlNode* node) +{ + xsProperty* property; + xsPropertyIO* ioHandler; + + PropertyList::compatibility_iterator propNode = m_lstProperties.GetFirst(); + while(propNode) + { + property = propNode->GetData(); + + if(property->m_fSerialize) + { + ioHandler = wxXmlSerializer::m_mapPropertyIOHandlers[property->m_sDataType]; + if(ioHandler) + { + ioHandler->Write(property, node); + } + } + + propNode = propNode->GetNext(); + } + + return node; +} + +void xsSerializable::Deserialize(wxXmlNode* node) +{ + wxASSERT(node); + if(!node)return; + + xsProperty* property; + xsPropertyIO* ioHandler; + wxString propName; + + wxXmlNode *xmlNode = node->GetChildren(); + while(xmlNode) + { + if(xmlNode->GetName() == wxT("property")) + { + xmlNode->GetAttribute(wxT("name"), &propName); + property = GetProperty(propName); + + if(property) + { + ioHandler = wxXmlSerializer::m_mapPropertyIOHandlers[property->m_sDataType]; + if(ioHandler) + { + ioHandler->Read(property, xmlNode); + } + } + } + + xmlNode = xmlNode->GetNext(); + } +} + +void xsSerializable::InitChild(xsSerializable* child) +{ + if( child ) + { + child->m_pParentItem = this; + + if( m_pParentManager ) + { + if( child->m_pParentManager != m_pParentManager ) + { + child->m_pParentManager = m_pParentManager; + + // assign unique ids to the child object + if( child->GetId() == -1 ) child->SetId(m_pParentManager->GetNewId()); + else + m_pParentManager->GetUsedIDs()[child->GetId()] = child; + + // if the child has another children, set their parent manager and ID as well + xsSerializable *pItem; + SerializableList lstChildren; + child->GetChildrenRecursively( NULL, lstChildren ); + + SerializableList::compatibility_iterator node = lstChildren.GetFirst(); + while( node ) + { + pItem = node->GetData(); + + pItem->SetParentManager( m_pParentManager ); + + if( pItem->GetId() == -1 ) pItem->SetId(m_pParentManager->GetNewId()); + else + m_pParentManager->GetUsedIDs()[pItem->GetId()] = pItem; + + node = node->GetNext(); + } + } + } + } +} + +///////////////////////////////////////////////////////////////////////////////////// +// wxXmlSerializer class //////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +XS_IMPLEMENT_CLONABLE_CLASS(wxXmlSerializer, wxObject); + +// constructor and destructor /////////////////////////////////////////////////////// + +wxXmlSerializer::wxXmlSerializer() +{ + m_sOwner = wxT(""); + m_sRootName = wxT("root"); + m_sVersion = wxT(""); + m_fClone = true; + + m_pRoot = NULL; + SetRootItem(new xsSerializable()); + + if(m_nRefCounter == 0) + { + InitializeAllIOHandlers(); + } + m_nRefCounter++; +} + +wxXmlSerializer::wxXmlSerializer(const wxXmlSerializer &obj) +: wxObject(obj) +{ + m_sOwner = obj.m_sOwner; + m_sRootName = obj.m_sRootName; + m_sVersion = obj.m_sVersion; + m_fClone = obj.m_fClone; + + m_pRoot = NULL; + + SetRootItem((xsSerializable*)obj.m_pRoot->Clone()); + + m_nRefCounter++; +} + +wxXmlSerializer::wxXmlSerializer(const wxString& owner, const wxString& root, const wxString& version) +{ + m_sOwner = owner; + m_sRootName = root; + m_sVersion = version; + m_fClone = true; + + m_pRoot = NULL; + SetRootItem(new xsSerializable()); + + if(m_nRefCounter == 0) + { + InitializeAllIOHandlers(); + } + m_nRefCounter++; +} + +wxXmlSerializer::~wxXmlSerializer() +{ + if( m_pRoot ) delete m_pRoot; + + m_nRefCounter--; + if(m_nRefCounter == 0) + { + ClearIOHandlers(); + } +} + +// public functions ////////////////////////////////////////////////////////////////// + +void wxXmlSerializer::InitializeAllIOHandlers() +{ + ClearIOHandlers(); + + XS_REGISTER_IO_HANDLER(wxT("string"), xsStringPropIO); + XS_REGISTER_IO_HANDLER(wxT("char"), xsCharPropIO); + XS_REGISTER_IO_HANDLER(wxT("int"), xsIntPropIO); + XS_REGISTER_IO_HANDLER(wxT("long"), xsLongPropIO); + XS_REGISTER_IO_HANDLER(wxT("float"), xsFloatPropIO); + XS_REGISTER_IO_HANDLER(wxT("double"), xsDoublePropIO); + XS_REGISTER_IO_HANDLER(wxT("bool"), xsBoolPropIO); + XS_REGISTER_IO_HANDLER(wxT("point"), xsPointPropIO); + XS_REGISTER_IO_HANDLER(wxT("size"), xsSizePropIO); + XS_REGISTER_IO_HANDLER(wxT("realpoint"), xsRealPointPropIO); + XS_REGISTER_IO_HANDLER(wxT("colour"), xsColourPropIO); + XS_REGISTER_IO_HANDLER(wxT("brush"), xsBrushPropIO); + XS_REGISTER_IO_HANDLER(wxT("pen"), xsPenPropIO); + XS_REGISTER_IO_HANDLER(wxT("font"), xsFontPropIO); + XS_REGISTER_IO_HANDLER(wxT("arraystring"), xsArrayStringPropIO); + XS_REGISTER_IO_HANDLER(wxT("arraychar"), xsArrayCharPropIO); + XS_REGISTER_IO_HANDLER(wxT("arrayint"), xsArrayIntPropIO); + XS_REGISTER_IO_HANDLER(wxT("arraylong"), xsArrayLongPropIO); + XS_REGISTER_IO_HANDLER(wxT("arraydouble"), xsArrayDoublePropIO); + XS_REGISTER_IO_HANDLER(wxT("arrayrealpoint"), xsArrayRealPointPropIO); + XS_REGISTER_IO_HANDLER(wxT("mapstring"), xsMapStringPropIO); + XS_REGISTER_IO_HANDLER(wxT("listrealpoint"), xsListRealPointPropIO); + XS_REGISTER_IO_HANDLER(wxT("serializablestatic"), xsStaticObjPropIO); + XS_REGISTER_IO_HANDLER(wxT("serializabledynamic"), xsDynObjPropIO); + XS_REGISTER_IO_HANDLER(wxT("serializabledynamicnocreate"), xsDynNCObjPropIO); +} + +void wxXmlSerializer::ClearIOHandlers() +{ + PropertyIOMap::iterator it = m_mapPropertyIOHandlers.begin(); + while(it != m_mapPropertyIOHandlers.end()) + { + if(it->second)delete it->second; + it++; + } + m_mapPropertyIOHandlers.clear(); +} + +xsSerializable* wxXmlSerializer::GetItem(long id) +{ + if( m_pRoot ) + { + IDMap::iterator it = m_mapUsedIDs.find( id ); + if( it != m_mapUsedIDs.end() ) return it->second; + } + + return NULL; +} + +bool wxXmlSerializer::Contains(xsSerializable *object) const +{ + if( m_pRoot ) + { + return _Contains(object, m_pRoot); + } + + return false; +} + +bool wxXmlSerializer::Contains(wxClassInfo *type) +{ + SerializableList lstItems; + + GetItems( type, lstItems ); + + return !lstItems.IsEmpty(); +} + +void wxXmlSerializer::GetItems(wxClassInfo* type, SerializableList& list, xsSerializable::SEARCHMODE mode) +{ + if( m_pRoot ) + { + m_pRoot->GetChildrenRecursively(type, list, mode); + } +} + +void wxXmlSerializer::CopyItems(const wxXmlSerializer& src) +{ + // clear current content + m_pRoot->GetChildrenList().DeleteContents( true ); + m_pRoot->GetChildrenList().Clear(); + m_pRoot->GetChildrenList().DeleteContents( false ); + + m_mapUsedIDs.clear(); + + SerializableList::compatibility_iterator node = src.GetRootItem()->GetFirstChildNode(); + while( node ) + { + AddItem( m_pRoot, (xsSerializable*)node->GetData()->Clone() ); + node = node->GetNext(); + } +} + +xsSerializable* wxXmlSerializer::AddItem(long parentId, xsSerializable* item) +{ + return AddItem(GetItem(parentId), item); +} + +xsSerializable* wxXmlSerializer::AddItem(xsSerializable* parent, xsSerializable* item) +{ + wxASSERT(m_pRoot); + wxASSERT(item); + + if( item ) + { + if( parent )parent->AddChild(item); + else + m_pRoot->AddChild(item); + } + + return item; +} + +void wxXmlSerializer::RemoveItem(long id) +{ + RemoveItem(GetItem(id)); +} + +void wxXmlSerializer::RemoveItem(xsSerializable* item) +{ + wxASSERT(item); + + if(item) + { + if( item->GetParent() ) + { + item->GetParent()->GetChildrenList().DeleteObject(item); + } + delete item; + } +} + +void wxXmlSerializer::RemoveAll() +{ + SetRootItem(new xsSerializable()); +} + +void wxXmlSerializer::SetRootItem(xsSerializable* root, bool bDeleteCurrentRoot /*= true*/) +{ + //wxASSERT(root); + //wxASSERT(root->IsKindOf(CLASSINFO(xsSerializable))); + + if (m_pRoot && bDeleteCurrentRoot) + delete m_pRoot; + + if(root && root->IsKindOf(CLASSINFO(xsSerializable))) + { + m_pRoot = root; + } + else + m_pRoot = new xsSerializable(); + + // update pointers to parent manager + m_mapUsedIDs.clear(); + + m_pRoot->m_pParentManager = this; + m_mapUsedIDs[m_pRoot->GetId()] = m_pRoot; + + xsSerializable *pItem; + SerializableList lstItems; + GetItems(NULL, lstItems); + + SerializableList::compatibility_iterator node = lstItems.GetFirst(); + while( node ) + { + pItem = node->GetData(); + + pItem->m_pParentManager = this; + m_mapUsedIDs[pItem->GetId()] = pItem; + + node = node->GetNext(); + } +} + +bool wxXmlSerializer::SerializeToXml(const wxString& file, bool withroot) +{ + wxFileOutputStream outstream(file); + + if(outstream.IsOk()) + { + return this->SerializeToXml(outstream, withroot); + } + else + wxMessageBox(wxT("Unable to initialize output file stream."), m_sOwner, wxOK|wxICON_ERROR); + + return false; +} + +bool wxXmlSerializer::SerializeToXml(wxOutputStream& outstream, bool withroot) +{ + // create root node + wxXmlNode *root = new wxXmlNode(wxXML_ELEMENT_NODE, m_sRootName); + + if(root) + { + // add version + root->AddAttribute(wxT("owner"), m_sOwner); + root->AddAttribute(wxT("version"), m_sVersion); + + // serialize root item properties + if(withroot) + { + wxXmlNode *root_props = new wxXmlNode(wxXML_ELEMENT_NODE, m_sRootName + wxT("_properties")); + root_props->AddChild(m_pRoot->SerializeObject(NULL)); + root->AddChild(root_props); + } + + // serialize shapes recursively + this->SerializeObjects(m_pRoot, root, false); + + // create XML document + try + { + wxXmlDocument xmlDoc; + xmlDoc.SetRoot(root); + + xmlDoc.Save(outstream, 2); + } + catch (...) + { + wxMessageBox(wxT("Unable to save XML document."), m_sOwner, wxOK|wxICON_ERROR); + return false; + } + } + + return true; +} + +bool wxXmlSerializer::DeserializeFromXml(const wxString& file) +{ + wxFileInputStream instream(file); + + if(instream.IsOk()) + { + return this->DeserializeFromXml(instream); + } + else + wxMessageBox(wxT("Unable to initialize input stream."), m_sOwner, wxOK|wxICON_ERROR); + + return false; +} + +bool wxXmlSerializer::DeserializeFromXml(wxInputStream& instream) +{ + // load an XML file + try + { + wxXmlDocument xmlDoc; + xmlDoc.Load(instream); + + wxXmlNode* root = xmlDoc.GetRoot(); + if(root && (root->GetName() == m_sRootName)) + { + // read project node's properties here... + wxString version, owner; + root->GetAttribute(wxT("owner"), &owner); + root->GetAttribute(wxT("version"), &version); + + if( (owner == m_sOwner) && (version == m_sVersion) ) + { + // read shape objects from XML recursively + this->DeserializeObjects(NULL, root); + return true; + } + else + wxMessageBox(wxT("No matching file owner or version."), m_sOwner, wxOK|wxICON_WARNING); + } + else + wxMessageBox(wxT("Unknown file format."), m_sOwner, wxOK|wxICON_WARNING); + } + catch (...) + { + wxMessageBox(wxT("Unable to load XML file."), m_sOwner, wxOK|wxICON_ERROR); + } + + return false; +} + +void wxXmlSerializer::SerializeObjects(xsSerializable* parent, wxXmlNode* node, bool withparent) +{ + wxASSERT(parent); + if(!parent)return; + + wxXmlNode* projectNode = NULL; + xsSerializable* pChild; + + // serialize parent shape + if(withparent) + { + if(parent->IsSerialized()) + { + projectNode = parent->SerializeObject(NULL); + if(projectNode) + { + SerializeObjects(parent, projectNode, false); + node->AddChild(projectNode); + } + } + } + else + { + // serialize parent's children + SerializableList::compatibility_iterator snode = parent->GetChildrenList().GetFirst(); + while(snode) + { + pChild = snode->GetData(); + + if(pChild->IsSerialized()) + { + projectNode = pChild->SerializeObject(NULL); + if(projectNode) + { + SerializeObjects(pChild, projectNode, false); + node->AddChild(projectNode); + } + } + + snode = snode->GetNext(); + } + } +} + +void wxXmlSerializer::DeserializeObjects(xsSerializable* parent, wxXmlNode* node) +{ + wxASSERT(m_pRoot); + if(!m_pRoot)return; + + xsSerializable *pItem; + + wxXmlNode* projectNode = node->GetChildren(); + while(projectNode) + { + if(projectNode->GetName() == wxT("object")) + { + pItem = (xsSerializable*)wxCreateDynamicObject(projectNode->GetAttribute(wxT("type"), wxT(""))); + if(pItem) + { + if(parent) + { + parent->AddChild(pItem); + } + else + m_pRoot->AddChild(pItem); + + pItem->DeserializeObject(projectNode); + // id could change so we must update the IDs map + m_mapUsedIDs[pItem->GetId()] = pItem; + + // deserialize child objects + DeserializeObjects(pItem, projectNode); + } + } + else if(projectNode->GetName() == m_sRootName + wxT("_properties")) + { + m_pRoot->DeserializeObject(projectNode->GetChildren()); + } + + projectNode = projectNode->GetNext(); + } +} + +bool wxXmlSerializer::IsIdUsed(long id) +{ + //return (GetIDCount(id) > 0); + return (m_mapUsedIDs.find( id ) != m_mapUsedIDs.end()); +} + +int wxXmlSerializer::GetIDCount(long id) +{ + int nCount = 0; + + SerializableList items; + GetItems(CLASSINFO(xsSerializable), items); + + SerializableList::compatibility_iterator node = items.GetFirst(); + while(node) + { + if( node->GetData()->GetId() == id ) nCount++; + node = node->GetNext(); + } + + if( m_pRoot->GetId() == id ) nCount++; + + return nCount; +} + +long wxXmlSerializer::GetNewId() +{ +/* long nId = 1; + + for ( IDMap::iterator it = m_mapUsedIDs.begin(); it != m_mapUsedIDs.end(); it++, nId++ ) + { + if (it->first != nId) break; + } + + return nId;*/ + + long nId = 1; + + while( m_mapUsedIDs.find( nId ) != m_mapUsedIDs.end() ) nId++; + + return nId; +} + +// private virtual functions /////////////////////////////////////////////////////// + +xsSerializable* wxXmlSerializer::_GetItem(long id, xsSerializable* parent) +{ + wxASSERT(parent); + + if( !parent )return NULL; + + if( parent->GetId() == id )return parent; + + xsSerializable *pItem = NULL; + SerializableList::compatibility_iterator node = parent->GetChildrenList().GetFirst(); + while(node) + { + pItem = _GetItem(id, node->GetData()); + if( pItem )break; + node = node->GetNext(); + } + return pItem; +} + +bool wxXmlSerializer::_Contains(xsSerializable* object, xsSerializable* parent) const +{ + wxASSERT(parent); + + if( !parent )return false; + + if( parent == object )return true; + + bool fFound = false; + SerializableList::compatibility_iterator node = parent->GetChildrenList().GetFirst(); + while(node) + { + fFound = _Contains(object, node->GetData()); + if( fFound )break; + node = node->GetNext(); + } + return fFound; +} diff --git a/ThirdParty/wxXS/src/wx_pch.cpp b/ThirdParty/wxXS/src/wx_pch.cpp new file mode 100644 index 0000000..ed9c389 --- /dev/null +++ b/ThirdParty/wxXS/src/wx_pch.cpp @@ -0,0 +1 @@ +#include "wx_pch.h" diff --git a/ThirdParty/wxXS/src/wx_pch.h b/ThirdParty/wxXS/src/wx_pch.h new file mode 100644 index 0000000..d2fb6a9 --- /dev/null +++ b/ThirdParty/wxXS/src/wx_pch.h @@ -0,0 +1,43 @@ +/*************************************************************** + * Name: wx_pch.h + * Purpose: Header to create Pre-Compiled Header (PCH) + * Author: Michal Bližňák () + * Created: 2007-03-04 + * Copyright: Michal Bližňák () + * License: + **************************************************************/ + +#ifndef WX_PCH_H_INCLUDED +#define WX_PCH_H_INCLUDED + +#ifdef _DISWARNINGS_MSVC +//#pragma warning( disable : 4100 ) +#pragma warning( disable : 4251 ) +#pragma warning( disable : 4275 ) +#endif + +// basic wxWidgets headers +#include + +#ifdef _DEBUG_MSVC +#ifdef _DEBUG +#include +#define DEBUG_NEW new(_NORMAL_BLOCK ,__FILE__, __LINE__) +#else +#define DEBUG_NEW new +#endif +#endif + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include +#endif + +#ifdef WX_PRECOMP + // put here all your rarely-changing header files +#endif // WX_PRECOMP + +#endif // WX_PCH_H_INCLUDED diff --git a/Utils/BlobToJSONFormatter.cpp b/Utils/BlobToJSONFormatter.cpp new file mode 100644 index 0000000..6cd394c --- /dev/null +++ b/Utils/BlobToJSONFormatter.cpp @@ -0,0 +1,46 @@ +#include "stdwx.h" +#include +#include +#include "JSONObjectFactory.h" +#include "BlobToJSONFormatter.h" + +wxString BlobToJSONFormatter::Format(iFloorBlobVector & blobs) +{ + wxString result; + + wxJSONValue root = JSONObjectFactory::Create(JSON_ACTION_BLOBS); + if (blobs.size() > 0) + { + // This should resize the array of items inside root["b"] + auto & blobRoot = root["b"]; + auto & tmp = blobRoot[blobs.size() - 1]; + + #pragma omp parallel for shared(root) + for (auto i = 0; i < blobs.size(); i++) + { + auto & item = blobRoot[i]; + item["c"]["x"] = static_cast(blobs[i].centroid.x); + item["c"]["y"] = static_cast(blobs[i].centroid.y); + item["l"]["x"] = static_cast(blobs[i].lastCentroid.x); + item["l"]["y"] = static_cast(blobs[i].lastCentroid.y); + auto pointsCount = blobs[i].pts.size(); + // This should resize the array of point coords + auto & pointRoot = item["p"]; + auto & tmp1 = pointRoot[pointsCount - 1]; + for (auto j = 0; j < pointsCount; ++j) + { + pointRoot[j]["x"] = static_cast(blobs[i].pts[j].x); + pointRoot[j]["y"] = static_cast(blobs[i].pts[j].y); + } + } + } + else + { + wxJSONValue null; + root["b"] = null; + } + wxJSONWriter writer(wxJSONWRITER_NONE); + writer.Write(root, result); + result.Replace(" ", ""); + return result; +} \ No newline at end of file diff --git a/Utils/BlobToJSONFormatter.h b/Utils/BlobToJSONFormatter.h new file mode 100644 index 0000000..a1bec70 --- /dev/null +++ b/Utils/BlobToJSONFormatter.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +#define JSON_ACTION_BLOBS wxT("blobs") + +class BlobToJSONFormatter +{ +public: + static wxString Format(iFloorBlobVector & blobs); +}; \ No newline at end of file diff --git a/Utils/CMakeLists.txt b/Utils/CMakeLists.txt new file mode 100644 index 0000000..3a509c7 --- /dev/null +++ b/Utils/CMakeLists.txt @@ -0,0 +1,46 @@ +# +# Stuff the average programmer needs to change +# +set(SRCS + wxFPValidator.cpp + MACAddressUtility.cpp + Guid.cpp + BlobToJSONFormatter.cpp + JSONObjectFactory.cpp +) +set(HFILES + wxFPValidator.h + wxMACAddressUtility.h + MACAddressUtility.h + wxTemplateClientData.h + Guid.h + BlobToJSONFormatter.h + JSONObjectFactory.h +) + + +set(INCLUDE_DIRECTORIES ${BASE_INCLUDE_DIRECTORIES} + ${THIRD_PARTY_DIR}/wxJSON/include + ${THIRD_PARTY_DIR}/MotionPrimitives) +set(LIBRARY_NAME Utils) +if(WIN32) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D_LIB) +endif(WIN32) +set(SRCS ${SRCS} ${HFILES} ${PROJECT_ROOT_DIR}/include/stdwx.cpp ${PROJECT_ROOT_DIR}/include/stdwx.h) + +# +# Non Builds programmer should not need to change anything beyond this +# + +add_definitions(${PREPROCESSOR_DEFINITIONS}) +include_directories(${INCLUDE_DIRECTORIES}) + +add_library(${LIBRARY_NAME} STATIC ${SRCS}) +# Precompiled header stuff must be after the target is added +#set_precompiled_header(${LIBRARY_NAME} ${PROJECT_ROOT_DIR}/include/stdwx.h ${PROJECT_ROOT_DIR}/include/stdwx.cpp) + + +target_precompile_headers(${LIBRARY_NAME} + PRIVATE + "${PROJECT_ROOT_DIR}/include/stdwx.h" +) diff --git a/Utils/DiskInfo.cpp b/Utils/DiskInfo.cpp new file mode 100644 index 0000000..d1a82cd --- /dev/null +++ b/Utils/DiskInfo.cpp @@ -0,0 +1,932 @@ +#include "stdwx.h" +//for native code only uncomment the next line and use UnmanagedCode.h and UnmanagedCode.cpp +//as source files in your project, for managed C++ leave it as is +//#define NATIVE_CODE +#include "DiskInfo.h" +#ifndef NATIVE_CODE +using namespace System::Runtime::InteropServices; +#endif + +#undef UNICODE +#undef _UNICODE + +char DiskInfo::HardDriveSerialNumber [1024]; + +DiskInfo* DiskInfo::m_instance = NULL; + +BOOL DiskInfo::AddIfNew(USHORT *pIdSector) +{ + BOOL bAdd = TRUE; + for(size_t i = 0; i< m_list.size();i++) + { + if(memcmp(pIdSector, m_list[i], 256 * sizeof(WORD)) == 0) + { + bAdd = false; + break; + } + } + if(bAdd) + { + auto diskdata = new WORD[256]; + ::memcpy(diskdata,pIdSector,256*sizeof(WORD)); + m_list.push_back(diskdata); + } + return bAdd; +} + +int DiskInfo::ReadPhysicalDriveInNTUsingSmart (void) +{ + int done = FALSE; + int drive = 0; + + for (drive = 0; drive < MAX_IDE_DRIVES; drive++) + { + HANDLE hPhysicalDriveIOCTL = 0; + + // Try to get a handle to PhysicalDrive IOCTL, report failure + // and exit if can't. + + TCHAR driveName [256]; + sprintf(driveName, "\\\\.\\PhysicalDrive%d", drive); + + // Windows NT, Windows 2000, Windows Server 2003, Vista + hPhysicalDriveIOCTL = CreateFile (driveName, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + nullptr, OPEN_EXISTING, 0, nullptr); + + if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE) + { + + } + else + { + GETVERSIONINPARAMS GetVersionParams; + DWORD cbBytesReturned = 0; + + // Get the version, etc of PhysicalDrive IOCTL + memset ((void*) & GetVersionParams, 0, sizeof(GetVersionParams)); + + if ( DeviceIoControl (hPhysicalDriveIOCTL, SMART_GET_VERSION, + nullptr, + 0, + &GetVersionParams, sizeof (GETVERSIONINPARAMS), + &cbBytesReturned, nullptr) ) + { + // Allocate the command buffer + ULONG CommandSize = sizeof(SENDCMDINPARAMS) + IDENTIFY_BUFFER_SIZE; + PSENDCMDINPARAMS Command = (PSENDCMDINPARAMS) malloc (CommandSize); + // Retrieve the IDENTIFY data + // Prepare the command +#define ID_CMD 0xEC // Returns ID sector for ATA + Command -> irDriveRegs.bCommandReg = ID_CMD; + DWORD BytesReturned = 0; + if ( DeviceIoControl (hPhysicalDriveIOCTL, + SMART_RCV_DRIVE_DATA, Command, sizeof(SENDCMDINPARAMS), + Command, CommandSize, + &BytesReturned, NULL) ) + + { + // Print the IDENTIFY data + //DWORD diskdata [256]; + USHORT *pIdSector = (USHORT *) + (PIDENTIFY_DATA) ((PSENDCMDOUTPARAMS) Command) -> bBuffer; + + + AddIfNew(pIdSector); + + done = TRUE; + } + // Done + CloseHandle (hPhysicalDriveIOCTL); + free (Command); + } + } + } + + return done; +} + +int DiskInfo::ReadPhysicalDriveInNTWithAdminRights (void) +{ + int done = FALSE; + int drive = 0; + BYTE IdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1]; + for (drive = 0; drive < MAX_IDE_DRIVES; drive++) + { + HANDLE hPhysicalDriveIOCTL = 0; + + // Try to get a handle to PhysicalDrive IOCTL, report failure + // and exit if can't. + TCHAR driveName [256]; + + swprintf (driveName, L"\\\\.\\PhysicalDrive%d", drive); + + // Windows NT, Windows 2000, must have admin rights + hPhysicalDriveIOCTL = CreateFile (driveName, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, + OPEN_EXISTING, 0, nullptr); + + if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE) + { + GETVERSIONOUTPARAMS VersionParams; + DWORD cbBytesReturned = 0; + + // Get the version, etc of PhysicalDrive IOCTL + memset ((void*) &VersionParams, 0, sizeof(VersionParams)); + + if ( DeviceIoControl (hPhysicalDriveIOCTL, DFP_GET_VERSION, + nullptr, + 0, + &VersionParams, + sizeof(VersionParams), + &cbBytesReturned, nullptr) ) + { + + + // If there is a IDE device at number "i" issue commands + // to the device + if (VersionParams.bIDEDeviceMap > 0) + { + BYTE bIDCmd = 0; // IDE or ATAPI IDENTIFY cmd + SENDCMDINPARAMS scip; + + // Now, get the ID sector for all IDE devices in the system. + // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command, + // otherwise use the IDE_ATA_IDENTIFY command + bIDCmd = (VersionParams.bIDEDeviceMap >> drive & 0x10) ? \ + IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY; + + memset (&scip, 0, sizeof(scip)); + memset (IdOutCmd, 0, sizeof(IdOutCmd)); + + if ( DoIDENTIFY (hPhysicalDriveIOCTL, + &scip, + (PSENDCMDOUTPARAMS)&IdOutCmd, + (BYTE) bIDCmd, + (BYTE) drive, + &cbBytesReturned)) + { + + + USHORT *pIdSector = (USHORT *) ((PSENDCMDOUTPARAMS)IdOutCmd)->bBuffer; + AddIfNew(pIdSector); + done = TRUE; + } + } + } + + CloseHandle (hPhysicalDriveIOCTL); + } + } + + return done; +} + + +// Required to ensure correct PhysicalDrive IOCTL structure setup +#pragma pack(4) + + +// +// IOCTL_STORAGE_QUERY_PROPERTY +// +// Input Buffer: +// a STORAGE_PROPERTY_QUERY structure which describes what type of query +// is being done, what property is being queried for, and any additional +// parameters which a particular property query requires. +// +// Output Buffer: +// Contains a buffer to place the results of the query into. Since all +// property descriptors can be cast into a STORAGE_DESCRIPTOR_HEADER, +// the IOCTL can be called once with a small buffer then again using +// a buffer as large as the header reports is necessary. +// + + +// +// Types of queries +// + +//typedef enum _STORAGE_QUERY_TYPE { +// PropertyStandardQuery = 0, // Retrieves the descriptor +// PropertyExistsQuery, // Used to test whether the descriptor is supported +// PropertyMaskQuery, // Used to retrieve a mask of writeable fields in the descriptor +// PropertyQueryMaxDefined // use to validate the value +//} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE; + +// +// define some initial property id's +// + +//typedef enum _STORAGE_PROPERTY_ID { +// StorageDeviceProperty = 0, +// StorageAdapterProperty +//} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID; + +// +// Query structure - additional parameters for specific queries can follow +// the header +// + +//typedef struct _STORAGE_PROPERTY_QUERY { +// +// // +// // ID of the property being retrieved +// // +// +// STORAGE_PROPERTY_ID PropertyId; +// +// // +// // Flags indicating the type of query being performed +// // +// +// STORAGE_QUERY_TYPE QueryType; +// +// // +// // Space for additional parameters if necessary +// // +// +// UCHAR AdditionalParameters[1]; +// +//} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY; + + +#define IOCTL_STORAGE_QUERY_PROPERTY CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS) + + +// +// Device property descriptor - this is really just a rehash of the inquiry +// data retrieved from a scsi device +// +// This may only be retrieved from a target device. Sending this to the bus +// will result in an error +// + +//typedef struct _STORAGE_DEVICE_DESCRIPTOR { +// +// // +// // Sizeof(STORAGE_DEVICE_DESCRIPTOR) +// // +// +// ULONG Version; +// +// // +// // Total size of the descriptor, including the space for additional +// // data and id strings +// // +// +// ULONG Size; +// +// // +// // The SCSI-2 device type +// // +// +// UCHAR DeviceType; +// +// // +// // The SCSI-2 device type modifier (if any) - this may be zero +// // +// +// UCHAR DeviceTypeModifier; +// +// // +// // Flag indicating whether the device's media (if any) is removable. This +// // field should be ignored for media-less devices +// // +// +// BOOLEAN RemovableMedia; +// +// // +// // Flag indicating whether the device can support mulitple outstanding +// // commands. The actual synchronization in this case is the responsibility +// // of the port driver. +// // +// +// BOOLEAN CommandQueueing; +// +// // +// // Byte offset to the zero-terminated ascii string containing the device's +// // vendor id string. For devices with no such ID this will be zero +// // +// +// ULONG VendorIdOffset; +// +// // +// // Byte offset to the zero-terminated ascii string containing the device's +// // product id string. For devices with no such ID this will be zero +// // +// +// ULONG ProductIdOffset; +// +// // +// // Byte offset to the zero-terminated ascii string containing the device's +// // product revision string. For devices with no such string this will be +// // zero +// // +// +// ULONG ProductRevisionOffset; +// +// // +// // Byte offset to the zero-terminated ascii string containing the device's +// // serial number. For devices with no serial number this will be zero +// // +// +// ULONG SerialNumberOffset; +// +// // +// // Contains the bus type (as defined above) of the device. It should be +// // used to interpret the raw device properties at the end of this structure +// // (if any) +// // +// +// STORAGE_BUS_TYPE BusType; +// +// // +// // The number of bytes of bus-specific data which have been appended to +// // this descriptor +// // +// +// ULONG RawPropertiesLength; +// +// // +// // Place holder for the first byte of the bus specific property data +// // +// +// UCHAR RawDeviceProperties[1]; +// +//} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR; + + + // function to decode the serial numbers of IDE hard drives + // using the IOCTL_STORAGE_QUERY_PROPERTY command +char * DiskInfo::flipAndCodeBytes (char * str) +{ + static char flipped [1000]; + int num = strlen (str); + strcpy (flipped, ""); + for (int i = 0; i < num; i += 4) + { + for (int j = 1; j >= 0; j--) + { + int sum = 0; + for (int k = 0; k < 2; k++) + { + sum *= 16; + switch (str [i + j * 2 + k]) + { + case '0': sum += 0; break; + case '1': sum += 1; break; + case '2': sum += 2; break; + case '3': sum += 3; break; + case '4': sum += 4; break; + case '5': sum += 5; break; + case '6': sum += 6; break; + case '7': sum += 7; break; + case '8': sum += 8; break; + case '9': sum += 9; break; + case 'a': sum += 10; break; + case 'b': sum += 11; break; + case 'c': sum += 12; break; + case 'd': sum += 13; break; + case 'e': sum += 14; break; + case 'f': sum += 15; break; + } + } + if (sum > 0) + { + char sub [2]; + sub [0] = (char) sum; + sub [1] = 0; + strcat (flipped, sub); + } + } + } + + return flipped; +} + + +typedef struct _MEDIA_SERAL_NUMBER_DATA { + ULONG SerialNumberLength; + ULONG Result; + ULONG Reserved[2]; + UCHAR SerialNumberData[1]; +} MEDIA_SERIAL_NUMBER_DATA, *PMEDIA_SERIAL_NUMBER_DATA; + + +int DiskInfo::ReadPhysicalDriveInNTWithZeroRights (void) +{ + int done = FALSE; + int drive = 0; + + for (drive = 0; drive < MAX_IDE_DRIVES; drive++) + { + HANDLE hPhysicalDriveIOCTL = 0; + + // Try to get a handle to PhysicalDrive IOCTL, report failure + // and exit if can't. + TCHAR driveName [256]; + + swprintf (driveName, L"\\\\.\\PhysicalDrive%d", drive); + + // Windows NT, Windows 2000, Windows XP - admin rights not required + hPhysicalDriveIOCTL = CreateFile (driveName, 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, 0, NULL); + + + if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE) + { + STORAGE_PROPERTY_QUERY query; + DWORD cbBytesReturned = 0; + char buffer [10000]; + + memset ((void *) & query, 0, sizeof (query)); + query.PropertyId = StorageDeviceProperty; + query.QueryType = PropertyStandardQuery; + + memset (buffer, 0, sizeof (buffer)); + + if ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY, + & query, + sizeof (query), + & buffer, + sizeof (buffer), + & cbBytesReturned, NULL) ) + { + STORAGE_DEVICE_DESCRIPTOR * descrip = (STORAGE_DEVICE_DESCRIPTOR *) & buffer; + char serialNumber [1000]; + + strcpy (serialNumber, + flipAndCodeBytes ( & buffer [descrip -> SerialNumberOffset])); + } + else + { + DWORD err = GetLastError (); + + } + + memset (buffer, 0, sizeof (buffer)); + + if ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, + NULL, + 0, + & buffer, + sizeof (buffer), + & cbBytesReturned, NULL) ) + { + MEDIA_SERIAL_NUMBER_DATA * mediaSerialNumber = + (MEDIA_SERIAL_NUMBER_DATA *) & buffer; + char serialNumber [1000]; + + strcpy (serialNumber, (char *) mediaSerialNumber -> SerialNumberData); + + } + else + { + DWORD err = GetLastError (); + } + + CloseHandle (hPhysicalDriveIOCTL); + } + } + + return done; +} + + + // DoIDENTIFY + // FUNCTION: Send an IDENTIFY command to the drive + // bDriveNum = 0-3 + // bIDCmd = IDE_ATA_IDENTIFY or IDE_ATAPI_IDENTIFY +BOOL DiskInfo::DoIDENTIFY (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP, + PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum, + PDWORD lpcbBytesReturned) +{ + // Set up data structures for IDENTIFY command. + pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE; + pSCIP -> irDriveRegs.bFeaturesReg = 0; + pSCIP -> irDriveRegs.bSectorCountReg = 1; + pSCIP -> irDriveRegs.bSectorNumberReg = 1; + pSCIP -> irDriveRegs.bCylLowReg = 0; + pSCIP -> irDriveRegs.bCylHighReg = 0; + + // Compute the drive number. + pSCIP -> irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4); + + // The command can either be IDE identify or ATAPI identify. + pSCIP -> irDriveRegs.bCommandReg = bIDCmd; + pSCIP -> bDriveNumber = bDriveNum; + pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE; + + return ( DeviceIoControl (hPhysicalDriveIOCTL, DFP_RECEIVE_DRIVE_DATA, + (LPVOID) pSCIP, + sizeof(SENDCMDINPARAMS) - 1, + (LPVOID) pSCOP, + sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1, + lpcbBytesReturned, NULL) ); +} + + +// --------------------------------------------------- + + // (* Output Bbuffer for the VxD (rt_IdeDinfo record) *) +typedef struct _rt_IdeDInfo_ +{ + BYTE IDEExists[4]; + BYTE DiskExists[8]; + WORD DisksRawInfo[8*256]; +} rt_IdeDInfo, *pt_IdeDInfo; + + + // (* IdeDinfo "data fields" *) +typedef struct _rt_DiskInfo_ +{ + BOOL DiskExists; + BOOL ATAdevice; + BOOL RemovableDevice; + WORD TotLogCyl; + WORD TotLogHeads; + WORD TotLogSPT; + char SerialNumber[20]; + char FirmwareRevision[8]; + char ModelNumber[40]; + WORD CurLogCyl; + WORD CurLogHeads; + WORD CurLogSPT; +} rt_DiskInfo; + + +#define m_cVxDFunctionIdesDInfo 1 + + +// --------------------------------------------------- + + +int DiskInfo::ReadDrivePortsInWin9X (void) +{ + int done = FALSE; + + HANDLE VxDHandle = 0; + pt_IdeDInfo pOutBufVxD = 0; + DWORD lpBytesReturned = 0; + + // set the thread priority high so that we get exclusive access to the disk + BOOL status = + // SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + SetPriorityClass (GetCurrentProcess (), REALTIME_PRIORITY_CLASS); + // SetPriorityClass (GetCurrentProcess (), HIGH_PRIORITY_CLASS); + + // 1. Make an output buffer for the VxD + rt_IdeDInfo info; + pOutBufVxD = &info; + + // ***************** + // KLUDGE WARNING!!! + // HAVE to zero out the buffer space for the IDE information! + // If this is NOT done then garbage could be in the memory + // locations indicating if a disk exists or not. + ZeroMemory (&info, sizeof(info)); + + // 1. Try to load the VxD + // must use the short file name path to open a VXD file + //char StartupDirectory [2048]; + //char shortFileNamePath [2048]; + //char *p = NULL; + //char vxd [2048]; + // get the directory that the exe was started from + //GetModuleFileName (hInst, (LPSTR) StartupDirectory, sizeof (StartupDirectory)); + // cut the exe name from string + //p = &(StartupDirectory [strlen (StartupDirectory) - 1]); + //while (p >= StartupDirectory && *p && '\\' != *p) p--; + //*p = '\0'; + //GetShortPathName (StartupDirectory, shortFileNamePath, 2048); + //sprintf (vxd, "\\\\.\\%s\\IDE21201.VXD", shortFileNamePath); + //VxDHandle = CreateFile (vxd, 0, 0, 0, + // 0, FILE_FLAG_DELETE_ON_CLOSE, 0); + VxDHandle = CreateFile (L"\\\\.\\IDE21201.VXD", 0, 0, 0, + 0, FILE_FLAG_DELETE_ON_CLOSE, 0); + + if (VxDHandle != INVALID_HANDLE_VALUE) + { + // 2. Run VxD function + DeviceIoControl (VxDHandle, m_cVxDFunctionIdesDInfo, + 0, 0, pOutBufVxD, sizeof(pt_IdeDInfo), &lpBytesReturned, 0); + + // 3. Unload VxD + CloseHandle (VxDHandle); + } + else + //::MessageBox (NULL, L"ERROR: Could not open IDE21201.VXD file", + // TITLE, MB_ICONSTOP); + return FALSE; + + + // 4. Translate and store data + unsigned long int i = 0; + for (i=0; i<8; i++) + { + if((pOutBufVxD->DiskExists[i]) && (pOutBufVxD->IDEExists[i/2])) + { + + WORD* diskdata = new WORD[256]; + for (int j = 0; j < 256; j++) + diskdata [j] = pOutBufVxD -> DisksRawInfo [i * 256 + j]; + + // process the information for this buffer + BOOL bAdd = TRUE; + for(UINT j =0; j< m_list.size();j++) + { + if(memcmp(diskdata,m_list[j],256 * sizeof(WORD)) == 0) + { + bAdd = false; + break; + } + } + if(bAdd) + m_list.push_back(diskdata); + else + wxDELETEA(diskdata); + done = TRUE; + } + } + + // reset the thread priority back to normal + SetPriorityClass (GetCurrentProcess (), NORMAL_PRIORITY_CLASS); + + return done; +} + + +#define SENDIDLENGTH sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE + + +int DiskInfo::ReadIdeDriveAsScsiDriveInNT (void) +{ + int done = FALSE; + int controller = 0; + + for (controller = 0; controller < 16; controller++) + { + HANDLE hScsiDriveIOCTL = 0; + TCHAR driveName [256]; + + // Try to get a handle to PhysicalDrive IOCTL, report failure + // and exit if can't. + swprintf (driveName, L"\\\\.\\Scsi%d:", controller); + + // Windows NT, Windows 2000, any rights should do + hScsiDriveIOCTL = CreateFile (driveName, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, 0, NULL); + + + if (hScsiDriveIOCTL != INVALID_HANDLE_VALUE) + { + int drive = 0; + + for (drive = 0; drive < 2; drive++) + { + char buffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH]; + SRB_IO_CONTROL *p = (SRB_IO_CONTROL *) buffer; + SENDCMDINPARAMS *pin = + (SENDCMDINPARAMS *) (buffer + sizeof (SRB_IO_CONTROL)); + DWORD dummy; + + memset (buffer, 0, sizeof (buffer)); + p -> HeaderLength = sizeof (SRB_IO_CONTROL); + p -> Timeout = 10000; + p -> Length = SENDIDLENGTH; + p -> ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY; + strncpy ((char *) p -> Signature, "SCSIDISK", 8); + + pin -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY; + pin -> bDriveNumber = drive; + + if (DeviceIoControl (hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT, + buffer, + sizeof (SRB_IO_CONTROL) + + sizeof (SENDCMDINPARAMS) - 1, + buffer, + sizeof (SRB_IO_CONTROL) + SENDIDLENGTH, + &dummy, NULL)) + { + SENDCMDOUTPARAMS *pOut = + (SENDCMDOUTPARAMS *) (buffer + sizeof (SRB_IO_CONTROL)); + IDSECTOR *pId = (IDSECTOR *) (pOut -> bBuffer); + if (pId -> sModelNumber [0]) + { + + USHORT *pIdSector = (USHORT *) pId; + AddIfNew(pIdSector); + //BOOL bAdd = TRUE; + // for(UINT i =0; i< m_list.size();i++) + // { + // if(memcmp(pIdSector,m_list[i],256 * sizeof(WORD)) == 0) + // { + // bAdd = false; + // break; + // } + // } + // if(bAdd) + // { + // WORD* diskdata = new WORD[256]; + // ::memcpy(diskdata,pIdSector,256*sizeof(WORD)); + // m_list.push_back(diskdata); + // } + + done = TRUE; + } + } + } + CloseHandle (hScsiDriveIOCTL); + } + } + + return done; +} + +#ifndef NATIVE_CODE +String^ DiskInfo::GetModelNumber(UINT drive) +{ + String^ ms = GetString (m_list[drive], 27, 46); + return ms->Trim(); +} +String^ DiskInfo::GetSerialNumber(UINT drive) +{ + String^ ms = GetString (m_list[drive], 10, 19); + return ms->Trim(); +} + +String^ DiskInfo::GetRevisionNumber(UINT drive) +{ + String^ ms = GetString (m_list[drive], 23, 26); + return ms->Trim(); +} + +String^ DiskInfo::GetDriveType (UINT drive) +{ + if (m_list[drive][0] & 0x0080) + return "Removable"; + else if (m_list[drive][0] & 0x0040) + return "Fixed"; + else return "Unknown"; +} + +String^ DiskInfo::GetString (WORD* pdiskdata, int firstIndex, int lastIndex) +{ + int index = 0; + int position = 0; + //if(lastIndex < firstIndex) + // return (String^)NULL; + // each integer has two characters stored in it backwards + char* string = new char[2*(lastIndex- firstIndex +1)]; + for (index = firstIndex; index <= lastIndex; index++) + { + // get high byte for 1st character + string [position] = (char) (pdiskdata [index] / 256); + position++; + + // get low byte for 2nd character + string [position] = (char) (pdiskdata [index] % 256); + position++; + } + + String^ ms = Marshal::PtrToStringAnsi((IntPtr)string,2*(lastIndex- firstIndex +1)); + delete string; + return ms; +} +#else + +char* DiskInfo::ModelNumber (UINT drive) +{ + return ConvertToString(m_list[drive], 27, 46); +} + +char* DiskInfo::SerialNumber (UINT drive) +{ + return ConvertToString(m_list[drive], 10, 19); +} + + + +char* DiskInfo::RevisionNumber (UINT drive) +{ + return ConvertToString(m_list[drive], 23, 26); +} + +char* DiskInfo::DriveType (UINT drive) +{ + if (m_list[drive][0] & 0x0080) + return "Removable"; + else if (m_list[drive][0] & 0x0040) + return "Fixed"; + else return "Unknown"; +} + + + +char * DiskInfo::ConvertToString (WORD diskdata [256], int firstIndex, int lastIndex) +{ + static char string [1024]; + int index = 0; + int position = 0; + + // each integer has two characters stored in it backwards + for (index = firstIndex; index <= lastIndex; index++) + { + // get high byte for 1st character + string [position] = (char) (diskdata [index] / 256); + position++; + + // get low byte for 2nd character + string [position] = (char) (diskdata [index] % 256); + position++; + } + + // end the string + string [position] = '\0'; + + // cut off the trailing blanks + for (index = position - 1; index > 0 && ' ' == string [index]; index--) + string [index] = '\0'; + + return string; +} +#endif + +unsigned __int64 DiskInfo::DriveSize (UINT drive) +{ + unsigned __int64 bytes = 0,sectors =0; + if (m_list[drive] [83] & 0x400) + sectors = m_list[drive][103] * 65536I64 * 65536I64 * 65536I64 + + m_list[drive][102] * 65536I64 * 65536I64 + + m_list[drive][101] * 65536I64 + + m_list[drive][100]; + else + sectors = m_list[drive][61] * 65536 + m_list[drive][60]; + // there are 512 bytes in a sector + bytes = sectors * 512; + return bytes; +} + +DiskInfo::DiskInfo(void) +{ + //m_DriveCount = 0; +} + +DiskInfo::~DiskInfo(void) +{ + for(UINT i = 0; i< m_list.size(); i++) + delete m_list[i]; + m_list.clear(); +} + + +long DiskInfo::LoadDiskInfo () + { + int done = FALSE; + __int64 id = 0; + OSVERSIONINFO version; + memset (&version, 0, sizeof (version)); + version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + GetVersionEx (&version); + for(UINT i = 0; i< m_list.size(); i++) + delete m_list[i]; + m_list.clear(); + if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + // this works under WinNT4 or Win2K if you have admin rights + done = ReadPhysicalDriveInNTWithAdminRights (); + + // this should work in WinNT or Win2K if previous did not work + // this is kind of a backdoor via the SCSI mini port driver into + // the IDE drives + done = ReadIdeDriveAsScsiDriveInNT (); + + //this works under WinNT4 or Win2K or WinXP if you have any rights + //done = ReadPhysicalDriveInNTWithZeroRights (); + done = ReadPhysicalDriveInNTUsingSmart(); + + } + else + { + // this works under Win9X and calls a VXD + int attempt = 0; + + // try this up to 10 times to get a hard drive serial number + for (attempt = 0; + attempt < 10 && !done ; + attempt++) + done = ReadDrivePortsInWin9X (); + } + return (long) m_list.size(); + } + +UINT DiskInfo::BufferSize (UINT drive) +{ + return m_list[drive][21] * 512; +} \ No newline at end of file diff --git a/Utils/DiskInfo.h b/Utils/DiskInfo.h new file mode 100644 index 0000000..2b33346 --- /dev/null +++ b/Utils/DiskInfo.h @@ -0,0 +1,280 @@ +#pragma once + + +#include +#include +#include +#include +#include +#include + +#define NATIVE_CODE + +#pragma warning(disable:4996) + // Required to ensure correct PhysicalDrive IOCTL structure setup +#pragma pack(1) + +#define IDENTIFY_BUFFER_SIZE 512 + + + // IOCTL commands +#define DFP_GET_VERSION 0x00074080 +#define DFP_SEND_DRIVE_COMMAND 0x0007c084 +#define DFP_RECEIVE_DRIVE_DATA 0x0007c088 + +#define FILE_DEVICE_SCSI 0x0000001b +#define IOCTL_SCSI_MINIPORT_IDENTIFY ((FILE_DEVICE_SCSI << 16) + 0x0501) +#define IOCTL_SCSI_MINIPORT 0x0004D008 // see NTDDSCSI.H for definition + + +#define SMART_GET_VERSION CTL_CODE(IOCTL_DISK_BASE, 0x0020, METHOD_BUFFERED, FILE_READ_ACCESS) +#define SMART_SEND_DRIVE_COMMAND CTL_CODE(IOCTL_DISK_BASE, 0x0021, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define SMART_RCV_DRIVE_DATA CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + + // GETVERSIONOUTPARAMS contains the data returned from the + // Get Driver Version function. +typedef struct _GETVERSIONOUTPARAMS +{ + BYTE bVersion; // Binary driver version. + BYTE bRevision; // Binary driver revision. + BYTE bReserved; // Not used. + BYTE bIDEDeviceMap; // Bit map of IDE devices. + DWORD fCapabilities; // Bit mask of driver capabilities. + DWORD dwReserved[4]; // For future use. +} GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS; + + + // Bits returned in the fCapabilities member of GETVERSIONOUTPARAMS +#define CAP_IDE_ID_FUNCTION 1 // ATA ID command supported +#define CAP_IDE_ATAPI_ID 2 // ATAPI ID command supported +#define CAP_IDE_EXECUTE_SMART_FUNCTION 4 // SMART commannds supported + +//typedef struct _GETVERSIONINPARAMS { +// UCHAR bVersion; // Binary driver version. +// UCHAR bRevision; // Binary driver revision. +// UCHAR bReserved; // Not used. +// UCHAR bIDEDeviceMap; // Bit map of IDE devices. +// ULONG fCapabilities; // Bit mask of driver capabilities. +// ULONG dwReserved[4]; // For future use. +//} GETVERSIONINPARAMS, *PGETVERSIONINPARAMS, *LPGETVERSIONINPARAMS; +// +// // IDE registers +//typedef struct _IDEREGS +//{ +// BYTE bFeaturesReg; // Used for specifying SMART "commands". +// BYTE bSectorCountReg; // IDE sector count register +// BYTE bSectorNumberReg; // IDE sector number register +// BYTE bCylLowReg; // IDE low order cylinder value +// BYTE bCylHighReg; // IDE high order cylinder value +// BYTE bDriveHeadReg; // IDE drive/head register +// BYTE bCommandReg; // Actual IDE command. +// BYTE bReserved; // reserved for future use. Must be zero. +//} IDEREGS, *PIDEREGS, *LPIDEREGS; +// +// +// // SENDCMDINPARAMS contains the input parameters for the +// // Send Command to Drive function. +//typedef struct _SENDCMDINPARAMS +//{ +// DWORD cBufferSize; // Buffer size in bytes +// IDEREGS irDriveRegs; // Structure with drive register values. +// BYTE bDriveNumber; // Physical drive number to send +// // command to (0,1,2,3). +// BYTE bReserved[3]; // Reserved for future expansion. +// DWORD dwReserved[4]; // For future use. +// BYTE bBuffer[1]; // Input buffer. +//} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS; + + + // Valid values for the bCommandReg member of IDEREGS. +#define IDE_ATAPI_IDENTIFY 0xA1 // Returns ID sector for ATAPI. +#define IDE_ATA_IDENTIFY 0xEC // Returns ID sector for ATA. + + + // Status returned from driver +//typedef struct _DRIVERSTATUS +//{ +// BYTE bDriverError; // Error code from driver, or 0 if no error. +// BYTE bIDEStatus; // Contents of IDE Error register. +// // Only valid when bDriverError is SMART_IDE_ERROR. +// BYTE bReserved[2]; // Reserved for future expansion. +// DWORD dwReserved[2]; // Reserved for future expansion. +//} DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS; +// +// +// // Structure returned by PhysicalDrive IOCTL for several commands +//typedef struct _SENDCMDOUTPARAMS +//{ +// DWORD cBufferSize; // Size of bBuffer in bytes +// DRIVERSTATUS DriverStatus; // Driver status structure. +// BYTE bBuffer[1]; // Buffer of arbitrary length in which to store the data read from the // drive. +//} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS; +// +// +// // The following struct defines the interesting part of the IDENTIFY +// // buffer: +typedef struct _IDSECTOR +{ + USHORT wGenConfig; + USHORT wNumCyls; + USHORT wReserved; + USHORT wNumHeads; + USHORT wBytesPerTrack; + USHORT wBytesPerSector; + USHORT wSectorsPerTrack; + USHORT wVendorUnique[3]; + CHAR sSerialNumber[20]; + USHORT wBufferType; + USHORT wBufferSize; + USHORT wECCSize; + CHAR sFirmwareRev[8]; + CHAR sModelNumber[40]; + USHORT wMoreVendorUnique; + USHORT wDoubleWordIO; + USHORT wCapabilities; + USHORT wReserved1; + USHORT wPIOTiming; + USHORT wDMATiming; + USHORT wBS; + USHORT wNumCurrentCyls; + USHORT wNumCurrentHeads; + USHORT wNumCurrentSectorsPerTrack; + ULONG ulCurrentSectorCapacity; + USHORT wMultSectorStuff; + ULONG ulTotalAddressableSectors; + USHORT wSingleWordDMA; + USHORT wMultiWordDMA; + BYTE bReserved[128]; +} IDSECTOR, *PIDSECTOR; + +// +// IDENTIFY data (from ATAPI driver source) +// + +#pragma pack(1) + +typedef struct _IDENTIFY_DATA { + USHORT GeneralConfiguration; // 00 00 + USHORT NumberOfCylinders; // 02 1 + USHORT Reserved1; // 04 2 + USHORT NumberOfHeads; // 06 3 + USHORT UnformattedBytesPerTrack; // 08 4 + USHORT UnformattedBytesPerSector; // 0A 5 + USHORT SectorsPerTrack; // 0C 6 + USHORT VendorUnique1[3]; // 0E 7-9 + USHORT SerialNumber[10]; // 14 10-19 + USHORT BufferType; // 28 20 + USHORT BufferSectorSize; // 2A 21 + USHORT NumberOfEccBytes; // 2C 22 + USHORT FirmwareRevision[4]; // 2E 23-26 + USHORT ModelNumber[20]; // 36 27-46 + UCHAR MaximumBlockTransfer; // 5E 47 + UCHAR VendorUnique2; // 5F + USHORT DoubleWordIo; // 60 48 + USHORT Capabilities; // 62 49 + USHORT Reserved2; // 64 50 + UCHAR VendorUnique3; // 66 51 + UCHAR PioCycleTimingMode; // 67 + UCHAR VendorUnique4; // 68 52 + UCHAR DmaCycleTimingMode; // 69 + USHORT TranslationFieldsValid:1; // 6A 53 + USHORT Reserved3:15; + USHORT NumberOfCurrentCylinders; // 6C 54 + USHORT NumberOfCurrentHeads; // 6E 55 + USHORT CurrentSectorsPerTrack; // 70 56 + ULONG CurrentSectorCapacity; // 72 57-58 + USHORT CurrentMultiSectorSetting; // 59 + ULONG UserAddressableSectors; // 60-61 + USHORT SingleWordDMASupport : 8; // 62 + USHORT SingleWordDMAActive : 8; + USHORT MultiWordDMASupport : 8; // 63 + USHORT MultiWordDMAActive : 8; + USHORT AdvancedPIOModes : 8; // 64 + USHORT Reserved4 : 8; + USHORT MinimumMWXferCycleTime; // 65 + USHORT RecommendedMWXferCycleTime; // 66 + USHORT MinimumPIOCycleTime; // 67 + USHORT MinimumPIOCycleTimeIORDY; // 68 + USHORT Reserved5[2]; // 69-70 + USHORT ReleaseTimeOverlapped; // 71 + USHORT ReleaseTimeServiceCommand; // 72 + USHORT MajorRevision; // 73 + USHORT MinorRevision; // 74 + USHORT Reserved6[50]; // 75-126 + USHORT SpecialFunctionsEnabled; // 127 + USHORT Reserved7[128]; // 128-255 +} IDENTIFY_DATA, *PIDENTIFY_DATA; + +#pragma pack() + +typedef struct _SRB_IO_CONTROL +{ + ULONG HeaderLength; + UCHAR Signature[8]; + ULONG Timeout; + ULONG ControlCode; + ULONG ReturnCode; + ULONG Length; +} SRB_IO_CONTROL, *PSRB_IO_CONTROL; +#define SMART_RCV_DRIVE_DATA CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#ifndef NATIVE_CODE +using namespace System; +#endif +#include +using namespace std ; +typedef vector LISTDATA; +#define MAX_IDE_DRIVES 16 +class DiskInfo +{ + static DiskInfo* m_instance; + static char HardDriveSerialNumber [1024]; + LISTDATA m_list; +public: + static DiskInfo& GetDiskInfo() + { + if(m_instance == NULL) + m_instance = new DiskInfo(); + return *m_instance; + }; + + static void Destroy() + { + if(m_instance != NULL) + delete m_instance; + m_instance = NULL; + }; + ~DiskInfo(void); + int ReadIdeDriveAsScsiDriveInNT (void); + long LoadDiskInfo (); + int ReadPhysicalDriveInNTWithAdminRights (void); + int ReadPhysicalDriveInNTWithZeroRights (void); + int ReadDrivePortsInWin9X (void); + int ReadPhysicalDriveInNTUsingSmart (void); + + unsigned __int64 DriveSize (UINT drive); + UINT GetCount (){return m_list.size();}; + UINT BufferSize (UINT drive); +#ifndef NATIVE_CODE + String^ GetModelNumber (UINT drive); + String^ GetSerialNumber(UINT drive); + String^ GetRevisionNumber (UINT drive); + String^ GetDriveType (UINT drive); +#else + char* ModelNumber (UINT drive); + char* SerialNumber (UINT drive); + char* RevisionNumber (UINT drive); + char* DriveType (UINT drive); +#endif +private: + DiskInfo(void); + static char * flipAndCodeBytes (char * str); + static char * ConvertToString (WORD diskdata [256], int firstIndex, int lastIndex); + + static BOOL DoIDENTIFY (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP, + PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum, + PDWORD lpcbBytesReturned); + BOOL AddIfNew(USHORT *pIdSector); +#ifndef NATIVE_CODE + String^ GetString (WORD* pdiskdata, int firstIndex, int lastIndex); +#endif +}; diff --git a/Utils/Guid.cpp b/Utils/Guid.cpp new file mode 100644 index 0000000..1900a5a --- /dev/null +++ b/Utils/Guid.cpp @@ -0,0 +1,23 @@ +#include "stdwx.h" +#include "Guid.h" +#include +#if defined(__WXMSW__) +#include +#endif + +wxString GenerateGuid() +{ +#if defined(__WXMSW__) + Uuid uid; + uid.Create(); + return wxString::Format(wxT("{%s}"), (const wxChar*)uid).Upper(); +#else + srand(time(NULL)); + return wxString::Format(wxT("{%x%x-%x-%x-%x-%x%x%x}"), + rand(), rand(), // Generates a 64-bit Hex number + rand(), // Generates a 32-bit Hex number + ((rand() & 0x0fff) | 0x4000), // Generates a 32-bit Hex number of the form 4xxx (4 indicates the UUID version) + rand() % 0x3fff + 0x8000, // Generates a 32-bit Hex number in the range [0x8000, 0xbfff] + rand(), rand(), rand()); // Generates a 96-bit Hex number +#endif +} diff --git a/Utils/Guid.h b/Utils/Guid.h new file mode 100644 index 0000000..4527a54 --- /dev/null +++ b/Utils/Guid.h @@ -0,0 +1,6 @@ +#ifndef _GUID_H +#define _GUID_H + +wxString GenerateGuid(); + +#endif // _GUID_H \ No newline at end of file diff --git a/Utils/JSONObjectFactory.cpp b/Utils/JSONObjectFactory.cpp new file mode 100644 index 0000000..e53308a --- /dev/null +++ b/Utils/JSONObjectFactory.cpp @@ -0,0 +1,10 @@ +#include "stdwx.h" +#include +#include "JSONObjectFactory.h" + +wxJSONValue JSONObjectFactory::Create(const wxString & action) +{ + wxJSONValue result; + result[JSON_KEY_ACTION] = action; + return result; +} \ No newline at end of file diff --git a/Utils/JSONObjectFactory.h b/Utils/JSONObjectFactory.h new file mode 100644 index 0000000..eaf9892 --- /dev/null +++ b/Utils/JSONObjectFactory.h @@ -0,0 +1,12 @@ +#pragma once + +class wxJSONValue; + +#define JSON_KEY_ACTION wxT("action") +#define JSON_KEY_PROCESSED wxT("processed") + +class JSONObjectFactory +{ +public: + static wxJSONValue Create(const wxString & action); +}; \ No newline at end of file diff --git a/Utils/MACAddressUtility.cpp b/Utils/MACAddressUtility.cpp new file mode 100644 index 0000000..2e63728 --- /dev/null +++ b/Utils/MACAddressUtility.cpp @@ -0,0 +1,214 @@ +#include "stdwx.h" +#include "MACAddressUtility.h" +#include + +#include + +#if defined(WIN32) || defined(UNDER_CE) +# include +# if defined(UNDER_CE) +# include +# endif +#elif defined(__APPLE__) +# include +# include +# include +# include +# include +#elif defined(LINUX) || defined(linux) +# include +# include +# include +# include +# include +#endif + +long MACAddressUtility::GetMACAddress(unsigned char * result) +{ + // Fill result with zeroes + memset(result, 0, 6); + // Call appropriate function for each platform +#if defined(WIN32) || defined(UNDER_CE) + return GetMACAddressMSW(result); +#elif defined(__APPLE__) + return GetMACAddressMAC(result); +#elif defined(LINUX) || defined(linux) + return GetMACAddressLinux(result); +#endif + // If platform is not supported then return error code + return -1; +} + +#if defined(WIN32) || defined(UNDER_CE) + +inline long MACAddressUtility::GetMACAddressMSW(unsigned char * result) +{ + +#if defined(UNDER_CE) + IP_ADAPTER_INFO AdapterInfo[16]; // Allocate information + DWORD dwBufLen = sizeof(AdapterInfo); // Save memory size of buffer + if(GetAdaptersInfo(AdapterInfo, &dwBufLen) == ERROR_SUCCESS) + { + memcpy(result, AdapterInfo->Address, 6); + } + else return -1; +#else + //UUID uuid; + //if(UuidCreateSequential(&uuid) == RPC_S_UUID_NO_ADDRESS) return -1; + //memcpy(result, (char*)(uuid.Data4+2), 6); +#endif + + for (int i = 0; i < 6; ++i) { + result[i] = 1; + } + return 0; + + return 0; +} + +#elif defined(__APPLE__) + +static kern_return_t FindEthernetInterfaces(io_iterator_t *matchingServices) +{ + kern_return_t kernResult; + CFMutableDictionaryRef matchingDict; + CFMutableDictionaryRef propertyMatchDict; + + matchingDict = IOServiceMatching(kIOEthernetInterfaceClass); + + if (NULL != matchingDict) + { + propertyMatchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (NULL != propertyMatchDict) + { + CFDictionarySetValue(propertyMatchDict, CFSTR(kIOPrimaryInterface), kCFBooleanTrue); + CFDictionarySetValue(matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict); + CFRelease(propertyMatchDict); + } + } + kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, matchingServices); + return kernResult; +} + +static kern_return_t GetMACAddress(io_iterator_t intfIterator, UInt8 *MACAddress, UInt8 bufferSize) +{ + io_object_t intfService; + io_object_t controllerService; + kern_return_t kernResult = KERN_FAILURE; + + if (bufferSize < kIOEthernetAddressSize) { + return kernResult; + } + + bzero(MACAddress, bufferSize); + + while (intfService = IOIteratorNext(intfIterator)) + { + CFTypeRef MACAddressAsCFData; + + // IONetworkControllers can't be found directly by the IOServiceGetMatchingServices call, + // since they are hardware nubs and do not participate in driver matching. In other words, + // registerService() is never called on them. So we've found the IONetworkInterface and will + // get its parent controller by asking for it specifically. + + // IORegistryEntryGetParentEntry retains the returned object, so release it when we're done with it. + kernResult = IORegistryEntryGetParentEntry(intfService, + kIOServicePlane, + &controllerService); + + if (KERN_SUCCESS != kernResult) { + printf("IORegistryEntryGetParentEntry returned 0x%08x\n", kernResult); + } + else { + // Retrieve the MAC address property from the I/O Registry in the form of a CFData + MACAddressAsCFData = IORegistryEntryCreateCFProperty(controllerService, + CFSTR(kIOMACAddress), + kCFAllocatorDefault, + 0); + if (MACAddressAsCFData) { + CFShow(MACAddressAsCFData); // for display purposes only; output goes to stderr + + // Get the raw bytes of the MAC address from the CFData + CFDataGetBytes((CFDataRef)MACAddressAsCFData, CFRangeMake(0, kIOEthernetAddressSize), MACAddress); + CFRelease(MACAddressAsCFData); + } + + // Done with the parent Ethernet controller object so we release it. + (void) IOObjectRelease(controllerService); + } + + // Done with the Ethernet interface object so we release it. + (void) IOObjectRelease(intfService); + } + + return kernResult; +} + +long MACAddressUtility::GetMACAddressMAC(unsigned char * result) +{ + io_iterator_t intfIterator; + kern_return_t kernResult = KERN_FAILURE; + do + { + kernResult = ::FindEthernetInterfaces(&intfIterator); + if (KERN_SUCCESS != kernResult) break; + kernResult = ::GetMACAddress(intfIterator, (UInt8*)result, 6); + } + while(false); + (void) IOObjectRelease(intfIterator); +} + +#elif defined(LINUX) || defined(linux) + +long MACAddressUtility::GetMACAddressLinux(unsigned char * result) +{ + struct ifreq ifr; + struct ifreq *IFR; + struct ifconf ifc; + char buf[1024]; + int s, i; + int ok = 0; + + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s == -1) + { + return -1; + } + + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = buf; + ioctl(s, SIOCGIFCONF, &ifc); + + IFR = ifc.ifc_req; + for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; IFR++) + { + strcpy(ifr.ifr_name, IFR->ifr_name); + if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) + { + if (! (ifr.ifr_flags & IFF_LOOPBACK)) + { + if (ioctl(s, SIOCGIFHWADDR, &ifr) == 0) + { + ok = 1; + break; + } + } + } + } + + shutdown(s, SHUT_RDWR); + if (ok) + { + bcopy( ifr.ifr_hwaddr.sa_data, result, 6); + } + else + { + return -1; + } + return 0; +} + +#endif diff --git a/Utils/MACAddressUtility.h b/Utils/MACAddressUtility.h new file mode 100644 index 0000000..2340c7d --- /dev/null +++ b/Utils/MACAddressUtility.h @@ -0,0 +1,18 @@ +#ifndef _MACADDRESS_UTILITY_H +#define _MACADDRESS_UTILITY_H + +class MACAddressUtility +{ +public: + static long GetMACAddress(unsigned char * result); +private: +#if defined(WIN32) || defined(UNDER_CE) + static long GetMACAddressMSW(unsigned char * result); +#elif defined(__APPLE__) + static long GetMACAddressMAC(unsigned char * result); +#elif defined(LINUX) || defined(linux) + static long GetMACAddressLinux(unsigned char * result); +#endif +}; + +#endif diff --git a/Utils/Win/Utils.vcxproj b/Utils/Win/Utils.vcxproj new file mode 100644 index 0000000..92f6b46 --- /dev/null +++ b/Utils/Win/Utils.vcxproj @@ -0,0 +1,235 @@ + + + + x64 + + + + Debug + x64 + + + Release + x64 + + + + {14D82890-BB7F-3748-8713-43304E91CFA1} + Win32Proj + 10.0.26100.0 + x64 + Utils + NoUpgrade + + + + StaticLibrary + Unicode + v143 + + + StaticLibrary + Unicode + v143 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\ + Utils.dir\Debug\ + Utils + .lib + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\ + Utils.dir\Release\ + Utils + .lib + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;%(AdditionalIncludeDirectories) + $(IntDir) + EnableFastChecks + + + ProgramDatabase + 4996 + Sync + + + Disabled + stdcpp17 + + true + Disabled + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/Utils.dir/Debug//cmake_pch.pch + + MultiThreadedDebugDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_LIB;CMAKE_INTDIR="Debug" + $(IntDir) + false + + + %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_LIB;CMAKE_INTDIR=\"Debug\" + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + %(AdditionalOptions) /machine:x64 + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;%(AdditionalIncludeDirectories) + $(IntDir) + Default + + + 4996 + Sync + + + AnySuitable + stdcpp17 + + true + MaxSpeed + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/Utils.dir/Release//cmake_pch.pch + + MultiThreadedDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_LIB;CMAKE_INTDIR="Release" + $(IntDir) + + + false + + + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_LIB;CMAKE_INTDIR=\"Release\" + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\MotionPrimitives;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + %(AdditionalOptions) /machine:x64 + + + + + Always + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\Utils\Win\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\Utils\Win\CMakeFiles\generate.stamp + false + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/Utils.dir/Debug//cmake_pch.pch + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/Utils.dir/Release//cmake_pch.pch + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/Utils/Win/CMakeFiles/Utils.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + ZERO_CHECK + false + Never + + + + + + \ No newline at end of file diff --git a/Utils/Win/Utils.vcxproj.filters b/Utils/Win/Utils.vcxproj.filters new file mode 100644 index 0000000..e7e1063 --- /dev/null +++ b/Utils/Win/Utils.vcxproj.filters @@ -0,0 +1,72 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Precompile Header File + + + Precompile Header File + + + + + + + + {4951AEE1-75F2-3C38-B593-C6BC8C809FB0} + + + {112D4227-BB51-3360-BB5B-5EA5DBA5A65F} + + + {05450AB2-CB7B-34EA-83DF-1EE86424EDF0} + + + diff --git a/Utils/wxFPValidator.cpp b/Utils/wxFPValidator.cpp new file mode 100644 index 0000000..6465cc6 --- /dev/null +++ b/Utils/wxFPValidator.cpp @@ -0,0 +1,265 @@ +#include "stdwx.h" +#ifdef linux +#include +#include +#endif +#include "wxFPValidator.h" +#include +#include +#include + +wxFPValidator::wxFPValidator(double * valPtr) +{ + Initialize(); + m_pDouble = valPtr; +} + +wxFPValidator::wxFPValidator(int * valPtr) +{ + Initialize(); + m_pInt = valPtr; +} + +wxFPValidator::wxFPValidator(long * valPtr) +{ + Initialize(); + m_pLong = valPtr; +} + +wxFPValidator::wxFPValidator(wxString * valPtr) +{ + Initialize(); + m_pString = valPtr; +} + +wxFPValidator::wxFPValidator(const wxFPValidator & validator) +: m_pDouble(validator.m_pDouble), m_pInt(validator.m_pInt), +m_pLong(validator.m_pLong), m_pString(validator.m_pString) +{ +} + +wxFPValidator::~wxFPValidator() +{ +} + +void wxFPValidator::Initialize() +{ + m_pDouble = nullptr; + m_pInt = nullptr; + m_pLong = nullptr; + m_pString = nullptr; +} + +wxValidator* wxFPValidator::Clone() const +{ + return new wxFPValidator(*this); +} + +bool wxFPValidator::TransferFromWindow() +{ + if(!m_validatorWindow) + { + return false; + } +#if wxUSE_TEXTCTRL + if (m_validatorWindow->IsKindOf(CLASSINFO(wxTextCtrl)) ) + { + wxTextCtrl * pControl = (wxTextCtrl*) m_validatorWindow; + if(m_pDouble) + { + return pControl->GetValue().ToDouble(m_pDouble); + } + else if(m_pInt) + { + double tmp; + bool res = pControl->GetValue().ToDouble(&tmp); + if(tmp >= INT_MIN && tmp <= INT_MAX && (fmod(tmp,1) == 0)) + { + *m_pInt = (int)tmp; + } else res = false; + return res; + } + else if(m_pLong) + { + double tmp; + bool res = pControl->GetValue().ToDouble(&tmp); + if(tmp >= LONG_MIN && tmp <= LONG_MAX && (fmod(tmp,1) == 0)) + { + *m_pLong = (long)tmp; + } else res = false; + return res; + } + else if(m_pString) + { + wxString tmp = pControl->GetValue(); + if(!tmp.IsEmpty()) + { + *m_pString = tmp; + return true; + } + return false; + } + } + else +#endif + +#if wxUSE_SPINCTRL + if (m_validatorWindow->IsKindOf(CLASSINFO(wxSpinCtrl)) ) + { + wxSpinCtrl * pControl = (wxSpinCtrl*) m_validatorWindow; + + if(m_pLong) + { + int tmp = pControl->GetValue(); + *m_pLong = (long)tmp; + return true; + } + } + else +#endif + +#if wxUSE_FILEPICKERCTRL + if (m_validatorWindow->IsKindOf(CLASSINFO(wxFilePickerCtrl))) + { + wxFilePickerCtrl * pControl = (wxFilePickerCtrl*) m_validatorWindow; + if (m_pString) + { + *m_pString = pControl->GetPath(); + return true; + } + else + return false; + } + else +#endif + return false; + return false; +} + +bool wxFPValidator::TransferToWindow() +{ + if(!m_validatorWindow) + { + return false; + } +#if wxUSE_SPINCTRL + if (m_validatorWindow->IsKindOf(CLASSINFO(wxSpinCtrl)) ) + { + wxSpinCtrl * pControl = (wxSpinCtrl *) m_validatorWindow; + if(m_pLong) + { + pControl->SetValue((int)*m_pLong); + return true; + } + } + else +#endif +#if wxUSE_TEXTCTRL + if (m_validatorWindow->IsKindOf(CLASSINFO(wxTextCtrl)) ) + { + wxTextCtrl * pControl = (wxTextCtrl*) m_validatorWindow; + if(m_pDouble) + { + pControl->SetValue(wxString::Format(wxT("%1.6f"), *m_pDouble)); + return true; + } + else if(m_pInt) + { + pControl->SetValue(wxString::Format(wxT("%i"), *m_pInt)); + return true; + } + else if(m_pLong) + { + pControl->SetValue(wxString::Format(wxT("%l"), *m_pLong)); + return true; + } + else if(m_pString) + { + pControl->SetValue(*m_pString); + return true; + } + } + else +#endif +#if wxUSE_FILEPICKERCTRL + if (m_validatorWindow->IsKindOf(CLASSINFO(wxFilePickerCtrl))) + { + wxFilePickerCtrl * pControl = (wxFilePickerCtrl*) m_validatorWindow; + if (m_pString) + { + pControl->SetPath(*m_pString); + return true; + } + else + return false; + } + else +#endif + return false; + return false; +} + +bool wxFPValidator::Validate(wxWindow * parent) +{ + if(!m_validatorWindow) + { + return false; + } +#if wxUSE_TEXTCTRL + if (m_validatorWindow->IsKindOf(CLASSINFO(wxTextCtrl)) ) + { + wxTextCtrl * pControl = (wxTextCtrl*) m_validatorWindow; + if(m_pDouble != NULL) + { + return pControl->GetValue().ToDouble(m_pDouble); + } + else if(m_pInt != NULL) + { + double tmp; + bool res = pControl->GetValue().ToDouble(&tmp); + if(tmp >= INT_MIN && tmp <= INT_MAX && (fmod(tmp,1) == 0)) + { + *m_pInt = (int)tmp; + } else res = false; + return res; + } + else if(m_pLong != NULL) + { + double tmp; + bool res = pControl->GetValue().ToDouble(&tmp); + if(tmp >= LONG_MIN && tmp <= LONG_MAX && (fmod(tmp,1) == 0)) + { + *m_pLong = (long)tmp; + } else res = false; + return res; + } + else if(m_pString != NULL) + { + return !pControl->GetValue().IsEmpty(); + } + } + else +#endif +#if wxUSE_TEXTCTRL + if (m_validatorWindow->IsKindOf(CLASSINFO(wxSpinCtrl)) ) + { + wxSpinCtrl * pControl = (wxSpinCtrl*) m_validatorWindow; + if(m_pLong != NULL) + { + int tmp = pControl->GetValue(); + *m_pLong = (long)tmp; + return true; + } + } + else +#endif +#if wxUSE_FILEPICKERCTRL + if (m_validatorWindow->IsKindOf(CLASSINFO(wxFilePickerCtrl))) + { + return true; + } + else +#endif + return false; + return false; +} diff --git a/Utils/wxFPValidator.h b/Utils/wxFPValidator.h new file mode 100644 index 0000000..41f31ac --- /dev/null +++ b/Utils/wxFPValidator.h @@ -0,0 +1,25 @@ +#ifndef _WX_FP_VALIDATOR_H +#define _WX_FP_VALIDATOR_H + +class wxFPValidator : public wxValidator +{ +protected: + double * m_pDouble; + int * m_pInt; + long * m_pLong; + wxString * m_pString; + void Initialize(); +public: + wxFPValidator(double * valPtr); + wxFPValidator(int * valPtr); + wxFPValidator(long * valPtr); + wxFPValidator(wxString * valPtr); + wxFPValidator(const wxFPValidator & validator); + ~wxFPValidator(); + virtual wxValidator* Clone() const; + virtual bool TransferFromWindow(); + virtual bool TransferToWindow(); + virtual bool Validate(wxWindow * parent); +}; + +#endif diff --git a/Utils/wxMACAddressUtility.h b/Utils/wxMACAddressUtility.h new file mode 100644 index 0000000..2035dbe --- /dev/null +++ b/Utils/wxMACAddressUtility.h @@ -0,0 +1,28 @@ +#ifndef _WX_MACADDRESS_UTILITY_H +#define _WX_MACADDRESS_UTILITY_H + +#include "MACAddressUtility.h" +#include + +class wxMACAddressUtility +{ +public: + static wxString GetMACAddress() + { + unsigned char result[6]; + if(MACAddressUtility::GetMACAddress(result) == 0) + { + return wxString::Format(wxT("%02X:%02X:%02X:%02X:%02X:%02X"), + (unsigned int)result[0], (unsigned int)result[1], (unsigned int)result[2], + (unsigned int)result[3], (unsigned int)result[4], (unsigned int)result[5]); + } + return wxEmptyString; + } + + static bool GetMACAddress(unsigned char * data) + { + return (MACAddressUtility::GetMACAddress(data) == 0); + } +}; + +#endif diff --git a/Utils/wxTemplateClientData.h b/Utils/wxTemplateClientData.h new file mode 100644 index 0000000..7bbb60a --- /dev/null +++ b/Utils/wxTemplateClientData.h @@ -0,0 +1,40 @@ +#ifndef _WXTEMPLATECLIENTDATA_H +#define _WXTEMPLATECLIENTDATA_H + +template +class wxTemplateClientData : public wxClientData +{ +public: + wxTemplateClientData(T * item, bool takeOwnership = true) + : m_Item(item) + , m_TakeOwnership(takeOwnership) + {} + ~wxTemplateClientData() + { + if (m_TakeOwnership) + wxDELETE(m_Item); + } + T * GetItem() + { + return m_Item; + } + void SetItem(T * item, bool takeOwnership = true) + { + if (m_TakeOwnership) + wxDELETE(m_Item); + m_Item = item; + m_TakeOwnership = takeOwnership; + } + T * DetachItem() + { + T * res = m_Item; + m_Item = NULL; + return res; + } + +private: + T * m_Item; + bool m_TakeOwnership; +}; + +#endif // _WXTEMPLATECLIENTDATA_H \ No newline at end of file diff --git a/VideoSourceDirectShow/CMakeLists.txt b/VideoSourceDirectShow/CMakeLists.txt new file mode 100644 index 0000000..ff02a32 --- /dev/null +++ b/VideoSourceDirectShow/CMakeLists.txt @@ -0,0 +1,117 @@ +set(SRCS + VideoSourceDirectShowPlugin.cpp + VideoSourceDirectShowApp.cpp + VideoSourceDirectShowExports.cpp + VideoGrabberDirectShow.cpp + VideoSourceDirectShow.def +) +set(HFILES + VideoSourceDirectShowPlugin.h + VideoGrabberDirectShow.h + VideoSourceDirectShowApp.h +) +set(DSNATIVE_SRCS + DSNative/Crossbar.cpp + DSNative/Device.cpp + DSNative/DeviceManager.cpp + DSNative/Format.cpp + DSNative/FrameGrabber.cpp + DSNative/DirectShow/Sources/DSCategoryHelper.cpp + DSNative/DirectShow/Sources/DSFileWriter.cpp + DSNative/DirectShow/Sources/DSFilter.cpp + DSNative/DirectShow/Sources/DSFilterGraphBase.cpp + DSNative/DirectShow/Sources/DSObjectBase.cpp + DSNative/DirectShow/Sources/DSSampleGrabber.cpp +) +set(DSNATIVE_HFILES + DSNative/Crossbar.h + DSNative/Device.h + DSNative/DeviceManager.h + DSNative/Format.h + DSNative/FrameGrabber.h + DSNative/DirectShow/Include/DSCategoryHelper.h + DSNative/DirectShow/Include/DSCommon.h + DSNative/DirectShow/Include/DSFilter.h + DSNative/DirectShow/Include/DSFilterGraphBase.h + DSNative/DirectShow/Include/DSFiltersDefinition.h + DSNative/DirectShow/Include/DSObjectBase.h +) + +source_group("DSNative\\DirectShow\\Sources" REGULAR_EXPRESSION DSNative/DirectShow/Sources/.*) +source_group("DSNative\\DirectShow\\Include" REGULAR_EXPRESSION DSNative/DirectShow/Include/.*) +source_group("DSNative\\Sources" REGULAR_EXPRESSION DSNative/.*\\.cpp) +source_group("DSNative\\Include" REGULAR_EXPRESSION DSNative/.*\\.h) + +set(LOCAL_INCLUDE_DIR "${PROJECT_ROOT_DIR}/include") + +set(INCLUDE_DIRECTORIES + ${LOCAL_INCLUDE_DIR} + DSNative + ${CMAKE_CURRENT_SOURCE_DIR}/../VideoSourcePluginBase + ${CMAKE_CURRENT_SOURCE_DIR}/../CommonPluginBase + ${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty/wxXS/include + ${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty/strmbas + ${OpenCV_INCLUDE_DIRS} +) + +if(WIN32) + set(INCLUDE_DIRECTORIES ${INCLUDE_DIRECTORIES} ${QEDIT_PATH}) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D_USRDLL;/DEXPORTS_API=) +endif() + +set(ALL_PROJECT_FILES ${SRCS} ${HFILES} ${DSNATIVE_SRCS} ${DSNATIVE_HFILES} "${LOCAL_INCLUDE_DIR}/stdwx.h" "${LOCAL_INCLUDE_DIR}/stdwx.cpp") + +add_definitions(${PREPROCESSOR_DEFINITIONS}) +include_directories(${INCLUDE_DIRECTORIES}) + +set(LIBRARY_NAME VideoSourceDirectShow) + +add_library(${LIBRARY_NAME} SHARED ${ALL_PROJECT_FILES}) + +target_link_libraries(${LIBRARY_NAME} + ${wxWidgets_LIBRARIES} + VideoSourcePluginBase + CommonPluginBase + MotionDetectorPluginBase + Utils + strmbas + strmiids + quartz + ole32 + oleaut32 + winmm +) + +add_dependencies(${LIBRARY_NAME} + VideoSourcePluginBase + CommonPluginBase + MotionDetectorPluginBase +) + + +if(WIN32) + set_target_properties(${LIBRARY_NAME} PROPERTIES + LINK_FLAGS "/NODEFAULTLIB:atlthunk.lib" + ) +endif() + +target_precompile_headers(${LIBRARY_NAME} + PRIVATE + "${LOCAL_INCLUDE_DIR}/stdwx.h" +) + +# Post Build Events +if(WIN32) + add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different "\"$(TargetPath)\"" "\"$(TargetDir)../$(TargetFileName)\"" + ) +endif() + +set(PLUGIN_TARGET_DIR "${OUTPUT_BIN_DIR}/plugins/video_source") + +add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "${PLUGIN_TARGET_DIR}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "$" + "${PLUGIN_TARGET_DIR}/$" +) \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/Crossbar.cpp b/VideoSourceDirectShow/DSNative/Crossbar.cpp new file mode 100644 index 0000000..902b79d --- /dev/null +++ b/VideoSourceDirectShow/DSNative/Crossbar.cpp @@ -0,0 +1,235 @@ +#include "stdwx.h" +#include "Crossbar.h" +#include "DirectShow\Include\DSCommon.h" + +CCrossBar::CCrossBar(IAMCrossbar * pCrossbar) + //: CFactoryObject() + : m_pCrossbar(pCrossbar) +{ + if (m_pCrossbar) + { + m_pCrossbar->AddRef(); + } +} + +CCrossBar::~CCrossBar() +{ + SAFERELEASE(m_pCrossbar); +} + +long CCrossBar::get_Count(BOOL bVideo) +{ + long lCount = 0; + if (m_pCrossbar) + { + long lInputs = 0; + long lOutputs = 0; + m_pCrossbar->get_PinCounts(&lOutputs,&lInputs); + if (lInputs > 0) + { + for (long i = 0; i < lInputs; i++) + { + if (IsVideo(i,FALSE)) + { + lCount++; + } + } + } + + } + return lCount; +} + +long CCrossBar::get_Active(BOOL bVideo) +{ + long lInput = -1; + if (m_pCrossbar) + { + long lInputs = 0; + long lOutputs = 0; + m_pCrossbar->get_PinCounts(&lOutputs,&lInputs); + long lPin = 0; + while (lPin < lOutputs) + { + if (IsVideo(lPin,TRUE)) + { + if (bVideo) break; + } + else + { + if (!bVideo) break; + } + lPin++; + } + m_pCrossbar->get_IsRoutedTo(lPin,&lInput); + long lCount = get_Count(bVideo); + if (lInput >= lCount) + { + lInput -= get_Count(!bVideo); + } + } + return lInput; +} + +LPWSTR CCrossBar::get_PinName(long lIndex,BOOL bVideo) +{ + if (m_pCrossbar) + { + long lRelatedIndex; + long lPhysicalType; + if (IsVideo(lIndex,FALSE)) + { + if (!bVideo) lIndex += get_Count(bVideo); + } + else + { + if (bVideo) lIndex += get_Count(!bVideo); + } + + if (S_OK == m_pCrossbar->get_CrossbarPinInfo(TRUE,lIndex,&lRelatedIndex,&lPhysicalType)) + { + switch (lPhysicalType) + { + case PhysConn_Video_Tuner: + return L"Video Tuner"; + case PhysConn_Video_Composite: + return L"Video Composite"; + case PhysConn_Video_SVideo: + return L"Video S-Video"; + case PhysConn_Video_RGB: + return L"Video RGB"; + case PhysConn_Video_YRYBY: + return L"Video YRYBY"; + case PhysConn_Video_SerialDigital: + return L"Video SerialDigital"; + case PhysConn_Video_ParallelDigital: + return L"Video ParallelDigital"; + case PhysConn_Video_SCSI: + return L"Video SCSI"; + case PhysConn_Video_AUX: + return L"Video AUX"; + case PhysConn_Video_1394: + return L"Video 1394"; + case PhysConn_Video_USB: + return L"Video USB"; + case PhysConn_Video_VideoDecoder: + return L"Video VideoDecoder"; + case PhysConn_Video_VideoEncoder: + return L"Video VideoEncoder"; + case PhysConn_Video_SCART: + return L"Video SCART"; + case PhysConn_Audio_Tuner: + return L"Audio Tuner"; + case PhysConn_Audio_Line: + return L"Audio Line"; + case PhysConn_Audio_Mic: + return L"Audio Mic"; + case PhysConn_Audio_AESDigital: + return L"Audio AESDigital"; + case PhysConn_Audio_SPDIFDigital: + return L"Audio SPDIFDigital"; + case PhysConn_Audio_SCSI: + return L"Audio SCSI"; + case PhysConn_Audio_AUX: + return L"Audio AUX"; + case PhysConn_Audio_1394: + return L"Audio 1394"; + case PhysConn_Audio_USB: + return L"Audio USB"; + case PhysConn_Audio_AudioDecoder: + return L"Audio AudioDecoder"; + } + } + } + return NULL; +} + +HRESULT CCrossBar::Route(long lIndex,BOOL bVideo) +{ + if (!m_pCrossbar) return E_FAIL; + if (IsVideo(lIndex,FALSE)) + { + if (!bVideo) lIndex += get_Count(bVideo); + } + else + { + if (bVideo) lIndex += get_Count(!bVideo); + } + long lInputs = 0; + long lOutputs = 0; + m_pCrossbar->get_PinCounts(&lOutputs,&lInputs); + long lPin = 0; + while (lPin < lOutputs) + { + if (IsVideo(lPin,TRUE)) + { + if (bVideo) break; + } + else + { + if (!bVideo) break; + } + lPin++; + } + return m_pCrossbar->Route(lPin,lIndex); +} + +BOOL CCrossBar::IsVideo(long lPin,BOOL bOutput) +{ + if (m_pCrossbar) + { + long lRelatedIndex; + long lPhysicalType; + if (S_OK == m_pCrossbar->get_CrossbarPinInfo(!bOutput,lPin,&lRelatedIndex,&lPhysicalType)) + { + return (lPhysicalType < PhysConn_Audio_Tuner); + } + } + return FALSE; +} + +long CCrossBar::get_InputByType(PhysicalConnectorType _type) +{ + if (m_pCrossbar) + { + long lInputs = 0; + long lOutputs = 0; + m_pCrossbar->get_PinCounts(&lOutputs,&lInputs); + if (lInputs > 0) + { + for (long i = 0; i < lInputs; i++) + { + long lRelatedIndex; + long lPhysicalType; + if (S_OK == m_pCrossbar->get_CrossbarPinInfo(TRUE,i,&lRelatedIndex,&lPhysicalType)) + { + if (lPhysicalType == _type) return i; + } + } + } + } + return -1; +} + +long CCrossBar::get_OutputByType(PhysicalConnectorType _type) +{ + if (m_pCrossbar) + { + long lInputs = 0; + long lOutputs = 0; + m_pCrossbar->get_PinCounts(&lOutputs,&lInputs); + if (lOutputs > 0) + { + for (long i = 0; i < lOutputs; i++) + { + long lRelatedIndex; + long lPhysicalType; + if (S_OK == m_pCrossbar->get_CrossbarPinInfo(FALSE,i,&lRelatedIndex,&lPhysicalType)) + { + if (lPhysicalType == _type) return i; + } + } + } + } + return -1; +} \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/Crossbar.h b/VideoSourceDirectShow/DSNative/Crossbar.h new file mode 100644 index 0000000..9d41d0e --- /dev/null +++ b/VideoSourceDirectShow/DSNative/Crossbar.h @@ -0,0 +1,28 @@ +#ifndef __Crossbar_H__ +#define __Crossbar_H__ +///////////////////////////////////////////////////// +//#include "ClassFactory.h" +#include "stdwx.h" +#include +///////////////////////////////////////////////////// +class EXPORTS_API CCrossBar //: public CFactoryObject +{ + friend class CFrameGrabber; +private: + IAMCrossbar * m_pCrossbar; +private: + BOOL IsVideo(long lPin,BOOL bOutput); +public: + long get_Count(BOOL bVideo = TRUE); + long get_Active(BOOL bVideo = TRUE); + long get_InputByType(PhysicalConnectorType _type); + long get_OutputByType(PhysicalConnectorType _type); + LPWSTR get_PinName(long lIndex,BOOL bVideo = TRUE); + HRESULT Route(long lIndex,BOOL bVideo = TRUE); +private: + CCrossBar(IAMCrossbar * pCrossbar); +public: + virtual ~CCrossBar(); +}; +///////////////////////////////////////////////////// +#endif // __Crossbar_H__ \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/Device.cpp b/VideoSourceDirectShow/DSNative/Device.cpp new file mode 100644 index 0000000..cf668cc --- /dev/null +++ b/VideoSourceDirectShow/DSNative/Device.cpp @@ -0,0 +1,124 @@ + +#include "stdwx.h" +#include "Device.h" +#include "FrameGrabber.h" +#include "Format.h" + +CDevice::CDevice(LPOLESTR szMoniker) + //: CFactoryObject() + : m_lpwstrMoniker(NULL) +{ + m_pFilter = new DSFilterBase(szMoniker); + IBaseFilter * pFilter = NULL; + BOOL bFailed = TRUE; + if (m_pFilter->GetIBaseFilter(&pFilter)) + { + bFailed = (pFilter == NULL); + } + if (bFailed) + { + SAFEDELETE(m_pFilter); + } + else + { + set_Moniker(szMoniker); + } +} + +CDevice::CDevice(REFCLSID iid) + //: CFactoryObject() + : m_lpwstrMoniker(NULL) +{ + m_pFilter = new DSFilterBase(iid); + IBaseFilter * pFilter = NULL; + BOOL bFailed = TRUE; + if (m_pFilter->GetIBaseFilter(&pFilter)) + { + bFailed = (pFilter == NULL); + } + if (bFailed) + { + SAFEDELETE(m_pFilter); + } +} + +CDevice::CDevice(DSFilterBase * pFilter) + //: CFactoryObject() + : m_pFilter(pFilter) + , m_lpwstrMoniker(NULL) +{ + IBaseFilter * pBaseFilter = NULL; + BOOL bFailed = TRUE; + if (m_pFilter->GetIBaseFilter(&pBaseFilter)) + { + bFailed = (pBaseFilter == NULL); + } + if (bFailed) + { + SAFEDELETE(m_pFilter); + } +} + +CDevice::~CDevice() +{ + SAFEDELETEARRAY(m_lpwstrMoniker); + SAFEDELETE(m_pFilter); +} + +HRESULT CDevice::ShowProperties(HWND hwndParent) +{ + if (m_pFilter) + { + return m_pFilter->ShowProperties(hwndParent); + } + return E_FAIL; +} + +BOOL CDevice::HaveProperties() +{ + if (m_pFilter) + { + return m_pFilter->HaveProperties()? TRUE : FALSE; + } + return FALSE; +} +LPWSTR CDevice::get_Moniker() +{ + return m_lpwstrMoniker; +} + +void CDevice::set_Moniker(LPCWSTR lpwstrMoniker) +{ + SAFEDELETEARRAY(m_lpwstrMoniker); + if (lpwstrMoniker) + { + int cch = (int)(wcslen(lpwstrMoniker) + 1); + m_lpwstrMoniker = new WCHAR[cch]; + ZeroMemory(m_lpwstrMoniker,cch * sizeof(WCHAR)); + wcscpy_s(m_lpwstrMoniker, cch, lpwstrMoniker); + } +} +CFrameGrabber * CDevice::CreateFrameGrabber() +{ + return new CFrameGrabber(this); +} + +CVideoFormats * CDevice::get_VideoFormats() +{ + CVideoFormats * pFormats = NULL; + if (m_pFilter) + { + IAMStreamConfig * pStreamConfig = NULL; + IPin * pPin = m_pFilter->GetPinByCategory(PIN_CATEGORY_CAPTURE); + if (pPin) + { + if (SUCCEEDED(pPin->QueryInterface(IID_IAMStreamConfig,(void**)&pStreamConfig))) + { + pFormats = new CVideoFormats(pStreamConfig); + pStreamConfig->Release(); + } + pPin->Release(); + } + } + return pFormats; +} \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/Device.h b/VideoSourceDirectShow/DSNative/Device.h new file mode 100644 index 0000000..774a8c6 --- /dev/null +++ b/VideoSourceDirectShow/DSNative/Device.h @@ -0,0 +1,36 @@ +#ifndef __Device_H__ +#define __Device_H__ +///////////////////////////////////////////////////// +//#include "ClassFactory.h" +#include "stdwx.h" +#include "DirectShow/Include/DSCategoryHelper.h" +#include "DirectShow/Include/DSFilter.h" +///////////////////////////////////////////////////// +class CDeviceManager; +class CFrameGrabber; +class CVideoFormats; +///////////////////////////////////////////////////// +class EXPORTS_API CDevice //: public CFactoryObject +{ + friend class CDeviceManager; + friend class CFrameGrabber; +private: + LPWSTR m_lpwstrMoniker; + DSFilterBase * m_pFilter; +private: + CDevice(DSFilterBase * pFilter); +public: + LPWSTR get_Moniker(); + void set_Moniker(LPCWSTR lpwstrMoniker); + CFrameGrabber * CreateFrameGrabber(); + CVideoFormats * get_VideoFormats(); +public: + HRESULT ShowProperties(HWND hwndParent = NULL); + BOOL HaveProperties(); +public: + CDevice(LPOLESTR szMoniker); + CDevice(REFCLSID iid); + virtual ~CDevice(); +}; +///////////////////////////////////////////////////// +#endif //__Device_H__ \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/DeviceManager.cpp b/VideoSourceDirectShow/DSNative/DeviceManager.cpp new file mode 100644 index 0000000..c2cedc0 --- /dev/null +++ b/VideoSourceDirectShow/DSNative/DeviceManager.cpp @@ -0,0 +1,132 @@ +#include "stdwx.h" +#include "DeviceManager.h" +///////////////////////////////////////////////////// +CDeviceManager::CDeviceManager(REFCLSID _category) +//: CFactoryObject() +: m_pCategory(NULL) +, m_clsidCategory(_category) +{ + m_pCategory = new DSCategory(m_clsidCategory); +} + +CDeviceManager::~CDeviceManager() +{ + SAFEDELETE(m_pCategory); +} + +///////////////////////////////////////////////////// +long CDeviceManager::get_Count() +{ + if (m_pCategory) + { + return m_pCategory->get_Count(); + } + return 0; +} + +///////////////////////////////////////////////////// +CDevice * CDeviceManager::get_DeviceByMoniker(LPCWSTR lpwstrMonikerName) +{ + CDevice * pDevice = new CDevice((LPOLESTR)lpwstrMonikerName); + if (pDevice->m_pFilter) + { + return pDevice; + } + else + { + delete pDevice; + } + return NULL; +} + +///////////////////////////////////////////////////// +LPWSTR CDeviceManager::get_DeviceName(const long lIndex) +{ + if (m_pCategory) + { + long lNumber = lIndex; + return m_pCategory->GetName(lNumber); + } + return NULL; +} + +LPWSTR CDeviceManager::get_DeviceMonikerString(const long lIndex) +{ + if (m_pCategory) + { + long lNumber = lIndex; + return m_pCategory->GetDeviceMonikerString(lNumber); + } + return NULL; +} +///////////////////////////////////////////////////// +CDevice * CDeviceManager::get_Device(const long lIndex) +{ + if (m_pCategory) + { + DSFilterBase * pFilter = m_pCategory->GetDevice(lIndex); + if (pFilter) + { + CDevice * pDevice = new CDevice(pFilter); + if (pDevice) + { + LPWSTR lpwstrMoniker = get_DeviceMonikerString(lIndex); + if (lpwstrMoniker) + { + pDevice->set_Moniker(lpwstrMoniker); + SAFEDELETEARRAY(lpwstrMoniker); + } + else + { + delete pDevice; + pDevice = NULL; + } + } + return pDevice; + } + } + return NULL; +} + +CDevice * CDeviceManager::get_Device(LPCWSTR lpwstrName) +{ + if (m_pCategory) + { + long lCount = m_pCategory->get_Count(); + while (lCount > 0) + { + lCount--; + LPWSTR lpwstrDevice = m_pCategory->GetName(lCount); + bool found = wcscmp(lpwstrDevice, lpwstrName) == 0; + SAFEDELETEARRAY(lpwstrDevice); + if (found) + return get_Device(lCount); + } + } + return NULL; +} + +long CDeviceManager::get_DeviceIndex(LPCWSTR lpwstrMonikerName) +{ + if (m_pCategory) + { + long lCount = m_pCategory->get_Count(); + while (lCount > 0) + { + lCount--; + LPWSTR lpwstrDevice = get_DeviceMonikerString(lCount); + bool found = wcscmp(lpwstrDevice, lpwstrMonikerName) == 0; + SAFEDELETEARRAY(lpwstrDevice); + if (found) + return lCount; + } + } + return -1; +} + +void CDeviceManager::RefreshDevices() +{ + SAFEDELETE(m_pCategory); + m_pCategory = new DSCategory(m_clsidCategory); +} +///////////////////////////////////////////////////// \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/DeviceManager.h b/VideoSourceDirectShow/DSNative/DeviceManager.h new file mode 100644 index 0000000..edcaeef --- /dev/null +++ b/VideoSourceDirectShow/DSNative/DeviceManager.h @@ -0,0 +1,29 @@ +#ifndef __DeviceManager_H__ +#define __DeviceManager_H__ +///////////////////////////////////////////////////// +//#include "ClassFactory.h" +#include "Device.h" +#include "DirectShow/Include/DSCategoryHelper.h" +///////////////////////////////////////////////////// +class EXPORTS_API CDeviceManager//: public CFactoryObject +{ +private: + DSCategory * m_pCategory; + REFCLSID m_clsidCategory; +public: + static CDevice * get_DeviceByMoniker(LPCWSTR lpwstrMonikerName); +public: + long get_Count(); + CDevice * get_Device(LPCWSTR lpwstrName); + CDevice * get_Device(const long lIndex); + LPWSTR get_DeviceName(const long lIndex); + LPWSTR get_DeviceMonikerString(const long lIndex); + long get_DeviceIndex(LPCWSTR lpwstrMonikerName); + + void RefreshDevices(); +public: + CDeviceManager(REFCLSID _category); + virtual ~CDeviceManager(); +}; +///////////////////////////////////////////////////// +#endif // __DeviceManager_H__ \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/DirectShow/Include/DSCategoryHelper.h b/VideoSourceDirectShow/DSNative/DirectShow/Include/DSCategoryHelper.h new file mode 100644 index 0000000..e3913dc --- /dev/null +++ b/VideoSourceDirectShow/DSNative/DirectShow/Include/DSCategoryHelper.h @@ -0,0 +1,64 @@ +#ifndef __DS_CATEGORY_HELPER_H__ +#define __DS_CATEGORY_HELPER_H__ + +#include "DSFilter.h" + +// Base category helper class +class DSCategory : public DSObjectBase +{ +protected: + HRESULT GetFiltersCount(long & lCount); + HRESULT GetFilterName(long lNumber, LPWSTR * plpwstrDevName); + HRESULT GetDeviceFilter(long lNumber, IBaseFilter ** ppOutFilter); + HRESULT GetFilterMonikerString(long lNumber, LPWSTR * plpwstrDevMoniker); +protected: + ICreateDevEnum * m_pDevEnum; + IEnumMoniker * m_pEnumMoniker; + REFCLSID m_clsidCategory; +public: + virtual void Release(); + virtual HRESULT QueryInterface(const IID &riid,void ** ppvObject); +public: + long get_Count(); + LPWSTR GetName(long lNumber); + LPWSTR GetDeviceMonikerString(long lNumber); +public: + virtual DSFilterBase * GetDevice(long lNumber); +public: + DSCategory(REFCLSID clsidCategory); + virtual ~DSCategory(); +}; + +// Base video capture category helper class +class DSVideoCaptureCategory: public DSCategory +{ +public: + DSVideoCaptureCategory():DSCategory(CLSID_VideoInputDeviceCategory) {} + virtual ~DSVideoCaptureCategory() {} +}; + +// Base audio capture category helper class +class DSAudioCaptureCategory: public DSCategory +{ +public: + DSAudioCaptureCategory():DSCategory(CLSID_AudioInputDeviceCategory) {} + virtual ~DSAudioCaptureCategory() {} +}; + +// Base video compressor category helper class +class DSVideoCompressorCategory: public DSCategory +{ +public: + DSVideoCompressorCategory():DSCategory(CLSID_VideoCompressorCategory) {} + virtual ~DSVideoCompressorCategory() {} +}; + +// Base audio compressor category helper class +class DSAudioCompressorCategory: public DSCategory +{ +public: + DSAudioCompressorCategory():DSCategory(CLSID_AudioCompressorCategory) {} + virtual ~DSAudioCompressorCategory() {} +}; + +#endif diff --git a/VideoSourceDirectShow/DSNative/DirectShow/Include/DSCommon.h b/VideoSourceDirectShow/DSNative/DirectShow/Include/DSCommon.h new file mode 100644 index 0000000..3de16eb --- /dev/null +++ b/VideoSourceDirectShow/DSNative/DirectShow/Include/DSCommon.h @@ -0,0 +1,96 @@ +////////////////////////////////////////////////////////// +// Helper macro definitions +// Created by Sonic +// for any additional features contact sonic@YoooMedia.com +///////////////////////////////////////////////////////// + +#ifndef __ATLBASE_H__ +#include +#endif + +#ifndef __YoooCommonDefs_H__ +#define __YoooCommonDefs_H__ + +// Safe releasing COM object +#define SAFERELEASE(comobj) \ +if (comobj) \ +{ \ + comobj->Release(); \ + comobj = NULL; \ +} \ + +// Deleting object +#define SAFEDELETE(obj) \ +if (obj) \ +{ \ + delete obj; \ + obj = NULL; \ +} + +// Free memory +#define SAFECOTASKFREE(obj) \ +if (obj) \ +{ \ + CoTaskMemFree((LPVOID)obj); \ + obj = NULL; \ +} + +// delete an array +#define SAFEDELETEARRAY(obj) \ +if (obj) \ +{ \ + delete[] obj; \ + obj = NULL; \ +} + +// Safe Check HRESULT value +#define SAFECHECK(hr) \ +ASSERT( S_OK == hr ); \ +if (FAILED(hr)) \ +{ \ + return hr; \ +} + +// Safe Check HRESULT value and close interfaces +#define SAFECHECKCLOSE(hr) \ +ASSERT( S_OK == hr ); \ +if (FAILED(hr)) \ +{ \ + CloseInterfaces(); \ + return hr; \ +} + +#define CHECKRET(object,ret) \ +if (!object) return ret + +#define CHECKRETBOOL(object) \ +CHECKRET(object,false) + +#define CHECKRETHR(object) \ +CHECKRET(object,E_POINTER) + +#define THROWHR(hr) \ +if (hr != S_OK) throw hr; + +#define SAFERELEASEDC(hdc,hwnd) \ +if (hdc) \ +{ \ + ReleaseDC(hwnd,hdc); \ + hdc = NULL; \ +} + +#define DELETEGDIOBJECT(obj) \ +if (obj) \ +{ \ + DeleteObject(obj); \ + obj = NULL; \ +} + +#define DELETEGDIDC(hdc) \ +if (hdc) \ +{ \ + DeleteDC(hdc); \ + hdc = NULL; \ +} + +#endif // __YoooCommonDefs_H__ \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/DirectShow/Include/DSFilter.h b/VideoSourceDirectShow/DSNative/DirectShow/Include/DSFilter.h new file mode 100644 index 0000000..f99f60b --- /dev/null +++ b/VideoSourceDirectShow/DSNative/DirectShow/Include/DSFilter.h @@ -0,0 +1,52 @@ + +#ifndef __DS_FILTER_HELPER_H__ +#define __DS_FILTER_HELPER_H__ + +#include "DSObjectBase.h" + +class DSFilterBase : public virtual DSObjectBase +{ +protected: + IBaseFilter * m_pFilter; +protected: + HRESULT GetFilterByMoniker(LPOLESTR szMoniker); +public: + virtual void Release(); + virtual HRESULT QueryInterface(const IID &riid,void ** ppvObject); +public: + bool GetIBaseFilter(IBaseFilter ** pIBaseFilter); + HRESULT AddToFilterGraph(IGraphBuilder * pGraphBuilder); + HRESULT RemoveFromFilterGraph(IGraphBuilder * pGraphBuilder); +public: + HRESULT ShowProperties(HWND hwndParent = NULL); + bool HaveProperties(); + IPin * GetPinByDirection(PIN_DIRECTION direction,long lPinNumber); + IPin * GetPinByCategory(REFGUID guidPinCategory); + + HRESULT GetOutputPinCapabilitiesCount(long lPinNumber, int *piCount); + HRESULT GetOutputPinCapabilitiesCount(IPin * pPin, int *piCount); + HRESULT GetOutputPinCapabilitiesCount(REFGUID guidPinCategory, int *piCount); + + HRESULT GetOutputPinCapabilities(REFGUID guidPinCategory, int iCapNumber, AM_MEDIA_TYPE ** ppmt); + HRESULT GetOutputPinCapabilities(long lPinNumber, int iCapNumber, AM_MEDIA_TYPE ** ppmt); + HRESULT GetOutputPinCapabilities(IPin * pPin, int iCapNumber, AM_MEDIA_TYPE ** ppmt); + + HRESULT GetOutputPinFormat(long lPinNumber, AM_MEDIA_TYPE ** ppmt); + HRESULT GetOutputPinFormat(IPin * pPin, AM_MEDIA_TYPE ** ppmt); + HRESULT GetOutputPinFormat(REFGUID guidPinCategory, AM_MEDIA_TYPE ** ppmt); + + HRESULT SetOutputPinFormat(long lPinNumber, AM_MEDIA_TYPE * pmt); + HRESULT SetOutputPinFormat(IPin * pPin, AM_MEDIA_TYPE * pmt); + HRESULT SetOutputPinFormat(REFGUID guidPinCategory, AM_MEDIA_TYPE * pmt); + +protected: + DSFilterBase(); +public: + DSFilterBase(LPOLESTR szMoniker); + DSFilterBase(REFCLSID iid); + virtual ~DSFilterBase(); +public: + DSFilterBase(IBaseFilter * pFilter, bool bReleaseOnDestroy = false); +}; + +#endif diff --git a/VideoSourceDirectShow/DSNative/DirectShow/Include/DSFilterGraphBase.h b/VideoSourceDirectShow/DSNative/DirectShow/Include/DSFilterGraphBase.h new file mode 100644 index 0000000..f26d3bf --- /dev/null +++ b/VideoSourceDirectShow/DSNative/DirectShow/Include/DSFilterGraphBase.h @@ -0,0 +1,100 @@ + +#ifndef __DS_FILTERGRAPH_BASE_H__ +#define __DS_FILTERGRAPH_BASE_H__ + +#include "DSFilter.h" + +#define WM_GRAPH_NOTIFY WM_USER + 0x100 +#define WM_SAMPLE_CALLBACK WM_USER + 0x101 +#define WM_VIDEO_SIZE WM_USER + 0x102 +//#define USE_DS_OBJECT + +#ifdef _DEBUG + //#define ROT_DEBUG +#else + #ifdef ROT_DEBUG + #undef ROT_DEBUG + #endif +#endif + +#ifdef ROT_DEBUG + +class DSYoooROTFilter : public DSFilterBase +{ +public: + DSYoooROTFilter():DSFilterBase(L"@device:sw:{1C41D721-C2B6-46B2-A3E7-2845ED43A8F5}\\{CECB095D-B900-496F-9FDF-9C6EF331468F}") + { + } +}; + + +#endif + +class DSFilterGraphBase +#ifdef USE_DS_OBJECT + : public DSObjectBase +#endif +{ +private: +#ifdef ROT_DEBUG + DSYoooROTFilter * m_pDSYoooROTFilter; +#endif +protected: + IGraphBuilder * m_pGraphBuilder; // graph for rendering + IMediaControl * m_pMediaControl; // main media + IMediaEventEx * m_pMediaEventEx; // to check the stop + IVideoWindow * m_pVideoWindow; + IBasicAudio * m_pBasicAudio; + IBasicVideo * m_pBasicVideo; + IMediaSeeking * m_pMediaSeeking; +protected: + HWND m_hWnd; + HWND m_hWndNotify; + bool m_bShouldPreview; + bool m_bMute; + int m_iVolume; +protected: + virtual HRESULT InitInterfaces(); + virtual HRESULT CloseInterfaces(); + virtual void SettingUpVideoWindow(); + virtual HRESULT PreparePlayback(); +public: + virtual HRESULT ProcessGraphMessage(); + virtual HRESULT ProcessStepMessage(); +protected: + HRESULT SetVolume(int nVolume); + IBaseFilter * GetVideoRenderer(); + IBaseFilter * GetAudioRenderer(); +public: + int get_Volume(); + void set_Volume(int nVolume); + bool get_Mute(); + void set_Mute(bool bMute); + bool IsAudioSupported(); + bool IsRunning(); + bool IsPaused(); + HWND get_PreviewWindow(); + void set_PreviewWindow(HWND hWnd); + HWND get_NotifyWindow(); + void set_NotifyWindow(HWND hWnd); + bool get_ShouldPreview(); + void set_ShouldPreview(bool bShouldPreview); + RECT get_VideoSize(); + RECT get_SourceVideoSize(); + void set_VideoSize(RECT _rect); + REFERENCE_TIME get_Position(); + void set_Position(REFERENCE_TIME _time); + REFERENCE_TIME get_Duration(); +public: + STDMETHOD(Start)(); + STDMETHOD(Stop)(); + STDMETHOD(Pause)(); + + void ResizeVideoWindow(); + void ResizeVideoWindow(RECT rect); +public: + DSFilterGraphBase(); + virtual ~DSFilterGraphBase(); +}; + +#endif \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/DirectShow/Include/DSFiltersDefinition.h b/VideoSourceDirectShow/DSNative/DirectShow/Include/DSFiltersDefinition.h new file mode 100644 index 0000000..8600316 --- /dev/null +++ b/VideoSourceDirectShow/DSNative/DirectShow/Include/DSFiltersDefinition.h @@ -0,0 +1,243 @@ + +#ifndef __DS_FILTERS_DEFINITION_H__ +#define __DS_FILTERS_DEFINITION_H__ + +#include "DSFilter.h" + +#pragma include_alias( "dxtrans.h", "qedit.h" ) +#define __IDxtCompositor_INTERFACE_DEFINED__ +#define __IDxtAlphaSetter_INTERFACE_DEFINED__ +#define __IDxtJpeg_INTERFACE_DEFINED__ +#define __IDxtKey_INTERFACE_DEFINED__ +#include + +#define SAMPLE_GETTED WM_USER + 500 + +class DecompressorType +{ +public: + typedef enum { + None = 0, + AVI = 1, + MJPEG = 2 + } DECOMPTYPE, * LPDECOMPTYPE; +private: + DecompressorType() {} + ~DecompressorType() {} +}; + +// Inf Tee Filter +class DSInfTeeFilter : public DSFilterBase +{ +public: + DSInfTeeFilter():DSFilterBase(CLSID_InfTee) + { + } +}; + +class DSSmartTeeFilter : public DSFilterBase +{ +public: + DSSmartTeeFilter():DSFilterBase(CLSID_SmartTee) + { + } +}; + +class DSFileWritterBase: public DSFilterBase +{ +public: + HRESULT SetOutputFileName(LPWSTR lpwstrFileName); +public: + DSFileWritterBase(LPOLESTR szMoniker); + DSFileWritterBase(REFCLSID iid); +}; + +// File Writer Filter +class DSFileWriter: public DSFileWritterBase +{ +public: + DSFileWriter():DSFileWritterBase(CLSID_FileWriter) + { + } +}; + +// DSound Renderer +class DSDSoundRendererFilter : public DSFilterBase +{ +public: + DSDSoundRendererFilter():DSFilterBase(CLSID_DSoundRender) + { + } +}; + +// Sample Grabber +class CSampleCallBack +{ +protected: + GUID m_FormatType; + + LPBYTE m_lpFormat; + +public: + double m_dTimeStamp; + virtual void OnFormat(GUID guidFormatType,BYTE *pbFormat,long lFormatLength) + { + SAFECOTASKFREE(m_lpFormat); + m_FormatType = guidFormatType; + m_lpFormat = (LPBYTE)CoTaskMemAlloc(lFormatLength); + CopyMemory(m_lpFormat,pbFormat,lFormatLength); + } + virtual void OnSample(BYTE *pBuffer,long lBufferLen)PURE; +public: + CSampleCallBack() + :m_lpFormat(NULL) + ,m_FormatType(GUID_NULL) + { + + } + virtual ~CSampleCallBack() + { + SAFECOTASKFREE(m_lpFormat); + } + virtual HRESULT GetSampleTime(double& time)PURE; +}; + +class DSSampleGrabberFilter : public DSFilterBase +{ +private: + class SampleGrabberCB:public ISampleGrabberCB + { + public: + HWND m_hwnd; + UINT m_Message; + private: + ISampleGrabber * m_pISampleGrabber; + HANDLE m_hMutex; + BOOL m_bGrabbing; + BYTE * m_pbtBuffer; + long m_lBufferSize; + DWORD m_dwWidth; + DWORD m_dwHeight; + CSampleCallBack * m_pCallBack; + BOOL m_bFormatSetted; + public: + STDMETHODIMP_(ULONG) AddRef() { return 2; } + STDMETHODIMP_(ULONG) Release() { return 1; } + STDMETHODIMP QueryInterface(REFIID riid, void ** ppv) + { + if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown ) + { + *ppv = (void *) static_cast ( this ); + return NOERROR; + } + return E_NOINTERFACE; + } + public: + virtual HRESULT STDMETHODCALLTYPE BufferCB(double SampleTime,BYTE *pBuffer,long BufferLen); + virtual HRESULT STDMETHODCALLTYPE SampleCB(double SampleTime,IMediaSample *pSample); + public: + HRESULT SetCallback(CSampleCallBack * pCallBack); + BOOL Grab(BYTE ** ppbtBuffer,long * plBufferSize); + public: + SampleGrabberCB(ISampleGrabber * pISampleGrabber) + : m_pISampleGrabber(pISampleGrabber) + , m_hMutex(INVALID_HANDLE_VALUE) + , m_bGrabbing(FALSE) + , m_pbtBuffer(NULL) + , m_lBufferSize(0) + , m_dwWidth(0) + , m_dwHeight(0) + , m_pCallBack(NULL) + , m_bFormatSetted(FALSE) + { + m_hMutex = CreateMutex(NULL,FALSE,NULL); + } + ~SampleGrabberCB() + { + m_pCallBack = NULL; + SAFECOTASKFREE(m_pbtBuffer); + m_lBufferSize = 0; + CloseHandle(m_hMutex); + m_hMutex = INVALID_HANDLE_VALUE; + } + }; +protected: + SampleGrabberCB * m_pCB; + ISampleGrabber * m_pISampleGrabber; +public: + BOOL Grab(BYTE ** ppbtBuffer,long * plBufferSize); + HRESULT SetMediaType(AM_MEDIA_TYPE mt); + HRESULT GetMediaType(AM_MEDIA_TYPE * pmt); + HRESULT SetCallback(CSampleCallBack * pCallBack); + HRESULT SetCallback(ISampleGrabberCB *pCallback,long WhichMethodToCallback = 0); + HRESULT SetOneShot(BOOL bOneShot = FALSE); + void SetCallbackWnd(HWND wnd, UINT message); + bool IsFrameReady(); +public: + DSSampleGrabberFilter(); + virtual ~DSSampleGrabberFilter(); +}; + +// WM ASF Writer +class DSWMAsfWritter : public DSFileWritterBase +{ +public: + DSWMAsfWritter(): DSFileWritterBase(CLSID_WMAsfWriter) + { + } +}; + +// Default Video Renderer +class DSVideoRenderer: public DSFilterBase +{ +public: + DSVideoRenderer():DSFilterBase(CLSID_VideoRenderer) + { + } +}; + +// VMR Renderer +class DSVMRRenderer: public DSFilterBase +{ +public: + DSVMRRenderer():DSFilterBase(CLSID_VideoMixingRenderer9) + { + } +}; + +// Avi Muxer +class DSAviMuxFilter: public DSFilterBase +{ +public: + DSAviMuxFilter():DSFilterBase(CLSID_AviDest) + { + } +}; + +// Avi Decompressor +class DSAviDecompressorFilter: public DSFilterBase +{ +public: + DSAviDecompressorFilter():DSFilterBase(CLSID_AVIDec) + { + } +}; + +// MJPEG Decompressor Filter +class DSMJPEGDecompressorFilter: public DSFilterBase +{ +public: + DSMJPEGDecompressorFilter():DSFilterBase(CLSID_MjpegDec) + { + } +}; + +class DSNullRenderer: public DSFilterBase +{ +public: + DSNullRenderer():DSFilterBase(CLSID_NullRenderer) + { + } +}; + +#endif \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/DirectShow/Include/DSObjectBase.h b/VideoSourceDirectShow/DSNative/DirectShow/Include/DSObjectBase.h new file mode 100644 index 0000000..3eae5ce --- /dev/null +++ b/VideoSourceDirectShow/DSNative/DirectShow/Include/DSObjectBase.h @@ -0,0 +1,25 @@ + +#ifndef __DS_OBJECT_BASE_H__ +#define __DS_OBJECT_BASE_H__ + +#include +#include "DSCommon.h" +#include + +class DSObjectBase +{ +protected: + bool m_bReleaseOnDestroy; +public: + bool get_ReleaseOnDestroy(); + void set_ReleaseOnDestroy(bool bReleaseOnDestroy); +public: + virtual void Release(); + virtual HRESULT QueryInterface(const IID &riid,void ** ppvObject); +protected: + DSObjectBase(); +public: + virtual ~DSObjectBase(); +}; + +#endif \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSCategoryHelper.cpp b/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSCategoryHelper.cpp new file mode 100644 index 0000000..b21912f --- /dev/null +++ b/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSCategoryHelper.cpp @@ -0,0 +1,242 @@ + +#include "../Include/DSCategoryHelper.h" + +DSCategory::DSCategory(REFCLSID clsidCategory) + : DSObjectBase() + , m_clsidCategory(clsidCategory) + , m_pDevEnum(NULL) + , m_pEnumMoniker(NULL) +{ + HRESULT hr = CoCreateInstance( + CLSID_SystemDeviceEnum, + NULL, + CLSCTX_INPROC_SERVER, + IID_ICreateDevEnum, + (void**) &m_pDevEnum); + + ASSERT(hr == S_OK && m_pDevEnum != NULL); + + hr = m_pDevEnum->CreateClassEnumerator( + m_clsidCategory, + &m_pEnumMoniker, + 0); + + //ASSERT(hr == S_OK && m_pEnumMoniker != NULL); +} + +DSCategory::~DSCategory() +{ +} + +void DSCategory::Release() +{ + SAFERELEASE(m_pDevEnum); + SAFERELEASE(m_pEnumMoniker); +} + +HRESULT DSCategory::QueryInterface(const IID &riid,void ** ppvObject) +{ + HRESULT hr = E_NOINTERFACE; + if (m_pEnumMoniker) + { + hr = m_pEnumMoniker->QueryInterface(riid,ppvObject); + } + if (hr == S_OK) return hr; + if (m_pDevEnum) return m_pDevEnum->QueryInterface(riid,ppvObject); + return E_NOINTERFACE; +} + +HRESULT DSCategory::GetFiltersCount(long & lCount) +{ + lCount = 0; + if (!m_pEnumMoniker) return NOERROR; + m_pEnumMoniker->Reset(); + while(1) + { + ULONG cFetched = 0; + CComPtr< IMoniker > pMoniker; + + HRESULT hr = m_pEnumMoniker->Next(1, &pMoniker, &cFetched); + if(!pMoniker || hr != S_OK) break; + + CComPtr< IPropertyBag > pBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**) &pBag); + if(!FAILED(hr)) + { + lCount++; + pBag.Release(); + } + pMoniker.Release(); + } + + return S_OK; +} + +HRESULT DSCategory::GetFilterName(long lNumber, LPWSTR * plpwstrDevName) +{ + * plpwstrDevName = NULL; + HRESULT hr = S_OK; + if (!m_pEnumMoniker) return E_FAIL; + m_pEnumMoniker->Reset(); + while(1) + { + ULONG cFetched = 0; + CComPtr< IMoniker > pMoniker; + + hr = m_pEnumMoniker->Next(1, &pMoniker, &cFetched); + if(!pMoniker || hr != S_OK) break; + if (lNumber > 0) + { + lNumber--; + pMoniker.Release(); + continue; + } + + CComPtr< IPropertyBag > pBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**) &pBag); + if(!FAILED(hr)) + { + VARIANT var; + VariantInit(&var); + //var.vt = VT_BSTR; + //hr = pBag->Read(L"FilterData",&var, NULL); + //if (S_OK == hr) VariantClear(&var); + //hr = pBag->Read(L"CLSID",&var, NULL); + //if (S_OK == hr) VariantClear(&var); + hr = pBag->Read(L"FriendlyName",&var, NULL); + if(hr == NOERROR) + { + *plpwstrDevName = new WCHAR[MAX_PATH]; + wcscpy_s(*plpwstrDevName, MAX_PATH, var.bstrVal); + //SysFreeString(var.bstrVal); + VariantClear(&var); + } + pBag.Release(); + } + pMoniker.Release(); + break; + } + if (!(*plpwstrDevName)) hr = E_FAIL; + return hr; +} + +HRESULT DSCategory::GetDeviceFilter(long lNumber, IBaseFilter ** ppOutFilter) +{ + HRESULT hr = S_OK; + (*ppOutFilter) = NULL; + if (!m_pEnumMoniker) return E_FAIL; + m_pEnumMoniker->Reset(); + while(1) + { + ULONG cFetched = 0; + CComPtr< IMoniker > pMoniker; + + hr = m_pEnumMoniker->Next(1, &pMoniker, &cFetched); + if(!pMoniker || hr != S_OK) break; + if (lNumber > 0) + { + lNumber--; + pMoniker.Release(); + continue; + } + CComPtr< IPropertyBag > pBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**) &pBag); + if(SUCCEEDED(hr)) + { + VARIANT var; + VariantInit(&var); + hr = pBag->Read(L"FriendlyName",&var, NULL); + if(FAILED(hr)) + { + hr = pBag->Read(L"Description",&var, NULL); + } + VariantClear(&var); + pBag.Release(); + if (SUCCEEDED(hr)) + { + hr = BindMoniker(pMoniker,0,IID_IBaseFilter, (void**)ppOutFilter); + //hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)ppOutFilter); + } + } + pMoniker.Release(); + break; + } + if (hr == S_OK && (*ppOutFilter) == NULL) hr = E_FAIL; + return hr; +} + +HRESULT DSCategory::GetFilterMonikerString(long lNumber, LPWSTR * plpwstrDevMoniker) +{ + * plpwstrDevMoniker = NULL; + HRESULT hr = S_OK; + if (!m_pEnumMoniker) return E_FAIL; + m_pEnumMoniker->Reset(); + while(1) + { + ULONG cFetched = 0; + CComPtr< IMoniker > pMoniker; + + hr = m_pEnumMoniker->Next(1, &pMoniker, &cFetched); + if(!pMoniker || hr != S_OK) break; + if (lNumber > 0) + { + lNumber--; + pMoniker.Release(); + continue; + } + /* + CLSID _clsid; + hr = pMoniker->GetClassID(&_clsid); + _clsid = GUID_NULL; + + */ + CComPtr pBindCtx = NULL; + hr = CreateBindCtx(NULL,&pBindCtx); + + LPOLESTR lpolestrTemp = NULL; + hr = pMoniker->GetDisplayName(pBindCtx,NULL,&lpolestrTemp); + + *plpwstrDevMoniker = new WCHAR[MAX_PATH]; + wcscpy_s(*plpwstrDevMoniker, MAX_PATH, lpolestrTemp); + //*plpwstrDevMoniker + + pBindCtx.Release(); + pMoniker.Release(); + break; + } + if (!(*plpwstrDevMoniker)) hr = E_FAIL; + return hr; +} +long DSCategory::get_Count() +{ + long lResult = -1; + if (GetFiltersCount(lResult) == S_OK) return lResult; + return -1; +} + +LPWSTR DSCategory::GetName(long lNumber) +{ + LPWSTR lpwstrName = NULL; + if (GetFilterName(lNumber,(WCHAR**)&lpwstrName) == S_OK) return lpwstrName; + return NULL; +} + +DSFilterBase * DSCategory::GetDevice(long lNumber) +{ + IBaseFilter * pFilter = NULL; + if (SUCCEEDED(GetDeviceFilter(lNumber, &pFilter))) + { + return new DSFilterBase(pFilter); + } + return NULL; +} + +LPWSTR DSCategory::GetDeviceMonikerString(long lNumber) +{ + LPWSTR lpwstrName = NULL; + if (GetFilterMonikerString(lNumber,(WCHAR**)&lpwstrName) == S_OK) + { + return lpwstrName; + } + return NULL; +} diff --git a/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSFileWriter.cpp b/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSFileWriter.cpp new file mode 100644 index 0000000..9a9e29c --- /dev/null +++ b/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSFileWriter.cpp @@ -0,0 +1,26 @@ + +#include "../Include/DSFiltersDefinition.h" + +DSFileWritterBase::DSFileWritterBase(LPOLESTR szMoniker) + : DSFilterBase(szMoniker) +{ + m_bReleaseOnDestroy = true; +} + +DSFileWritterBase::DSFileWritterBase(REFCLSID iid) + : DSFilterBase(iid) +{ + m_bReleaseOnDestroy = true; +} + +HRESULT DSFileWritterBase::SetOutputFileName(LPWSTR lpwstrFileName) +{ + if (!m_pFilter) return E_POINTER; + CComPtr pSinkFilter; + HRESULT hr = m_pFilter->QueryInterface(IID_IFileSinkFilter,(void**)&pSinkFilter); + SAFECHECK(hr); + DeleteFileW(lpwstrFileName); + hr = pSinkFilter->SetFileName(lpwstrFileName, NULL); + SAFECHECK(hr); + return S_OK; +} \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSFilter.cpp b/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSFilter.cpp new file mode 100644 index 0000000..3e3570a --- /dev/null +++ b/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSFilter.cpp @@ -0,0 +1,392 @@ + +#include "../Include/DSFilter.h" + +//#define USE_NON_CRITICAL_ASSERTS + +DSFilterBase::DSFilterBase() + : DSObjectBase() + , m_pFilter(NULL) +{ +} + +DSFilterBase::DSFilterBase(LPOLESTR szMoniker) + : DSObjectBase() + , m_pFilter(NULL) +{ + HRESULT hr = GetFilterByMoniker(szMoniker); +#ifdef USE_NON_CRITICAL_ASSERTS + ASSERT(hr == S_OK); +#endif +} + +DSFilterBase::DSFilterBase(REFCLSID iid) + : DSObjectBase() + , m_pFilter(NULL) +{ + HRESULT hr = CoCreateInstance(iid, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&m_pFilter); +#ifdef USE_NON_CRITICAL_ASSERTS + ASSERT(hr == S_OK); +#endif +} + +DSFilterBase::DSFilterBase(IBaseFilter * pFilter, bool bReleaseOnDestroy) + : DSObjectBase() + , m_pFilter(pFilter) +{ + m_bReleaseOnDestroy = bReleaseOnDestroy; +#ifdef USE_NON_CRITICAL_ASSERTS + ASSERT(m_pFilter != NULL); +#endif +} + +DSFilterBase::~DSFilterBase() +{ + if (m_bReleaseOnDestroy) Release(); +} + +HRESULT DSFilterBase::QueryInterface(const IID &riid,void ** ppvObject) +{ + return m_pFilter->QueryInterface(riid,ppvObject); +} + +void DSFilterBase::Release() +{ + SAFERELEASE(m_pFilter); +} + +bool DSFilterBase::HaveProperties() +{ + CComPtr< ISpecifyPropertyPages > pPropertyPages; + HRESULT hr = S_OK; + hr = m_pFilter->QueryInterface(IID_ISpecifyPropertyPages,(void **)&pPropertyPages); + return SUCCEEDED(hr); +} + +HRESULT DSFilterBase::ShowProperties(HWND hwndParent) +{ + CComPtr< ISpecifyPropertyPages > pPropertyPages; + HRESULT hr = S_OK; + hr = m_pFilter->QueryInterface(IID_ISpecifyPropertyPages,(void **)&pPropertyPages); + if (FAILED(hr)) return hr; + CAUUID caGUID; + hr = pPropertyPages->GetPages(&caGUID); + if (FAILED(hr)) return hr; + + IUnknown * pFilterUnk; + hr = m_pFilter->QueryInterface(IID_IUnknown, (void **)&pFilterUnk); + if (FAILED(hr)) return hr; + + FILTER_INFO fiInfo; + hr = m_pFilter->QueryFilterInfo(&fiInfo); + if (FAILED(hr)) return hr; + + hr = OleCreatePropertyFrame(hwndParent,0,0,fiInfo.achName,1, &pFilterUnk, caGUID.cElems,caGUID.pElems,NULL, 0, NULL); + SAFERELEASE(pFilterUnk); + CoTaskMemFree(caGUID.pElems); + SAFERELEASE(fiInfo.pGraph); + return hr; +} +bool DSFilterBase::GetIBaseFilter(IBaseFilter ** pIBaseFilter) +{ + *pIBaseFilter = m_pFilter; + return true; +} + +HRESULT DSFilterBase::AddToFilterGraph(IGraphBuilder * pGraphBuilder) +{ + ASSERT(pGraphBuilder != NULL); + return pGraphBuilder->AddFilter(m_pFilter,NULL); +} + +HRESULT DSFilterBase::RemoveFromFilterGraph(IGraphBuilder * pGraphBuilder) +{ + ASSERT(pGraphBuilder != NULL); + return pGraphBuilder->RemoveFilter(m_pFilter); +} + +IPin * DSFilterBase::GetPinByDirection(PIN_DIRECTION direction,long lPinNumber) +{ + IPin * pPin = NULL; + HRESULT hr = S_OK; + + CComPtr pEnumPins; + + hr = m_pFilter->EnumPins(&pEnumPins); +#ifdef USE_NON_CRITICAL_ASSERTS + ASSERT( S_OK == hr ); +#endif + if(!FAILED(hr)) + { + while (pEnumPins->Next(1, &pPin, NULL) == S_OK) + { + PIN_DIRECTION pinDirection; + hr = pPin->QueryDirection(&pinDirection); + ASSERT( S_OK == hr ); + if(pinDirection != direction) + { + pPin->Release(); + continue; + } + if(lPinNumber > 0) + { + lPinNumber--; + pPin->Release(); + continue; + } + break; + } + pEnumPins.Release(); + } + return pPin; +} + + +IPin * DSFilterBase::GetPinByCategory(REFGUID guidPinCategory) +{ + IPin * pPin = NULL; + HRESULT hr = S_OK; + + CComPtr pEnumPins; + + hr = m_pFilter->EnumPins(&pEnumPins); +#ifdef USE_NON_CRITICAL_ASSERTS + ASSERT( S_OK == hr ); +#endif + if(!FAILED(hr)) + { + while (pEnumPins->Next(1, &pPin, NULL) == S_OK) + { + CComPtr pPropertySet; + hr = pPin->QueryInterface(IID_IKsPropertySet,(void**)&pPropertySet); + if (hr == S_OK) + { + GUID guidOutput; + DWORD dwReturned; + hr = pPropertySet->Get(AMPROPSETID_Pin,AMPROPERTY_PIN_CATEGORY,NULL,NULL,(PVOID)&guidOutput,sizeof(GUID),&dwReturned); + if (hr == S_OK && guidOutput == guidPinCategory) + { + pPropertySet.Release(); + break; + } + pPropertySet.Release(); + } + pPin->Release(); + pPin = NULL; + } + pEnumPins.Release(); + } + return pPin; +} + +HRESULT DSFilterBase::GetFilterByMoniker(LPOLESTR szMoniker) +{ + HRESULT hr = S_OK; + + m_pFilter = NULL; + + CComPtr pBindCtx; + hr = CreateBindCtx(0, &pBindCtx); + ASSERT( S_OK == hr ); + + ULONG chEaten = 0; + CComPtr pIMoniker; + hr = MkParseDisplayName(pBindCtx, szMoniker, &chEaten, &pIMoniker); + pBindCtx.Release(); + if (SUCCEEDED(hr)) + { + // Get the display name, or bind to a DirectShow filter. + hr = pIMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_pFilter); +#ifdef USE_NON_CRITICAL_ASSERTS + ASSERT( S_OK == hr ); +#endif + if (FAILED(hr)) m_pFilter = NULL; + pIMoniker.Release(); + } + if(m_pFilter == NULL && SUCCEEDED(hr)) hr = -1; + return hr; +} + + +HRESULT DSFilterBase::GetOutputPinCapabilitiesCount(IPin * pPin, int *piCount) +{ + *piCount = -1; + HRESULT hr; + /* + CComPtr pEnum; + hr = pPin->EnumMediaTypes(&pEnum); + if (hr == S_OK && pEnum != NULL) + { + pEnum->Reset(); + AM_MEDIA_TYPE * pmt = NULL; + int iCount = 0; + while (hr == S_OK) + { + hr = pEnum->Next(1,&pmt, NULL); + if (hr == S_OK && pmt != NULL) + { + iCount++; + DeleteMediaType(pmt); + } + } + hr = S_OK; + if (iCount != 0) *piCount = iCount; + pEnum.Release(); + } + */ + + CComPtr pStreamConfig; + hr = pPin->QueryInterface(IID_IAMStreamConfig,(void**)&pStreamConfig); + if (hr == S_OK && pStreamConfig != NULL) + { + int iSize; + hr = pStreamConfig->GetNumberOfCapabilities(piCount,&iSize); + pStreamConfig.Release(); + } + + return hr; +} + +HRESULT DSFilterBase::GetOutputPinCapabilitiesCount(long lPinNumber, int *piCount) +{ + *piCount = -1; + IPin * pPin = GetPinByDirection(PINDIR_OUTPUT, lPinNumber); + if (pPin == NULL) return E_FAIL; + HRESULT hr = GetOutputPinCapabilitiesCount(pPin,piCount); + pPin->Release(); + return hr; +} + +HRESULT DSFilterBase::GetOutputPinCapabilitiesCount(REFGUID guidPinCategory, int *piCount) +{ + *piCount = -1; + IPin * pPin = GetPinByCategory(guidPinCategory); + if (pPin == NULL) return E_FAIL; + HRESULT hr = GetOutputPinCapabilitiesCount(pPin,piCount); + pPin->Release(); + return hr; +} + +HRESULT DSFilterBase::GetOutputPinCapabilities(long lPinNumber, int iCapNumber, AM_MEDIA_TYPE ** ppmt) +{ + IPin * pPin = GetPinByDirection(PINDIR_OUTPUT, lPinNumber); + if (pPin == NULL) return E_FAIL; + HRESULT hr = GetOutputPinCapabilities(pPin,iCapNumber,ppmt); + pPin->Release(); + return hr; +} + + +HRESULT DSFilterBase::GetOutputPinCapabilities(IPin * pPin, int iCapNumber, AM_MEDIA_TYPE ** ppmt) +{ + *ppmt = NULL; + HRESULT hr; +/* + CComPtr pEnum; + hr = pPin->EnumMediaTypes(&pEnum); + if (hr == S_OK && pEnum != NULL) + { + pEnum->Reset(); + AM_MEDIA_TYPE * pmt = NULL; + while (hr == S_OK) + { + hr = pEnum->Next(1,&pmt, NULL); + if (iCapNumber > 0) + { + iCapNumber--; + DeleteMediaType(pmt); + } + else + { + *ppmt = pmt; + } + } + if (*ppmt == NULL) hr = E_FAIL; else hr = S_OK; + pEnum.Release(); + } +*/ + CComPtr pStreamConfig; + hr = pPin->QueryInterface(IID_IAMStreamConfig,(void**)&pStreamConfig); + if (hr == S_OK && pStreamConfig != NULL) + { + int iCount, iSize; + hr = pStreamConfig->GetNumberOfCapabilities(&iCount,&iSize); + if (iCapNumber >= 0 && iCount > iCapNumber) + { + LPBYTE pbtSCC = (LPBYTE)CoTaskMemAlloc(iSize); + hr = pStreamConfig->GetStreamCaps(iCapNumber,ppmt,pbtSCC); + CoTaskMemFree(pbtSCC); + } + pStreamConfig.Release(); + } + return hr; +} + +HRESULT DSFilterBase::GetOutputPinCapabilities(REFGUID guidPinCategory, int iCapNumber, AM_MEDIA_TYPE ** ppmt) +{ + IPin * pPin = GetPinByCategory(guidPinCategory); + if (pPin == NULL) return E_FAIL; + HRESULT hr = GetOutputPinCapabilities(pPin,iCapNumber,ppmt); + pPin->Release(); + return hr; +} + +HRESULT DSFilterBase::GetOutputPinFormat(IPin * pPin, AM_MEDIA_TYPE ** ppmt) +{ + *ppmt = NULL; + CComPtr pStreamConfig; + HRESULT hr = pPin->QueryInterface(IID_IAMStreamConfig,(void**)&pStreamConfig); + if (hr == S_OK && pStreamConfig != NULL) + { + hr = pStreamConfig->GetFormat(ppmt); + pStreamConfig.Release(); + } + return hr; +} + +HRESULT DSFilterBase::GetOutputPinFormat(long lPinNumber, AM_MEDIA_TYPE ** ppmt) +{ + IPin * pPin = GetPinByDirection(PINDIR_OUTPUT, lPinNumber); + if (pPin == NULL) return E_FAIL; + HRESULT hr = GetOutputPinFormat(pPin,ppmt); + pPin->Release(); + return hr; +} + +HRESULT DSFilterBase::GetOutputPinFormat(REFGUID guidPinCategory, AM_MEDIA_TYPE ** ppmt) +{ + IPin * pPin = GetPinByCategory(guidPinCategory); + if (pPin == NULL) return E_FAIL; + HRESULT hr = GetOutputPinFormat(pPin,ppmt); + pPin->Release(); + return hr; +} + +HRESULT DSFilterBase::SetOutputPinFormat(long lPinNumber, AM_MEDIA_TYPE * pmt) +{ + IPin * pPin = GetPinByDirection(PINDIR_OUTPUT, lPinNumber); + if (pPin == NULL) return E_FAIL; + HRESULT hr = SetOutputPinFormat(pPin,pmt); + pPin->Release(); + return hr; +} + +HRESULT DSFilterBase::SetOutputPinFormat(IPin * pPin, AM_MEDIA_TYPE * pmt) +{ + CComPtr pStreamConfig; + HRESULT hr = pPin->QueryInterface(IID_IAMStreamConfig,(void**)&pStreamConfig); + if (hr == S_OK && pStreamConfig != NULL) + { + hr = pStreamConfig->SetFormat(pmt); + pStreamConfig.Release(); + } + return hr; +} + +HRESULT DSFilterBase::SetOutputPinFormat(REFGUID guidPinCategory, AM_MEDIA_TYPE * pmt) +{ + IPin * pPin = GetPinByCategory(guidPinCategory); + if (pPin == NULL) return E_FAIL; + HRESULT hr = SetOutputPinFormat(pPin,pmt); + pPin->Release(); + return hr; +} diff --git a/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSFilterGraphBase.cpp b/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSFilterGraphBase.cpp new file mode 100644 index 0000000..6c95fd7 --- /dev/null +++ b/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSFilterGraphBase.cpp @@ -0,0 +1,485 @@ + +#include "../Include/DSFilterGraphBase.h" + +DSFilterGraphBase::DSFilterGraphBase() + : m_pGraphBuilder(NULL) +#ifdef USE_DS_OBJECT + , DSObjectBase() +#endif + , m_pMediaControl(NULL) + , m_pVideoWindow(NULL) + , m_pMediaEventEx(NULL) + , m_pMediaSeeking(NULL) + , m_hWnd(NULL) + , m_hWndNotify(NULL) + , m_bShouldPreview(true) + , m_pBasicAudio(NULL) + , m_pBasicVideo(NULL) + , m_bMute(false) + , m_iVolume(0) +#ifdef ROT_DEBUG + , m_pDSYoooROTFilter(NULL) +#endif +{ +} + +DSFilterGraphBase::~DSFilterGraphBase() +{ + Stop(); + CloseInterfaces(); +} + +STDMETHODIMP DSFilterGraphBase::Start() +{ + HRESULT hr = S_OK; + if (!m_pMediaControl) + { + hr = InitInterfaces(); + CHECKRET(hr == S_OK,hr); + CHECKRET(m_pMediaControl,E_FAIL); + } + SetVolume(m_iVolume); + hr = S_FALSE; + while (hr == S_FALSE) + { + hr = m_pMediaControl->Run(); + if (hr == S_FALSE) Sleep(50); + } + return hr; +} + +STDMETHODIMP DSFilterGraphBase::Stop() +{ + CHECKRET(m_pMediaControl,E_FAIL); + m_pMediaControl->Stop(); + return CloseInterfaces(); +} + +STDMETHODIMP DSFilterGraphBase::Pause() +{ + if (!m_pMediaControl) + { + HRESULT hr = Start(); + hr = InitInterfaces(); + CHECKRET(hr == S_OK,hr); + } + return m_pMediaControl->Pause(); +} + +HRESULT DSFilterGraphBase::InitInterfaces() +{ + try + { + CloseInterfaces(); + HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, + IID_IGraphBuilder, (void **)&m_pGraphBuilder); + SAFECHECK(hr); + +#ifdef ROT_DEBUG + m_pDSYoooROTFilter = new DSYoooROTFilter(); + hr = m_pDSYoooROTFilter->AddToFilterGraph(m_pGraphBuilder); + SAFECHECK(hr); +#endif + return S_OK; + } + catch (...) + { + return E_FAIL; + } +} + +HRESULT DSFilterGraphBase::CloseInterfaces() +{ +#ifdef ROT_DEBUG + if (m_pGraphBuilder && m_pDSYoooROTFilter) m_pDSYoooROTFilter->RemoveFromFilterGraph(m_pGraphBuilder); + SAFEDELETE(m_pDSYoooROTFilter); +#endif + if (m_pMediaEventEx) + { + m_pMediaEventEx->SetNotifyWindow(NULL,NULL,NULL); + SAFERELEASE(m_pMediaEventEx); + } + if (m_pVideoWindow) + { + m_pVideoWindow->put_Visible(FALSE); + m_pVideoWindow->put_Owner(NULL); + SAFERELEASE(m_pVideoWindow); + } + SAFERELEASE(m_pMediaSeeking); + SAFERELEASE(m_pBasicVideo); + SAFERELEASE(m_pBasicAudio); + SAFERELEASE(m_pMediaControl); + SAFERELEASE(m_pGraphBuilder); + return S_OK; +} + +HWND DSFilterGraphBase::get_NotifyWindow() +{ + return m_hWndNotify; +} + +void DSFilterGraphBase::set_NotifyWindow(HWND hWnd) +{ + m_hWndNotify = hWnd; +} + +HWND DSFilterGraphBase::get_PreviewWindow() +{ + return m_hWnd; +} + +void DSFilterGraphBase::set_PreviewWindow(HWND hWnd) +{ + m_hWnd = hWnd; +} + +bool DSFilterGraphBase::get_ShouldPreview() +{ + return m_bShouldPreview; +} + +void DSFilterGraphBase::set_ShouldPreview(bool bShouldPreview) +{ + m_bShouldPreview = bShouldPreview; + SettingUpVideoWindow(); +} + +HRESULT DSFilterGraphBase::PreparePlayback() +{ + HRESULT hr = m_pGraphBuilder->QueryInterface(IID_IMediaControl,(void**)&m_pMediaControl); + SAFECHECKCLOSE(hr); + hr = m_pGraphBuilder->QueryInterface(IID_IBasicVideo,(void**)&m_pBasicVideo); + hr = m_pGraphBuilder->QueryInterface(IID_IMediaSeeking,(void**)&m_pMediaSeeking); + hr = m_pGraphBuilder->QueryInterface(IID_IVideoWindow,(void**)&m_pVideoWindow); + if (hr != E_NOINTERFACE && m_pBasicVideo) SettingUpVideoWindow(); + if (m_hWndNotify) + { + hr = m_pGraphBuilder->QueryInterface(IID_IMediaEventEx,(void**)&m_pMediaEventEx); + hr = m_pMediaEventEx->SetNotifyWindow((OAHWND)m_hWndNotify,WM_GRAPH_NOTIFY,(LONG_PTR)this); + //::SetWindowLong(m_hWnd, GWL_STYLE, ::GetWindowLong(m_hWnd, GWL_STYLE) &~SS_GRAYRECT); + } + return hr; +} + +HRESULT DSFilterGraphBase::ProcessStepMessage() +{ + HRESULT bFinished = S_OK; + if (m_pMediaEventEx) + { + long lEventCode; + LONG_PTR lParam1,lParam2; + HRESULT hr = m_pMediaEventEx->GetEvent(&lEventCode,&lParam1,&lParam2,INFINITE); + if (SUCCEEDED(hr)) + { + bFinished = lEventCode == EC_STEP_COMPLETE ? S_FALSE : NOERROR; + hr = m_pMediaEventEx->FreeEventParams(lEventCode,lParam1,lParam2); + ASSERT(hr == S_OK); + } + } + return bFinished; +} + +HRESULT DSFilterGraphBase::ProcessGraphMessage() +{ + HRESULT bFinished = S_OK; + if (m_pMediaEventEx) + { + long lEventCode; + LONG_PTR lParam1,lParam2; + //HRESULT hr = m_pMediaEventEx->GetEvent(&lEventCode,&lParam1,&lParam2,INFINITE); + HRESULT hr = m_pMediaEventEx->GetEvent(&lEventCode,&lParam1,&lParam2,50); + if (SUCCEEDED(hr)) + { + bFinished = lEventCode == EC_COMPLETE ? S_FALSE : NOERROR; + hr = m_pMediaEventEx->FreeEventParams(lEventCode,lParam1,lParam2); + ASSERT(hr == S_OK); + } + } + return bFinished; +} + +bool DSFilterGraphBase::IsAudioSupported() +{ + if (!m_pBasicAudio) + { + if (m_pGraphBuilder) + { + if (SUCCEEDED(m_pGraphBuilder->QueryInterface(IID_IBasicAudio,(void**)&m_pBasicAudio))) + { + return true; + } + } + return false; + } + return true; +} + +void DSFilterGraphBase::SettingUpVideoWindow() +{ + if (m_pVideoWindow != NULL) + { + if (m_hWnd) + { + m_pVideoWindow->put_Owner((OAHWND)m_hWnd); + m_pVideoWindow->put_MessageDrain((OAHWND)m_hWnd); + m_pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS); + ResizeVideoWindow(); + } + if (!m_bShouldPreview) + { + m_pVideoWindow->put_AutoShow(OAFALSE); + m_pVideoWindow->put_Visible(OAFALSE); + } + else + { + m_pVideoWindow->put_AutoShow(OATRUE); + m_pVideoWindow->put_Visible(OATRUE); + } + } +} +void DSFilterGraphBase::ResizeVideoWindow() +{ + if (m_hWnd) + { + RECT rect; + GetClientRect(m_hWnd, &rect); + ResizeVideoWindow(rect); + } +} + +void DSFilterGraphBase::ResizeVideoWindow(RECT rect) +{ + if (m_pVideoWindow != NULL) m_pVideoWindow->SetWindowPosition(rect.left, rect.top, rect.right, rect.bottom); +} + +int DSFilterGraphBase::get_Volume() +{ + return m_iVolume; +} +void DSFilterGraphBase::set_Volume(int nVolume) +{ + m_iVolume = nVolume; + if (!m_bMute) + { + SetVolume(m_iVolume); + } +} + +bool DSFilterGraphBase::get_Mute() +{ + return m_bMute; +} + +void DSFilterGraphBase::set_Mute(bool bMute) +{ + m_bMute = bMute; + if (!m_bMute) + { + SetVolume(m_iVolume); + } + else + { + SetVolume(-10000); + } +} + + +HRESULT DSFilterGraphBase::SetVolume(int nVolume) +{ + if (!m_pBasicAudio) + { + if (m_pGraphBuilder) + { + HRESULT hr = m_pGraphBuilder->QueryInterface(IID_IBasicAudio,(void**)&m_pBasicAudio); + if (FAILED(hr)) return hr; + } + return E_NOINTERFACE; + } + return m_pBasicAudio->put_Volume(nVolume); +} + +void DSFilterGraphBase::set_VideoSize(RECT _rect) +{ + if (m_pBasicVideo != NULL) + { + HRESULT hr; + LONG lLeft,lTop,lWidth,lHeight; + lLeft = _rect.left; + lTop = _rect.top; + lHeight = _rect.bottom - lTop; + lWidth = _rect.right - lLeft; + hr = m_pBasicVideo->SetDestinationPosition(lLeft,lTop,lWidth,lHeight); + ASSERT(hr == S_OK); + } +} + +RECT DSFilterGraphBase::get_VideoSize() +{ + RECT _rect; + _rect.left = 0; + _rect.top = 0; + _rect.bottom = 0; + _rect.right = 0; + if (m_pBasicVideo != NULL) + { + HRESULT hr; + LONG lLeft,lTop,lWidth,lHeight; + hr = m_pBasicVideo->GetDestinationPosition(&lLeft,&lTop,&lWidth,&lHeight); + ASSERT(hr == S_OK); + _rect.left = lLeft; + _rect.top = lTop; + _rect.bottom = lTop + lHeight; + _rect.right = lLeft + lWidth; + } + return _rect; +} + +RECT DSFilterGraphBase::get_SourceVideoSize() +{ + RECT _rect; + _rect.left = 0; + _rect.top = 0; + _rect.bottom = 0; + _rect.right = 0; + if (m_pBasicVideo != NULL) + { + HRESULT hr; + LONG lLeft,lTop,lWidth,lHeight; + hr = m_pBasicVideo->GetSourcePosition(&lLeft,&lTop,&lWidth,&lHeight); + ASSERT(hr == S_OK); + _rect.left = lLeft; + _rect.top = lTop; + _rect.bottom = lTop + lHeight; + _rect.right = lLeft + lWidth; + } + return _rect; +} + +bool DSFilterGraphBase::IsRunning() +{ + if (m_pMediaControl) + { + OAFilterState _state; + HRESULT hr = m_pMediaControl->GetState(50,&_state); + ASSERT(hr == S_OK); + if (SUCCEEDED(hr)) + { + return (_state != State_Stopped); + } + } + return false; +} + +bool DSFilterGraphBase::IsPaused() +{ + if (m_pMediaControl) + { + OAFilterState _state; + HRESULT hr = m_pMediaControl->GetState(50,&_state); + ASSERT(hr == S_OK); + if (SUCCEEDED(hr)) + { + return (_state == State_Paused); + } + } + return false; +} +REFERENCE_TIME DSFilterGraphBase::get_Position() +{ + if (m_pMediaSeeking) + { + REFERENCE_TIME _time; + HRESULT hr = m_pMediaSeeking->GetCurrentPosition(&_time); + ASSERT(hr == S_OK); + if (SUCCEEDED(hr)) return _time; + } + return -1; +} +void DSFilterGraphBase::set_Position(REFERENCE_TIME _time) +{ + if (m_pMediaSeeking) + { + REFERENCE_TIME _stop = 0; + HRESULT hr = m_pMediaSeeking->SetPositions(&_time,AM_SEEKING_AbsolutePositioning,&_stop,AM_SEEKING_NoPositioning); + //ASSERT(hr == S_OK); + } +} + +REFERENCE_TIME DSFilterGraphBase::get_Duration() +{ + if (m_pMediaSeeking) + { + REFERENCE_TIME _time; + HRESULT hr = m_pMediaSeeking->GetDuration(&_time); + ASSERT(hr == S_OK); + if (SUCCEEDED(hr)) return _time; + } + return -1; +} + +IBaseFilter * DSFilterGraphBase::GetVideoRenderer() +{ + IBaseFilter * _filter = NULL; + if (m_pGraphBuilder) + { + HRESULT hr; + IEnumFilters * pEnumFilters; + hr = m_pGraphBuilder->EnumFilters(&pEnumFilters); + ASSERT(hr == S_OK); + if (SUCCEEDED(hr)) + { + IBaseFilter * pFilter; + ULONG ulFetched; + hr = pEnumFilters->Next(1,&pFilter,&ulFetched); + while (hr != S_FALSE) + { + IVideoWindow * pVideoWindow; + hr = pFilter->QueryInterface(IID_IVideoWindow,(void**)&pVideoWindow); + if (SUCCEEDED(hr)) + { + SAFERELEASE(pVideoWindow); + _filter = pFilter; + break; + } + SAFERELEASE(pFilter); + hr = pEnumFilters->Next(1,&pFilter,&ulFetched); + } + SAFERELEASE(pEnumFilters); + } + } + return _filter; +} + +IBaseFilter * DSFilterGraphBase::GetAudioRenderer() +{ + IBaseFilter * _filter = NULL; + if (m_pGraphBuilder) + { + HRESULT hr; + IEnumFilters * pEnumFilters; + hr = m_pGraphBuilder->EnumFilters(&pEnumFilters); + ASSERT(hr == S_OK); + if (SUCCEEDED(hr)) + { + IBaseFilter * pFilter; + ULONG ulFetched; + hr = pEnumFilters->Next(1,&pFilter,&ulFetched); + while (hr != S_FALSE) + { + IBasicAudio * pBasicAudio; + hr = pFilter->QueryInterface(IID_IBasicAudio,(void**)&pBasicAudio); + if (SUCCEEDED(hr)) + { + SAFERELEASE(pBasicAudio); + _filter = pFilter; + //_filter = new DSFilterBase(pFilter,true); + break; + } + SAFERELEASE(pFilter); + hr = pEnumFilters->Next(1,&pFilter,&ulFetched); + } + SAFERELEASE(pEnumFilters); + } + } + return _filter; +} \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSObjectBase.cpp b/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSObjectBase.cpp new file mode 100644 index 0000000..9fc0b70 --- /dev/null +++ b/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSObjectBase.cpp @@ -0,0 +1,23 @@ + +#include "../Include/DSObjectBase.h" +#include + +DSObjectBase::DSObjectBase() + : m_bReleaseOnDestroy(true) +{ + CoInitialize(NULL); +} + +DSObjectBase::~DSObjectBase() +{ + if (m_bReleaseOnDestroy) Release(); +} + +HRESULT DSObjectBase::QueryInterface(const IID &riid,void ** ppvObject) +{ + return E_NOINTERFACE; +} + +void DSObjectBase::Release() +{ +} diff --git a/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSSampleGrabber.cpp b/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSSampleGrabber.cpp new file mode 100644 index 0000000..ad57acc --- /dev/null +++ b/VideoSourceDirectShow/DSNative/DirectShow/Sources/DSSampleGrabber.cpp @@ -0,0 +1,200 @@ + +#include "../Include/DSFiltersDefinition.h" +#include + +DSSampleGrabberFilter::DSSampleGrabberFilter() + : DSFilterBase() + , m_pISampleGrabber(NULL) + , m_pCB(NULL) +{ + m_bReleaseOnDestroy = true; + HRESULT hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&m_pFilter); + THROWHR(hr); + hr = m_pFilter->QueryInterface(IID_ISampleGrabber,(void**)&m_pISampleGrabber); + THROWHR(hr); + m_pCB = new SampleGrabberCB(m_pISampleGrabber); + hr = m_pISampleGrabber->SetCallback(m_pCB,1); + THROWHR(hr); +} + +DSSampleGrabberFilter::~DSSampleGrabberFilter() +{ + if (m_pISampleGrabber) + { + m_pISampleGrabber->SetCallback(NULL,0); + SAFERELEASE(m_pISampleGrabber); + } + SAFEDELETE(m_pCB); +} + +HRESULT DSSampleGrabberFilter::SetMediaType(AM_MEDIA_TYPE mt) +{ + return m_pISampleGrabber->SetMediaType(&mt); +} + +HRESULT DSSampleGrabberFilter::SetCallback(ISampleGrabberCB *pCallback,long WhichMethodToCallback) +{ + SAFEDELETE(m_pCB); + return m_pISampleGrabber->SetCallback(pCallback,WhichMethodToCallback); +} + +void DSSampleGrabberFilter::SetCallbackWnd( HWND wnd, UINT message ) +{ + m_pCB->m_hwnd = wnd; + m_pCB->m_Message = message; +} + +HRESULT DSSampleGrabberFilter::SetCallback(CSampleCallBack * pCallBack) +{ + if (m_pCB) + { + return m_pCB->SetCallback(pCallBack); + } + return E_FAIL; +} +HRESULT DSSampleGrabberFilter::GetMediaType(AM_MEDIA_TYPE * pmt) +{ + CheckPointer(pmt,E_POINTER); + if (m_pISampleGrabber) + { + return m_pISampleGrabber->GetConnectedMediaType(pmt); + } + return E_FAIL; +} + +HRESULT DSSampleGrabberFilter::SetOneShot( BOOL bOneShot /*= FALSE*/ ) +{ + m_pISampleGrabber->SetOneShot(bOneShot); + return S_FALSE; +} + +BOOL DSSampleGrabberFilter::Grab(BYTE ** ppbtBuffer,long * plBufferSize) +{ + if (m_pCB) + { + return m_pCB->Grab(ppbtBuffer,plBufferSize); + } + return FALSE; +} + +HRESULT DSSampleGrabberFilter::SampleGrabberCB::SetCallback(CSampleCallBack * pCallBack) +{ + if (m_pCallBack != pCallBack) + { + if (WaitForSingleObject(m_hMutex,INFINITE) == WAIT_OBJECT_0) + { + m_bFormatSetted = FALSE; + m_pCallBack = pCallBack; + ReleaseMutex(m_hMutex); + return NOERROR; + } + } + return E_FAIL; +} + +BOOL DSSampleGrabberFilter::SampleGrabberCB::Grab(BYTE ** ppbtBuffer,long * plBufferSize) +{ + if (WaitForSingleObject(m_hMutex,INFINITE) == WAIT_OBJECT_0) + { + m_bGrabbing = TRUE; + ReleaseMutex(m_hMutex); + } + while(m_bGrabbing) + { + Sleep(50); + } + + if (*ppbtBuffer == NULL) + { + *ppbtBuffer = static_cast(CoTaskMemAlloc(m_lBufferSize)); + } + + LPBYTE lpbtTemp = *ppbtBuffer; + DWORD _pitch = m_dwWidth * 3; + + auto segmentCount = max(1, omp_get_num_procs() / 4); + auto segmentLength = m_dwHeight / segmentCount; + auto i = 0; + + // Rotate and reset BGR to RGB + #pragma omp parallel for private(i) shared(lpbtTemp) + for (i = 0; i < segmentCount; ++i) + { + DWORD start = segmentLength * i; + DWORD end = start + segmentLength; + for (DWORD y = start; y < end; ++y) + { + for (DWORD x = 0; x < _pitch; x += 3) + { + lpbtTemp[y * _pitch + x] = m_pbtBuffer[(m_dwHeight - (y + 1)) * _pitch + x + 2]; + lpbtTemp[y * _pitch + x + 1] = m_pbtBuffer[(m_dwHeight - (y + 1)) * _pitch + x + 1]; + lpbtTemp[y * _pitch + x + 2] = m_pbtBuffer[(m_dwHeight - (y + 1)) * _pitch + x]; + } + } + } + // Rotate + /* + for (DWORD y = 0; y < m_dwHeight; y++) + { + for (DWORD x = 0;x < _pitch; x++) + { + lpbtTemp[y * _pitch + x] = m_pbtBuffer[(m_dwHeight - (y + 1)) * _pitch + x]; + } + } + */ + + *plBufferSize = m_lBufferSize; + return TRUE; +} + +HRESULT STDMETHODCALLTYPE DSSampleGrabberFilter::SampleGrabberCB::BufferCB(double SampleTime,BYTE *pBuffer,long BufferLen) +{ + if (WaitForSingleObject(m_hMutex,INFINITE) == WAIT_OBJECT_0) + { + if (!m_bFormatSetted) + { + if (m_pISampleGrabber) + { + AM_MEDIA_TYPE mt; + if (SUCCEEDED(m_pISampleGrabber->GetConnectedMediaType(&mt))) + { + VIDEOINFOHEADER *vih = (VIDEOINFOHEADER*) mt.pbFormat; + m_dwWidth = vih->bmiHeader.biWidth; + m_dwHeight = vih->bmiHeader.biHeight; + if (m_pCallBack) + { + m_pCallBack->OnFormat(mt.formattype,mt.pbFormat,mt.cbFormat); + } + m_bFormatSetted = TRUE; + FreeMediaType(mt); + } + } + } + if (m_pCallBack) + { + m_pCallBack->OnSample(pBuffer,BufferLen); + m_pCallBack->m_dTimeStamp = SampleTime; + } + if (m_bGrabbing) + { + if (m_lBufferSize != BufferLen) + { + SAFECOTASKFREE(m_pbtBuffer); + } + if (!m_pbtBuffer) + { + m_pbtBuffer = (LPBYTE)CoTaskMemAlloc(BufferLen); + } + m_lBufferSize = BufferLen; + CopyMemory(m_pbtBuffer,pBuffer,m_lBufferSize); + m_bGrabbing = FALSE; + } + ReleaseMutex(m_hMutex); + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE DSSampleGrabberFilter::SampleGrabberCB::SampleCB(double SampleTime,IMediaSample *pSample) +{ + return S_OK; +} \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/Format.cpp b/VideoSourceDirectShow/DSNative/Format.cpp new file mode 100644 index 0000000..129c53e --- /dev/null +++ b/VideoSourceDirectShow/DSNative/Format.cpp @@ -0,0 +1,248 @@ +#include "stdwx.h" +#include "Format.h" +#include +#include "DirectShow\Include\DSCommon.h" + +CVideoFormats::CVideoFormats(IAMStreamConfig * pConfig) + //: CFactoryObject() + : m_pConfig(pConfig) +{ + if (m_pConfig) + { + m_pConfig->AddRef(); + } +} + +CVideoFormats::~CVideoFormats() +{ + SAFERELEASE(m_pConfig); +} + +SIZE CVideoFormats::get_Resolution() +{ + SIZE _size; + _size.cx = 0; + _size.cy = 0; + if (m_pConfig) + { + AM_MEDIA_TYPE *pmt = NULL; + if (SUCCEEDED(m_pConfig->GetFormat(&pmt))) + { + if (pmt->majortype == MEDIATYPE_Video) + { + if (pmt->formattype == FORMAT_VideoInfo) + { + VIDEOINFO * pvi = (VIDEOINFO *)pmt->pbFormat; + _size.cx = pvi->bmiHeader.biWidth; + _size.cy = pvi->bmiHeader.biHeight; + } + else + if (pmt->formattype == FORMAT_VideoInfo2) + { + VIDEOINFOHEADER2 * pvi = (VIDEOINFOHEADER2 *)pmt->pbFormat; + _size.cx = pvi->bmiHeader.biWidth; + _size.cy = pvi->bmiHeader.biHeight; + } + } + DeleteMediaType(pmt); + } + } + return _size; +} + +int CVideoFormats::get_Count() +{ + SIZE _aPrefferedSizes[] = + { + { 160,120 }, + { 176,144 }, + { 240,176 }, + { 240,180 }, + { 320,240 }, + { 352,288 }, + { 640,240 }, + { 640,288 }, + { 640,480 }, + { 704,576 }, + { 720,240 }, + { 720,288 }, + { 720,480 }, + { 720,576 }, + { 800,480 }, + { 800,600 }, + { 1024,768 }, + { 1280,1024 }, + { 1600,1200 } + }; + + int iSizesCount = sizeof(_aPrefferedSizes)/sizeof(_aPrefferedSizes[0]); + int iCurrentIndex = 0; + HRESULT hr = NOERROR; + bool bResult = false; + int nIndex = -1; + if (m_pConfig) + { + int iCount, iSize; + hr = m_pConfig->GetNumberOfCapabilities(&iCount,&iSize); + if (hr == S_OK) + { + LPBYTE pbtSCC = (LPBYTE)CoTaskMemAlloc(iSize); + for (int i = 0; i < iCount; i++) + { + AM_MEDIA_TYPE * pmt = NULL; + hr = m_pConfig->GetStreamCaps(i,&pmt,pbtSCC); + if (hr == S_OK) + { + VIDEO_STREAM_CONFIG_CAPS * pCaps = (VIDEO_STREAM_CONFIG_CAPS *)pbtSCC; + if (pmt->formattype == FORMAT_VideoInfo) + { + if (iCurrentIndex == nIndex) + { + /* + VIDEOINFOHEADER * pFormat = (VIDEOINFOHEADER*)pmt->pbFormat; + _size.cx = pFormat->bmiHeader.biWidth; + _size.cy = pFormat->bmiHeader.biHeight; + bResult = true; + */ + } + else + { + iCurrentIndex++; + if ( pCaps->MinOutputSize.cx != pCaps->MaxOutputSize.cx + && pCaps->MinOutputSize.cy != pCaps->MaxOutputSize.cy) + { + // check list of pre-defined formats + for (int j = 0; j < iSizesCount; j++) + { + // check if supported + if ( + pCaps->MinOutputSize.cx <= _aPrefferedSizes[j].cx + && pCaps->MaxOutputSize.cx >= _aPrefferedSizes[j].cx + && pCaps->MinOutputSize.cy <= _aPrefferedSizes[j].cy + && pCaps->MaxOutputSize.cy >= _aPrefferedSizes[j].cy + ) + { + if (iCurrentIndex == nIndex) + { + /* + _size.cx = _aPrefferedSizes[j].cx; + _size.cx = _aPrefferedSizes[j].cy; + bResult = true; + */ + } + else iCurrentIndex++; + } + if (bResult) break; + } + } + } + } + DeleteMediaType(pmt); + } + if (bResult) break; + } + CoTaskMemFree(pbtSCC); + } + } + return iCurrentIndex; +} + +SIZE CVideoFormats::get_Resolution(int nIndex) +{ + SIZE _aPrefferedSizes[] = + { + { 160,120 }, + { 176,144 }, + { 240,176 }, + { 240,180 }, + { 320,240 }, + { 352,288 }, + { 640,240 }, + { 640,288 }, + { 640,480 }, + { 704,576 }, + { 720,240 }, + { 720,288 }, + { 720,480 }, + { 720,576 }, + { 800,480 }, + { 800,600 }, + { 1024,768 }, + { 1280,1024 }, + { 1600,1200 } + }; + + int iSizesCount = sizeof(_aPrefferedSizes)/sizeof(_aPrefferedSizes[0]); + int iCurrentIndex = 0; + HRESULT hr = NOERROR; + bool bResult = false; + SIZE _size; + _size.cx = 0; + _size.cy = 0; + if (m_pConfig) + { + int iCount, iSize; + hr = m_pConfig->GetNumberOfCapabilities(&iCount,&iSize); + if (hr == S_OK) + { + LPBYTE pbtSCC = (LPBYTE)CoTaskMemAlloc(iSize); + for (int i = 0; i < iCount; i++) + { + AM_MEDIA_TYPE * pmt = NULL; + hr = m_pConfig->GetStreamCaps(i,&pmt,pbtSCC); + if (hr == S_OK) + { + VIDEO_STREAM_CONFIG_CAPS * pCaps = (VIDEO_STREAM_CONFIG_CAPS *)pbtSCC; + if (pmt->formattype == FORMAT_VideoInfo) + { + if (iCurrentIndex == nIndex) + { + VIDEOINFOHEADER * pFormat = (VIDEOINFOHEADER*)pmt->pbFormat; + _size.cx = pFormat->bmiHeader.biWidth; + _size.cy = pFormat->bmiHeader.biHeight; + bResult = true; + } + else + { + iCurrentIndex++; + if ( pCaps->MinOutputSize.cx != pCaps->MaxOutputSize.cx + && pCaps->MinOutputSize.cy != pCaps->MaxOutputSize.cy) + { + // check list of pre-defined formats + for (int j = 0; j < iSizesCount; j++) + { + // check if supported + if ( + pCaps->MinOutputSize.cx <= _aPrefferedSizes[j].cx + && pCaps->MaxOutputSize.cx >= _aPrefferedSizes[j].cx + && pCaps->MinOutputSize.cy <= _aPrefferedSizes[j].cy + && pCaps->MaxOutputSize.cy >= _aPrefferedSizes[j].cy + ) + { + if (iCurrentIndex == nIndex) + { + _size.cx = _aPrefferedSizes[j].cx; + _size.cy = _aPrefferedSizes[j].cy; + bResult = true; + } + else iCurrentIndex++; + } + if (bResult) break; + } + } + } + } + DeleteMediaType(pmt); + } + if (bResult) break; + } + CoTaskMemFree(pbtSCC); + } + } + return _size; +} + +HRESULT CVideoFormats::set_Resolution(SIZE _size) +{ + return NOERROR; +} \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/Format.h b/VideoSourceDirectShow/DSNative/Format.h new file mode 100644 index 0000000..70614b3 --- /dev/null +++ b/VideoSourceDirectShow/DSNative/Format.h @@ -0,0 +1,24 @@ +#ifndef __Formats_H__ +#define __Formats_H__ +///////////////////////////////////////////////////// +//#include "ClassFactory.h" +#include "stdwx.h" +#include +///////////////////////////////////////////////////// +class EXPORTS_API CVideoFormats //: public CFactoryObject +{ + friend class CDevice; +private: + IAMStreamConfig * m_pConfig; +public: + SIZE get_Resolution(); + int get_Count(); + SIZE get_Resolution(int nIndex); + HRESULT set_Resolution(SIZE _size); +private: + CVideoFormats(IAMStreamConfig * pConfig); +public: + virtual ~CVideoFormats(); +}; +///////////////////////////////////////////////////// +#endif // __Formats_H__ \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/FrameGrabber.cpp b/VideoSourceDirectShow/DSNative/FrameGrabber.cpp new file mode 100644 index 0000000..a9100bd --- /dev/null +++ b/VideoSourceDirectShow/DSNative/FrameGrabber.cpp @@ -0,0 +1,251 @@ +#include "stdwx.h" +#include "FrameGrabber.h" +#include "Crossbar.h" +#include + +CFrameGrabber::CFrameGrabber(CDevice * pVideoDevice) + //: CFactoryObject() + : m_pVideoDevice(pVideoDevice) + , m_pCaptureGraph(NULL) + , m_pVideoPicker(NULL) + , m_pNullRenderer(NULL) + , m_pDecompressor(NULL) +{ + +} + +CFrameGrabber::~CFrameGrabber() +{ + CloseInterfaces(); +} + +CDevice * CFrameGrabber::get_VideoDevice() +{ + return m_pVideoDevice; +} + +HRESULT CFrameGrabber::InitInterfaces() +{ + HRESULT hr = __super::InitInterfaces(); + SAFECHECKCLOSE(hr); + + hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, + IID_ICaptureGraphBuilder2, (void **)&m_pCaptureGraph); + SAFECHECKCLOSE(hr); + + hr = m_pCaptureGraph->SetFiltergraph(m_pGraphBuilder); + SAFECHECKCLOSE(hr); + + if (m_pVideoDevice && m_pVideoDevice->m_pFilter) + { + hr = m_pVideoDevice->m_pFilter->AddToFilterGraph(m_pGraphBuilder); + SAFECHECKCLOSE(hr); + + DecompressorType::DECOMPTYPE _decompressorType = ConfigureVideoSource(); + + IBaseFilter * pDecompressor = NULL; + if (_decompressorType == DecompressorType::AVI) + { + m_pDecompressor = new DSAviDecompressorFilter(); + m_pDecompressor->GetIBaseFilter(&pDecompressor); + } else + if (_decompressorType == DecompressorType::MJPEG) + { + m_pDecompressor = new DSMJPEGDecompressorFilter(); + m_pDecompressor->GetIBaseFilter(&pDecompressor); + } + + m_pVideoPicker = new DSSampleGrabberFilter(); + AM_MEDIA_TYPE mt; + ZeroMemory(&mt,sizeof(mt)); + mt.majortype = MEDIATYPE_Video; + mt.subtype = MEDIASUBTYPE_RGB24; + m_pVideoPicker->SetMediaType(mt); + m_pVideoPicker->AddToFilterGraph(m_pGraphBuilder); + IBaseFilter * pPicker; + m_pVideoPicker->GetIBaseFilter(&pPicker); + + if (pDecompressor) + { + m_pDecompressor->AddToFilterGraph(m_pGraphBuilder); + + IBaseFilter * pSource; + m_pVideoDevice->m_pFilter->GetIBaseFilter(&pSource); + hr = m_pCaptureGraph->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,pSource,pDecompressor,pPicker); + //hr = m_pCaptureGraph->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,pSource,pDecompressor,pPicker); + if (FAILED(hr)) + { + CloseInterfaces(); + return hr; + } + hr = m_pCaptureGraph->RenderStream(NULL , NULL ,pPicker,NULL,NULL); + if (FAILED(hr)) + { + CloseInterfaces(); + return hr; + } + } + else + { + IBaseFilter * pSource; + m_pVideoDevice->m_pFilter->GetIBaseFilter(&pSource); + hr = m_pCaptureGraph->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,pSource,pPicker,NULL); + + //m_pNullRenderer = new DSNullRenderer(); + /* + m_pNullRenderer->AddToFilterGraph(m_pGraphBuilder); + + IBaseFilter * pNullRenderer; + m_pNullRenderer->GetIBaseFilter(&pNullRenderer); + hr = m_pCaptureGraph->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,pSource,pPicker,pNullRenderer); + if (FAILED(hr)) + { + CloseInterfaces(); + return hr; + } + */ + } + } + return PreparePlayback(); +} + +HRESULT CFrameGrabber::CloseInterfaces() +{ + if (m_pVideoDevice && m_pVideoDevice->m_pFilter && m_pGraphBuilder) + { + m_pVideoDevice->m_pFilter->RemoveFromFilterGraph(m_pGraphBuilder); + } + SAFEDELETE(m_pNullRenderer); + SAFERELEASE(m_pCaptureGraph); + SAFEDELETE(m_pDecompressor); + SAFEDELETE(m_pVideoPicker); + return __super::CloseInterfaces(); +} + +DecompressorType::DECOMPTYPE CFrameGrabber::ConfigureVideoSource() +{ + DecompressorType::DECOMPTYPE _decompressorType = DecompressorType::None; + if (m_pVideoDevice && m_pVideoDevice->m_pFilter) + { + IPin * pPin = NULL; + pPin = m_pVideoDevice->m_pFilter->GetPinByCategory(PIN_CATEGORY_CAPTURE); + if (!pPin) pPin = m_pVideoDevice->m_pFilter->GetPinByDirection(PINDIR_OUTPUT,0); + if (pPin) + { + AM_MEDIA_TYPE * pmt; + HRESULT hr = m_pVideoDevice->m_pFilter->GetOutputPinFormat(pPin,&pmt); + if (hr == S_OK) + { + if ( pmt->formattype == FORMAT_VideoInfo) + { + GUID _fmtSubType = pmt->subtype; + hr = E_FAIL; + if (hr != S_OK) + { + if (_fmtSubType != MEDIASUBTYPE_YUY2) pmt->subtype = MEDIASUBTYPE_YUY2; + hr = m_pVideoDevice->m_pFilter->SetOutputPinFormat(pPin,pmt); + _decompressorType = DecompressorType::AVI; + } + if (hr != S_OK) + { + if (_fmtSubType != MEDIASUBTYPE_RGB32) pmt->subtype = MEDIASUBTYPE_RGB32; + hr = m_pVideoDevice->m_pFilter->SetOutputPinFormat(pPin,pmt); + _decompressorType = DecompressorType::None; + } + if (hr != S_OK) + { + if (_fmtSubType != MEDIASUBTYPE_RGB24) pmt->subtype = MEDIASUBTYPE_RGB24; + hr = m_pVideoDevice->m_pFilter->SetOutputPinFormat(pPin,pmt); + _decompressorType = DecompressorType::None; + } + if (hr != S_OK) + { + if (_fmtSubType != MEDIASUBTYPE_MJPG) pmt->subtype = MEDIASUBTYPE_MJPG; + hr = m_pVideoDevice->m_pFilter->SetOutputPinFormat(pPin,pmt); + _decompressorType = DecompressorType::MJPEG; + } + if (hr != S_OK) + { + _decompressorType = DecompressorType::None; + } + } + DeleteMediaType(pmt); + } + pPin->Release(); + } + } + return _decompressorType; +} +void CFrameGrabber::set_PreviewWindow(HWND hWnd) +{ + __super::set_PreviewWindow(hWnd); +} + +void CFrameGrabber::set_ShouldPreview(bool bShouldPreview) +{ + __super::set_ShouldPreview(bShouldPreview); +} + +void CFrameGrabber::ResizeVideoWindow() +{ + __super::ResizeVideoWindow(); +} + +void CFrameGrabber::ResizeVideoWindow(RECT rect) +{ + __super::ResizeVideoWindow(rect); +} + +CCrossBar * CFrameGrabber::get_Crossbar() +{ + if (m_pCaptureGraph && m_pVideoPicker) + { + IBaseFilter * pPicker; + m_pVideoPicker->GetIBaseFilter(&pPicker); + IAMCrossbar *pICrossBar = NULL; + if (SUCCEEDED(m_pCaptureGraph->FindInterface(&LOOK_UPSTREAM_ONLY,NULL,pPicker,IID_IAMCrossbar,(void**)&pICrossBar))) + { + CCrossBar * pCrossbar = new CCrossBar(pICrossBar); + pICrossBar->Release(); + return pCrossbar; + } + } + return NULL; +} + +HRESULT CFrameGrabber::get_Format(BITMAPINFOHEADER ** pbmi) +{ + CheckPointer(pbmi,E_POINTER); + *pbmi = NULL; + if (m_pVideoPicker) + { + AM_MEDIA_TYPE mt; + HRESULT hr = m_pVideoPicker->GetMediaType(&mt); + if (FAILED(hr)) return hr; + if (mt.formattype == FORMAT_VideoInfo) + { + VIDEOINFO * pvi = (VIDEOINFO *)mt.pbFormat; + *pbmi = (BITMAPINFOHEADER *)CoTaskMemAlloc(sizeof(pvi->bmiHeader)); + CopyMemory(*pbmi,&pvi->bmiHeader,sizeof(pvi->bmiHeader)); + } + if (mt.formattype == FORMAT_VideoInfo2) + { + VIDEOINFOHEADER2 * pvi = (VIDEOINFOHEADER2 *)mt.pbFormat; + *pbmi = (BITMAPINFOHEADER *)CoTaskMemAlloc(sizeof(pvi->bmiHeader)); + CopyMemory(*pbmi,&pvi->bmiHeader,sizeof(pvi->bmiHeader)); + } + FreeMediaType(mt); + if (*pbmi == NULL) return E_UNEXPECTED; + return NOERROR; + } + return E_FAIL; +} + +BOOL CFrameGrabber::GrabFrame(BYTE ** ppbtBuffer,long * plBufferSize) +{ + if (m_pVideoPicker) + { + return m_pVideoPicker->Grab(ppbtBuffer,plBufferSize); + } + return FALSE; +} \ No newline at end of file diff --git a/VideoSourceDirectShow/DSNative/FrameGrabber.h b/VideoSourceDirectShow/DSNative/FrameGrabber.h new file mode 100644 index 0000000..6605a3a --- /dev/null +++ b/VideoSourceDirectShow/DSNative/FrameGrabber.h @@ -0,0 +1,43 @@ +#ifndef __FrameGrabber_H__ +#define __FrameGrabber_H__ + +///////////////////////////////////////////////////// +#include "Device.h" +#include "DirectShow/Include/DSFilterGraphBase.h" +#include "DirectShow/Include/DSFiltersDefinition.h" +///////////////////////////////////////////////////// +#pragma warning( disable : 4275 ) +///////////////////////////////////////////////////// +class CCrossBar; +///////////////////////////////////////////////////// +class EXPORTS_API CFrameGrabber//: public CFactoryObject + : public DSFilterGraphBase +{ +protected: + ICaptureGraphBuilder2 * m_pCaptureGraph; + DSSampleGrabberFilter * m_pVideoPicker; + DSFilterBase * m_pNullRenderer; + DSFilterBase * m_pDecompressor; + CDevice * m_pVideoDevice; +public: + CDevice * get_VideoDevice(); + CCrossBar * get_Crossbar(); +protected: + DecompressorType::DECOMPTYPE ConfigureVideoSource(); +protected: + virtual HRESULT InitInterfaces(); + virtual HRESULT CloseInterfaces(); +public: + void set_PreviewWindow(HWND hWnd); + void set_ShouldPreview(bool bShouldPreview); + void ResizeVideoWindow(); + void ResizeVideoWindow(RECT rect); +public: + BOOL GrabFrame(BYTE ** ppbtBuffer,long * plBufferSize); + HRESULT get_Format(BITMAPINFOHEADER ** pbmi); +public: + CFrameGrabber(CDevice * pVideoDevice); + virtual ~CFrameGrabber(); +}; +///////////////////////////////////////////////////// +#endif // __FrameGrabber_H__ \ No newline at end of file diff --git a/VideoSourceDirectShow/VideoGrabberDirectShow.cpp b/VideoSourceDirectShow/VideoGrabberDirectShow.cpp new file mode 100644 index 0000000..d948362 --- /dev/null +++ b/VideoSourceDirectShow/VideoGrabberDirectShow.cpp @@ -0,0 +1,253 @@ +#include "stdwx.h" +#include "VideoGrabberDirectShow.h" +#include "Crossbar.h" + +VideoGrabberDirectShow::VideoGrabberDirectShow() +: m_DeviceIndex(0) +, m_DeviceManager(CLSID_VideoInputDeviceCategory) +, m_pDevice(nullptr) +, m_pGrabber(nullptr) +, m_pbmi(nullptr) +, m_pBuffer(nullptr) +{ +} + +VideoGrabberDirectShow::VideoGrabberDirectShow(VideoSourcePluginBase * owner, size_t index) +: VideoGrabberBase(owner) +, m_DeviceIndex((int)index) +, m_DeviceManager(CLSID_VideoInputDeviceCategory) +, m_pDevice(nullptr) +, m_pGrabber(nullptr) +, m_pbmi(nullptr) +, m_pBuffer(nullptr) +{ + m_ImageSize = wxDefaultSize; + m_pDevice = m_DeviceManager.get_Device(m_DeviceIndex); + if (m_pDevice) + { + m_DeviceID = m_pDevice->get_Moniker(); + ReadName(); + } + StartGrabber(); +} + +VideoGrabberDirectShow::VideoGrabberDirectShow(VideoSourcePluginBase * owner, const wxString & id) +: VideoGrabberBase(owner) +, m_DeviceManager(CLSID_VideoInputDeviceCategory) +, m_pDevice(nullptr) +, m_pGrabber(nullptr) +, m_DeviceID(id) +, m_pbmi(nullptr) +, m_pBuffer(nullptr) +{ + m_ImageSize = wxDefaultSize; + m_pDevice = m_DeviceManager.get_DeviceByMoniker(m_DeviceID.wc_str()); + m_DeviceIndex = m_DeviceManager.get_DeviceIndex(m_DeviceID.wc_str()); + if (m_pDevice) + ReadName(); + StartGrabber(); +} +VideoGrabberDirectShow::~VideoGrabberDirectShow() +{ + CAutoLock lock(&m_csLock); + StopGrabber(); + wxDELETE(m_pDevice); +} + +wxString VideoGrabberDirectShow::GetName() const +{ + return m_DeviceName; +} + +wxString VideoGrabberDirectShow::GetID() const +{ + return m_DeviceID; +} + +size_t VideoGrabberDirectShow::GetFrameDataLength() +{ + return m_ImageSize.GetWidth() * m_ImageSize.GetHeight() * 3; +} + +wxSize VideoGrabberDirectShow::GetFrameSize() +{ + return m_ImageSize; +} + +size_t VideoGrabberDirectShow::get_ResolutionsCount() +{ + size_t _result = 0; + if (m_pDevice) + { + CVideoFormats * pFormats = m_pDevice->get_VideoFormats(); + if (pFormats) + { + _result = pFormats->get_Count(); + delete pFormats; + pFormats = nullptr; + } + } + return _result; +} + +wxSize VideoGrabberDirectShow::get_ResolutionByIndex(size_t nIndex) +{ + wxSize _result = m_ImageSize; + if (m_pDevice) + { + CVideoFormats * pFormats = m_pDevice->get_VideoFormats(); + if (pFormats) + { + SIZE _size = pFormats->get_Resolution((int)nIndex); + _result.x = _size.cx; + _result.y = _size.cy; + delete pFormats; + pFormats = nullptr; + } + } + return _result; +} + +bool VideoGrabberDirectShow::set_Resolution(wxSize _size) +{ + bool bResult = false; + if (m_pDevice) + { + CAutoLock lock(&m_csLock); + StopGrabber(); + CVideoFormats * pFormats = m_pDevice->get_VideoFormats(); + if (pFormats) + { + SIZE _SizeToSet; + _SizeToSet.cx = _size.x; + _SizeToSet.cy = _size.y; + bResult = SUCCEEDED(pFormats->set_Resolution(_SizeToSet)); + delete pFormats; + pFormats = nullptr; + } + StartGrabber(); + } + return bResult; +} + +bool VideoGrabberDirectShow::set_Resolution(size_t nIndex) +{ + return set_Resolution(get_ResolutionByIndex(nIndex)); +} + +unsigned char * VideoGrabberDirectShow::GetBuffer() +{ + return m_pBuffer; +} + +unsigned char * VideoGrabberDirectShow::GrabFrame(bool bUseInternalBuffer) +{ + unsigned char * pBuffer = nullptr; + long lLength = 0; + if (bUseInternalBuffer) + { + lLength = GetFrameDataLength(); + pBuffer = m_pBuffer; + } + if (GrabFrame(&pBuffer,&lLength)) + { + return pBuffer; + } + else + { + if (!bUseInternalBuffer) + { + if (pBuffer) CoTaskMemFree(pBuffer); + pBuffer = nullptr; + } + } + return nullptr; +} + +int VideoGrabberDirectShow::GrabFrame(unsigned char ** data, long * length) +{ + CAutoLock lock(&m_csLock); + if (m_pGrabber) + { + try + { + return m_pGrabber->GrabFrame(data,length); + } + catch (...) + { + DbgOutString(_T("Error while perform grab into passed buffer")); + } + } + return 0; +} + +bool VideoGrabberDirectShow::IsOK() +{ + return m_pGrabber != nullptr; +} + +bool VideoGrabberDirectShow::StartGrabber() +{ + if (m_pDevice) + { + CAutoLock lock(&m_csLock); + if(m_pGrabber) StopGrabber(); + m_pGrabber = m_pDevice->CreateFrameGrabber(); + if (m_pGrabber) + { + m_pGrabber->set_ShouldPreview(false); + if (SUCCEEDED(m_pGrabber->Start())) + { + if (S_OK == m_pGrabber->get_Format(&m_pbmi)) + { + m_ImageSize.x = m_pbmi->biWidth; + m_ImageSize.y = m_pbmi->biHeight; + } + m_pBuffer = (LPBYTE)CoTaskMemAlloc(GetFrameDataLength()); + /* + CCrossBar * pCrossBar = m_pGrabber->get_Crossbar(); + if (pCrossBar) + { + long lIndex = pCrossBar->get_InputByType(PhysConn_Video_Composite); + //long lIndex = pCrossBar->get_InputByType(PhysConn_Video_Tuner); + if (lIndex != -1) + { + pCrossBar->Route(lIndex); + } + delete pCrossBar; + } + */ + return true; + } + else + { + StopGrabber(); + } + } + } + return false; +} +bool VideoGrabberDirectShow::StopGrabber() +{ + CAutoLock lock(&m_csLock); + wxDELETE(m_pGrabber); + + if (m_pbmi != nullptr) + { + CoTaskMemFree(m_pbmi); + m_pbmi = nullptr; + } + if (m_pBuffer) + { + CoTaskMemFree(m_pBuffer); + m_pBuffer = nullptr; + } + return true; +} + +void VideoGrabberDirectShow::ReadName() +{ + LPWSTR lpwstrName = m_DeviceManager.get_DeviceName(m_DeviceIndex); + m_DeviceName = lpwstrName; + wxDELETEA(lpwstrName); +} \ No newline at end of file diff --git a/VideoSourceDirectShow/VideoGrabberDirectShow.h b/VideoSourceDirectShow/VideoGrabberDirectShow.h new file mode 100644 index 0000000..ce78a83 --- /dev/null +++ b/VideoSourceDirectShow/VideoGrabberDirectShow.h @@ -0,0 +1,49 @@ +#ifndef _VIDEOGRABBERDIRECTSHOW_H +#define _VIDEOGRABBERDIRECTSHOW_H + +#include +#include "FrameGrabber.h" +#include "DeviceManager.h" +#include "Format.h" + +class VideoGrabberDirectShow : public VideoGrabberBase +{ +private: + CDeviceManager m_DeviceManager; + CDevice * m_pDevice; + CFrameGrabber * m_pGrabber; + int m_DeviceIndex; + wxString m_DeviceID; + wxString m_DeviceName; + wxSize m_ImageSize; + CCritSec m_csLock; + BITMAPINFOHEADER * m_pbmi; + LPBYTE m_pBuffer; +private: + bool StopGrabber(); + bool StartGrabber(); + void ReadName(); +public: + // TODO: make it compatible with your plugin + virtual size_t get_ResolutionsCount(); + virtual wxSize get_ResolutionByIndex(size_t nIndex); + virtual bool set_Resolution(wxSize _size); + virtual bool set_Resolution(size_t nIndex); +public: + virtual wxString GetName() const; + virtual wxString GetID() const; + virtual wxSize GetFrameSize(); + virtual size_t GetFrameDataLength(); + virtual unsigned char * GetBuffer(); + virtual unsigned char * GrabFrame(bool bUseInternalBuffer = true); + virtual int GrabFrame(unsigned char ** data, long * length); + virtual bool IsOK(); + +public: + VideoGrabberDirectShow(); + VideoGrabberDirectShow(VideoSourcePluginBase * owner, size_t index); + VideoGrabberDirectShow(VideoSourcePluginBase * owner, const wxString & id); + ~VideoGrabberDirectShow(); +}; + +#endif // _VIDEOGRABBERDIRECTSHOW_H \ No newline at end of file diff --git a/SampleGuiPlugin2/SampleGuiPlugin2.def b/VideoSourceDirectShow/VideoSourceDirectShow.def similarity index 65% rename from SampleGuiPlugin2/SampleGuiPlugin2.def rename to VideoSourceDirectShow/VideoSourceDirectShow.def index 806b31b..3cc3882 100644 --- a/SampleGuiPlugin2/SampleGuiPlugin2.def +++ b/VideoSourceDirectShow/VideoSourceDirectShow.def @@ -1,5 +1,5 @@ -LIBRARY "SampleGuiPlugin2" - -EXPORTS - CreatePlugin=CreatePlugin +LIBRARY "VideoSourceDirectShow" + +EXPORTS + CreatePlugin=CreatePlugin DeletePlugin=DeletePlugin \ No newline at end of file diff --git a/VideoSourceDirectShow/VideoSourceDirectShowApp.cpp b/VideoSourceDirectShow/VideoSourceDirectShowApp.cpp new file mode 100644 index 0000000..456741a --- /dev/null +++ b/VideoSourceDirectShow/VideoSourceDirectShowApp.cpp @@ -0,0 +1,9 @@ +#include "stdwx.h" +#include "VideoSourceDirectShowApp.h" + +IMPLEMENT_APP_NO_MAIN(VideoSourceDirectShowApp); + +bool VideoSourceDirectShowApp::OnInit() +{ + return true; +} diff --git a/VideoSourceDirectShow/VideoSourceDirectShowApp.h b/VideoSourceDirectShow/VideoSourceDirectShowApp.h new file mode 100644 index 0000000..73fdfa0 --- /dev/null +++ b/VideoSourceDirectShow/VideoSourceDirectShowApp.h @@ -0,0 +1,10 @@ +#ifndef _VIDEOSOURCEDIRECTSHOWAPP_H +#define _VIDEOSOURCEDIRECTSHOWAPP_H + +class VideoSourceDirectShowApp : public wxApp +{ +public: + virtual bool OnInit(); +}; + +#endif // _VIDEOSOURCEDIRECTSHOWAPP_H diff --git a/VideoSourceDirectShow/VideoSourceDirectShowExports.cpp b/VideoSourceDirectShow/VideoSourceDirectShowExports.cpp new file mode 100644 index 0000000..8a521c6 --- /dev/null +++ b/VideoSourceDirectShow/VideoSourceDirectShowExports.cpp @@ -0,0 +1,13 @@ +#include "stdwx.h" +#include +#include "VideoSourceDirectShowPlugin.h" + +WXEXPORT VideoSourcePluginBase * CreatePlugin() +{ + return new VideoSourceDirectShowPlugin; +} + +WXEXPORT void DeletePlugin(VideoSourcePluginBase * plugin) +{ + wxDELETE(plugin); +} diff --git a/VideoSourceDirectShow/VideoSourceDirectShowPlugin.cpp b/VideoSourceDirectShow/VideoSourceDirectShowPlugin.cpp new file mode 100644 index 0000000..7822525 --- /dev/null +++ b/VideoSourceDirectShow/VideoSourceDirectShowPlugin.cpp @@ -0,0 +1,90 @@ +#include "stdwx.h" +#include "DeviceManager.h" +#include "VideoSourceDirectShowPlugin.h" +#include "VideoGrabberDirectShow.h" + +IMPLEMENT_DYNAMIC_CLASS(VideoSourceDirectShowPlugin, VideoSourcePluginBase) + +VideoSourceDirectShowPlugin::VideoSourceDirectShowPlugin() +: m_ID(wxT("{DEADA8F3-62BB-45d5-9F04-45AC1FF3A996}")) +, m_pDeviceManager(NULL) +{ + CoInitializeEx(NULL,COINIT_MULTITHREADED); + m_pDeviceManager = new CDeviceManager(CLSID_VideoInputDeviceCategory); +} + +VideoSourceDirectShowPlugin::~VideoSourceDirectShowPlugin() +{ + wxDELETE(m_pDeviceManager); + CoUninitialize(); +} + +wxString VideoSourceDirectShowPlugin::GetID() const +{ + return m_ID; +} + +wxString VideoSourceDirectShowPlugin::GetName() const +{ + return _("DirectShow Video Source"); +} + +size_t VideoSourceDirectShowPlugin::GetDeviceCount() const +{ + return m_pDeviceManager->get_Count(); +} + +wxString VideoSourceDirectShowPlugin::GetName(size_t index) const +{ + LPWSTR lpwstrName = m_pDeviceManager->get_DeviceName(index); + wxString name(lpwstrName); + wxDELETEA(lpwstrName); + return name; +} + +wxString VideoSourceDirectShowPlugin::GetName(const wxString & id) const +{ + long lCount = m_pDeviceManager->get_Count(); + while (lCount > 0) + { + lCount--; + wxString _string = GetID(lCount); + if (_string == id) return GetName(lCount); + } + return wxEmptyString; +} + +wxString VideoSourceDirectShowPlugin::GetID(size_t index) const +{ + LPWSTR lpwstrName = m_pDeviceManager->get_DeviceMonikerString(index); + wxString name(lpwstrName); + wxDELETEA(lpwstrName); + return name; +} + +VideoGrabberBase * VideoSourceDirectShowPlugin::CreateGrabber(size_t index) +{ + VideoGrabberDirectShow * grabber = new VideoGrabberDirectShow(this, index); + if (!grabber->IsOK()) + wxDELETE(grabber); + return grabber; +} + +VideoGrabberBase * VideoSourceDirectShowPlugin::CreateGrabber(const wxString & id) +{ + VideoGrabberDirectShow * grabber = new VideoGrabberDirectShow(this, id); + if (!grabber->IsOK()) + wxDELETE(grabber); + return grabber; +} + +void VideoSourceDirectShowPlugin::DeleteGrabber(VideoGrabberBase * grabber) +{ + wxLogDebug(wxT("VideoSourceDirectShowPlugin::DeleteGrabber")); + wxDELETE(grabber); +} + +void VideoSourceDirectShowPlugin::RefreshDevices() +{ + m_pDeviceManager->RefreshDevices(); +} \ No newline at end of file diff --git a/VideoSourceDirectShow/VideoSourceDirectShowPlugin.h b/VideoSourceDirectShow/VideoSourceDirectShowPlugin.h new file mode 100644 index 0000000..9131b6c --- /dev/null +++ b/VideoSourceDirectShow/VideoSourceDirectShowPlugin.h @@ -0,0 +1,31 @@ +#ifndef _VIDEOSOURCEDIRECTSHOWPLUGIN_H +#define _VIDEOSOURCEDIRECTSHOWPLUGIN_H + +#include + +class CDeviceManager; + +/// Base class for all iFloor effect plugins +class VideoSourceDirectShowPlugin : public VideoSourcePluginBase +{ + DECLARE_DYNAMIC_CLASS(VideoSourceDirectShowPlugin) +public: + VideoSourceDirectShowPlugin(); + ~VideoSourceDirectShowPlugin(); + virtual wxString GetID() const; + virtual wxString GetName() const; + + virtual size_t GetDeviceCount() const; + virtual wxString GetName(size_t index) const; + virtual wxString GetName(const wxString & id) const; + virtual wxString GetID(size_t index) const; + virtual VideoGrabberBase * CreateGrabber(size_t index); + virtual VideoGrabberBase * CreateGrabber(const wxString & id); + virtual void DeleteGrabber(VideoGrabberBase * grabber); + virtual void RefreshDevices(); +private: + wxString m_ID; + CDeviceManager * m_pDeviceManager; +}; + +#endif // _VIDEOSOURCEDIRECTSHOWPLUGIN_H \ No newline at end of file diff --git a/VideoSourceDirectShow/Win/Qedit.h b/VideoSourceDirectShow/Win/Qedit.h new file mode 100644 index 0000000..31aab12 --- /dev/null +++ b/VideoSourceDirectShow/Win/Qedit.h @@ -0,0 +1,142 @@ +#pragma once + +#ifndef __ISampleGrabberCB_INTERFACE_DEFINED__ +#define __ISampleGrabberCB_INTERFACE_DEFINED__ + +#include + +/* interface ISampleGrabberCB */ +/* [unique][helpstring][local][uuid][object] */ + +EXTERN_C const IID IID_ISampleGrabberCB; + +MIDL_INTERFACE("0579154A-2B53-4994-B0D0-E773148EFF85") +ISampleGrabberCB : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE SampleCB( + double SampleTime, + IMediaSample * pSample) = 0; + + virtual HRESULT STDMETHODCALLTYPE BufferCB( + double SampleTime, + BYTE* pBuffer, + long BufferLen) = 0; +}; + +#endif /* __ISampleGrabberCB_INTERFACE_DEFINED__ */ + +#ifndef __ISampleGrabber_INTERFACE_DEFINED__ +#define __ISampleGrabber_INTERFACE_DEFINED__ + +/* interface ISampleGrabber */ +/* [unique][helpstring][local][uuid][object] */ + +EXTERN_C const IID IID_ISampleGrabber; + +MIDL_INTERFACE("6B652FFF-11FE-4fce-92AD-0266B5D7C78F") +ISampleGrabber : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE SetOneShot( + BOOL OneShot) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetMediaType( + const AM_MEDIA_TYPE* pType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetConnectedMediaType( + AM_MEDIA_TYPE* pType) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetBufferSamples( + BOOL BufferThem) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentBuffer( + /* [out][in] */ long* pBufferSize, + /* [out] */ long* pBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentSample( + /* [retval][out] */ IMediaSample** ppSample) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetCallback( + ISampleGrabberCB* pCallback, + long WhichMethodToCallback) = 0; +}; + +DEFINE_GUID(CLSID_SampleGrabber, 0xc1f400a0, 0x3f08, 0x11d3, 0x9f, 0x0b, 0x00, 0x60, 0x08, 0x03, 0x9e, 0x37); + +#endif /* __ISampleGrabber_INTERFACE_DEFINED__ */ + +#ifndef __IMediaDet_INTERFACE_DEFINED__ +#define __IMediaDet_INTERFACE_DEFINED__ + +/* interface IMediaDet */ +/* [unique][helpstring][uuid][object] */ + +EXTERN_C const IID IID_IMediaDet; + +MIDL_INTERFACE("65BD0710-24D2-4ff7-9324-ED2E5D3ABAFA") +IMediaDet : public IUnknown +{ +public: + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Filter( + /* [retval][out] */ __RPC__deref_out_opt IUnknown * *pVal) = 0; + + virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_Filter( + /* [in] */ __RPC__in_opt IUnknown* newVal) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_OutputStreams( + /* [retval][out] */ __RPC__out long* pVal) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentStream( + /* [retval][out] */ __RPC__out long* pVal) = 0; + + virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentStream( + /* [in] */ long newVal) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_StreamType( + /* [retval][out] */ __RPC__out GUID* pVal) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_StreamTypeB( + /* [retval][out] */ __RPC__deref_out_opt BSTR* pVal) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_StreamLength( + /* [retval][out] */ __RPC__out double* pVal) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Filename( + /* [retval][out] */ __RPC__deref_out_opt BSTR* pVal) = 0; + + virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_Filename( + /* [in] */ __RPC__in BSTR newVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetBitmapBits( + double StreamTime, + __RPC__in long* pBufferSize, + __RPC__in char* pBuffer, + long Width, + long Height) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE WriteBitmapBits( + double StreamTime, + long Width, + long Height, + __RPC__in BSTR Filename) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_StreamMediaType( + /* [retval][out] */ __RPC__out AM_MEDIA_TYPE* pVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetSampleGrabber( + /* [out] */ __RPC__deref_out_opt ISampleGrabber** ppVal) = 0; + + virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_FrameRate( + /* [retval][out] */ __RPC__out double* pVal) = 0; + + virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE EnterBitmapGrabMode( + double SeekTime) = 0; +}; + +#endif /* __IMediaDet_INTERFACE_DEFINED__ */ + +EXTERN_C const CLSID CLSID_MediaDet; + +class DECLSPEC_UUID("65BD0711-24D2-4ff7-9324-ED2E5D3ABAFA") + MediaDet; diff --git a/VideoSourceDirectShow/Win/VideoSourceDirectShow.dll b/VideoSourceDirectShow/Win/VideoSourceDirectShow.dll new file mode 100644 index 0000000..7319ae5 Binary files /dev/null and b/VideoSourceDirectShow/Win/VideoSourceDirectShow.dll differ diff --git a/VideoSourceDirectShow/Win/VideoSourceDirectShow.vcxproj b/VideoSourceDirectShow/Win/VideoSourceDirectShow.vcxproj new file mode 100644 index 0000000..26ee474 --- /dev/null +++ b/VideoSourceDirectShow/Win/VideoSourceDirectShow.vcxproj @@ -0,0 +1,392 @@ + + + + x64 + + + + Debug + x64 + + + Release + x64 + + + + {CED1E685-B9B8-3A52-B44F-57BB9BCEC78D} + Win32Proj + 10.0.26100.0 + x64 + VideoSourceDirectShow + NoUpgrade + + + + DynamicLibrary + Unicode + v143 + + + DynamicLibrary + Unicode + v143 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + VideoSourceDirectShow.dir\Debug\ + VideoSourceDirectShow + .dll + true + true + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + VideoSourceDirectShow.dir\Release\ + VideoSourceDirectShow + .dll + false + true + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\DSNative;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\VideoSourcePluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\ThirdParty\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + $(IntDir) + EnableFastChecks + + + ProgramDatabase + 4996 + Sync + + + Disabled + stdcpp17 + + true + Disabled + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/VideoSourceDirectShow.dir/Debug//cmake_pch.pch + + MultiThreadedDebugDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;EXPORTS_API=;CMAKE_INTDIR="Debug";VideoSourceDirectShow_EXPORTS + $(IntDir) + false + + + %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;EXPORTS_API=;CMAKE_INTDIR=\"Debug\";VideoSourceDirectShow_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\DSNative;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\VideoSourcePluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\ThirdParty\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\DSNative;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\VideoSourcePluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\ThirdParty\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different "$(TargetPath)" "$(TargetDir)../$(TargetFileName)" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd +setlocal +"C:\Program Files\CMake\bin\cmake.exe" -E make_directory C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin/plugins/video_source +if %errorlevel% neq 0 goto :cmEnd +"C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/VideoSourceDirectShow.dll C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin/plugins/video_source/VideoSourceDirectShow.dll +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\VideoSourcePluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\MotionDetectorPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\strmbas.lib;strmiids.lib;quartz.lib;ole32.lib;oleaut32.lib;winmm.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\CommonPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxXS.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxJSON.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + true + atlthunk.lib;%(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Debug/VideoSourceDirectShow.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/VideoSourceDirectShow.def + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/VideoSourceDirectShow.pdb + + Console + + + false + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\DSNative;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\VideoSourcePluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\ThirdParty\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + $(IntDir) + Default + + + 4996 + Sync + + + AnySuitable + stdcpp17 + + true + MaxSpeed + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/VideoSourceDirectShow.dir/Release//cmake_pch.pch + + MultiThreadedDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;EXPORTS_API=;CMAKE_INTDIR="Release";VideoSourceDirectShow_EXPORTS + $(IntDir) + + + false + + + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;EXPORTS_API=;CMAKE_INTDIR=\"Release\";VideoSourceDirectShow_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\DSNative;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\VideoSourcePluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\ThirdParty\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\DSNative;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\VideoSourcePluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\..\ThirdParty\strmbas;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\strmbas;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different "$(TargetPath)" "$(TargetDir)../$(TargetFileName)" +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd +setlocal +"C:\Program Files\CMake\bin\cmake.exe" -E make_directory C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin/plugins/video_source +if %errorlevel% neq 0 goto :cmEnd +"C:\Program Files\CMake\bin\cmake.exe" -E copy_if_different C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/VideoSourceDirectShow.dll C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../bin/plugins/video_source/VideoSourceDirectShow.dll +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\VideoSourcePluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\MotionDetectorPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\strmbas.lib;strmiids.lib;quartz.lib;ole32.lib;oleaut32.lib;winmm.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\CommonPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxXS.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxJSON.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + false + atlthunk.lib;%(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Release/VideoSourceDirectShow.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/VideoSourceDirectShow.def + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/VideoSourceDirectShow.pdb + + Console + + + false + + + + + Always + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\Win\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourceDirectShow\Win\CMakeFiles\generate.stamp + false + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/VideoSourceDirectShow.dir/Debug//cmake_pch.pch + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/VideoSourceDirectShow.dir/Release//cmake_pch.pch + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + + + + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourceDirectShow/Win/CMakeFiles/VideoSourceDirectShow.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + ZERO_CHECK + false + Never + + + {751A15C0-76C2-3506-AB9D-0CD3545003FA} + CommonPluginBase + + + {1F4B7EAD-4694-3453-AD34-1757E387661E} + MotionDetectorPluginBase + + + {14D82890-BB7F-3748-8713-43304E91CFA1} + Utils + + + {08E74159-4CA2-36BC-B137-45C65F9868A7} + VideoSourcePluginBase + + + {23CF91DE-A1B5-3EE0-827D-ACAFD80C7CB2} + strmbas + + + {7887B55C-77B9-3262-AFAD-ABA738C61029} + wxJSON + + + {78CFCEBE-5466-3128-9717-547416DBFFE5} + wxXS + + + + + + \ No newline at end of file diff --git a/VideoSourceDirectShow/Win/VideoSourceDirectShow.vcxproj.filters b/VideoSourceDirectShow/Win/VideoSourceDirectShow.vcxproj.filters new file mode 100644 index 0000000..ca72303 --- /dev/null +++ b/VideoSourceDirectShow/Win/VideoSourceDirectShow.vcxproj.filters @@ -0,0 +1,146 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DSNative\Sources + + + DSNative\Sources + + + DSNative\Sources + + + DSNative\Sources + + + DSNative\Sources + + + DSNative\DirectShow\Sources + + + DSNative\DirectShow\Sources + + + DSNative\DirectShow\Sources + + + DSNative\DirectShow\Sources + + + DSNative\DirectShow\Sources + + + DSNative\DirectShow\Sources + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + DSNative\Include + + + DSNative\Include + + + DSNative\Include + + + DSNative\Include + + + DSNative\Include + + + DSNative\DirectShow\Include + + + DSNative\DirectShow\Include + + + DSNative\DirectShow\Include + + + DSNative\DirectShow\Include + + + DSNative\DirectShow\Include + + + DSNative\DirectShow\Include + + + Header Files + + + Precompile Header File + + + Precompile Header File + + + + + + + + Source Files + + + + + {92D75CDB-6B0D-36E2-B6CD-6A45DA6910EF} + + + {5230ED5F-4004-3097-AD60-9838A9A11E79} + + + {E59ADCBE-1FB0-3336-8CF7-0AFA452EC6A3} + + + {A30B23EA-255B-3698-99B5-7D45717AF558} + + + {4B99EE2E-88CC-366B-B27A-5CE169B8688C} + + + {A8A68941-16AF-3A8A-9CFE-F73D7F1D5ACB} + + + {4951AEE1-75F2-3C38-B593-C6BC8C809FB0} + + + {112D4227-BB51-3360-BB5B-5EA5DBA5A65F} + + + {05450AB2-CB7B-34EA-83DF-1EE86424EDF0} + + + diff --git a/VideoSourcePluginBase/CMakeLists.txt b/VideoSourcePluginBase/CMakeLists.txt new file mode 100644 index 0000000..a688b42 --- /dev/null +++ b/VideoSourcePluginBase/CMakeLists.txt @@ -0,0 +1,48 @@ +# +# Stuff the average programmer needs to change +# +set(SRCS + VideoSourcePluginBase.cpp + VideoGrabberBase.cpp + VideoSourceConfigWindowBase.cpp +) +set(HFILES + VideoSourcePluginBase.h + VideoGrabberBase.h + VideoSourceConfigWindowBase.h + VideoSourcePlugin.h +) + +set(INCLUDE_DIRECTORIES ${BASE_INCLUDE_DIRECTORIES} + ${THIRD_PARTY_DIR}/wxXS/include + ${PROJECT_ROOT_DIR}/CommonPluginBase +) + +set(LIBRARY_NAME VideoSourcePluginBase) + +if(WIN32) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D_USRDLL;/DIFLOOR_EXPORTS) +endif(WIN32) + +set(SRCS ${SRCS} ${HFILES} ${PROJECT_ROOT_DIR}/include/stdwx.h ${PROJECT_ROOT_DIR}/include/stdwx.cpp) + +add_definitions(${PREPROCESSOR_DEFINITIONS}) +include_directories(${INCLUDE_DIRECTORIES}) + +add_library(${LIBRARY_NAME} SHARED ${SRCS}) + +target_link_libraries(${LIBRARY_NAME} + ${wxWidgets_LIBRARIES} + CommonPluginBase + Utils + wxXS +) + +add_dependencies(${LIBRARY_NAME} + CommonPluginBase +) + +target_precompile_headers(${LIBRARY_NAME} + PRIVATE + "${PROJECT_ROOT_DIR}/include/stdwx.h" +) \ No newline at end of file diff --git a/VideoSourcePluginBase/VideoGrabberBase.cpp b/VideoSourcePluginBase/VideoGrabberBase.cpp new file mode 100644 index 0000000..77fa772 --- /dev/null +++ b/VideoSourcePluginBase/VideoGrabberBase.cpp @@ -0,0 +1,27 @@ +#include "stdwx.h" +#include "VideoGrabberBase.h" +#include "VideoSourcePluginBase.h" +#include + +IMPLEMENT_ABSTRACT_CLASS(VideoGrabberBase, wxObject) + +WX_DEFINE_USER_EXPORTED_LIST(VideoGrabberBaseList); + +VideoGrabberBase::VideoGrabberBase() +: m_VideoSource(NULL) +{ +} + +VideoGrabberBase::VideoGrabberBase(VideoSourcePluginBase * owner) +: m_VideoSource(owner) +{ +} + +VideoGrabberBase::~VideoGrabberBase() +{ +} + +VideoSourcePluginBase * VideoGrabberBase::GetVideoSource() +{ + return m_VideoSource; +} diff --git a/VideoSourcePluginBase/VideoGrabberBase.h b/VideoSourcePluginBase/VideoGrabberBase.h new file mode 100644 index 0000000..63f1456 --- /dev/null +++ b/VideoSourcePluginBase/VideoGrabberBase.h @@ -0,0 +1,31 @@ +#ifndef _VIDEOGRABBERBASE_H +#define _VIDEOGRABBERBASE_H + +#include "VideoSourcePlugin.h" +#include + +class VideoSourcePluginBase; + +class IFLOOR_API VideoGrabberBase : public SerializableBase +{ + DECLARE_ABSTRACT_CLASS(VideoGrabberBase) +public: + VideoGrabberBase(); + VideoGrabberBase(VideoSourcePluginBase * owner); + virtual ~VideoGrabberBase(); + virtual wxSize GetFrameSize() = 0; + virtual size_t GetFrameDataLength() = 0; + virtual unsigned char * GetBuffer() = 0; + virtual unsigned char * GrabFrame(bool bUseInternalBuffer = true) = 0; + virtual int GrabFrame(unsigned char ** data, long * length) = 0; + virtual bool IsOK() = 0; + VideoSourcePluginBase * GetVideoSource(); + virtual CommonConfigWindowBase * CreateSettingsEditor(wxWindow * parent = NULL){return NULL;}; + +protected: + VideoSourcePluginBase * m_VideoSource; +}; + +WX_DECLARE_USER_EXPORTED_LIST(VideoGrabberBase, VideoGrabberBaseList, IFLOOR_API); //-V521 + +#endif // _VIDEOGRABBERBASE_H \ No newline at end of file diff --git a/VideoSourcePluginBase/VideoSourceConfigWindowBase.cpp b/VideoSourcePluginBase/VideoSourceConfigWindowBase.cpp new file mode 100644 index 0000000..e35d22f --- /dev/null +++ b/VideoSourcePluginBase/VideoSourceConfigWindowBase.cpp @@ -0,0 +1,33 @@ +#include "stdwx.h" +#include "VideoSourceConfigWindowBase.h" + + +VideoSourceConfigWindowBase::VideoSourceConfigWindowBase() +: m_Plugin(NULL) +{ +} + +VideoSourceConfigWindowBase::VideoSourceConfigWindowBase(VideoSourcePluginBase * plugin, wxWindow * parent) +{ + Create(plugin, parent); +} + +bool VideoSourceConfigWindowBase::Create(VideoSourcePluginBase * plugin, wxWindow * parent) +{ + m_Plugin = plugin; + return wxPanel::Create(parent); +} + +VideoSourceConfigWindowBase::~VideoSourceConfigWindowBase(void) +{ +} + +bool VideoSourceConfigWindowBase::ReadConfig() +{ + return false; +} + +bool VideoSourceConfigWindowBase::SaveConfig() +{ + return false; +} diff --git a/VideoSourcePluginBase/VideoSourceConfigWindowBase.h b/VideoSourcePluginBase/VideoSourceConfigWindowBase.h new file mode 100644 index 0000000..f7f945c --- /dev/null +++ b/VideoSourcePluginBase/VideoSourceConfigWindowBase.h @@ -0,0 +1,28 @@ +#ifndef _VIDEOSOURCECONFIGWINDOWBASE_H +#define _VIDEOSOURCECONFIGWINDOWBASE_H + +#include "VideoSourcePlugin.h" +#include + +class VideoSourcePluginBase; + +class IFLOOR_API VideoSourceConfigWindowBase : public CommonConfigWindowBase +{ +public: + VideoSourceConfigWindowBase(); + VideoSourceConfigWindowBase(VideoSourcePluginBase * plugin, wxWindow * parent); + + bool Create(VideoSourcePluginBase * plugin, wxWindow * parent); + virtual ~VideoSourceConfigWindowBase(void); + + /// Reads config from the video source plugin + virtual bool ReadConfig(); + + /// Saves config to the video source plugin + virtual bool SaveConfig(); + +protected: + VideoSourcePluginBase * m_Plugin; +}; + +#endif // _VIDEOSOURCECONFIGWINDOWBASE_H \ No newline at end of file diff --git a/VideoSourcePluginBase/VideoSourcePlugin.h b/VideoSourcePluginBase/VideoSourcePlugin.h new file mode 100644 index 0000000..1ab6fcb --- /dev/null +++ b/VideoSourcePluginBase/VideoSourcePlugin.h @@ -0,0 +1,14 @@ +#ifndef _VIDEOSOURCEPLUGIN_H +#define _VIDEOSOURCEPLUGIN_H + +#if defined(__WXMSW__) +#ifdef IFLOOR_EXPORTS +#define IFLOOR_API __declspec(dllexport) +#else +#define IFLOOR_API __declspec(dllimport) +#endif +#else +#define IFLOOR_API +#endif + +#endif // _VIDEOSOURCEPLUGIN_H diff --git a/VideoSourcePluginBase/VideoSourcePluginBase.cpp b/VideoSourcePluginBase/VideoSourcePluginBase.cpp new file mode 100644 index 0000000..0e7fc78 --- /dev/null +++ b/VideoSourcePluginBase/VideoSourcePluginBase.cpp @@ -0,0 +1,19 @@ +#include "stdwx.h" +#include "VideoSourcePluginBase.h" +#include "VideoGrabberBase.h" + +IMPLEMENT_ABSTRACT_CLASS(VideoSourcePluginBase, SerializableBase) + +VideoSourcePluginBase::~VideoSourcePluginBase() +{ +} + +void VideoSourcePluginBase::DeleteGrabber(VideoGrabberBase * grabber) +{ + wxDELETE(grabber); +} + +VideoSourceConfigWindowBase* VideoSourcePluginBase::CreateSettingsEditor(wxWindow* parent) +{ + return new VideoSourceConfigWindowBase(this, parent); +}; \ No newline at end of file diff --git a/VideoSourcePluginBase/VideoSourcePluginBase.h b/VideoSourcePluginBase/VideoSourcePluginBase.h new file mode 100644 index 0000000..d6c7fba --- /dev/null +++ b/VideoSourcePluginBase/VideoSourcePluginBase.h @@ -0,0 +1,40 @@ +#ifndef _VIDEOSOURCEPLUGINBASE_H +#define _VIDEOSOURCEPLUGINBASE_H + +#include +#include "VideoSourcePlugin.h" +#include "VideoSourceConfigWindowBase.h" +#if defined(__LINUX__) +#include +#endif + +class VideoGrabberBase; + +/// Base class for all iFloor effect plugins +class IFLOOR_API VideoSourcePluginBase : public SerializableBase//wxObject +{ + DECLARE_ABSTRACT_CLASS(VideoSourcePluginBase) +public: + virtual ~VideoSourcePluginBase(); + /// Returns GUID (unique identifier) of plugin + /// \return string which contains unique identifier of plugin + virtual wxString GetID() const = 0; + /// Returns name of plugin + /// \return string which contains human-readable name of plugin + virtual wxString GetName() const = 0; + + virtual VideoSourceConfigWindowBase* CreateSettingsEditor(wxWindow* parent); + virtual size_t GetDeviceCount() const = 0; + virtual wxString GetName(size_t index) const = 0; + virtual wxString GetName(const wxString & id) const = 0; + virtual wxString GetID(size_t index) const = 0; + virtual VideoGrabberBase * CreateGrabber(size_t index) = 0; + virtual VideoGrabberBase * CreateGrabber(const wxString & id) = 0; + virtual void DeleteGrabber(VideoGrabberBase * grabber); + virtual void RefreshDevices() {}; +}; + +typedef VideoSourcePluginBase * (*CreateVideoSourcePlugin_function)(); +typedef void (*DeleteVideoSourcePlugin_function)(VideoSourcePluginBase * plugin); + +#endif // _VIDEOSOURCEPLUGINBASE_H \ No newline at end of file diff --git a/VideoSourcePluginBase/Win/VideoSourcePluginBase.vcxproj b/VideoSourcePluginBase/Win/VideoSourcePluginBase.vcxproj new file mode 100644 index 0000000..90b1278 --- /dev/null +++ b/VideoSourcePluginBase/Win/VideoSourcePluginBase.vcxproj @@ -0,0 +1,273 @@ + + + + x64 + + + + Debug + x64 + + + Release + x64 + + + + {08E74159-4CA2-36BC-B137-45C65F9868A7} + Win32Proj + 10.0.26100.0 + x64 + VideoSourcePluginBase + NoUpgrade + + + + DynamicLibrary + Unicode + v143 + + + DynamicLibrary + Unicode + v143 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + VideoSourcePluginBase.dir\Debug\ + VideoSourcePluginBase + .dll + true + true + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + VideoSourcePluginBase.dir\Release\ + VideoSourcePluginBase + .dll + false + true + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + $(IntDir) + EnableFastChecks + + + ProgramDatabase + 4996 + Sync + + + Disabled + stdcpp17 + + true + Disabled + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/VideoSourcePluginBase.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/VideoSourcePluginBase.dir/Debug//cmake_pch.pch + + MultiThreadedDebugDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;IFLOOR_EXPORTS;CMAKE_INTDIR="Debug";VideoSourcePluginBase_EXPORTS + $(IntDir) + false + + + %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;IFLOOR_EXPORTS;CMAKE_INTDIR=\"Debug\";VideoSourcePluginBase_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\CommonPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxXS.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\wxJSON.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + true + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Debug/VideoSourcePluginBase.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/VideoSourcePluginBase.pdb + + Console + + + false + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + $(IntDir) + Default + + + 4996 + Sync + + + AnySuitable + stdcpp17 + + true + MaxSpeed + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/VideoSourcePluginBase.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/VideoSourcePluginBase.dir/Release//cmake_pch.pch + + MultiThreadedDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;IFLOOR_EXPORTS;CMAKE_INTDIR="Release";VideoSourcePluginBase_EXPORTS + $(IntDir) + + + false + + + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;IFLOOR_EXPORTS;CMAKE_INTDIR=\"Release\";VideoSourcePluginBase_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxXS\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\CommonPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxXS\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\ThirdParty\wxJSON\build\..\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\CommonPluginBase.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\Utils.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxXS.lib;C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\wxJSON.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + false + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Release/VideoSourcePluginBase.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/VideoSourcePluginBase.pdb + + Console + + + false + + + + + Always + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourcePluginBase\Win\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\VideoSourcePluginBase\Win\CMakeFiles\generate.stamp + false + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/VideoSourcePluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/VideoSourcePluginBase.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/VideoSourcePluginBase.dir/Debug//cmake_pch.pch + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/VideoSourcePluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/VideoSourcePluginBase.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/VideoSourcePluginBase.dir/Release//cmake_pch.pch + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/VideoSourcePluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/VideoSourcePluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/VideoSourcePluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/VideoSourcePluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/VideoSourcePluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/VideoSourcePluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/VideoSourcePluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/VideoSourcePluginBase/Win/CMakeFiles/VideoSourcePluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + ZERO_CHECK + false + Never + + + {751A15C0-76C2-3506-AB9D-0CD3545003FA} + CommonPluginBase + + + {14D82890-BB7F-3748-8713-43304E91CFA1} + Utils + + + {7887B55C-77B9-3262-AFAD-ABA738C61029} + wxJSON + + + {78CFCEBE-5466-3128-9717-547416DBFFE5} + wxXS + + + + + + \ No newline at end of file diff --git a/VideoSourcePluginBase/Win/VideoSourcePluginBase.vcxproj.filters b/VideoSourcePluginBase/Win/VideoSourcePluginBase.vcxproj.filters new file mode 100644 index 0000000..89d5bd5 --- /dev/null +++ b/VideoSourcePluginBase/Win/VideoSourcePluginBase.vcxproj.filters @@ -0,0 +1,57 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Precompile Header File + + + Precompile Header File + + + + + + + + {4951AEE1-75F2-3C38-B593-C6BC8C809FB0} + + + {112D4227-BB51-3360-BB5B-5EA5DBA5A65F} + + + {05450AB2-CB7B-34EA-83DF-1EE86424EDF0} + + + diff --git a/bin/CommonPluginBase.dll b/bin/CommonPluginBase.dll new file mode 100644 index 0000000..ea755ec Binary files /dev/null and b/bin/CommonPluginBase.dll differ diff --git a/bin/MotionDetectorCore.dll b/bin/MotionDetectorCore.dll new file mode 100644 index 0000000..d92f22b Binary files /dev/null and b/bin/MotionDetectorCore.dll differ diff --git a/bin/MotionDetectorMultiCam.dll b/bin/MotionDetectorMultiCam.dll new file mode 100644 index 0000000..d3c2679 Binary files /dev/null and b/bin/MotionDetectorMultiCam.dll differ diff --git a/bin/MotionDetectorMultiCamGui.dll b/bin/MotionDetectorMultiCamGui.dll new file mode 100644 index 0000000..ae7fc18 Binary files /dev/null and b/bin/MotionDetectorMultiCamGui.dll differ diff --git a/bin/MotionDetectorPluginBase.dll b/bin/MotionDetectorPluginBase.dll new file mode 100644 index 0000000..7d7a1f1 Binary files /dev/null and b/bin/MotionDetectorPluginBase.dll differ diff --git a/bin/VideoSourceDirectShow.dll b/bin/VideoSourceDirectShow.dll new file mode 100644 index 0000000..e4561e9 Binary files /dev/null and b/bin/VideoSourceDirectShow.dll differ diff --git a/bin/VideoSourcePluginBase.dll b/bin/VideoSourcePluginBase.dll new file mode 100644 index 0000000..a6458c0 Binary files /dev/null and b/bin/VideoSourcePluginBase.dll differ diff --git a/bin/plugins/gui/MotionDetectorMultiCamGui.dll b/bin/plugins/gui/MotionDetectorMultiCamGui.dll new file mode 100644 index 0000000..ae7fc18 Binary files /dev/null and b/bin/plugins/gui/MotionDetectorMultiCamGui.dll differ diff --git a/bin/plugins/motion_detector/MotionDetectorCore.dll b/bin/plugins/motion_detector/MotionDetectorCore.dll new file mode 100644 index 0000000..d92f22b Binary files /dev/null and b/bin/plugins/motion_detector/MotionDetectorCore.dll differ diff --git a/bin/plugins/video_source/VideoSourceDirectShow.dll b/bin/plugins/video_source/VideoSourceDirectShow.dll new file mode 100644 index 0000000..e4561e9 Binary files /dev/null and b/bin/plugins/video_source/VideoSourceDirectShow.dll differ diff --git a/bin/wxGuiPluginBase.dll b/bin/wxGuiPluginBase.dll new file mode 100644 index 0000000..41fa90e Binary files /dev/null and b/bin/wxGuiPluginBase.dll differ diff --git a/bin/wxModularHost.exe b/bin/wxModularHost.exe new file mode 100644 index 0000000..5b4e905 Binary files /dev/null and b/bin/wxModularHost.exe differ diff --git a/bin/wxNonGuiPluginBase.dll b/bin/wxNonGuiPluginBase.dll new file mode 100644 index 0000000..8fd96cd Binary files /dev/null and b/bin/wxNonGuiPluginBase.dll differ diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt deleted file mode 100644 index 8eb0f4f..0000000 --- a/build/CMakeLists.txt +++ /dev/null @@ -1,123 +0,0 @@ -cmake_minimum_required(VERSION 2.6.0) - -include(PCHSupport.cmake) - -# We will generate both Debug and Release project files at the same time -# for Windows and OS X -if(WIN32 OR APPLE) - set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE) - set(LIB_SUFFIX "") -endif(WIN32 OR APPLE) - -# For Linux we will need to execute CMake twice in order to generate -# Debug and Release versions of Makefiles -if(UNIX AND NOT APPLE) - set(LINUX ON) - set(LIB_SUFFIX /${CMAKE_BUILD_TYPE}) -endif(UNIX AND NOT APPLE) - -set(PROJECT_NAME wxModularHost) -project(${PROJECT_NAME}) - -# If there are any additional CMake modules (e.g. module which searches -# for OpenCV or for DirectShow libs), then CMake should start searching -# for them in current folder -set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}) - -if(APPLE) - set(OS_BASE_NAME Mac) - set(CMAKE_OSX_SYSROOT "macosx10.8") -endif(APPLE) -if(LINUX) - set(OS_BASE_NAME Linux) -endif(LINUX) -if(WIN32) - set(OS_BASE_NAME Win) -endif(WIN32) - -# Here we specify the list of wxWidgets libs which we will use in our project -set(wxWidgets_USE_LIBS base core adv aui net gl xml propgrid html) - -# Here we specify that we need DLL version of wxWidgets libs and dynamic CRT -# This is a MUST for applications with plugins. Both app and DLL plugin MUST -# use the same instance of wxWidgets and the same event loop. -set(BUILD_SHARED_LIBS 1) - -# Find wxWidgets library on current PC -# You should have %WXWIN% environment variable which should point to the -# directory where wxWidgets source code is placed. -# wxWidgets libs MUST be compiled for both Debug and Release versions -find_package(wxWidgets REQUIRED) - - -# For some reason CMake generates wrong list of definitions. -# Each item should start with /D but it does not. -# We need to fix that manually -set(wxWidgets_DEFINITIONS_TEMP) -foreach(DEFINITION ${wxWidgets_DEFINITIONS}) - - if(NOT ${DEFINITION} MATCHES "/D.*") - set(DEFINITION "/D${DEFINITION}") - endif() - set(wxWidgets_DEFINITIONS_TEMP ${wxWidgets_DEFINITIONS_TEMP} - ${DEFINITION}) -endforeach(${DEFINITION}) -set(wxWidgets_DEFINITIONS ${wxWidgets_DEFINITIONS_TEMP}) - -# Here we add some definitions which prevent Visual Studio from -# generating tons of warnings about unsecure function calls. -# See http://msdn.microsoft.com/en-us/library/ttcz0bys.aspx -if(WIN32) - set(wxWidgets_DEFINITIONS ${wxWidgets_DEFINITIONS}; - /D_CRT_SECURE_NO_DEPRECATE; - /D_CRT_NONSTDC_NO_DEPRECATE; - /D_UNICODE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /wd4996") -endif(WIN32) - -# Since we are going to use wxWidgets in all subrojects, -# it's OK to create the variable which will contain -# common preprocessor definitions. This variable will be -# used in subprojects. -set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS}; - ${wxWidgets_DEFINITIONS}) - -# Variable which points to root folder of our source code -set(PROJECT_ROOT_DIR ${PROJECT_SOURCE_DIR}/..) - -# If any ThirdParty libraries are going to be -# used in our project then it would be better to put -# them into separate subfolder. We will create -# the variable which points to this subfolder. -set(THIRD_PARTY_DIR ${PROJECT_ROOT_DIR}/ThirdParty) - -set(BASE_INCLUDE_DIRECTORIES ${PROJECT_ROOT_DIR}/include) - -# Add wxWidgets include paths to the list of -# include directories for all projects. -include_directories(${wxWidgets_INCLUDE_DIRS}) - -if(WIN32 OR LINUX) - set(CMAKE_CXX_FLAGS_DEBUG - "${CMAKE_CXX_FLAGS_DEBUG} - /D__WXDEBUG__=1" ) -endif(WIN32 OR LINUX) - -# Now we can include all our subprojects. -# CMake will generate project files for them -add_subdirectory (../wxModularHost - ../../wxModularHost/${OS_BASE_NAME}${LIB_SUFFIX}) -add_subdirectory (../wxModularCore - ../../wxModularCore/${OS_BASE_NAME}${LIB_SUFFIX}) - -add_subdirectory (../wxNonGuiPluginBase - ../../wxNonGuiPluginBase/${OS_BASE_NAME}${LIB_SUFFIX}) -add_subdirectory (../SampleNonGuiPlugin - ../../SampleNonGuiPlugin/${OS_BASE_NAME}${LIB_SUFFIX}) - -add_subdirectory (../wxGuiPluginBase - ../../wxGuiPluginBase/${OS_BASE_NAME}${LIB_SUFFIX}) -add_subdirectory (../SampleGuiPlugin1 - ../../SampleGuiPlugin1/${OS_BASE_NAME}${LIB_SUFFIX}) -add_subdirectory (../SampleGuiPlugin2 - ../../SampleGuiPlugin2/${OS_BASE_NAME}${LIB_SUFFIX}) diff --git a/build/FindPackageHandleStandardArgs.cmake b/build/FindPackageHandleStandardArgs.cmake deleted file mode 100644 index c6db433..0000000 --- a/build/FindPackageHandleStandardArgs.cmake +++ /dev/null @@ -1,614 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#[=======================================================================[.rst: -FindPackageHandleStandardArgs ------------------------------ - -This module provides functions intended to be used in :ref:`Find Modules` -implementing :command:`find_package()` calls. - -.. command:: find_package_handle_standard_args - - This command handles the ``REQUIRED``, ``QUIET`` and version-related - arguments of :command:`find_package`. It also sets the - ``_FOUND`` variable. The package is considered found if all - variables listed contain valid results, e.g. valid filepaths. - - There are two signatures: - - .. code-block:: cmake - - find_package_handle_standard_args( - (DEFAULT_MSG|) - ... - ) - - find_package_handle_standard_args( - [FOUND_VAR ] - [REQUIRED_VARS ...] - [VERSION_VAR ] - [HANDLE_VERSION_RANGE] - [HANDLE_COMPONENTS] - [CONFIG_MODE] - [NAME_MISMATCHED] - [REASON_FAILURE_MESSAGE ] - [FAIL_MESSAGE ] - ) - - The ``_FOUND`` variable will be set to ``TRUE`` if all - the variables ``...`` are valid and any optional - constraints are satisfied, and ``FALSE`` otherwise. A success or - failure message may be displayed based on the results and on - whether the ``REQUIRED`` and/or ``QUIET`` option was given to - the :command:`find_package` call. - - The options are: - - ``(DEFAULT_MSG|)`` - In the simple signature this specifies the failure message. - Use ``DEFAULT_MSG`` to ask for a default message to be computed - (recommended). Not valid in the full signature. - - ``FOUND_VAR `` - .. deprecated:: 3.3 - - Specifies either ``_FOUND`` or - ``_FOUND`` as the result variable. This exists only - for compatibility with older versions of CMake and is now ignored. - Result variables of both names are always set for compatibility. - - ``REQUIRED_VARS ...`` - Specify the variables which are required for this package. - These may be named in the generated failure message asking the - user to set the missing variable values. Therefore these should - typically be cache entries such as ``FOO_LIBRARY`` and not output - variables like ``FOO_LIBRARIES``. - - .. versionchanged:: 3.18 - If ``HANDLE_COMPONENTS`` is specified, this option can be omitted. - - ``VERSION_VAR `` - Specify the name of a variable that holds the version of the package - that has been found. This version will be checked against the - (potentially) specified required version given to the - :command:`find_package` call, including its ``EXACT`` option. - The default messages include information about the required - version and the version which has been actually found, both - if the version is ok or not. - - ``HANDLE_VERSION_RANGE`` - .. versionadded:: 3.19 - - Enable handling of a version range, if one is specified. Without this - option, a developer warning will be displayed if a version range is - specified. - - ``HANDLE_COMPONENTS`` - Enable handling of package components. In this case, the command - will report which components have been found and which are missing, - and the ``_FOUND`` variable will be set to ``FALSE`` - if any of the required components (i.e. not the ones listed after - the ``OPTIONAL_COMPONENTS`` option of :command:`find_package`) are - missing. - - ``CONFIG_MODE`` - Specify that the calling find module is a wrapper around a - call to ``find_package( NO_MODULE)``. This implies - a ``VERSION_VAR`` value of ``_VERSION``. The command - will automatically check whether the package configuration file - was found. - - ``REASON_FAILURE_MESSAGE `` - .. versionadded:: 3.16 - - Specify a custom message of the reason for the failure which will be - appended to the default generated message. - - ``FAIL_MESSAGE `` - Specify a custom failure message instead of using the default - generated message. Not recommended. - - ``NAME_MISMATCHED`` - .. versionadded:: 3.17 - - Indicate that the ```` does not match - ``${CMAKE_FIND_PACKAGE_NAME}``. This is usually a mistake and raises a - warning, but it may be intentional for usage of the command for components - of a larger package. - -Example for the simple signature: - -.. code-block:: cmake - - find_package_handle_standard_args(LibXml2 DEFAULT_MSG - LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR) - -The ``LibXml2`` package is considered to be found if both -``LIBXML2_LIBRARY`` and ``LIBXML2_INCLUDE_DIR`` are valid. -Then also ``LibXml2_FOUND`` is set to ``TRUE``. If it is not found -and ``REQUIRED`` was used, it fails with a -:command:`message(FATAL_ERROR)`, independent whether ``QUIET`` was -used or not. If it is found, success will be reported, including -the content of the first ````. On repeated CMake runs, -the same message will not be printed again. - -.. note:: - - If ```` does not match ``CMAKE_FIND_PACKAGE_NAME`` for the - calling module, a warning that there is a mismatch is given. The - ``FPHSA_NAME_MISMATCHED`` variable may be set to bypass the warning if using - the old signature and the ``NAME_MISMATCHED`` argument using the new - signature. To avoid forcing the caller to require newer versions of CMake for - usage, the variable's value will be used if defined when the - ``NAME_MISMATCHED`` argument is not passed for the new signature (but using - both is an error).. - -Example for the full signature: - -.. code-block:: cmake - - find_package_handle_standard_args(LibArchive - REQUIRED_VARS LibArchive_LIBRARY LibArchive_INCLUDE_DIR - VERSION_VAR LibArchive_VERSION) - -In this case, the ``LibArchive`` package is considered to be found if -both ``LibArchive_LIBRARY`` and ``LibArchive_INCLUDE_DIR`` are valid. -Also the version of ``LibArchive`` will be checked by using the version -contained in ``LibArchive_VERSION``. Since no ``FAIL_MESSAGE`` is given, -the default messages will be printed. - -Another example for the full signature: - -.. code-block:: cmake - - find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4) - find_package_handle_standard_args(Automoc4 CONFIG_MODE) - -In this case, a ``FindAutmoc4.cmake`` module wraps a call to -``find_package(Automoc4 NO_MODULE)`` and adds an additional search -directory for ``automoc4``. Then the call to -``find_package_handle_standard_args`` produces a proper success/failure -message. - -.. command:: find_package_check_version - - .. versionadded:: 3.19 - - Helper function which can be used to check if a ```` is valid - against version-related arguments of :command:`find_package`. - - .. code-block:: cmake - - find_package_check_version( - [HANDLE_VERSION_RANGE] - [RESULT_MESSAGE_VARIABLE ] - ) - - The ```` will hold a boolean value giving the result of the check. - - The options are: - - ``HANDLE_VERSION_RANGE`` - Enable handling of a version range, if one is specified. Without this - option, a developer warning will be displayed if a version range is - specified. - - ``RESULT_MESSAGE_VARIABLE `` - Specify a variable to get back a message describing the result of the check. - -Example for the usage: - -.. code-block:: cmake - - find_package_check_version(1.2.3 result HANDLE_VERSION_RANGE - RESULT_MESSAGE_VARIABLE reason) - if (result) - message (STATUS "${reason}") - else() - message (FATAL_ERROR "${reason}") - endif() -#]=======================================================================] - -include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake) - - -cmake_policy(PUSH) -# numbers and boolean constants -cmake_policy (SET CMP0012 NEW) -# IN_LIST operator -cmake_policy (SET CMP0057 NEW) - - -# internal helper macro -macro(_FPHSA_FAILURE_MESSAGE _msg) - set (__msg "${_msg}") - if (FPHSA_REASON_FAILURE_MESSAGE) - string(APPEND __msg "\n Reason given by package: ${FPHSA_REASON_FAILURE_MESSAGE}\n") - elseif(NOT DEFINED PROJECT_NAME) - string(APPEND __msg "\n" - "Hint: The project() command has not yet been called. It sets up system-specific search paths.") - endif() - if (${_NAME}_FIND_REQUIRED) - message(FATAL_ERROR "${__msg}") - else () - if (NOT ${_NAME}_FIND_QUIETLY) - message(STATUS "${__msg}") - endif () - endif () -endmacro() - - -# internal helper macro to generate the failure message when used in CONFIG_MODE: -macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE) - # _CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found: - if(${_NAME}_CONFIG) - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing:${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})") - else() - # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version. - # List them all in the error message: - if(${_NAME}_CONSIDERED_CONFIGS) - set(configsText "") - list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount) - math(EXPR configsCount "${configsCount} - 1") - foreach(currentConfigIndex RANGE ${configsCount}) - list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename) - list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version) - string(APPEND configsText "\n ${filename} (version ${version})") - endforeach() - if (${_NAME}_NOT_FOUND_MESSAGE) - if (FPHSA_REASON_FAILURE_MESSAGE) - string(PREPEND FPHSA_REASON_FAILURE_MESSAGE "${${_NAME}_NOT_FOUND_MESSAGE}\n ") - else() - set(FPHSA_REASON_FAILURE_MESSAGE "${${_NAME}_NOT_FOUND_MESSAGE}") - endif() - else() - string(APPEND configsText "\n") - endif() - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:${configsText}") - - else() - # Simple case: No Config-file was found at all: - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}") - endif() - endif() -endmacro() - - -function(FIND_PACKAGE_CHECK_VERSION version result) - cmake_parse_arguments (PARSE_ARGV 2 FPCV "HANDLE_VERSION_RANGE;NO_AUTHOR_WARNING_VERSION_RANGE" "RESULT_MESSAGE_VARIABLE" "") - - if (FPCV_UNPARSED_ARGUMENTS) - message (FATAL_ERROR "find_package_check_version(): ${FPCV_UNPARSED_ARGUMENTS}: unexpected arguments") - endif() - if ("RESULT_MESSAGE_VARIABLE" IN_LIST FPCV_KEYWORDS_MISSING_VALUES) - message (FATAL_ERROR "find_package_check_version(): RESULT_MESSAGE_VARIABLE expects an argument") - endif() - - set (${result} FALSE PARENT_SCOPE) - if (FPCV_RESULT_MESSAGE_VARIABLE) - unset (${FPCV_RESULT_MESSAGE_VARIABLE} PARENT_SCOPE) - endif() - - if (_CMAKE_FPHSA_PACKAGE_NAME) - set (package "${_CMAKE_FPHSA_PACKAGE_NAME}") - elseif (CMAKE_FIND_PACKAGE_NAME) - set (package "${CMAKE_FIND_PACKAGE_NAME}") - else() - message (FATAL_ERROR "find_package_check_version(): Cannot be used outside a 'Find Module'") - endif() - - if (NOT FPCV_NO_AUTHOR_WARNING_VERSION_RANGE - AND ${package}_FIND_VERSION_RANGE AND NOT FPCV_HANDLE_VERSION_RANGE) - message(AUTHOR_WARNING - "`find_package()` specify a version range but the option " - "HANDLE_VERSION_RANGE` is not passed to `find_package_check_version()`. " - "Only the lower endpoint of the range will be used.") - endif() - - - set (version_ok FALSE) - unset (version_msg) - - if (FPCV_HANDLE_VERSION_RANGE AND ${package}_FIND_VERSION_RANGE) - if ((${package}_FIND_VERSION_RANGE_MIN STREQUAL "INCLUDE" - AND version VERSION_GREATER_EQUAL ${package}_FIND_VERSION_MIN) - AND ((${package}_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" - AND version VERSION_LESS_EQUAL ${package}_FIND_VERSION_MAX) - OR (${package}_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" - AND version VERSION_LESS ${package}_FIND_VERSION_MAX))) - set (version_ok TRUE) - set(version_msg "(found suitable version \"${version}\", required range is \"${${package}_FIND_VERSION_RANGE}\")") - else() - set(version_msg "Found unsuitable version \"${version}\", required range is \"${${package}_FIND_VERSION_RANGE}\"") - endif() - elseif (DEFINED ${package}_FIND_VERSION) - if(${package}_FIND_VERSION_EXACT) # exact version required - # count the dots in the version string - string(REGEX REPLACE "[^.]" "" version_dots "${version}") - # add one dot because there is one dot more than there are components - string(LENGTH "${version_dots}." version_dots) - if (version_dots GREATER ${package}_FIND_VERSION_COUNT) - # Because of the C++ implementation of find_package() ${package}_FIND_VERSION_COUNT - # is at most 4 here. Therefore a simple lookup table is used. - if (${package}_FIND_VERSION_COUNT EQUAL 1) - set(version_regex "[^.]*") - elseif (${package}_FIND_VERSION_COUNT EQUAL 2) - set(version_regex "[^.]*\\.[^.]*") - elseif (${package}_FIND_VERSION_COUNT EQUAL 3) - set(version_regex "[^.]*\\.[^.]*\\.[^.]*") - else() - set(version_regex "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*") - endif() - string(REGEX REPLACE "^(${version_regex})\\..*" "\\1" version_head "${version}") - if (NOT ${package}_FIND_VERSION VERSION_EQUAL version_head) - set(version_msg "Found unsuitable version \"${version}\", but required is exact version \"${${package}_FIND_VERSION}\"") - else () - set(version_ok TRUE) - set(version_msg "(found suitable exact version \"${version}\")") - endif () - else () - if (NOT ${package}_FIND_VERSION VERSION_EQUAL version) - set(version_msg "Found unsuitable version \"${version}\", but required is exact version \"${${package}_FIND_VERSION}\"") - else () - set(version_ok TRUE) - set(version_msg "(found suitable exact version \"${version}\")") - endif () - endif () - else() # minimum version - if (${package}_FIND_VERSION VERSION_GREATER version) - set(version_msg "Found unsuitable version \"${version}\", but required is at least \"${${package}_FIND_VERSION}\"") - else() - set(version_ok TRUE) - set(version_msg "(found suitable version \"${version}\", minimum required is \"${${package}_FIND_VERSION}\")") - endif() - endif() - else () - set(version_ok TRUE) - set(version_msg "(found version \"${version}\")") - endif() - - set (${result} ${version_ok} PARENT_SCOPE) - if (FPCV_RESULT_MESSAGE_VARIABLE) - set (${FPCV_RESULT_MESSAGE_VARIABLE} "${version_msg}" PARENT_SCOPE) - endif() -endfunction() - - -function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG) - - # Set up the arguments for `cmake_parse_arguments`. - set(options CONFIG_MODE HANDLE_COMPONENTS NAME_MISMATCHED HANDLE_VERSION_RANGE) - set(oneValueArgs FAIL_MESSAGE REASON_FAILURE_MESSAGE VERSION_VAR FOUND_VAR) - set(multiValueArgs REQUIRED_VARS) - - # Check whether we are in 'simple' or 'extended' mode: - set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} ) - list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX) - - unset(FPHSA_NAME_MISMATCHED_override) - if (DEFINED FPHSA_NAME_MISMATCHED) - # If the variable NAME_MISMATCHED variable is set, error if it is passed as - # an argument. The former is for old signatures, the latter is for new - # signatures. - list(FIND ARGN "NAME_MISMATCHED" name_mismatched_idx) - if (NOT name_mismatched_idx EQUAL "-1") - message(FATAL_ERROR - "The `NAME_MISMATCHED` argument may only be specified by the argument or " - "the variable, not both.") - endif () - - # But use the variable if it is not an argument to avoid forcing minimum - # CMake version bumps for calling modules. - set(FPHSA_NAME_MISMATCHED_override "${FPHSA_NAME_MISMATCHED}") - endif () - - if(${INDEX} EQUAL -1) - set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG}) - set(FPHSA_REQUIRED_VARS ${ARGN}) - set(FPHSA_VERSION_VAR) - else() - cmake_parse_arguments(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN}) - - if(FPHSA_UNPARSED_ARGUMENTS) - message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"") - endif() - - if(NOT FPHSA_FAIL_MESSAGE) - set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG") - endif() - - # In config-mode, we rely on the variable _CONFIG, which is set by find_package() - # when it successfully found the config-file, including version checking: - if(FPHSA_CONFIG_MODE) - list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG) - list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS) - set(FPHSA_VERSION_VAR ${_NAME}_VERSION) - endif() - - if(NOT FPHSA_REQUIRED_VARS AND NOT FPHSA_HANDLE_COMPONENTS) - message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()") - endif() - endif() - - if (DEFINED FPHSA_NAME_MISMATCHED_override) - set(FPHSA_NAME_MISMATCHED "${FPHSA_NAME_MISMATCHED_override}") - endif () - - if (DEFINED CMAKE_FIND_PACKAGE_NAME - AND NOT FPHSA_NAME_MISMATCHED - AND NOT _NAME STREQUAL CMAKE_FIND_PACKAGE_NAME) - message(AUTHOR_WARNING - "The package name passed to `find_package_handle_standard_args` " - "(${_NAME}) does not match the name of the calling package " - "(${CMAKE_FIND_PACKAGE_NAME}). This can lead to problems in calling " - "code that expects `find_package` result variables (e.g., `_FOUND`) " - "to follow a certain pattern.") - endif () - - if (${_NAME}_FIND_VERSION_RANGE AND NOT FPHSA_HANDLE_VERSION_RANGE) - message(AUTHOR_WARNING - "`find_package()` specify a version range but the module ${_NAME} does " - "not support this capability. Only the lower endpoint of the range " - "will be used.") - endif() - - # to propagate package name to FIND_PACKAGE_CHECK_VERSION - set(_CMAKE_FPHSA_PACKAGE_NAME "${_NAME}") - - # now that we collected all arguments, process them - - if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG") - set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}") - endif() - - if (FPHSA_REQUIRED_VARS) - list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR) - endif() - - string(TOUPPER ${_NAME} _NAME_UPPER) - string(TOLOWER ${_NAME} _NAME_LOWER) - - if(FPHSA_FOUND_VAR) - set(_FOUND_VAR_UPPER ${_NAME_UPPER}_FOUND) - set(_FOUND_VAR_MIXED ${_NAME}_FOUND) - if(FPHSA_FOUND_VAR STREQUAL _FOUND_VAR_MIXED OR FPHSA_FOUND_VAR STREQUAL _FOUND_VAR_UPPER) - set(_FOUND_VAR ${FPHSA_FOUND_VAR}) - else() - message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_FOUND_VAR_MIXED}\" and \"${_FOUND_VAR_UPPER}\" are valid names.") - endif() - else() - set(_FOUND_VAR ${_NAME_UPPER}_FOUND) - endif() - - # collect all variables which were not found, so they can be printed, so the - # user knows better what went wrong (#6375) - set(MISSING_VARS "") - set(DETAILS "") - # check if all passed variables are valid - set(FPHSA_FOUND_${_NAME} TRUE) - foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS}) - if(NOT ${_CURRENT_VAR}) - set(FPHSA_FOUND_${_NAME} FALSE) - string(APPEND MISSING_VARS " ${_CURRENT_VAR}") - else() - string(APPEND DETAILS "[${${_CURRENT_VAR}}]") - endif() - endforeach() - if(FPHSA_FOUND_${_NAME}) - set(${_NAME}_FOUND TRUE) - set(${_NAME_UPPER}_FOUND TRUE) - else() - set(${_NAME}_FOUND FALSE) - set(${_NAME_UPPER}_FOUND FALSE) - endif() - - # component handling - unset(FOUND_COMPONENTS_MSG) - unset(MISSING_COMPONENTS_MSG) - - if(FPHSA_HANDLE_COMPONENTS) - foreach(comp ${${_NAME}_FIND_COMPONENTS}) - if(${_NAME}_${comp}_FOUND) - - if(NOT DEFINED FOUND_COMPONENTS_MSG) - set(FOUND_COMPONENTS_MSG "found components:") - endif() - string(APPEND FOUND_COMPONENTS_MSG " ${comp}") - - else() - - if(NOT DEFINED MISSING_COMPONENTS_MSG) - set(MISSING_COMPONENTS_MSG "missing components:") - endif() - string(APPEND MISSING_COMPONENTS_MSG " ${comp}") - - if(${_NAME}_FIND_REQUIRED_${comp}) - set(${_NAME}_FOUND FALSE) - string(APPEND MISSING_VARS " ${comp}") - endif() - - endif() - endforeach() - set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}") - string(APPEND DETAILS "[c${COMPONENT_MSG}]") - endif() - - # version handling: - set(VERSION_MSG "") - set(VERSION_OK TRUE) - - # check that the version variable is not empty to avoid emitting a misleading - # message (i.e. `Found unsuitable version ""`) - if (DEFINED ${_NAME}_FIND_VERSION) - if(DEFINED ${FPHSA_VERSION_VAR}) - if(NOT "${${FPHSA_VERSION_VAR}}" STREQUAL "") - set(_FOUND_VERSION ${${FPHSA_VERSION_VAR}}) - if (FPHSA_HANDLE_VERSION_RANGE) - set (FPCV_HANDLE_VERSION_RANGE HANDLE_VERSION_RANGE) - else() - set(FPCV_HANDLE_VERSION_RANGE NO_AUTHOR_WARNING_VERSION_RANGE) - endif() - find_package_check_version ("${_FOUND_VERSION}" VERSION_OK RESULT_MESSAGE_VARIABLE VERSION_MSG - ${FPCV_HANDLE_VERSION_RANGE}) - else() - set(VERSION_OK FALSE) - endif() - endif() - if("${${FPHSA_VERSION_VAR}}" STREQUAL "") - # if the package was not found, but a version was given, add that to the output: - if(${_NAME}_FIND_VERSION_EXACT) - set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")") - elseif (FPHSA_HANDLE_VERSION_RANGE AND ${_NAME}_FIND_VERSION_RANGE) - set(VERSION_MSG "(Required is version range \"${${_NAME}_FIND_VERSION_RANGE}\")") - else() - set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")") - endif() - endif() - else () - # Check with DEFINED as the found version may be 0. - if(DEFINED ${FPHSA_VERSION_VAR}) - set(VERSION_MSG "(found version \"${${FPHSA_VERSION_VAR}}\")") - endif() - endif () - - if(VERSION_OK) - string(APPEND DETAILS "[v${${FPHSA_VERSION_VAR}}(${${_NAME}_FIND_VERSION})]") - else() - set(${_NAME}_FOUND FALSE) - endif() - - - # print the result: - if (${_NAME}_FOUND) - FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}") - else () - - if(FPHSA_CONFIG_MODE) - _FPHSA_HANDLE_FAILURE_CONFIG_MODE() - else() - if(NOT VERSION_OK) - set(RESULT_MSG) - if (_FIRST_REQUIRED_VAR) - string (APPEND RESULT_MSG "found ${${_FIRST_REQUIRED_VAR}}") - endif() - if (COMPONENT_MSG) - if (RESULT_MSG) - string (APPEND RESULT_MSG ", ") - endif() - string (APPEND RESULT_MSG "${FOUND_COMPONENTS_MSG}") - endif() - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (${RESULT_MSG})") - else() - _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing:${MISSING_VARS}) ${VERSION_MSG}") - endif() - endif() - - endif () - - set(${_NAME}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE) - set(${_NAME_UPPER}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE) -endfunction() - - -cmake_policy(POP) diff --git a/build/FindPackageMessage.cmake b/build/FindPackageMessage.cmake deleted file mode 100644 index 7efbe18..0000000 --- a/build/FindPackageMessage.cmake +++ /dev/null @@ -1,49 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#[=======================================================================[.rst: -FindPackageMessage ------------------- - -.. code-block:: cmake - - find_package_message( "message for user" "find result details") - -This function is intended to be used in FindXXX.cmake modules files. -It will print a message once for each unique find result. This is -useful for telling the user where a package was found. The first -argument specifies the name (XXX) of the package. The second argument -specifies the message to display. The third argument lists details -about the find result so that if they change the message will be -displayed again. The macro also obeys the QUIET argument to the -find_package command. - -Example: - -.. code-block:: cmake - - if(X11_FOUND) - find_package_message(X11 "Found X11: ${X11_X11_LIB}" - "[${X11_X11_LIB}][${X11_INCLUDE_DIR}]") - else() - ... - endif() -#]=======================================================================] - -function(find_package_message pkg msg details) - # Avoid printing a message repeatedly for the same find result. - if(NOT ${pkg}_FIND_QUIETLY) - string(REPLACE "\n" "" details "${details}") - set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg}) - if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}") - # The message has not yet been printed. - string(STRIP "${msg}" msg) - message(STATUS "${msg}") - - # Save the find details in the cache to avoid printing the same - # message again. - set("${DETAILS_VAR}" "${details}" - CACHE INTERNAL "Details about finding ${pkg}") - endif() - endif() -endfunction() diff --git a/build/FindwxWidgets.cmake b/build/FindwxWidgets.cmake deleted file mode 100644 index b42a85e..0000000 --- a/build/FindwxWidgets.cmake +++ /dev/null @@ -1,1245 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#[=======================================================================[.rst: -FindwxWidgets -------------- - -Find a wxWidgets (a.k.a., wxWindows) installation. - -This module finds if wxWidgets is installed and selects a default -configuration to use. wxWidgets is a modular library. To specify the -modules that you will use, you need to name them as components to the -package: - -find_package(wxWidgets COMPONENTS core base ... OPTIONAL_COMPONENTS net ...) - -.. versionadded:: 3.4 - Support for :command:`find_package` version argument; ``webview`` component. - -.. versionadded:: 3.14 - ``OPTIONAL_COMPONENTS`` support. - -There are two search branches: a windows style and a unix style. For -windows, the following variables are searched for and set to defaults -in case of multiple choices. Change them if the defaults are not -desired (i.e., these are the only variables you should change to -select a configuration): - -:: - - wxWidgets_ROOT_DIR - Base wxWidgets directory - (e.g., C:/wxWidgets-3.2.0). - wxWidgets_LIB_DIR - Path to wxWidgets libraries - (e.g., C:/wxWidgets-3.2.0/lib/vc_x64_lib). - wxWidgets_CONFIGURATION - Configuration to use - (e.g., msw, mswd, mswu, mswunivud, etc.) - wxWidgets_EXCLUDE_COMMON_LIBRARIES - - Set to TRUE to exclude linking of - commonly required libs (e.g., png tiff - jpeg zlib regex expat scintilla lexilla). - - - -For unix style it uses the wx-config utility. You can select between -debug/release, unicode/ansi, universal/non-universal, and -static/shared in the QtDialog or ccmake interfaces by turning ON/OFF -the following variables: - -:: - - wxWidgets_USE_DEBUG - wxWidgets_USE_UNICODE - wxWidgets_USE_UNIVERSAL - wxWidgets_USE_STATIC - -There is also a wxWidgets_CONFIG_OPTIONS variable for all other -options that need to be passed to the wx-config utility. For example, -to use the base toolkit found in the /usr/local path, set the variable -(before calling the FIND_PACKAGE command) as such: - -:: - - set(wxWidgets_CONFIG_OPTIONS --toolkit=base --prefix=/usr) - - - -The following are set after the configuration is done for both windows -and unix style: - -:: - - wxWidgets_FOUND - Set to TRUE if wxWidgets was found. - wxWidgets_INCLUDE_DIRS - Include directories for WIN32 - i.e., where to find "wx/wx.h" and - "wx/setup.h"; possibly empty for unices. - wxWidgets_LIBRARIES - Path to the wxWidgets libraries. - wxWidgets_LIBRARY_DIRS - compile time link dirs, useful for - rpath on UNIX. Typically an empty string - in WIN32 environment. - wxWidgets_DEFINITIONS - Contains defines required to compile/link - against WX, e.g. WXUSINGDLL - wxWidgets_DEFINITIONS_DEBUG- Contains defines required to compile/link - against WX debug builds, e.g. __WXDEBUG__ - wxWidgets_CXX_FLAGS - Include dirs and compiler flags for - unices, empty on WIN32. Essentially - "`wx-config --cxxflags`". - wxWidgets_USE_FILE - Convenience include file. - -.. versionadded:: 3.11 - The following environment variables can be used as hints: ``WX_CONFIG``, - ``WXRC_CMD``. - - -Sample usage: - -:: - - # Note that for MinGW users the order of libs is important! - find_package(wxWidgets COMPONENTS gl core base OPTIONAL_COMPONENTS net) - if(wxWidgets_FOUND) - include(${wxWidgets_USE_FILE}) - # and for each of your dependent executable/library targets: - target_link_libraries( ${wxWidgets_LIBRARIES}) - endif() - - - -If wxWidgets is required (i.e., not an optional part): - -:: - - find_package(wxWidgets REQUIRED gl core base OPTIONAL_COMPONENTS net) - include(${wxWidgets_USE_FILE}) - # and for each of your dependent executable/library targets: - target_link_libraries( ${wxWidgets_LIBRARIES}) - -Imported targets -^^^^^^^^^^^^^^^^ - -.. versionadded:: 3.27 - -This module defines the following :prop_tgt:`IMPORTED` targets: - -``wxWidgets::wxWidgets`` - An interface library providing usage requirements for the found components. -#]=======================================================================] - -# -# FIXME: check this and provide a correct sample usage... -# Remember to connect back to the upper text. -# Sample usage with monolithic wx build: -# -# find_package(wxWidgets COMPONENTS mono) -# ... - -# NOTES -# -# This module has been tested on the WIN32 platform with wxWidgets -# 2.6.2, 2.6.3, and 2.5.3. However, it has been designed to -# easily extend support to all possible builds, e.g., static/shared, -# debug/release, unicode, universal, multilib/monolithic, etc.. -# -# If you want to use the module and your build type is not supported -# out-of-the-box, please contact me to exchange information on how -# your system is setup and I'll try to add support for it. -# -# AUTHOR -# -# Miguel A. Figueroa-Villanueva (miguelf at ieee dot org). -# Jan Woetzel (jw at mip.informatik.uni-kiel.de). -# -# Based on previous works of: -# Jan Woetzel (FindwxWindows.cmake), -# Jorgen Bodde and Jerry Fath (FindwxWin.cmake). - -# TODO/ideas -# -# (1) Option/Setting to use all available wx libs -# In contrast to expert developer who lists the -# minimal set of required libs in wxWidgets_USE_LIBS -# there is the newbie user: -# - who just wants to link against WX with more 'magic' -# - doesn't know the internal structure of WX or how it was built, -# in particular if it is monolithic or not -# - want to link against all available WX libs -# Basically, the intent here is to mimic what wx-config would do by -# default (i.e., `wx-config --libs`). -# -# Possible solution: -# Add a reserved keyword "std" that initializes to what wx-config -# would default to. If the user has not set the wxWidgets_USE_LIBS, -# default to "std" instead of "base core" as it is now. To implement -# "std" will basically boil down to a FOR_EACH lib-FOUND, but maybe -# checking whether a minimal set was found. - - -# FIXME: This and all the DBG_MSG calls should be removed after the -# module stabilizes. -# -# Helper macro to control the debugging output globally. There are -# two versions for controlling how verbose your output should be. -macro(DBG_MSG _MSG) -# message(STATUS -# "${CMAKE_CURRENT_LIST_FILE}(${CMAKE_CURRENT_LIST_LINE}): ${_MSG}") -endmacro() -macro(DBG_MSG_V _MSG) -# message(STATUS -# "${CMAKE_CURRENT_LIST_FILE}(${CMAKE_CURRENT_LIST_LINE}): ${_MSG}") -endmacro() - -cmake_policy(PUSH) -cmake_policy(SET CMP0057 NEW) # if IN_LIST - -# Clear return values in case the module is loaded more than once. -set(wxWidgets_FOUND FALSE) -set(wxWidgets_INCLUDE_DIRS "") -set(wxWidgets_LIBRARIES "") -set(wxWidgets_LIBRARY_DIRS "") -set(wxWidgets_CXX_FLAGS "") - -# DEPRECATED: This is a patch to support the DEPRECATED use of -# wxWidgets_USE_LIBS. -# -# If wxWidgets_USE_LIBS is set: -# - if using , then override wxWidgets_USE_LIBS -# - else set wxWidgets_FIND_COMPONENTS to wxWidgets_USE_LIBS -if(wxWidgets_USE_LIBS AND NOT wxWidgets_FIND_COMPONENTS) - set(wxWidgets_FIND_COMPONENTS ${wxWidgets_USE_LIBS}) -endif() -DBG_MSG("wxWidgets_FIND_COMPONENTS : ${wxWidgets_FIND_COMPONENTS}") - -# Add the convenience use file if available. -# -# Get dir of this file which may reside in: -# - CMAKE_MAKE_ROOT/Modules on CMake installation -# - CMAKE_MODULE_PATH if user prefers his own specialized version -set(wxWidgets_USE_FILE "") -get_filename_component( - wxWidgets_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) -# Prefer an existing customized version, but the user might override -# the FindwxWidgets module and not the UsewxWidgets one. -if(EXISTS "${wxWidgets_CURRENT_LIST_DIR}/UsewxWidgets.cmake") - set(wxWidgets_USE_FILE - "${wxWidgets_CURRENT_LIST_DIR}/UsewxWidgets.cmake") -else() - set(wxWidgets_USE_FILE UsewxWidgets) -endif() - -# Known wxWidgets versions. -set(wx_versions 3.3 3.2 3.1 3.0 2.9 2.8 2.7 2.6 2.5) - -macro(wx_extract_version) - unset(_wx_filename) - find_file(_wx_filename wx/version.h PATHS ${wxWidgets_INCLUDE_DIRS} NO_DEFAULT_PATH) - dbg_msg("_wx_filename: ${_wx_filename}") - - if(NOT _wx_filename) - message(FATAL_ERROR "wxWidgets wx/version.h file not found in ${wxWidgets_INCLUDE_DIRS}.") - endif() - - file(READ "${_wx_filename}" _wx_version_h) - unset(_wx_filename CACHE) - - string(REGEX REPLACE "^(.*\n)?#define +wxMAJOR_VERSION +([0-9]+).*" - "\\2" wxWidgets_VERSION_MAJOR "${_wx_version_h}" ) - string(REGEX REPLACE "^(.*\n)?#define +wxMINOR_VERSION +([0-9]+).*" - "\\2" wxWidgets_VERSION_MINOR "${_wx_version_h}" ) - string(REGEX REPLACE "^(.*\n)?#define +wxRELEASE_NUMBER +([0-9]+).*" - "\\2" wxWidgets_VERSION_PATCH "${_wx_version_h}" ) - string(REGEX REPLACE "^(.*\n)?#define +wxSUBRELEASE_NUMBER +([0-9]+).*" - "\\2" wxWidgets_VERSION_TWEAK "${_wx_version_h}" ) - - set(wxWidgets_VERSION_STRING - "${wxWidgets_VERSION_MAJOR}.${wxWidgets_VERSION_MINOR}.${wxWidgets_VERSION_PATCH}" ) - if(${wxWidgets_VERSION_TWEAK} GREATER 0) - string(APPEND wxWidgets_VERSION_STRING ".${wxWidgets_VERSION_TWEAK}") - endif() - dbg_msg("wxWidgets_VERSION_STRING: ${wxWidgets_VERSION_STRING}") -endmacro() - -#===================================================================== -# Determine whether unix or win32 paths should be used -#===================================================================== -if(WIN32 AND NOT CYGWIN AND NOT MSYS AND NOT CMAKE_CROSSCOMPILING) - set(wxWidgets_FIND_STYLE "win32") -else() - set(wxWidgets_FIND_STYLE "unix") -endif() - -#===================================================================== -# WIN32_FIND_STYLE -#===================================================================== -if(wxWidgets_FIND_STYLE STREQUAL "win32") - # Useful common wx libs needed by almost all components. - set(wxWidgets_COMMON_LIBRARIES png tiff jpeg zlib regex expat) - - # Libraries needed by stc component - set(wxWidgets_STC_LIBRARIES scintilla lexilla) - - # DEPRECATED: Use find_package(wxWidgets COMPONENTS mono) instead. - if(NOT wxWidgets_FIND_COMPONENTS) - if(wxWidgets_USE_MONOLITHIC) - set(wxWidgets_FIND_COMPONENTS mono) - else() - set(wxWidgets_FIND_COMPONENTS core base) # this is default - endif() - endif() - - # Add the common (usually required libs) unless - # wxWidgets_EXCLUDE_COMMON_LIBRARIES has been set. - if(NOT wxWidgets_EXCLUDE_COMMON_LIBRARIES) - if(stc IN_LIST wxWidgets_FIND_COMPONENTS) - list(APPEND wxWidgets_FIND_COMPONENTS ${wxWidgets_STC_LIBRARIES}) - endif() - list(APPEND wxWidgets_FIND_COMPONENTS ${wxWidgets_COMMON_LIBRARIES}) - endif() - - # Remove duplicates, for example when user has specified common libraries. - list(REMOVE_DUPLICATES wxWidgets_FIND_COMPONENTS) - - #------------------------------------------------------------------- - # WIN32: Helper MACROS - #------------------------------------------------------------------- - # - # Get filename components for a configuration. For example, - # if _CONFIGURATION = mswunivud, then _PF="msw", _UNV=univ, _UCD=u _DBG=d - # if _CONFIGURATION = mswu, then _PF="msw", _UNV="", _UCD=u _DBG="" - # - macro(WX_GET_NAME_COMPONENTS _CONFIGURATION _PF _UNV _UCD _DBG) - DBG_MSG_V(${_CONFIGURATION}) - string(REGEX MATCH "univ" ${_UNV} "${_CONFIGURATION}") - string(REGEX REPLACE "[msw|qt].*(u)[d]*$" "u" ${_UCD} "${_CONFIGURATION}") - if(${_UCD} STREQUAL ${_CONFIGURATION}) - set(${_UCD} "") - endif() - string(REGEX MATCH "d$" ${_DBG} "${_CONFIGURATION}") - string(REGEX MATCH "^[msw|qt]*" ${_PF} "${_CONFIGURATION}") - endmacro() - - # - # Find libraries associated to a configuration. - # - macro(WX_FIND_LIBS _PF _UNV _UCD _DBG _VER) - DBG_MSG_V("m_unv = ${_UNV}") - DBG_MSG_V("m_ucd = ${_UCD}") - DBG_MSG_V("m_dbg = ${_DBG}") - DBG_MSG_V("m_ver = ${_VER}") - - # FIXME: What if both regex libs are available. regex should be - # found outside the loop and only wx${LIB}${_UCD}${_DBG}. - # Find wxWidgets common libraries. - foreach(LIB ${wxWidgets_COMMON_LIBRARIES} ${wxWidgets_STC_LIBRARIES}) - find_library(WX_${LIB}${_DBG} - NAMES - wx${LIB}${_UCD}${_DBG} # for regex - wx${LIB}${_DBG} - PATHS ${WX_LIB_DIR} - NO_DEFAULT_PATH - ) - mark_as_advanced(WX_${LIB}${_DBG}) - endforeach() - - # Find wxWidgets multilib base libraries. - find_library(WX_base${_DBG} - NAMES wxbase${_VER}${_UCD}${_DBG} - PATHS ${WX_LIB_DIR} - NO_DEFAULT_PATH - ) - mark_as_advanced(WX_base${_DBG}) - foreach(LIB net odbc xml) - find_library(WX_${LIB}${_DBG} - NAMES wxbase${_VER}${_UCD}${_DBG}_${LIB} - PATHS ${WX_LIB_DIR} - NO_DEFAULT_PATH - ) - mark_as_advanced(WX_${LIB}${_DBG}) - endforeach() - - # Find wxWidgets monolithic library. - find_library(WX_mono${_DBG} - NAMES wx${_PF}${_UNV}${_VER}${_UCD}${_DBG} - PATHS ${WX_LIB_DIR} - NO_DEFAULT_PATH - ) - mark_as_advanced(WX_mono${_DBG}) - - # Find wxWidgets multilib libraries. - foreach(LIB core adv aui html media xrc dbgrid gl qa richtext - stc ribbon propgrid webview) - find_library(WX_${LIB}${_DBG} - NAMES wx${_PF}${_UNV}${_VER}${_UCD}${_DBG}_${LIB} - PATHS ${WX_LIB_DIR} - NO_DEFAULT_PATH - ) - mark_as_advanced(WX_${LIB}${_DBG}) - endforeach() - endmacro() - - # - # Clear all library paths, so that FIND_LIBRARY refinds them. - # - # Clear a lib, reset its found flag, and mark as advanced. - macro(WX_CLEAR_LIB _LIB) - set(${_LIB} "${_LIB}-NOTFOUND" CACHE FILEPATH "Cleared." FORCE) - set(${_LIB}_FOUND FALSE) - mark_as_advanced(${_LIB}) - endmacro() - # Clear all debug or release library paths (arguments are "d" or ""). - macro(WX_CLEAR_ALL_LIBS _DBG) - # Clear wxWidgets common libraries. - foreach(LIB ${wxWidgets_COMMON_LIBRARIES} ${wxWidgets_STC_LIBRARIES}) - WX_CLEAR_LIB(WX_${LIB}${_DBG}) - endforeach() - - # Clear wxWidgets multilib base libraries. - WX_CLEAR_LIB(WX_base${_DBG}) - foreach(LIB net odbc xml) - WX_CLEAR_LIB(WX_${LIB}${_DBG}) - endforeach() - - # Clear wxWidgets monolithic library. - WX_CLEAR_LIB(WX_mono${_DBG}) - - # Clear wxWidgets multilib libraries. - foreach(LIB core adv aui html media xrc dbgrid gl qa richtext - webview stc ribbon propgrid) - WX_CLEAR_LIB(WX_${LIB}${_DBG}) - endforeach() - endmacro() - # Clear all wxWidgets debug libraries. - macro(WX_CLEAR_ALL_DBG_LIBS) - WX_CLEAR_ALL_LIBS("d") - endmacro() - # Clear all wxWidgets release libraries. - macro(WX_CLEAR_ALL_REL_LIBS) - WX_CLEAR_ALL_LIBS("") - endmacro() - - # - # Set the wxWidgets_LIBRARIES variable. - # Also, Sets output variable wxWidgets_FOUND to FALSE if it fails. - # - macro(WX_SET_LIBRARIES _LIBS _DBG) - DBG_MSG_V("Looking for ${${_LIBS}}") - if(WX_USE_REL_AND_DBG) - foreach(LIB ${${_LIBS}}) - DBG_MSG_V("Searching for ${LIB} and ${LIB}d") - DBG_MSG_V("WX_${LIB} : ${WX_${LIB}}") - DBG_MSG_V("WX_${LIB}d : ${WX_${LIB}d}") - if(WX_${LIB} AND WX_${LIB}d) - DBG_MSG_V("Found ${LIB} and ${LIB}d") - list(APPEND wxWidgets_LIBRARIES - debug ${WX_${LIB}d} optimized ${WX_${LIB}} - ) - set(wxWidgets_${LIB}_FOUND TRUE) - elseif(NOT wxWidgets_FIND_REQUIRED_${LIB}) - DBG_MSG_V("- ignored optional missing WX_${LIB}=${WX_${LIB}} or WX_${LIB}d=${WX_${LIB}d}") - else() - DBG_MSG_V("- not found due to missing WX_${LIB}=${WX_${LIB}} or WX_${LIB}d=${WX_${LIB}d}") - set(wxWidgets_FOUND FALSE) - endif() - endforeach() - else() - foreach(LIB ${${_LIBS}}) - DBG_MSG_V("Searching for ${LIB}${_DBG}") - DBG_MSG_V("WX_${LIB}${_DBG} : ${WX_${LIB}${_DBG}}") - if(WX_${LIB}${_DBG}) - DBG_MSG_V("Found ${LIB}${_DBG}") - list(APPEND wxWidgets_LIBRARIES ${WX_${LIB}${_DBG}}) - set(wxWidgets_${LIB}_FOUND TRUE) - elseif(NOT wxWidgets_FIND_REQUIRED_${LIB}) - DBG_MSG_V("- ignored optional missing WX_${LIB}${_DBG}=${WX_${LIB}${_DBG}}") - else() - DBG_MSG_V("- not found due to missing WX_${LIB}${_DBG}=${WX_${LIB}${_DBG}}") - set(wxWidgets_FOUND FALSE) - endif() - endforeach() - endif() - - DBG_MSG_V("OpenGL") - if(gl IN_LIST ${_LIBS}) - DBG_MSG_V("- is required.") - list(APPEND wxWidgets_LIBRARIES opengl32 glu32) - endif() - - if(stc IN_LIST ${_LIBS}) - list(APPEND wxWidgets_LIBRARIES imm32) - endif() - - list(APPEND wxWidgets_LIBRARIES winmm comctl32 uuid oleacc uxtheme rpcrt4 shlwapi version wsock32) - endmacro() - - #------------------------------------------------------------------- - # WIN32: Start actual work. - #------------------------------------------------------------------- - - set(wx_paths "wxWidgets") - foreach(version ${wx_versions}) - foreach(patch RANGE 15 0 -1) - list(APPEND wx_paths "wxWidgets-${version}.${patch}") - foreach(tweak RANGE 3 1 -1) - list(APPEND wx_paths "wxWidgets-${version}.${patch}.${tweak}") - endforeach() - endforeach() - endforeach() - - # Look for an installation tree. - find_path(wxWidgets_ROOT_DIR - NAMES include/wx/wx.h - PATHS - ENV wxWidgets_ROOT_DIR - ENV WXWIN - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\wxWidgets_is1;Inno Setup: App Path]" # WX 2.6.x - C:/ - D:/ - ENV ProgramFiles - PATH_SUFFIXES - ${wx_paths} - DOC "wxWidgets base/installation directory" - ) - - # If wxWidgets_ROOT_DIR changed, clear lib dir. - if(NOT WX_ROOT_DIR STREQUAL wxWidgets_ROOT_DIR) - if(NOT wxWidgets_LIB_DIR OR WX_ROOT_DIR) - set(wxWidgets_LIB_DIR "wxWidgets_LIB_DIR-NOTFOUND" - CACHE PATH "Cleared." FORCE) - endif() - set(WX_ROOT_DIR ${wxWidgets_ROOT_DIR} - CACHE INTERNAL "wxWidgets_ROOT_DIR") - endif() - - if(WX_ROOT_DIR) - # Select one default tree inside the already determined wx tree. - # Prefer static/shared order usually consistent with build - # settings. - set(_WX_TOOL "") - set(_WX_TOOLVER "") - set(_WX_ARCH "") - if(MINGW) - set(_WX_TOOL gcc) - elseif(MSVC) - set(_WX_TOOL vc) - set(_WX_TOOLVER ${MSVC_TOOLSET_VERSION}) - # support for a lib/vc14x_x64_dll/ path from wxW 3.1.3 distribution - string(REGEX REPLACE ".$" "x" _WX_TOOLVERx ${_WX_TOOLVER}) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(_WX_ARCH _x64) - endif() - endif() - if(BUILD_SHARED_LIBS) - find_path(wxWidgets_LIB_DIR - NAMES - qtu/wx/setup.h - qtud/wx/setup.h - msw/wx/setup.h - mswd/wx/setup.h - mswu/wx/setup.h - mswud/wx/setup.h - mswuniv/wx/setup.h - mswunivd/wx/setup.h - mswunivu/wx/setup.h - mswunivud/wx/setup.h - PATHS - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}_xp${_WX_ARCH}_dll # prefer shared - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}${_WX_ARCH}_dll # prefer shared - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVERx}_xp${_WX_ARCH}_dll # prefer shared - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVERx}${_WX_ARCH}_dll # prefer shared - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_ARCH}_dll # prefer shared - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}_xp${_WX_ARCH}_lib - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}${_WX_ARCH}_lib - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVERx}_xp${_WX_ARCH}_lib - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVERx}${_WX_ARCH}_lib - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_ARCH}_lib - DOC "Path to wxWidgets libraries" - NO_DEFAULT_PATH - ) - else() - find_path(wxWidgets_LIB_DIR - NAMES - qtu/wx/setup.h - qtud/wx/setup.h - msw/wx/setup.h - mswd/wx/setup.h - mswu/wx/setup.h - mswud/wx/setup.h - mswuniv/wx/setup.h - mswunivd/wx/setup.h - mswunivu/wx/setup.h - mswunivud/wx/setup.h - PATHS - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}_xp${_WX_ARCH}_lib # prefer static - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}${_WX_ARCH}_lib # prefer static - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVERx}_xp${_WX_ARCH}_lib # prefer static - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVERx}${_WX_ARCH}_lib # prefer static - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_ARCH}_lib # prefer static - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}_xp${_WX_ARCH}_dll - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}${_WX_ARCH}_dll - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVERx}_xp${_WX_ARCH}_dll - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVERx}${_WX_ARCH}_dll - ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_ARCH}_dll - DOC "Path to wxWidgets libraries" - NO_DEFAULT_PATH - ) - endif() - unset(_WX_TOOL) - unset(_WX_TOOLVER) - unset(_WX_ARCH) - - # If wxWidgets_LIB_DIR changed, clear all libraries. - if(NOT WX_LIB_DIR STREQUAL wxWidgets_LIB_DIR) - set(WX_LIB_DIR ${wxWidgets_LIB_DIR} CACHE INTERNAL "wxWidgets_LIB_DIR") - WX_CLEAR_ALL_DBG_LIBS() - WX_CLEAR_ALL_REL_LIBS() - endif() - - if(WX_LIB_DIR) - # If building shared libs, define WXUSINGDLL to use dllimport. - if(WX_LIB_DIR MATCHES "[dD][lL][lL]") - set(wxWidgets_DEFINITIONS WXUSINGDLL) - DBG_MSG_V("detected SHARED/DLL tree WX_LIB_DIR=${WX_LIB_DIR}") - endif() - - # Search for available configuration types. - foreach(CFG mswunivud mswunivd mswud mswd mswunivu mswuniv mswu msw qt qtd qtu qtud) - set(WX_${CFG}_FOUND FALSE) - if(EXISTS ${WX_LIB_DIR}/${CFG}) - list(APPEND WX_CONFIGURATION_LIST ${CFG}) - set(WX_${CFG}_FOUND TRUE) - set(WX_CONFIGURATION ${CFG}) - endif() - endforeach() - DBG_MSG_V("WX_CONFIGURATION_LIST=${WX_CONFIGURATION_LIST}") - - if(WX_CONFIGURATION) - set(wxWidgets_FOUND TRUE) - - # If the selected configuration wasn't found force the default - # one. Otherwise, use it but still force a refresh for - # updating the doc string with the current list of available - # configurations. - if(NOT WX_${wxWidgets_CONFIGURATION}_FOUND) - set(wxWidgets_CONFIGURATION ${WX_CONFIGURATION} CACHE STRING - "Set wxWidgets configuration (${WX_CONFIGURATION_LIST})" FORCE) - else() - set(wxWidgets_CONFIGURATION ${wxWidgets_CONFIGURATION} CACHE STRING - "Set wxWidgets configuration (${WX_CONFIGURATION_LIST})" FORCE) - endif() - - # If release config selected, and both release/debug exist. - if(WX_${wxWidgets_CONFIGURATION}d_FOUND) - option(wxWidgets_USE_REL_AND_DBG - "Use release and debug configurations?" TRUE) - set(WX_USE_REL_AND_DBG ${wxWidgets_USE_REL_AND_DBG}) - else() - # If the option exists (already in cache), force it false. - if(wxWidgets_USE_REL_AND_DBG) - set(wxWidgets_USE_REL_AND_DBG FALSE CACHE BOOL - "No ${wxWidgets_CONFIGURATION}d found." FORCE) - endif() - set(WX_USE_REL_AND_DBG FALSE) - endif() - - # Get configuration parameters from the name. - WX_GET_NAME_COMPONENTS(${wxWidgets_CONFIGURATION} PF UNV UCD DBG) - - # Set wxWidgets lib setup include directory. - if(EXISTS ${WX_LIB_DIR}/${wxWidgets_CONFIGURATION}/wx/setup.h) - set(wxWidgets_INCLUDE_DIRS - ${WX_LIB_DIR}/${wxWidgets_CONFIGURATION}) - else() - DBG_MSG("wxWidgets_FOUND FALSE because ${WX_LIB_DIR}/${wxWidgets_CONFIGURATION}/wx/setup.h does not exist.") - set(wxWidgets_FOUND FALSE) - endif() - - # Set wxWidgets main include directory. - if(EXISTS ${WX_ROOT_DIR}/include/wx/wx.h) - list(APPEND wxWidgets_INCLUDE_DIRS ${WX_ROOT_DIR}/include) - else() - DBG_MSG("wxWidgets_FOUND FALSE because WX_ROOT_DIR=${WX_ROOT_DIR} has no ${WX_ROOT_DIR}/include/wx/wx.h") - set(wxWidgets_FOUND FALSE) - endif() - - # Get version number. - wx_extract_version() - set(VER "${wxWidgets_VERSION_MAJOR}${wxWidgets_VERSION_MINOR}") - - # Find wxWidgets libraries. - WX_FIND_LIBS("${PF}" "${UNV}" "${UCD}" "${DBG}" "${VER}") - if(WX_USE_REL_AND_DBG) - WX_FIND_LIBS("${PF}" "${UNV}" "${UCD}" "d" "${VER}") - endif() - - # Settings for requested libs (i.e., include dir, libraries, etc.). - WX_SET_LIBRARIES(wxWidgets_FIND_COMPONENTS "${DBG}") - - # Add necessary definitions for unicode builds - if("${UCD}" STREQUAL "u") - list(APPEND wxWidgets_DEFINITIONS UNICODE _UNICODE) - endif() - - # Add necessary definitions for debug builds - set(wxWidgets_DEFINITIONS_DEBUG _DEBUG __WXDEBUG__) - - endif() - endif() - endif() - - if(MINGW AND NOT wxWidgets_FOUND) - # Try unix search mode as well. - set(wxWidgets_FIND_STYLE "unix") - dbg_msg_v("wxWidgets_FIND_STYLE changed to unix") - endif() -endif() - -#===================================================================== -# UNIX_FIND_STYLE -#===================================================================== -if(wxWidgets_FIND_STYLE STREQUAL "unix") - #----------------------------------------------------------------- - # UNIX: Helper MACROS - #----------------------------------------------------------------- - # - # Set the default values based on "wx-config --selected-config". - # - macro(WX_CONFIG_SELECT_GET_DEFAULT) - execute_process( - COMMAND sh "${wxWidgets_CONFIG_EXECUTABLE}" - ${wxWidgets_CONFIG_OPTIONS} --selected-config - OUTPUT_VARIABLE _wx_selected_config - RESULT_VARIABLE _wx_result - ERROR_QUIET - ) - if(_wx_result EQUAL 0) - foreach(_opt_name debug static unicode universal) - string(TOUPPER ${_opt_name} _upper_opt_name) - if(_wx_selected_config MATCHES "${_opt_name}") - set(wxWidgets_DEFAULT_${_upper_opt_name} ON) - else() - set(wxWidgets_DEFAULT_${_upper_opt_name} OFF) - endif() - endforeach() - else() - foreach(_upper_opt_name DEBUG STATIC UNICODE UNIVERSAL) - set(wxWidgets_DEFAULT_${_upper_opt_name} OFF) - endforeach() - endif() - endmacro() - - # - # Query a boolean configuration option to determine if the system - # has both builds available. If so, provide the selection option - # to the user. - # - macro(WX_CONFIG_SELECT_QUERY_BOOL _OPT_NAME _OPT_HELP) - execute_process( - COMMAND sh "${wxWidgets_CONFIG_EXECUTABLE}" - ${wxWidgets_CONFIG_OPTIONS} --${_OPT_NAME}=yes - RESULT_VARIABLE _wx_result_yes - OUTPUT_QUIET - ERROR_QUIET - ) - execute_process( - COMMAND sh "${wxWidgets_CONFIG_EXECUTABLE}" - ${wxWidgets_CONFIG_OPTIONS} --${_OPT_NAME}=no - RESULT_VARIABLE _wx_result_no - OUTPUT_QUIET - ERROR_QUIET - ) - string(TOUPPER ${_OPT_NAME} _UPPER_OPT_NAME) - if(_wx_result_yes EQUAL 0 AND _wx_result_no EQUAL 0) - option(wxWidgets_USE_${_UPPER_OPT_NAME} - ${_OPT_HELP} ${wxWidgets_DEFAULT_${_UPPER_OPT_NAME}}) - else() - # If option exists (already in cache), force to available one. - if(DEFINED wxWidgets_USE_${_UPPER_OPT_NAME}) - if(_wx_result_yes EQUAL 0) - set(wxWidgets_USE_${_UPPER_OPT_NAME} ON CACHE BOOL ${_OPT_HELP} FORCE) - else() - set(wxWidgets_USE_${_UPPER_OPT_NAME} OFF CACHE BOOL ${_OPT_HELP} FORCE) - endif() - endif() - endif() - endmacro() - - # - # Set wxWidgets_SELECT_OPTIONS to wx-config options for selecting - # among multiple builds. - # - macro(WX_CONFIG_SELECT_SET_OPTIONS) - set(wxWidgets_SELECT_OPTIONS ${wxWidgets_CONFIG_OPTIONS}) - foreach(_opt_name debug static unicode universal) - string(TOUPPER ${_opt_name} _upper_opt_name) - if(DEFINED wxWidgets_USE_${_upper_opt_name}) - if(wxWidgets_USE_${_upper_opt_name}) - list(APPEND wxWidgets_SELECT_OPTIONS --${_opt_name}=yes) - else() - list(APPEND wxWidgets_SELECT_OPTIONS --${_opt_name}=no) - endif() - endif() - endforeach() - endmacro() - - #----------------------------------------------------------------- - # UNIX: Start actual work. - #----------------------------------------------------------------- - # Support cross-compiling, only search in the target platform. - # - # Look for wx-config -- this can be set in the environment, - # or try versioned and toolchain-versioned variants of the -config - # executable as well. - set(wx_config_names "wx-config") - foreach(version ${wx_versions}) - list(APPEND wx_config_names "wx-config-${version}" "wxgtk3u-${version}-config" "wxgtk2u-${version}-config") - endforeach() - find_program(wxWidgets_CONFIG_EXECUTABLE - NAMES - $ENV{WX_CONFIG} - ${wx_config_names} - DOC "Location of wxWidgets library configuration provider binary (wx-config)." - ONLY_CMAKE_FIND_ROOT_PATH - ) - - if(wxWidgets_CONFIG_EXECUTABLE) - set(wxWidgets_FOUND TRUE) - - # get defaults based on "wx-config --selected-config" - WX_CONFIG_SELECT_GET_DEFAULT() - - # for each option: if both builds are available, provide option - WX_CONFIG_SELECT_QUERY_BOOL(debug "Use debug build?") - WX_CONFIG_SELECT_QUERY_BOOL(unicode "Use unicode build?") - WX_CONFIG_SELECT_QUERY_BOOL(universal "Use universal build?") - WX_CONFIG_SELECT_QUERY_BOOL(static "Link libraries statically?") - - # process selection to set wxWidgets_SELECT_OPTIONS - WX_CONFIG_SELECT_SET_OPTIONS() - DBG_MSG("wxWidgets_SELECT_OPTIONS=${wxWidgets_SELECT_OPTIONS}") - - # run the wx-config program to get cxxflags - execute_process( - COMMAND sh "${wxWidgets_CONFIG_EXECUTABLE}" - ${wxWidgets_SELECT_OPTIONS} --cxxflags - OUTPUT_VARIABLE wxWidgets_CXX_FLAGS - RESULT_VARIABLE RET - ERROR_QUIET - ) - if(RET EQUAL 0) - string(STRIP "${wxWidgets_CXX_FLAGS}" wxWidgets_CXX_FLAGS) - separate_arguments(wxWidgets_CXX_FLAGS_LIST NATIVE_COMMAND "${wxWidgets_CXX_FLAGS}") - - DBG_MSG_V("wxWidgets_CXX_FLAGS=${wxWidgets_CXX_FLAGS}") - - # parse definitions and include dirs from cxxflags - # drop the -D and -I prefixes - set(wxWidgets_CXX_FLAGS) - foreach(arg IN LISTS wxWidgets_CXX_FLAGS_LIST) - if("${arg}" MATCHES "^-I(.*)$") - # include directory - list(APPEND wxWidgets_INCLUDE_DIRS "${CMAKE_MATCH_1}") - elseif("${arg}" MATCHES "^-D(.*)$") - # compile definition - list(APPEND wxWidgets_DEFINITIONS "${CMAKE_MATCH_1}") - else() - list(APPEND wxWidgets_CXX_FLAGS "${arg}") - endif() - endforeach() - - DBG_MSG_V("wxWidgets_DEFINITIONS=${wxWidgets_DEFINITIONS}") - DBG_MSG_V("wxWidgets_INCLUDE_DIRS=${wxWidgets_INCLUDE_DIRS}") - DBG_MSG_V("wxWidgets_CXX_FLAGS=${wxWidgets_CXX_FLAGS}") - - else() - set(wxWidgets_FOUND FALSE) - DBG_MSG_V( - "${wxWidgets_CONFIG_EXECUTABLE} --cxxflags FAILED with RET=${RET}") - endif() - - # run the wx-config program to get the libs - # - NOTE: wx-config doesn't verify that the libs requested exist - # it just produces the names. Maybe a TRY_COMPILE would - # be useful here... - unset(_cmp_req) - unset(_cmp_opt) - foreach(_cmp IN LISTS wxWidgets_FIND_COMPONENTS) - if(wxWidgets_FIND_REQUIRED_${_cmp}) - list(APPEND _cmp_req "${_cmp}") - else() - list(APPEND _cmp_opt "${_cmp}") - endif() - endforeach() - DBG_MSG_V("wxWidgets required components : ${_cmp_req}") - DBG_MSG_V("wxWidgets optional components : ${_cmp_opt}") - if(DEFINED _cmp_opt) - string(REPLACE ";" "," _cmp_opt "${_cmp_opt}") - set(_cmp_opt "--optional-libs" ${_cmp_opt}) - endif() - string(REPLACE ";" "," _cmp_req "${_cmp_req}") - execute_process( - COMMAND sh "${wxWidgets_CONFIG_EXECUTABLE}" - ${wxWidgets_SELECT_OPTIONS} --libs ${_cmp_req} ${_cmp_opt} - OUTPUT_VARIABLE wxWidgets_LIBRARIES - RESULT_VARIABLE RET - ERROR_QUIET - ) - if(RET EQUAL 0) - string(STRIP "${wxWidgets_LIBRARIES}" wxWidgets_LIBRARIES) - separate_arguments(wxWidgets_LIBRARIES) - string(REPLACE "-framework;" "-framework " - wxWidgets_LIBRARIES "${wxWidgets_LIBRARIES}") - string(REPLACE "-weak_framework;" "-weak_framework " - wxWidgets_LIBRARIES "${wxWidgets_LIBRARIES}") - string(REPLACE "-arch;" "-arch " - wxWidgets_LIBRARIES "${wxWidgets_LIBRARIES}") - string(REPLACE "-isysroot;" "-isysroot " - wxWidgets_LIBRARIES "${wxWidgets_LIBRARIES}") - - # extract linkdirs (-L) for rpath (i.e., LINK_DIRECTORIES) - string(REGEX MATCHALL "-L[^;]+" - wxWidgets_LIBRARY_DIRS "${wxWidgets_LIBRARIES}") - string(REGEX REPLACE "-L([^;]+)" "\\1" - wxWidgets_LIBRARY_DIRS "${wxWidgets_LIBRARY_DIRS}") - - DBG_MSG_V("wxWidgets_LIBRARIES=${wxWidgets_LIBRARIES}") - DBG_MSG_V("wxWidgets_LIBRARY_DIRS=${wxWidgets_LIBRARY_DIRS}") - - else() - set(wxWidgets_FOUND FALSE) - DBG_MSG("${wxWidgets_CONFIG_EXECUTABLE} --libs ${_cmp_req} ${_cmp_opt} FAILED with RET=${RET}") - endif() - unset(_cmp_req) - unset(_cmp_opt) - endif() - - # When using wx-config in MSYS, the include paths are UNIX style paths which may or may - # not work correctly depending on you MSYS/MinGW configuration. CMake expects native - # paths internally. - if(wxWidgets_FOUND AND MSYS) - find_program(_cygpath_exe cygpath ONLY_CMAKE_FIND_ROOT_PATH) - DBG_MSG_V("_cygpath_exe: ${_cygpath_exe}") - if(_cygpath_exe) - set(_tmp_path "") - foreach(_path ${wxWidgets_INCLUDE_DIRS}) - execute_process( - COMMAND cygpath -w ${_path} - OUTPUT_VARIABLE _native_path - RESULT_VARIABLE _retv - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET - ) - if(_retv EQUAL 0) - file(TO_CMAKE_PATH ${_native_path} _native_path) - DBG_MSG_V("Path ${_path} converted to ${_native_path}") - string(APPEND _tmp_path " ${_native_path}") - endif() - endforeach() - DBG_MSG("Setting wxWidgets_INCLUDE_DIRS = ${_tmp_path}") - set(wxWidgets_INCLUDE_DIRS ${_tmp_path}) - separate_arguments(wxWidgets_INCLUDE_DIRS) - list(REMOVE_ITEM wxWidgets_INCLUDE_DIRS "") - - set(_tmp_path "") - foreach(_path ${wxWidgets_LIBRARY_DIRS}) - execute_process( - COMMAND cygpath -w ${_path} - OUTPUT_VARIABLE _native_path - RESULT_VARIABLE _retv - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET - ) - if(_retv EQUAL 0) - file(TO_CMAKE_PATH ${_native_path} _native_path) - DBG_MSG_V("Path ${_path} converted to ${_native_path}") - string(APPEND _tmp_path " ${_native_path}") - endif() - endforeach() - DBG_MSG("Setting wxWidgets_LIBRARY_DIRS = ${_tmp_path}") - set(wxWidgets_LIBRARY_DIRS ${_tmp_path}) - separate_arguments(wxWidgets_LIBRARY_DIRS) - list(REMOVE_ITEM wxWidgets_LIBRARY_DIRS "") - endif() - unset(_cygpath_exe CACHE) - endif() - - # Check that all libraries are present, as wx-config does not check it - set(_wx_lib_missing "") - foreach(_wx_lib_ ${wxWidgets_LIBRARIES}) - if("${_wx_lib_}" MATCHES "^-l(.*)") - set(_wx_lib_name "${CMAKE_MATCH_1}") - unset(_wx_lib_found CACHE) - find_library(_wx_lib_found NAMES ${_wx_lib_name} HINTS ${wxWidgets_LIBRARY_DIRS}) - if(_wx_lib_found STREQUAL _wx_lib_found-NOTFOUND) - list(APPEND _wx_lib_missing ${_wx_lib_name}) - endif() - unset(_wx_lib_found CACHE) - endif() - endforeach() - - if (_wx_lib_missing) - string(REPLACE ";" " " _wx_lib_missing "${_wx_lib_missing}") - DBG_MSG_V("wxWidgets not found due to following missing libraries: ${_wx_lib_missing}") - set(wxWidgets_FOUND FALSE) - unset(wxWidgets_LIBRARIES) - endif() - unset(_wx_lib_missing) -endif() - -# Check if a specific version was requested by find_package(). -if(wxWidgets_FOUND) - wx_extract_version() -endif() - -file(TO_CMAKE_PATH "${wxWidgets_INCLUDE_DIRS}" wxWidgets_INCLUDE_DIRS) -file(TO_CMAKE_PATH "${wxWidgets_LIBRARY_DIRS}" wxWidgets_LIBRARY_DIRS) - -# Debug output: -DBG_MSG("wxWidgets_FOUND : ${wxWidgets_FOUND}") -DBG_MSG("wxWidgets_INCLUDE_DIRS : ${wxWidgets_INCLUDE_DIRS}") -DBG_MSG("wxWidgets_LIBRARY_DIRS : ${wxWidgets_LIBRARY_DIRS}") -DBG_MSG("wxWidgets_LIBRARIES : ${wxWidgets_LIBRARIES}") -DBG_MSG("wxWidgets_CXX_FLAGS : ${wxWidgets_CXX_FLAGS}") -DBG_MSG("wxWidgets_USE_FILE : ${wxWidgets_USE_FILE}") - -#===================================================================== -#===================================================================== - -include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) - -# FIXME: set wxWidgets__FOUND for wx-config branch -# and use HANDLE_COMPONENTS on Unix too -if(wxWidgets_FIND_STYLE STREQUAL "win32") - set(wxWidgets_HANDLE_COMPONENTS "HANDLE_COMPONENTS") -endif() - -find_package_handle_standard_args(wxWidgets - REQUIRED_VARS wxWidgets_LIBRARIES wxWidgets_INCLUDE_DIRS - VERSION_VAR wxWidgets_VERSION_STRING - ${wxWidgets_HANDLE_COMPONENTS} - ) -unset(wxWidgets_HANDLE_COMPONENTS) - -if(wxWidgets_FOUND AND NOT TARGET wxWidgets::wxWidgets) - add_library(wxWidgets::wxWidgets INTERFACE IMPORTED) - target_link_libraries(wxWidgets::wxWidgets INTERFACE ${wxWidgets_LIBRARIES}) - target_link_directories(wxWidgets::wxWidgets INTERFACE ${wxWidgets_LIBRARY_DIRS}) - target_include_directories(wxWidgets::wxWidgets INTERFACE ${wxWidgets_INCLUDE_DIRS}) - target_compile_options(wxWidgets::wxWidgets INTERFACE ${wxWidgets_CXX_FLAGS}) - target_compile_definitions(wxWidgets::wxWidgets INTERFACE ${wxWidgets_DEFINITIONS}) - # FIXME: Add "$<$:${wxWidgets_DEFINITIONS_DEBUG}>" - # if the debug library variant is available. -endif() - -#===================================================================== -# Macros for use in wxWidgets apps. -# - This module will not fail to find wxWidgets based on the code -# below. Hence, it's required to check for validity of: -# -# wxWidgets_wxrc_EXECUTABLE -#===================================================================== - -# Resource file compiler. -find_program(wxWidgets_wxrc_EXECUTABLE - NAMES $ENV{WXRC_CMD} wxrc - PATHS ${wxWidgets_ROOT_DIR}/utils/wxrc/vc_msw - DOC "Location of wxWidgets resource file compiler binary (wxrc)" - ) - -# -# WX_SPLIT_ARGUMENTS_ON( ...) -# -# Sets and to contain arguments to the left and right, -# respectively, of . -# -# Example usage: -# function(WXWIDGETS_ADD_RESOURCES outfiles) -# WX_SPLIT_ARGUMENTS_ON(OPTIONS wxrc_files wxrc_options ${ARGN}) -# ... -# endfunction() -# -# WXWIDGETS_ADD_RESOURCES(sources ${xrc_files} OPTIONS -e -o file.C) -# -# NOTE: This is a generic piece of code that should be renamed to -# SPLIT_ARGUMENTS_ON and put in a file serving the same purpose as -# FindPackageStandardArgs.cmake. At the time of this writing -# FindQt4.cmake has a QT4_EXTRACT_OPTIONS, which I basically copied -# here a bit more generalized. So, there are already two find modules -# using this approach. -# -function(WX_SPLIT_ARGUMENTS_ON _keyword _leftvar _rightvar) - # FIXME: Document that the input variables will be cleared. - #list(APPEND ${_leftvar} "") - #list(APPEND ${_rightvar} "") - set(${_leftvar} "") - set(${_rightvar} "") - - set(_doing_right FALSE) - foreach(element ${ARGN}) - if("${element}" STREQUAL "${_keyword}") - set(_doing_right TRUE) - else() - if(_doing_right) - list(APPEND ${_rightvar} "${element}") - else() - list(APPEND ${_leftvar} "${element}") - endif() - endif() - endforeach() - - set(${_leftvar} ${${_leftvar}} PARENT_SCOPE) - set(${_rightvar} ${${_rightvar}} PARENT_SCOPE) -endfunction() - -# -# WX_GET_DEPENDENCIES_FROM_XML( -# -# -# -# -# -# ) -# -# FIXME: Add documentation here... -# -function(WX_GET_DEPENDENCIES_FROM_XML - _depends - _match_patt - _clean_patt - _xml_contents - _depends_path - ) - - string(REGEX MATCHALL - ${_match_patt} - dep_file_list - "${${_xml_contents}}" - ) - foreach(dep_file ${dep_file_list}) - string(REGEX REPLACE ${_clean_patt} "" dep_file "${dep_file}") - - # make the file have an absolute path - if(NOT IS_ABSOLUTE "${dep_file}") - set(dep_file "${${_depends_path}}/${dep_file}") - endif() - - # append file to dependency list - list(APPEND ${_depends} "${dep_file}") - endforeach() - - set(${_depends} ${${_depends}} PARENT_SCOPE) -endfunction() - -# -# WXWIDGETS_ADD_RESOURCES( -# OPTIONS [NO_CPP_CODE]) -# -# Adds a custom command for resource file compilation of the -# and appends the output files to . -# -# Example usages: -# WXWIDGETS_ADD_RESOURCES(sources xrc/main_frame.xrc) -# WXWIDGETS_ADD_RESOURCES(sources ${xrc_files} OPTIONS -e -o altname.cxx) -# -function(WXWIDGETS_ADD_RESOURCES _outfiles) - WX_SPLIT_ARGUMENTS_ON(OPTIONS rc_file_list rc_options ${ARGN}) - - # Parse files for dependencies. - set(rc_file_list_abs "") - set(rc_depends "") - foreach(rc_file ${rc_file_list}) - get_filename_component(depends_path ${rc_file} PATH) - - get_filename_component(rc_file_abs ${rc_file} ABSOLUTE) - list(APPEND rc_file_list_abs "${rc_file_abs}") - - # All files have absolute paths or paths relative to the location - # of the rc file. - file(READ "${rc_file_abs}" rc_file_contents) - - # get bitmap/bitmap2 files - WX_GET_DEPENDENCIES_FROM_XML( - rc_depends - "]*>" - rc_file_contents - depends_path - ) - - # get url files - WX_GET_DEPENDENCIES_FROM_XML( - rc_depends - "]*>" - rc_file_contents - depends_path - ) - - # get wxIcon files - WX_GET_DEPENDENCIES_FROM_XML( - rc_depends - "]*class=\"wxIcon\"[^<]+" - "^]*>" - rc_file_contents - depends_path - ) - endforeach() - - # - # Parse options. - # - # If NO_CPP_CODE option specified, then produce .xrs file rather - # than a .cpp file (i.e., don't add the default --cpp-code option). - list(FIND rc_options NO_CPP_CODE index) - if(index EQUAL -1) - list(APPEND rc_options --cpp-code) - # wxrc's default output filename for cpp code. - set(outfile resource.cpp) - else() - list(REMOVE_AT rc_options ${index}) - # wxrc's default output filename for xrs file. - set(outfile resource.xrs) - endif() - - # Get output name for use in ADD_CUSTOM_COMMAND. - # - short option scanning - list(FIND rc_options -o index) - if(NOT index EQUAL -1) - math(EXPR filename_index "${index} + 1") - list(GET rc_options ${filename_index} outfile) - #list(REMOVE_AT rc_options ${index} ${filename_index}) - endif() - # - long option scanning - string(REGEX MATCH "--output=[^;]*" outfile_opt "${rc_options}") - if(outfile_opt) - string(REPLACE "--output=" "" outfile "${outfile_opt}") - endif() - #string(REGEX REPLACE "--output=[^;]*;?" "" rc_options "${rc_options}") - #string(REGEX REPLACE ";$" "" rc_options "${rc_options}") - - if(NOT IS_ABSOLUTE "${outfile}") - set(outfile "${CMAKE_CURRENT_BINARY_DIR}/${outfile}") - endif() - add_custom_command( - OUTPUT "${outfile}" - COMMAND ${wxWidgets_wxrc_EXECUTABLE} ${rc_options} ${rc_file_list_abs} - DEPENDS ${rc_file_list_abs} ${rc_depends} - ) - - # Add generated header to output file list. - list(FIND rc_options -e short_index) - list(FIND rc_options --extra-cpp-code long_index) - if(NOT short_index EQUAL -1 OR NOT long_index EQUAL -1) - get_filename_component(outfile_ext ${outfile} EXT) - string(REPLACE "${outfile_ext}" ".h" outfile_header "${outfile}") - list(APPEND ${_outfiles} "${outfile_header}") - set_source_files_properties( - "${outfile_header}" PROPERTIES GENERATED TRUE - ) - endif() - - # Add generated file to output file list. - list(APPEND ${_outfiles} "${outfile}") - - set(${_outfiles} ${${_outfiles}} PARENT_SCOPE) -endfunction() - -cmake_policy(POP) diff --git a/build/PCHSupport.cmake b/build/PCHSupport.cmake deleted file mode 100644 index 78d0e84..0000000 --- a/build/PCHSupport.cmake +++ /dev/null @@ -1,336 +0,0 @@ -# - Try to find precompiled headers support for GCC 3.4 and 4.x -# Once done this will define: -# -# Variable: -# PCHSupport_FOUND -# -# Macro: -# ADD_PRECOMPILED_HEADER _targetName _input _dowarn -# ADD_PRECOMPILED_HEADER_TO_TARGET _targetName _input _pch_output_to_use _dowarn -# ADD_NATIVE_PRECOMPILED_HEADER _targetName _input _dowarn -# GET_NATIVE_PRECOMPILED_HEADER _targetName _input - -# SET_PRECOMPILED_HEADER: -# this was written by Ronnie for a staright forward call to set pch in Visual Studio -# which requires setting a create with a cpp file -# for other platforms this simply falls back to ADD_NATIVE_PRECOMPILED_HEADER -# SET_PRECOMPILED_HEADER targetName hFileName cppFileName - -IF(CMAKE_COMPILER_IS_GNUCXX) - - EXEC_PROGRAM( - ${CMAKE_CXX_COMPILER} - ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion - OUTPUT_VARIABLE gcc_compiler_version) - #MESSAGE("GCC Version: ${gcc_compiler_version}") - IF(gcc_compiler_version MATCHES "4\\.[0-9]\\.[0-9]") - SET(PCHSupport_FOUND TRUE) - ELSE(gcc_compiler_version MATCHES "4\\.[0-9]\\.[0-9]") - IF(gcc_compiler_version MATCHES "3\\.4\\.[0-9]") - SET(PCHSupport_FOUND TRUE) - ENDIF(gcc_compiler_version MATCHES "3\\.4\\.[0-9]") - ENDIF(gcc_compiler_version MATCHES "4\\.[0-9]\\.[0-9]") - - SET(_PCH_include_prefix "-I") - -ELSE(CMAKE_COMPILER_IS_GNUCXX) - IF(WIN32) - SET(PCHSupport_FOUND TRUE) # for experimental msvc support - SET(_PCH_include_prefix "/I") - ELSE(WIN32) - SET(PCHSupport_FOUND FALSE) - ENDIF(WIN32) -ENDIF(CMAKE_COMPILER_IS_GNUCXX) - - -MACRO(_PCH_GET_COMPILE_FLAGS _out_compile_flags) - - - STRING(TOUPPER "CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}" _flags_var_name) - SET(${_out_compile_flags} ${${_flags_var_name}} ) - - IF(CMAKE_COMPILER_IS_GNUCXX) - - GET_TARGET_PROPERTY(_targetType ${_PCH_current_target} TYPE) - IF(${_targetType} STREQUAL SHARED_LIBRARY) - LIST(APPEND ${_out_compile_flags} "${${_out_compile_flags}} -fPIC") - ENDIF(${_targetType} STREQUAL SHARED_LIBRARY) - - ELSE(CMAKE_COMPILER_IS_GNUCXX) - ## TODO ... ? or does it work out of the box - ENDIF(CMAKE_COMPILER_IS_GNUCXX) - - GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES ) - FOREACH(item ${DIRINC}) - LIST(APPEND ${_out_compile_flags} "${_PCH_include_prefix}${item}") - ENDFOREACH(item) - - GET_DIRECTORY_PROPERTY(_directory_flags DEFINITIONS) - #MESSAGE("_directory_flags ${_directory_flags}" ) - LIST(APPEND ${_out_compile_flags} ${_directory_flags}) - LIST(APPEND ${_out_compile_flags} ${CMAKE_CXX_FLAGS} ) - - SEPARATE_ARGUMENTS(${_out_compile_flags}) - -ENDMACRO(_PCH_GET_COMPILE_FLAGS) - - -MACRO(_PCH_WRITE_PCHDEP_CXX _targetName _include_file _dephelp) - - SET(${_dephelp} ${CMAKE_CURRENT_BINARY_DIR}/${_targetName}_pch_dephelp.cxx) - FILE(WRITE ${${_dephelp}} -"#include \"${_include_file}\" -int testfunction() -{ - return 0; -} -" - ) - -ENDMACRO(_PCH_WRITE_PCHDEP_CXX ) - -MACRO(_PCH_GET_COMPILE_COMMAND out_command _input _output) - - FILE(TO_NATIVE_PATH ${_input} _native_input) - FILE(TO_NATIVE_PATH ${_output} _native_output) - - - IF(CMAKE_COMPILER_IS_GNUCXX) - IF(CMAKE_CXX_COMPILER_ARG1) - # remove leading space in compiler argument - STRING(REGEX REPLACE "^ +" "" pchsupport_compiler_cxx_arg1 ${CMAKE_CXX_COMPILER_ARG1}) - - SET(${out_command} - ${CMAKE_CXX_COMPILER} ${pchsupport_compiler_cxx_arg1} ${_compile_FLAGS} -x c++-header -o ${_output} ${_input} - ) - ELSE(CMAKE_CXX_COMPILER_ARG1) - SET(${out_command} - ${CMAKE_CXX_COMPILER} ${_compile_FLAGS} -x c++-header -o ${_output} ${_input} - ) - ENDIF(CMAKE_CXX_COMPILER_ARG1) - ELSE(CMAKE_COMPILER_IS_GNUCXX) - - SET(_dummy_str "#include <${_input}>") - FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/pch_dummy.cpp ${_dummy_str}) - - SET(${out_command} - ${CMAKE_CXX_COMPILER} ${_compile_FLAGS} /c /Fp${_native_output} /Yc${_native_input} pch_dummy.cpp - ) - #/out:${_output} - - ENDIF(CMAKE_COMPILER_IS_GNUCXX) - -ENDMACRO(_PCH_GET_COMPILE_COMMAND ) - - - -MACRO(_PCH_GET_TARGET_COMPILE_FLAGS _cflags _header_name _pch_path _dowarn ) - - FILE(TO_NATIVE_PATH ${_pch_path} _native_pch_path) - - IF(CMAKE_COMPILER_IS_GNUCXX) - # for use with distcc and gcc >4.0.1 if preprocessed files are accessible - # on all remote machines set - # PCH_ADDITIONAL_COMPILER_FLAGS to -fpch-preprocess - # if you want warnings for invalid header files (which is very inconvenient - # if you have different versions of the headers for different build types - # you may set _pch_dowarn - IF (_dowarn) - SET(${_cflags} "${PCH_ADDITIONAL_COMPILER_FLAGS} -include ${CMAKE_CURRENT_BINARY_DIR}/${_header_name} -Winvalid-pch " ) - ELSE (_dowarn) - SET(${_cflags} "${PCH_ADDITIONAL_COMPILER_FLAGS} -include ${CMAKE_CURRENT_BINARY_DIR}/${_header_name} " ) - ENDIF (_dowarn) - ELSE(CMAKE_COMPILER_IS_GNUCXX) - - set(${_cflags} "/Fp${_native_pch_path} /Yu${_header_name}" ) - - ENDIF(CMAKE_COMPILER_IS_GNUCXX) - -ENDMACRO(_PCH_GET_TARGET_COMPILE_FLAGS ) - -MACRO(GET_PRECOMPILED_HEADER_OUTPUT _targetName _input _output) - GET_FILENAME_COMPONENT(_name ${_input} NAME) - GET_FILENAME_COMPONENT(_path ${_input} PATH) - SET(_output "${CMAKE_CURRENT_BINARY_DIR}/${_name}.gch/${_targetName}_${CMAKE_BUILD_TYPE}.h++") -ENDMACRO(GET_PRECOMPILED_HEADER_OUTPUT _targetName _input) - - -MACRO(ADD_PRECOMPILED_HEADER_TO_TARGET _targetName _input _pch_output_to_use ) - - # to do: test whether compiler flags match between target _targetName - # and _pch_output_to_use - GET_FILENAME_COMPONENT(_name ${_input} NAME) - - IF( "${ARGN}" STREQUAL "0") - SET(_dowarn 0) - ELSE( "${ARGN}" STREQUAL "0") - SET(_dowarn 1) - ENDIF("${ARGN}" STREQUAL "0") - - - _PCH_GET_TARGET_COMPILE_FLAGS(_target_cflags ${_name} ${_pch_output_to_use} ${_dowarn}) - # MESSAGE("Add flags ${_target_cflags} to ${_targetName} " ) - SET_TARGET_PROPERTIES(${_targetName} - PROPERTIES - COMPILE_FLAGS ${_target_cflags} - ) - - ADD_CUSTOM_TARGET(pch_Generate_${_targetName} - DEPENDS ${_pch_output_to_use} - ) - - ADD_DEPENDENCIES(${_targetName} pch_Generate_${_targetName} ) - -ENDMACRO(ADD_PRECOMPILED_HEADER_TO_TARGET) - -MACRO(ADD_PRECOMPILED_HEADER _targetName _input) - - SET(_PCH_current_target ${_targetName}) - - IF(NOT CMAKE_BUILD_TYPE) - MESSAGE(FATAL_ERROR - "This is the ADD_PRECOMPILED_HEADER macro. " - "You must set CMAKE_BUILD_TYPE!" - ) - ENDIF(NOT CMAKE_BUILD_TYPE) - - IF( "${ARGN}" STREQUAL "0") - SET(_dowarn 0) - ELSE( "${ARGN}" STREQUAL "0") - SET(_dowarn 1) - ENDIF("${ARGN}" STREQUAL "0") - - - GET_FILENAME_COMPONENT(_name ${_input} NAME) - GET_FILENAME_COMPONENT(_path ${_input} PATH) - GET_PRECOMPILED_HEADER_OUTPUT( ${_targetName} ${_input} _output) - - GET_FILENAME_COMPONENT(_outdir ${_output} PATH ) - - GET_TARGET_PROPERTY(_targetType ${_PCH_current_target} TYPE) - _PCH_WRITE_PCHDEP_CXX(${_targetName} ${_input} _pch_dephelp_cxx) - - IF(${_targetType} STREQUAL SHARED_LIBRARY) - ADD_LIBRARY(${_targetName}_pch_dephelp SHARED ${_pch_dephelp_cxx} ) - ELSE(${_targetType} STREQUAL SHARED_LIBRARY) - ADD_LIBRARY(${_targetName}_pch_dephelp STATIC ${_pch_dephelp_cxx}) - ENDIF(${_targetType} STREQUAL SHARED_LIBRARY) - - FILE(MAKE_DIRECTORY ${_outdir}) - - - _PCH_GET_COMPILE_FLAGS(_compile_FLAGS) - - #MESSAGE("_compile_FLAGS: ${_compile_FLAGS}") - #message("COMMAND ${CMAKE_CXX_COMPILER} ${_compile_FLAGS} -x c++-header -o ${_output} ${_input}") - SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${_name} PROPERTIES GENERATED 1) - ADD_CUSTOM_COMMAND( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_name} - COMMAND ${CMAKE_COMMAND} -E copy ${_input} ${CMAKE_CURRENT_BINARY_DIR}/${_name} # ensure same directory! Required by gcc - DEPENDS ${_input} - ) - - #message("_command ${_input} ${_output}") - _PCH_GET_COMPILE_COMMAND(_command ${CMAKE_CURRENT_BINARY_DIR}/${_name} ${_output} ) - - #message(${_input} ) - #message("_output ${_output}") - - ADD_CUSTOM_COMMAND( - OUTPUT ${_output} - COMMAND ${_command} - DEPENDS ${_input} ${CMAKE_CURRENT_BINARY_DIR}/${_name} ${_targetName}_pch_dephelp - ) - - - ADD_PRECOMPILED_HEADER_TO_TARGET(${_targetName} ${_input} ${_output} ${_dowarn}) -ENDMACRO(ADD_PRECOMPILED_HEADER) - - -# Generates the use of precompiled in a target, -# without using depency targets (2 extra for each target) -# Using Visual, must also add ${_targetName}_pch to sources -# Not needed by Xcode - -MACRO(GET_NATIVE_PRECOMPILED_HEADER _targetName _input) - - if(CMAKE_GENERATOR MATCHES Visual*) - - SET(_dummy_str "#include \"${_input}\"\n" - "// This is required to suppress LNK4221. Very annoying.\n" - "void *g_${_targetName}Dummy = 0\;\n") - - # Use of cxx extension for generated files (as Qt does) - SET(${_targetName}_pch ${CMAKE_CURRENT_BINARY_DIR}/${_targetName}_pch.cxx) - if(EXISTS ${${_targetName}_pch}) - # Check if contents is the same, if not rewrite - # todo - else(EXISTS ${${_targetName}_pch}) - FILE(WRITE ${${_targetName}_pch} ${_dummy_str}) - endif(EXISTS ${${_targetName}_pch}) - endif(CMAKE_GENERATOR MATCHES Visual*) - -ENDMACRO(GET_NATIVE_PRECOMPILED_HEADER) - - -MACRO(ADD_NATIVE_PRECOMPILED_HEADER _targetName _input) - - IF( "${ARGN}" STREQUAL "0") - SET(_dowarn 0) - ELSE( "${ARGN}" STREQUAL "0") - SET(_dowarn 1) - ENDIF("${ARGN}" STREQUAL "0") - - if(CMAKE_GENERATOR MATCHES Visual*) - # Auto include the precompile (useful for moc processing, since the use of - # precompiled is specified at the target level - # and I don't want to specifiy /F- for each moc/res/ui generated files (using Qt) - - GET_TARGET_PROPERTY(oldProps ${_targetName} COMPILE_FLAGS) - if (${oldProps} MATCHES NOTFOUND) - SET(oldProps "") - endif(${oldProps} MATCHES NOTFOUND) - - SET(newProperties "${oldProps} /Yu\"${_input}\" /FI\"${_input}\"") - SET_TARGET_PROPERTIES(${_targetName} PROPERTIES COMPILE_FLAGS "${newProperties}") - - #also inlude ${oldProps} to have the same compile options - SET_SOURCE_FILES_PROPERTIES(${${_targetName}_pch} PROPERTIES COMPILE_FLAGS "${oldProps} /Yc\"${_input}\"") - - else(CMAKE_GENERATOR MATCHES Visual*) - - if (CMAKE_GENERATOR MATCHES Xcode) - # For Xcode, cmake needs my patch to process - # GCC_PREFIX_HEADER and GCC_PRECOMPILE_PREFIX_HEADER as target properties - - GET_TARGET_PROPERTY(oldProps ${_targetName} COMPILE_FLAGS) - if (${oldProps} MATCHES NOTFOUND) - SET(oldProps "") - endif(${oldProps} MATCHES NOTFOUND) - - # When buiding out of the tree, precompiled may not be located - # Use full path instead. - GET_FILENAME_COMPONENT(fullPath ${_input} ABSOLUTE) - - SET_TARGET_PROPERTIES(${_targetName} PROPERTIES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${fullPath}") - SET_TARGET_PROPERTIES(${_targetName} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES") - - else (CMAKE_GENERATOR MATCHES Xcode) - - #Fallback to the "old" precompiled suppport - #ADD_PRECOMPILED_HEADER(${_targetName} ${_input} ${_dowarn}) - endif(CMAKE_GENERATOR MATCHES Xcode) - endif(CMAKE_GENERATOR MATCHES Visual*) - -ENDMACRO(ADD_NATIVE_PRECOMPILED_HEADER) - -MACRO(SET_PRECOMPILED_HEADER targetName hFileName cppFileName) - ADD_NATIVE_PRECOMPILED_HEADER(${targetName} ${hFileName}) - if(WIN32) - GET_TARGET_PROPERTY(oldProps "${cppFileName}" COMPILE_FLAGS) - if (${oldProps} MATCHES NOTFOUND) - SET(oldProps "") - endif(${oldProps} MATCHES NOTFOUND) - SET_SOURCE_FILES_PROPERTIES(${cppFileName} PROPERTIES COMPILE_FLAGS "${oldprops} /Yc\"${hFileName}\"") - endif(WIN32) -ENDMACRO(SET_PRECOMPILED_HEADER) diff --git a/build/cm.bat b/build/cm.bat deleted file mode 100644 index 625ef98..0000000 --- a/build/cm.bat +++ /dev/null @@ -1,25 +0,0 @@ -rem @echo off -IF "%1" == "" GOTO NO_PARAMS -IF "%1" == "x86" GOTO CMAKE_86 -IF "%1" == "86" GOTO CMAKE_86 -IF "%1" == "32" GOTO CMAKE_86 -IF "%1" == "x64" GOTO CMAKE_64 -IF "%1" == "64" GOTO CMAKE_64 - -ECHO %1 -ECHO "Nothing to do" -GOTO End - -:CMAKE_86 - ECHO "Configuring for x86" - cm86.bat - GOTO End -:CMAKE_64 - ECHO "Configuring for x64" - cm64.bat - GOTO End -:NO_PARAMS - ECHO "No parameters specified" - IF EXIST "%ProgramW6432%" GOTO CMAKE_64 - GOTO CMAKE_86 -:End diff --git a/build/cm.sh b/build/cm.sh deleted file mode 100755 index 1de4a7a..0000000 --- a/build/cm.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -rm -dr Mac -mkdir Mac -cd Mac -cmake ../ -G "Xcode" -cd .. diff --git a/build/cm64.bat b/build/cm64.bat deleted file mode 100644 index 4dcbbe8..0000000 --- a/build/cm64.bat +++ /dev/null @@ -1,7 +0,0 @@ -rem @echo off -rmdir /S /Q Win -mkdir Win -cd Win -cmake ../ -G "Visual Studio 17 2022" -copy ..\wxModularHost.sln64 .\wxModularHost.sln -cd .. diff --git a/build/cm86.bat b/build/cm86.bat deleted file mode 100644 index 4bae862..0000000 --- a/build/cm86.bat +++ /dev/null @@ -1,7 +0,0 @@ -rem @echo off -rmdir /S /Q Win -mkdir Win -cd Win -cmake ../ -G "Visual Studio 17 2022" -A Win32 -copy ..\wxModularHost.sln32 .\wxModularHost.sln -cd .. diff --git a/build/cmAppleMac.sh b/build/cmAppleMac.sh deleted file mode 100644 index 9e57352..0000000 --- a/build/cmAppleMac.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -rm -dr Mac -mkdir Mac -cd Mac -cmake ../ -DCMAKE_CXX_STANDARD_LIBRARIES="-lwx_osx_cocoau_aui-3.2" -cd .. diff --git a/build/cmLinux.sh b/build/cmLinux.sh deleted file mode 100755 index c0d0e63..0000000 --- a/build/cmLinux.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -echo OS Type: $OSTYPE - -# ---------------------------------- -# build Debug configuration makefile -# ---------------------------------- -echo building Debug configuration makefile -echo directory "LinuxDebug" -rm -dr "LinuxDebug" -mkdir "LinuxDebug" -cd "LinuxDebug" -cmake -G "Eclipse CDT4 - Unix Makefiles" -DCMAKE_BUILD_TYPE:STRING=Debug ../ -# cmake -DCMAKE_BUILD_TYPE:STRING=Debug ../ -cd .. - -# ---------------------------------- -# build Release configuration makefile -# ---------------------------------- -echo building Release configuration makefile -echo directory "LinuxRelease" -rm -dr "LinuxRelease" -mkdir "LinuxRelease" -cd "LinuxRelease" -cmake -G "Eclipse CDT4 - Unix Makefiles" -DCMAKE_BUILD_TYPE:STRING=Release ../ -# cmake -DCMAKE_BUILD_TYPE:STRING=Release ../ -cd .. - diff --git a/build/wxModularHost.sln32 b/build/wxModularHost.sln32 deleted file mode 100644 index 18c872f..0000000 --- a/build/wxModularHost.sln32 +++ /dev/null @@ -1,89 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ALL_BUILD", "ALL_BUILD.vcxproj", "{2DE4A902-0D74-3DF1-BBB3-6F1E75BC5C87}" - ProjectSection(ProjectDependencies) = postProject - {85E2C45A-3E70-38FB-80FC-42B0F7BA4014} = {85E2C45A-3E70-38FB-80FC-42B0F7BA4014} - {DB9A1667-1D3A-3B2E-803D-86D7EB3E85C5} = {DB9A1667-1D3A-3B2E-803D-86D7EB3E85C5} - {A793772E-ACC6-4B21-80A4-F4A7952754AC} = {A793772E-ACC6-4B21-80A4-F4A7952754AC} - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} = {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} - {E6CD9F9A-05BD-38E0-9F64-B3F8B7610FBD} = {E6CD9F9A-05BD-38E0-9F64-B3F8B7610FBD} - {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD} = {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD} - {47ABA340-A92C-3524-9020-D816EB794174} = {47ABA340-A92C-3524-9020-D816EB794174} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleGuiPlugin1", "..\..\SampleGuiPlugin1\Win\SampleGuiPlugin1.vcxproj", "{85E2C45A-3E70-38FB-80FC-42B0F7BA4014}" - ProjectSection(ProjectDependencies) = postProject - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} = {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleGuiPlugin2", "..\..\SampleGuiPlugin2\Win\SampleGuiPlugin2.vcxproj", "{DB9A1667-1D3A-3B2E-803D-86D7EB3E85C5}" - ProjectSection(ProjectDependencies) = postProject - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} = {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZERO_CHECK", "ZERO_CHECK.vcxproj", "{B9B972FB-3C1F-3FE3-85BD-E714A07BC659}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mswplugin_csharp", "..\..\mswplugin_csharp\Win\mswplugin_csharp.csproj", "{E6CD9F9A-05BD-38E0-9F64-B3F8B7610FBD}" - ProjectSection(ProjectDependencies) = postProject - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} = {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxModularCore", "..\..\wxModularCore\Win\wxModularCore.vcxproj", "{ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD}" - ProjectSection(ProjectDependencies) = postProject - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} = {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxModularHost", "..\..\wxModularHost\Win\wxModularHost.vcxproj", "{47ABA340-A92C-3524-9020-D816EB794174}" - ProjectSection(ProjectDependencies) = postProject - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} = {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} - {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD} = {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD} - EndProjectSection -EndProject -Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "mswplugin_vb", "..\..\mswplugin_vb\mswplugin_vb.vbproj", "{A793772E-ACC6-4B21-80A4-F4A7952754AC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2DE4A902-0D74-3DF1-BBB3-6F1E75BC5C87}.Debug|Win32.ActiveCfg = Debug|Win32 - {2DE4A902-0D74-3DF1-BBB3-6F1E75BC5C87}.Release|Win32.ActiveCfg = Release|Win32 - {85E2C45A-3E70-38FB-80FC-42B0F7BA4014}.Debug|Win32.ActiveCfg = Debug|Win32 - {85E2C45A-3E70-38FB-80FC-42B0F7BA4014}.Debug|Win32.Build.0 = Debug|Win32 - {85E2C45A-3E70-38FB-80FC-42B0F7BA4014}.Release|Win32.ActiveCfg = Release|Win32 - {85E2C45A-3E70-38FB-80FC-42B0F7BA4014}.Release|Win32.Build.0 = Release|Win32 - {DB9A1667-1D3A-3B2E-803D-86D7EB3E85C5}.Debug|Win32.ActiveCfg = Debug|Win32 - {DB9A1667-1D3A-3B2E-803D-86D7EB3E85C5}.Debug|Win32.Build.0 = Debug|Win32 - {DB9A1667-1D3A-3B2E-803D-86D7EB3E85C5}.Release|Win32.ActiveCfg = Release|Win32 - {DB9A1667-1D3A-3B2E-803D-86D7EB3E85C5}.Release|Win32.Build.0 = Release|Win32 - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659}.Debug|Win32.ActiveCfg = Debug|Win32 - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659}.Debug|Win32.Build.0 = Debug|Win32 - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659}.Release|Win32.ActiveCfg = Release|Win32 - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659}.Release|Win32.Build.0 = Release|Win32 - {E6CD9F9A-05BD-38E0-9F64-B3F8B7610FBD}.Debug|Win32.ActiveCfg = Debug|Win32 - {E6CD9F9A-05BD-38E0-9F64-B3F8B7610FBD}.Debug|Win32.Build.0 = Debug|Win32 - {E6CD9F9A-05BD-38E0-9F64-B3F8B7610FBD}.Release|Win32.ActiveCfg = Release|Win32 - {E6CD9F9A-05BD-38E0-9F64-B3F8B7610FBD}.Release|Win32.Build.0 = Release|Win32 - {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD}.Debug|Win32.ActiveCfg = Debug|Win32 - {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD}.Debug|Win32.Build.0 = Debug|Win32 - {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD}.Release|Win32.ActiveCfg = Release|Win32 - {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD}.Release|Win32.Build.0 = Release|Win32 - {47ABA340-A92C-3524-9020-D816EB794174}.Debug|Win32.ActiveCfg = Debug|Win32 - {47ABA340-A92C-3524-9020-D816EB794174}.Debug|Win32.Build.0 = Debug|Win32 - {47ABA340-A92C-3524-9020-D816EB794174}.Release|Win32.ActiveCfg = Release|Win32 - {47ABA340-A92C-3524-9020-D816EB794174}.Release|Win32.Build.0 = Release|Win32 - {A793772E-ACC6-4B21-80A4-F4A7952754AC}.Debug|Win32.ActiveCfg = Debug|Win32 - {A793772E-ACC6-4B21-80A4-F4A7952754AC}.Debug|Win32.Build.0 = Debug|Win32 - {A793772E-ACC6-4B21-80A4-F4A7952754AC}.Release|Win32.ActiveCfg = Release|Win32 - {A793772E-ACC6-4B21-80A4-F4A7952754AC}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {FAC590C9-0DBB-386A-90AD-E57D0D314630} - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/build/wxModularHost.sln64 b/build/wxModularHost.sln64 deleted file mode 100644 index 34f5d18..0000000 --- a/build/wxModularHost.sln64 +++ /dev/null @@ -1,89 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ALL_BUILD", "ALL_BUILD.vcxproj", "{2DE4A902-0D74-3DF1-BBB3-6F1E75BC5C87}" - ProjectSection(ProjectDependencies) = postProject - {85E2C45A-3E70-38FB-80FC-42B0F7BA4014} = {85E2C45A-3E70-38FB-80FC-42B0F7BA4014} - {DB9A1667-1D3A-3B2E-803D-86D7EB3E85C5} = {DB9A1667-1D3A-3B2E-803D-86D7EB3E85C5} - {A793772E-ACC6-4B21-80A4-F4A7952754AC} = {A793772E-ACC6-4B21-80A4-F4A7952754AC} - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} = {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} - {E6CD9F9A-05BD-38E0-9F64-B3F8B7610FBD} = {E6CD9F9A-05BD-38E0-9F64-B3F8B7610FBD} - {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD} = {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD} - {47ABA340-A92C-3524-9020-D816EB794174} = {47ABA340-A92C-3524-9020-D816EB794174} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleGuiPlugin1", "..\..\SampleGuiPlugin1\Win\SampleGuiPlugin1.vcxproj", "{85E2C45A-3E70-38FB-80FC-42B0F7BA4014}" - ProjectSection(ProjectDependencies) = postProject - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} = {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleGuiPlugin2", "..\..\SampleGuiPlugin2\Win\SampleGuiPlugin2.vcxproj", "{DB9A1667-1D3A-3B2E-803D-86D7EB3E85C5}" - ProjectSection(ProjectDependencies) = postProject - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} = {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZERO_CHECK", "ZERO_CHECK.vcxproj", "{B9B972FB-3C1F-3FE3-85BD-E714A07BC659}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mswplugin_csharp", "..\..\mswplugin_csharp\Win\mswplugin_csharp.csproj", "{E6CD9F9A-05BD-38E0-9F64-B3F8B7610FBD}" - ProjectSection(ProjectDependencies) = postProject - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} = {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxModularCore", "..\..\wxModularCore\Win\wxModularCore.vcxproj", "{ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD}" - ProjectSection(ProjectDependencies) = postProject - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} = {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxModularHost", "..\..\wxModularHost\Win\wxModularHost.vcxproj", "{47ABA340-A92C-3524-9020-D816EB794174}" - ProjectSection(ProjectDependencies) = postProject - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} = {B9B972FB-3C1F-3FE3-85BD-E714A07BC659} - {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD} = {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD} - EndProjectSection -EndProject -Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "mswplugin_vb", "..\..\mswplugin_vb\mswplugin_vb.vbproj", "{A793772E-ACC6-4B21-80A4-F4A7952754AC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2DE4A902-0D74-3DF1-BBB3-6F1E75BC5C87}.Debug|x64.ActiveCfg = Debug|x64 - {2DE4A902-0D74-3DF1-BBB3-6F1E75BC5C87}.Release|x64.ActiveCfg = Release|x64 - {85E2C45A-3E70-38FB-80FC-42B0F7BA4014}.Debug|x64.ActiveCfg = Debug|x64 - {85E2C45A-3E70-38FB-80FC-42B0F7BA4014}.Debug|x64.Build.0 = Debug|x64 - {85E2C45A-3E70-38FB-80FC-42B0F7BA4014}.Release|x64.ActiveCfg = Release|x64 - {85E2C45A-3E70-38FB-80FC-42B0F7BA4014}.Release|x64.Build.0 = Release|x64 - {DB9A1667-1D3A-3B2E-803D-86D7EB3E85C5}.Debug|x64.ActiveCfg = Debug|x64 - {DB9A1667-1D3A-3B2E-803D-86D7EB3E85C5}.Debug|x64.Build.0 = Debug|x64 - {DB9A1667-1D3A-3B2E-803D-86D7EB3E85C5}.Release|x64.ActiveCfg = Release|x64 - {DB9A1667-1D3A-3B2E-803D-86D7EB3E85C5}.Release|x64.Build.0 = Release|x64 - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659}.Debug|x64.ActiveCfg = Debug|x64 - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659}.Debug|x64.Build.0 = Debug|x64 - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659}.Release|x64.ActiveCfg = Release|x64 - {B9B972FB-3C1F-3FE3-85BD-E714A07BC659}.Release|x64.Build.0 = Release|x64 - {E6CD9F9A-05BD-38E0-9F64-B3F8B7610FBD}.Debug|x64.ActiveCfg = Debug|x64 - {E6CD9F9A-05BD-38E0-9F64-B3F8B7610FBD}.Debug|x64.Build.0 = Debug|x64 - {E6CD9F9A-05BD-38E0-9F64-B3F8B7610FBD}.Release|x64.ActiveCfg = Release|x64 - {E6CD9F9A-05BD-38E0-9F64-B3F8B7610FBD}.Release|x64.Build.0 = Release|x64 - {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD}.Debug|x64.ActiveCfg = Debug|x64 - {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD}.Debug|x64.Build.0 = Debug|x64 - {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD}.Release|x64.ActiveCfg = Release|x64 - {ED4A979D-43E8-3D24-97E0-53E2D2C7B5BD}.Release|x64.Build.0 = Release|x64 - {47ABA340-A92C-3524-9020-D816EB794174}.Debug|x64.ActiveCfg = Debug|x64 - {47ABA340-A92C-3524-9020-D816EB794174}.Debug|x64.Build.0 = Debug|x64 - {47ABA340-A92C-3524-9020-D816EB794174}.Release|x64.ActiveCfg = Release|x64 - {47ABA340-A92C-3524-9020-D816EB794174}.Release|x64.Build.0 = Release|x64 - {A793772E-ACC6-4B21-80A4-F4A7952754AC}.Debug|x64.ActiveCfg = Debug|x64 - {A793772E-ACC6-4B21-80A4-F4A7952754AC}.Debug|x64.Build.0 = Debug|x64 - {A793772E-ACC6-4B21-80A4-F4A7952754AC}.Release|x64.ActiveCfg = Release|x64 - {A793772E-ACC6-4B21-80A4-F4A7952754AC}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {FAC590C9-0DBB-386A-90AD-E57D0D314630} - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/include/qedit.h b/include/qedit.h new file mode 100644 index 0000000..169f07b --- /dev/null +++ b/include/qedit.h @@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef __qedit_h__ +#define __qedit_h__ + +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +/////////////////////////////////////////////////////////////////////////////////// + +interface +ISampleGrabberCB +: + public IUnknown +{ + virtual STDMETHODIMP SampleCB( double SampleTime, IMediaSample *pSample ) = 0; + virtual STDMETHODIMP BufferCB( double SampleTime, BYTE *pBuffer, long BufferLen ) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +IID IID_ISampleGrabberCB = { 0x0579154A, 0x2B53, 0x4994, { 0xB0, 0xD0, 0xE7, 0x73, 0x14, 0x8E, 0xFF, 0x85 } }; + +/////////////////////////////////////////////////////////////////////////////////// + +interface +ISampleGrabber +: + public IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE SetOneShot( BOOL OneShot ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetMediaType( const AM_MEDIA_TYPE *pType ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetConnectedMediaType( AM_MEDIA_TYPE *pType ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetBufferSamples( BOOL BufferThem ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentBuffer( long *pBufferSize, long *pBuffer ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentSample( IMediaSample **ppSample ) = 0; + virtual HRESULT STDMETHODCALLTYPE SetCallback( ISampleGrabberCB *pCallback, long WhichMethodToCallback ) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +IID IID_ISampleGrabber = { 0x6B652FFF, 0x11FE, 0x4fce, { 0x92, 0xAD, 0x02, 0x66, 0xB5, 0xD7, 0xC7, 0x8F } }; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +CLSID CLSID_SampleGrabber = { 0xC1F400A0, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } }; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +CLSID CLSID_NullRenderer = { 0xC1F400A4, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } }; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +CLSID CLSID_VideoEffects1Category = { 0xcc7bfb42, 0xf175, 0x11d1, { 0xa3, 0x92, 0x0, 0xe0, 0x29, 0x1f, 0x39, 0x59 } }; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +CLSID CLSID_VideoEffects2Category = { 0xcc7bfb43, 0xf175, 0x11d1, { 0xa3, 0x92, 0x0, 0xe0, 0x29, 0x1f, 0x39, 0x59 } }; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +CLSID CLSID_AudioEffects1Category = { 0xcc7bfb44, 0xf175, 0x11d1, { 0xa3, 0x92, 0x0, 0xe0, 0x29, 0x1f, 0x39, 0x59 } }; + +/////////////////////////////////////////////////////////////////////////////////// + +static +const +CLSID CLSID_AudioEffects2Category = { 0xcc7bfb45, 0xf175, 0x11d1, { 0xa3, 0x92, 0x0, 0xe0, 0x29, 0x1f, 0x39, 0x59 } }; + +/////////////////////////////////////////////////////////////////////////////////// + +#endif + +/////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/include/stdwx.cpp b/include/stdwx.cpp index eae3e7a..82fa7ac 100644 --- a/include/stdwx.cpp +++ b/include/stdwx.cpp @@ -1 +1 @@ -#include "stdwx.h" +#include "stdwx.h" \ No newline at end of file diff --git a/include/stdwx.h b/include/stdwx.h index e803d0f..12201f6 100644 --- a/include/stdwx.h +++ b/include/stdwx.h @@ -1,50 +1,50 @@ -#ifndef IFLOOR_STDWX_H_ -#define IFLOOR_STDWX_H_ - -#if defined(WIN32) || defined(WINDOWS) -#include -#include -#define PLUGIN_EXPORTED_API WXEXPORT -#else -#define PLUGIN_EXPORTED_API extern "C" -#endif - -// SYSTEM INCLUDES -// For compilers that support precompilation, includes "wx/wx.h". -#include "wx/wxprec.h" -#ifdef __BORLANDC__ - #pragma hdrstop -#endif -//#ifndef WX_PRECOMP - #include "wx/wx.h" -//#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// APPLICATION INCLUDES -#endif +#ifndef IFLOOR_STDWX_H_ +#define IFLOOR_STDWX_H_ + +#if defined(WIN32) || defined(WINDOWS) +#include +#include +#define PLUGIN_EXPORTED_API WXEXPORT +#else +#define PLUGIN_EXPORTED_API extern "C" +#endif + +// SYSTEM INCLUDES +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" +#ifdef __BORLANDC__ + #pragma hdrstop +#endif +//#ifndef WX_PRECOMP + #include "wx/wx.h" +//#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// APPLICATION INCLUDES +#endif diff --git a/wxGuiPluginBase/CMakeLists.txt b/wxGuiPluginBase/CMakeLists.txt index 7dfc7db..bbe9d2a 100644 --- a/wxGuiPluginBase/CMakeLists.txt +++ b/wxGuiPluginBase/CMakeLists.txt @@ -1,56 +1,30 @@ -set (SRCS - wxGuiPluginBase.cpp - wxGuiPluginWindowBase.cpp) -set (HEADERS - Declarations.h - wxGuiPluginBase.h - wxGuiPluginWindowBase.h) - -set(LIBRARY_NAME wxGuiPluginBase) - -if(WIN32) - set(SRCS ${SRCS} ${LIBRARY_NAME}.rc) - # Only for Windows: - # we add additional preprocessor definitons - set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS}; - /D_USRDLL;/DDEMO_PLUGIN_EXPORTS;/D__STDC_CONSTANT_MACROS) -endif(WIN32) - -# Add 2 files for precompiled headers -set(SRCS ${SRCS} ${HEADERS} - ${PROJECT_ROOT_DIR}/include/stdwx.h - ${PROJECT_ROOT_DIR}/include/stdwx.cpp) - -# Set preprocessor definitions -add_definitions(${PREPROCESSOR_DEFINITIONS}) -# Set include directories -include_directories(${INCLUDE_DIRECTORIES} ${BASE_INCLUDE_DIRECTORIES}) -# Set library search paths -link_directories(${LINK_DIRECTORIES}) -# Setup the project name and assign the source files for this project -add_library(${LIBRARY_NAME} SHARED ${SRCS}) - -#Setup the output folder -set(DLL_DIR bin) -set(TARGET_LOCATION ${PROJECT_SOURCE_DIR}/${DLL_DIR}${LIB_SUFFIX}) -if(APPLE) - set(TARGET_LOCATION - ${TARGET_LOCATION}/$(CONFIGURATION)/${PROJECT_NAME}.app/Contents/Frameworks) -endif(APPLE) -if(LINUX OR APPLE) - get_target_property(RESULT_FULL_PATH ${LIBRARY_NAME} LOCATION) - get_filename_component(RESULT_FILE_NAME ${RESULT_FULL_PATH} NAME) -endif(LINUX OR APPLE) -set_target_properties(${LIBRARY_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TARGET_LOCATION}) - -# Set additional dependencies -target_link_libraries(${LIBRARY_NAME} ${wxWidgets_LIBRARIES}) - -# Setup precompiled headers -target_precompile_headers(${LIBRARY_NAME} PRIVATE ${PROJECT_ROOT_DIR}/include/stdwx.h ${PROJECT_ROOT_DIR}/include/stdwx.cpp) - -if(LINUX OR APPLE) - add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy $ ${TARGET_LOCATION}/${RESULT_FILE_NAME} - ) -endif(LINUX OR APPLE) +set(SRCS + wxGuiPluginBase.cpp + wxGuiPluginWindowBase.cpp +) +set(HEADERS + Declarations.h + wxGuiPluginBase.h + wxGuiPluginWindowBase.h +) + +set(LIBRARY_NAME wxGuiPluginBase) + +if(WIN32) + set(SRCS ${SRCS} ${LIBRARY_NAME}.rc) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS}; + /D_USRDLL;/DDEMO_PLUGIN_EXPORTS;/D__STDC_CONSTANT_MACROS) +endif(WIN32) + +set(SRCS ${SRCS} ${HEADERS} + ${PROJECT_ROOT_DIR}/include/stdwx.h + ${PROJECT_ROOT_DIR}/include/stdwx.cpp) + +add_definitions(${PREPROCESSOR_DEFINITIONS}) +include_directories(${INCLUDE_DIRECTORIES} ${BASE_INCLUDE_DIRECTORIES}) + +add_library(${LIBRARY_NAME} SHARED ${SRCS}) + +target_link_libraries(${LIBRARY_NAME} ${wxWidgets_LIBRARIES}) + +target_precompile_headers(${LIBRARY_NAME} PRIVATE ${PROJECT_ROOT_DIR}/include/stdwx.h) \ No newline at end of file diff --git a/wxGuiPluginBase/Declarations.h b/wxGuiPluginBase/Declarations.h index 13dd0d3..fd08279 100644 --- a/wxGuiPluginBase/Declarations.h +++ b/wxGuiPluginBase/Declarations.h @@ -1,14 +1,14 @@ -#ifndef _DECLARATIONS_H -#define _DECLARATIONS_H - -#if defined(__WXMSW__) -#ifdef DEMO_PLUGIN_EXPORTS -#define DEMO_API __declspec(dllexport) -#else -#define DEMO_API __declspec(dllimport) -#endif -#else -#define DEMO_API -#endif - -#endif // _DECLARATIONS_H +#ifndef _DECLARATIONS_H +#define _DECLARATIONS_H + +#if defined(__WXMSW__) +#ifdef DEMO_PLUGIN_EXPORTS +#define DEMO_API __declspec(dllexport) +#else +#define DEMO_API __declspec(dllimport) +#endif +#else +#define DEMO_API +#endif + +#endif // _DECLARATIONS_H diff --git a/wxGuiPluginBase/Win/wxGuiPluginBase.vcxproj b/wxGuiPluginBase/Win/wxGuiPluginBase.vcxproj new file mode 100644 index 0000000..85f1e0c --- /dev/null +++ b/wxGuiPluginBase/Win/wxGuiPluginBase.vcxproj @@ -0,0 +1,256 @@ + + + + x64 + + + + Debug + x64 + + + Release + x64 + + + + {016D40A8-D2BA-3C2B-8741-718BD5CE7B51} + Win32Proj + 10.0.26100.0 + x64 + wxGuiPluginBase + NoUpgrade + + + + DynamicLibrary + Unicode + v143 + + + DynamicLibrary + Unicode + v143 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + wxGuiPluginBase.dir\Debug\ + wxGuiPluginBase + .dll + true + true + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + wxGuiPluginBase.dir\Release\ + wxGuiPluginBase + .dll + false + true + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + $(IntDir) + EnableFastChecks + + + ProgramDatabase + 4996 + Sync + + + Disabled + stdcpp17 + + true + Disabled + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/CMakeFiles/wxGuiPluginBase.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/wxGuiPluginBase.dir/Debug//cmake_pch.pch + + MultiThreadedDebugDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;DEMO_PLUGIN_EXPORTS;__STDC_CONSTANT_MACROS;CMAKE_INTDIR="Debug";wxGuiPluginBase_EXPORTS + $(IntDir) + false + + + %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;DEMO_PLUGIN_EXPORTS;__STDC_CONSTANT_MACROS;CMAKE_INTDIR=\"Debug\";wxGuiPluginBase_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + true + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Debug/wxGuiPluginBase.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/wxGuiPluginBase.pdb + + Console + + + false + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + $(IntDir) + Default + + + 4996 + Sync + + + AnySuitable + stdcpp17 + + true + MaxSpeed + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/CMakeFiles/wxGuiPluginBase.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/wxGuiPluginBase.dir/Release//cmake_pch.pch + + MultiThreadedDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;DEMO_PLUGIN_EXPORTS;__STDC_CONSTANT_MACROS;CMAKE_INTDIR="Release";wxGuiPluginBase_EXPORTS + $(IntDir) + + + false + + + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;DEMO_PLUGIN_EXPORTS;__STDC_CONSTANT_MACROS;CMAKE_INTDIR=\"Release\";wxGuiPluginBase_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + false + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Release/wxGuiPluginBase.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/wxGuiPluginBase.pdb + + Console + + + false + + + + + Always + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\wxGuiPluginBase\Win\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\wxGuiPluginBase\Win\CMakeFiles\generate.stamp + false + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/CMakeFiles/wxGuiPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/CMakeFiles/wxGuiPluginBase.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/wxGuiPluginBase.dir/Debug//cmake_pch.pch + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/CMakeFiles/wxGuiPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/CMakeFiles/wxGuiPluginBase.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/wxGuiPluginBase.dir/Release//cmake_pch.pch + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/CMakeFiles/wxGuiPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/CMakeFiles/wxGuiPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/CMakeFiles/wxGuiPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/CMakeFiles/wxGuiPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + NotUsing + NotUsing + + + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/CMakeFiles/wxGuiPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxGuiPluginBase/Win/CMakeFiles/wxGuiPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + ZERO_CHECK + false + Never + + + + + + \ No newline at end of file diff --git a/wxGuiPluginBase/Win/wxGuiPluginBase.vcxproj.filters b/wxGuiPluginBase/Win/wxGuiPluginBase.vcxproj.filters new file mode 100644 index 0000000..c46bcbe --- /dev/null +++ b/wxGuiPluginBase/Win/wxGuiPluginBase.vcxproj.filters @@ -0,0 +1,56 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Precompile Header File + + + Precompile Header File + + + + + + + + Source Files + + + + + {4951AEE1-75F2-3C38-B593-C6BC8C809FB0} + + + {112D4227-BB51-3360-BB5B-5EA5DBA5A65F} + + + {05450AB2-CB7B-34EA-83DF-1EE86424EDF0} + + + diff --git a/wxGuiPluginBase/wxGuiPluginBase.cpp b/wxGuiPluginBase/wxGuiPluginBase.cpp index 653a8ab..9eda281 100644 --- a/wxGuiPluginBase/wxGuiPluginBase.cpp +++ b/wxGuiPluginBase/wxGuiPluginBase.cpp @@ -1,25 +1,25 @@ -#include "stdwx.h" -#include "wxGuiPluginBase.h" - -DEFINE_EVENT_TYPE(wxEVT_GUI_PLUGIN_INTEROP) - -IMPLEMENT_ABSTRACT_CLASS(wxGuiPluginBase, wxObject) - -wxGuiPluginBase::wxGuiPluginBase(wxEvtHandler * handler) -: m_Handler(handler) -{ -} - -wxGuiPluginBase::~wxGuiPluginBase() -{ -} - -wxEvtHandler * wxGuiPluginBase::GetEventHandler() -{ - return m_Handler; -} - -void wxGuiPluginBase::SetEventHandler(wxEvtHandler * handler) -{ - m_Handler = handler; +#include "stdwx.h" +#include "wxGuiPluginBase.h" + +DEFINE_EVENT_TYPE(wxEVT_GUI_PLUGIN_INTEROP) + +IMPLEMENT_ABSTRACT_CLASS(wxGuiPluginBase, wxObject) + +wxGuiPluginBase::wxGuiPluginBase(wxEvtHandler * handler) +: m_Handler(handler) +{ +} + +wxGuiPluginBase::~wxGuiPluginBase() +{ +} + +wxEvtHandler * wxGuiPluginBase::GetEventHandler() +{ + return m_Handler; +} + +void wxGuiPluginBase::SetEventHandler(wxEvtHandler * handler) +{ + m_Handler = handler; } \ No newline at end of file diff --git a/wxGuiPluginBase/wxGuiPluginBase.h b/wxGuiPluginBase/wxGuiPluginBase.h index 82cb7da..72b7f39 100644 --- a/wxGuiPluginBase/wxGuiPluginBase.h +++ b/wxGuiPluginBase/wxGuiPluginBase.h @@ -1,25 +1,25 @@ -#pragma once - -#include "Declarations.h" - -class DEMO_API wxGuiPluginBase : public wxObject -{ - DECLARE_ABSTRACT_CLASS(wxGuiPluginBase) -public: - wxGuiPluginBase(wxEvtHandler * handler); - virtual ~wxGuiPluginBase(); - - virtual wxString GetName() const = 0; - virtual wxString GetId() const = 0; - virtual wxWindow * CreatePanel(wxWindow * parent) = 0; - - wxEvtHandler * GetEventHandler(); - virtual void SetEventHandler(wxEvtHandler * handler); -protected: - wxEvtHandler * m_Handler; -}; - -DECLARE_EXPORTED_EVENT_TYPE(DEMO_API, wxEVT_GUI_PLUGIN_INTEROP, wxEVT_USER_FIRST + 100) - -typedef wxGuiPluginBase * (*CreateGuiPlugin_function)(); +#pragma once + +#include "Declarations.h" + +class DEMO_API wxGuiPluginBase : public wxObject +{ + DECLARE_ABSTRACT_CLASS(wxGuiPluginBase) +public: + wxGuiPluginBase(wxEvtHandler * handler); + virtual ~wxGuiPluginBase(); + + virtual wxString GetName() const = 0; + virtual wxString GetId() const = 0; + virtual wxWindow * CreatePanel(wxWindow * parent) = 0; + + wxEvtHandler * GetEventHandler(); + virtual void SetEventHandler(wxEvtHandler * handler); +protected: + wxEvtHandler * m_Handler; +}; + +DECLARE_EXPORTED_EVENT_TYPE(DEMO_API, wxEVT_GUI_PLUGIN_INTEROP, wxEVT_USER_FIRST + 100) + +typedef wxGuiPluginBase * (*CreateGuiPlugin_function)(); typedef void (*DeleteGuiPlugin_function)(wxGuiPluginBase * plugin); \ No newline at end of file diff --git a/wxGuiPluginBase/wxGuiPluginBase.pjd b/wxGuiPluginBase/wxGuiPluginBase.pjd index 8c19101..4b5e088 100644 --- a/wxGuiPluginBase/wxGuiPluginBase.pjd +++ b/wxGuiPluginBase/wxGuiPluginBase.pjd @@ -1,279 +1,279 @@ - - -
- 0 - "" - "" - "" - "" - "" - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - "Volodymyr (T-Rex) Triapichko" - "Volodymyr (T-Rex) Triapichko, 2013" - "" - 0 - 0 - 0 - 0 - "<All platforms>" - "2.9.5" - "Standard" - "///////////////////////////////////////////////////////////////////////////// -// Name: %HEADER-FILENAME% -// Purpose: -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "///////////////////////////////////////////////////////////////////////////// -// Name: %SOURCE-FILENAME% -// Purpose: -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "///////////////////////////////////////////////////////////////////////////// -// Name: %SYMBOLS-FILENAME% -// Purpose: Symbols file -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "" - "// For compilers that support precompilation, includes "wx/wx.h". -#include "wx/wxprec.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#ifndef WX_PRECOMP -#include "wx/wx.h" -#endif - -" - " /// %BODY% -" - " -/* - * %BODY% - */ - -" - "app_resources.h" - "app_resources.cpp" - "AppResources" - "app.h" - "app.cpp" - "Application" - 0 - "" - "<None>" - "iso-8859-1" - "utf-8" - "utf-8" - "" - 0 - 0 - 4 - " " - "" - 0 - 0 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 -
- - - "" - "data-document" - "" - "" - 0 - 1 - 0 - 0 - - "Configurations" - "config-data-document" - "" - "" - 0 - 1 - 0 - 0 - "" - 1 - 0 - - - - - - - "Projects" - "root-document" - "" - "project" - 1 - 1 - 0 - 1 - - "Windows" - "html-document" - "" - "dialogsfolder" - 1 - 1 - 0 - 1 - - "wxGuiPluginWindowBase: ID_WXGUIPLUGINWINDOWBASE" - "dialog-document" - "" - "panel" - 0 - 1 - 0 - 0 - "wbPanelProxy" - 10000 - 0 - "" - 0 - "" - "Standard" - 0 - 0 - "m_Plugin|wxGuiPluginBase *|Plugin||0|0|" - "ID_WXGUIPLUGINWINDOWBASE" - 10000 - "" - "wxGuiPluginWindowBase" - "wxPanel" - 0 - 1 - "wxGuiPluginWindowBase.cpp" - "wxGuiPluginWindowBase.h" - "" - "" - "" - "" - "" - "" - 0 - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - "" - "Tiled" - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - "" - 1 - -1 - -1 - -1 - -1 - "Centre" - "Centre" - 0 - 5 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - "" - "" - "" - - - - "Sources" - "html-document" - "" - "sourcesfolder" - 1 - 1 - 0 - 1 - - "wxGuiPluginBase.rc" - "source-editor-document" - "wxGuiPluginBase.rc" - "source-editor" - 0 - 0 - 1 - 0 - "9/9/2013" - "" - - - - "Images" - "html-document" - "" - "bitmapsfolder" - 1 - 1 - 0 - 1 - - - - -
+ + +
+ 0 + "" + "" + "" + "" + "" + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + "Volodymyr (T-Rex) Triapichko" + "Volodymyr (T-Rex) Triapichko, 2013" + "" + 0 + 0 + 0 + 0 + "<All platforms>" + "2.9.5" + "Standard" + "///////////////////////////////////////////////////////////////////////////// +// Name: %HEADER-FILENAME% +// Purpose: +// Author: %AUTHOR% +// Modified by: +// Created: %DATE% +// RCS-ID: +// Copyright: %COPYRIGHT% +// Licence: +///////////////////////////////////////////////////////////////////////////// + +" + "///////////////////////////////////////////////////////////////////////////// +// Name: %SOURCE-FILENAME% +// Purpose: +// Author: %AUTHOR% +// Modified by: +// Created: %DATE% +// RCS-ID: +// Copyright: %COPYRIGHT% +// Licence: +///////////////////////////////////////////////////////////////////////////// + +" + "///////////////////////////////////////////////////////////////////////////// +// Name: %SYMBOLS-FILENAME% +// Purpose: Symbols file +// Author: %AUTHOR% +// Modified by: +// Created: %DATE% +// RCS-ID: +// Copyright: %COPYRIGHT% +// Licence: +///////////////////////////////////////////////////////////////////////////// + +" + "" + "// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#include "wx/wx.h" +#endif + +" + " /// %BODY% +" + " +/* + * %BODY% + */ + +" + "app_resources.h" + "app_resources.cpp" + "AppResources" + "app.h" + "app.cpp" + "Application" + 0 + "" + "<None>" + "iso-8859-1" + "utf-8" + "utf-8" + "" + 0 + 0 + 4 + " " + "" + 0 + 0 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 +
+ + + "" + "data-document" + "" + "" + 0 + 1 + 0 + 0 + + "Configurations" + "config-data-document" + "" + "" + 0 + 1 + 0 + 0 + "" + 1 + 0 + + + + + + + "Projects" + "root-document" + "" + "project" + 1 + 1 + 0 + 1 + + "Windows" + "html-document" + "" + "dialogsfolder" + 1 + 1 + 0 + 1 + + "wxGuiPluginWindowBase: ID_WXGUIPLUGINWINDOWBASE" + "dialog-document" + "" + "panel" + 0 + 1 + 0 + 0 + "wbPanelProxy" + 10000 + 0 + "" + 0 + "" + "Standard" + 0 + 0 + "m_Plugin|wxGuiPluginBase *|Plugin||0|0|" + "ID_WXGUIPLUGINWINDOWBASE" + 10000 + "" + "wxGuiPluginWindowBase" + "wxPanel" + 0 + 1 + "wxGuiPluginWindowBase.cpp" + "wxGuiPluginWindowBase.h" + "" + "" + "" + "" + "" + "" + 0 + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "Tiled" + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + "" + 1 + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + "" + "" + "" + + + + "Sources" + "html-document" + "" + "sourcesfolder" + 1 + 1 + 0 + 1 + + "wxGuiPluginBase.rc" + "source-editor-document" + "wxGuiPluginBase.rc" + "source-editor" + 0 + 0 + 1 + 0 + "9/9/2013" + "" + + + + "Images" + "html-document" + "" + "bitmapsfolder" + 1 + 1 + 0 + 1 + + + + +
diff --git a/wxGuiPluginBase/wxGuiPluginBase.rc b/wxGuiPluginBase/wxGuiPluginBase.rc old mode 100755 new mode 100644 index f63e693..b86c4e2 --- a/wxGuiPluginBase/wxGuiPluginBase.rc +++ b/wxGuiPluginBase/wxGuiPluginBase.rc @@ -1 +1 @@ -#include "wx/msw/wx.rc" +#include "wx/msw/wx.rc" diff --git a/wxGuiPluginBase/wxGuiPluginWindowBase.cpp b/wxGuiPluginBase/wxGuiPluginWindowBase.cpp old mode 100755 new mode 100644 index b052eef..d0cc9f3 --- a/wxGuiPluginBase/wxGuiPluginWindowBase.cpp +++ b/wxGuiPluginBase/wxGuiPluginWindowBase.cpp @@ -1,149 +1,149 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: wxGuiPluginWindowBase.cpp -// Purpose: -// Author: Volodymyr (T-Rex) Triapichko -// Modified by: -// Created: 09/09/2013 23:54:21 -// RCS-ID: -// Copyright: Volodymyr (T-Rex) Triapichko, 2013 -// Licence: -///////////////////////////////////////////////////////////////////////////// - -// For compilers that support precompilation, includes "wx/wx.h". -#include "wx/wxprec.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#ifndef WX_PRECOMP -#include "wx/wx.h" -#endif - -////@begin includes -////@end includes - -#include "wxGuiPluginWindowBase.h" -#include "wxGuiPluginBase.h" - -////@begin XPM images -////@end XPM images - - -/* - * wxGuiPluginWindowBase type definition - */ - -IMPLEMENT_DYNAMIC_CLASS( wxGuiPluginWindowBase, wxPanel ) - - -/* - * wxGuiPluginWindowBase event table definition - */ - -BEGIN_EVENT_TABLE( wxGuiPluginWindowBase, wxPanel ) - -////@begin wxGuiPluginWindowBase event table entries -////@end wxGuiPluginWindowBase event table entries - -END_EVENT_TABLE() - - -/* - * wxGuiPluginWindowBase constructors - */ - -wxGuiPluginWindowBase::wxGuiPluginWindowBase() -{ - Init(); -} - -wxGuiPluginWindowBase::wxGuiPluginWindowBase(wxGuiPluginBase * plugin, wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) -{ - Init(); - Create(plugin, parent, id, pos, size, style); -} - - -/* - * wxGuiPluginWindowBase creator - */ - -bool wxGuiPluginWindowBase::Create(wxGuiPluginBase * plugin, wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) -{ - m_Plugin = plugin; -////@begin wxGuiPluginWindowBase creation - wxPanel::Create(parent, id, pos, size, style); - CreateControls(); -////@end wxGuiPluginWindowBase creation - return true; -} - - -/* - * wxGuiPluginWindowBase destructor - */ - -wxGuiPluginWindowBase::~wxGuiPluginWindowBase() -{ -////@begin wxGuiPluginWindowBase destruction -////@end wxGuiPluginWindowBase destruction -} - - -/* - * Member initialisation - */ - -void wxGuiPluginWindowBase::Init() -{ -////@begin wxGuiPluginWindowBase member initialisation -////@end wxGuiPluginWindowBase member initialisation -} - - -/* - * Control creation for wxGuiPluginWindowBase - */ - -void wxGuiPluginWindowBase::CreateControls() -{ -////@begin wxGuiPluginWindowBase content construction -////@end wxGuiPluginWindowBase content construction -} - - -/* - * Should we show tooltips? - */ - -bool wxGuiPluginWindowBase::ShowToolTips() -{ - return true; -} - -/* - * Get bitmap resources - */ - -wxBitmap wxGuiPluginWindowBase::GetBitmapResource( const wxString& name ) -{ - // Bitmap retrieval -////@begin wxGuiPluginWindowBase bitmap retrieval - wxUnusedVar(name); - return wxNullBitmap; -////@end wxGuiPluginWindowBase bitmap retrieval -} - -/* - * Get icon resources - */ - -wxIcon wxGuiPluginWindowBase::GetIconResource( const wxString& name ) -{ - // Icon retrieval -////@begin wxGuiPluginWindowBase icon retrieval - wxUnusedVar(name); - return wxNullIcon; -////@end wxGuiPluginWindowBase icon retrieval -} +///////////////////////////////////////////////////////////////////////////// +// Name: wxGuiPluginWindowBase.cpp +// Purpose: +// Author: Volodymyr (T-Rex) Triapichko +// Modified by: +// Created: 09/09/2013 23:54:21 +// RCS-ID: +// Copyright: Volodymyr (T-Rex) Triapichko, 2013 +// Licence: +///////////////////////////////////////////////////////////////////////////// + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#include "wx/wx.h" +#endif + +////@begin includes +////@end includes + +#include "wxGuiPluginWindowBase.h" +#include "wxGuiPluginBase.h" + +////@begin XPM images +////@end XPM images + + +/* + * wxGuiPluginWindowBase type definition + */ + +IMPLEMENT_DYNAMIC_CLASS( wxGuiPluginWindowBase, wxPanel ) + + +/* + * wxGuiPluginWindowBase event table definition + */ + +BEGIN_EVENT_TABLE( wxGuiPluginWindowBase, wxPanel ) + +////@begin wxGuiPluginWindowBase event table entries +////@end wxGuiPluginWindowBase event table entries + +END_EVENT_TABLE() + + +/* + * wxGuiPluginWindowBase constructors + */ + +wxGuiPluginWindowBase::wxGuiPluginWindowBase() +{ + Init(); +} + +wxGuiPluginWindowBase::wxGuiPluginWindowBase(wxGuiPluginBase * plugin, wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) +{ + Init(); + Create(plugin, parent, id, pos, size, style); +} + + +/* + * wxGuiPluginWindowBase creator + */ + +bool wxGuiPluginWindowBase::Create(wxGuiPluginBase * plugin, wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) +{ + m_Plugin = plugin; +////@begin wxGuiPluginWindowBase creation + wxPanel::Create(parent, id, pos, size, style); + CreateControls(); +////@end wxGuiPluginWindowBase creation + return true; +} + + +/* + * wxGuiPluginWindowBase destructor + */ + +wxGuiPluginWindowBase::~wxGuiPluginWindowBase() +{ +////@begin wxGuiPluginWindowBase destruction +////@end wxGuiPluginWindowBase destruction +} + + +/* + * Member initialisation + */ + +void wxGuiPluginWindowBase::Init() +{ +////@begin wxGuiPluginWindowBase member initialisation +////@end wxGuiPluginWindowBase member initialisation +} + + +/* + * Control creation for wxGuiPluginWindowBase + */ + +void wxGuiPluginWindowBase::CreateControls() +{ +////@begin wxGuiPluginWindowBase content construction +////@end wxGuiPluginWindowBase content construction +} + + +/* + * Should we show tooltips? + */ + +bool wxGuiPluginWindowBase::ShowToolTips() +{ + return true; +} + +/* + * Get bitmap resources + */ + +wxBitmap wxGuiPluginWindowBase::GetBitmapResource( const wxString& name ) +{ + // Bitmap retrieval +////@begin wxGuiPluginWindowBase bitmap retrieval + wxUnusedVar(name); + return wxNullBitmap; +////@end wxGuiPluginWindowBase bitmap retrieval +} + +/* + * Get icon resources + */ + +wxIcon wxGuiPluginWindowBase::GetIconResource( const wxString& name ) +{ + // Icon retrieval +////@begin wxGuiPluginWindowBase icon retrieval + wxUnusedVar(name); + return wxNullIcon; +////@end wxGuiPluginWindowBase icon retrieval +} diff --git a/wxGuiPluginBase/wxGuiPluginWindowBase.h b/wxGuiPluginBase/wxGuiPluginWindowBase.h old mode 100755 new mode 100644 index 11034be..cef6fb4 --- a/wxGuiPluginBase/wxGuiPluginWindowBase.h +++ b/wxGuiPluginBase/wxGuiPluginWindowBase.h @@ -1,107 +1,107 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: wxGuiPluginWindowBase.h -// Purpose: -// Author: Volodymyr (T-Rex) Triapichko -// Modified by: -// Created: 09/09/2013 23:54:21 -// RCS-ID: -// Copyright: Volodymyr (T-Rex) Triapichko, 2013 -// Licence: -///////////////////////////////////////////////////////////////////////////// - -#ifndef _WXGUIPLUGINWINDOWBASE_H_ -#define _WXGUIPLUGINWINDOWBASE_H_ - - -/*! - * Includes - */ - -////@begin includes -////@end includes -#include "Declarations.h" - -/*! - * Forward declarations - */ - -////@begin forward declarations -class wxGuiPluginWindowBase; -////@end forward declarations -class wxGuiPluginBase; - -/*! - * Control identifiers - */ - -////@begin control identifiers -#define ID_WXGUIPLUGINWINDOWBASE 10000 -#define SYMBOL_WXGUIPLUGINWINDOWBASE_STYLE wxNO_BORDER|wxTAB_TRAVERSAL -#define SYMBOL_WXGUIPLUGINWINDOWBASE_IDNAME ID_WXGUIPLUGINWINDOWBASE -#define SYMBOL_WXGUIPLUGINWINDOWBASE_SIZE wxDefaultSize -#define SYMBOL_WXGUIPLUGINWINDOWBASE_POSITION wxDefaultPosition -////@end control identifiers - - -/*! - * wxGuiPluginWindowBase class declaration - */ - -class DEMO_API wxGuiPluginWindowBase: public wxPanel -{ - DECLARE_DYNAMIC_CLASS( wxGuiPluginWindowBase ) - DECLARE_EVENT_TABLE() - -public: - /// Constructors - wxGuiPluginWindowBase(); - wxGuiPluginWindowBase(wxGuiPluginBase * plugin, - wxWindow* parent, - wxWindowID id = ID_WXGUIPLUGINWINDOWBASE, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxNO_BORDER|wxTAB_TRAVERSAL); - - /// Creation - bool Create(wxGuiPluginBase * plugin, - wxWindow* parent, - wxWindowID id = ID_WXGUIPLUGINWINDOWBASE, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxNO_BORDER|wxTAB_TRAVERSAL); - - /// Destructor - ~wxGuiPluginWindowBase(); - - /// Initialises member variables - void Init(); - - /// Creates the controls and sizers - void CreateControls(); - -////@begin wxGuiPluginWindowBase event handler declarations - -////@end wxGuiPluginWindowBase event handler declarations - -////@begin wxGuiPluginWindowBase member function declarations - - wxGuiPluginBase * GetPlugin() const { return m_Plugin ; } - void SetPlugin(wxGuiPluginBase * value) { m_Plugin = value ; } - - /// Retrieves bitmap resources - wxBitmap GetBitmapResource( const wxString& name ); - - /// Retrieves icon resources - wxIcon GetIconResource( const wxString& name ); -////@end wxGuiPluginWindowBase member function declarations - - /// Should we show tooltips? - static bool ShowToolTips(); - -////@begin wxGuiPluginWindowBase member variables - wxGuiPluginBase * m_Plugin; -////@end wxGuiPluginWindowBase member variables -}; - -#endif - // _WXGUIPLUGINWINDOWBASE_H_ +///////////////////////////////////////////////////////////////////////////// +// Name: wxGuiPluginWindowBase.h +// Purpose: +// Author: Volodymyr (T-Rex) Triapichko +// Modified by: +// Created: 09/09/2013 23:54:21 +// RCS-ID: +// Copyright: Volodymyr (T-Rex) Triapichko, 2013 +// Licence: +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WXGUIPLUGINWINDOWBASE_H_ +#define _WXGUIPLUGINWINDOWBASE_H_ + + +/*! + * Includes + */ + +////@begin includes +////@end includes +#include "Declarations.h" + +/*! + * Forward declarations + */ + +////@begin forward declarations +class wxGuiPluginWindowBase; +////@end forward declarations +class wxGuiPluginBase; + +/*! + * Control identifiers + */ + +////@begin control identifiers +#define ID_WXGUIPLUGINWINDOWBASE 10000 +#define SYMBOL_WXGUIPLUGINWINDOWBASE_STYLE wxNO_BORDER|wxTAB_TRAVERSAL +#define SYMBOL_WXGUIPLUGINWINDOWBASE_IDNAME ID_WXGUIPLUGINWINDOWBASE +#define SYMBOL_WXGUIPLUGINWINDOWBASE_SIZE wxDefaultSize +#define SYMBOL_WXGUIPLUGINWINDOWBASE_POSITION wxDefaultPosition +////@end control identifiers + + +/*! + * wxGuiPluginWindowBase class declaration + */ + +class DEMO_API wxGuiPluginWindowBase: public wxPanel +{ + DECLARE_DYNAMIC_CLASS( wxGuiPluginWindowBase ) + DECLARE_EVENT_TABLE() + +public: + /// Constructors + wxGuiPluginWindowBase(); + wxGuiPluginWindowBase(wxGuiPluginBase * plugin, + wxWindow* parent, + wxWindowID id = ID_WXGUIPLUGINWINDOWBASE, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxNO_BORDER|wxTAB_TRAVERSAL); + + /// Creation + bool Create(wxGuiPluginBase * plugin, + wxWindow* parent, + wxWindowID id = ID_WXGUIPLUGINWINDOWBASE, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxNO_BORDER|wxTAB_TRAVERSAL); + + /// Destructor + ~wxGuiPluginWindowBase(); + + /// Initialises member variables + void Init(); + + /// Creates the controls and sizers + void CreateControls(); + +////@begin wxGuiPluginWindowBase event handler declarations + +////@end wxGuiPluginWindowBase event handler declarations + +////@begin wxGuiPluginWindowBase member function declarations + + wxGuiPluginBase * GetPlugin() const { return m_Plugin ; } + void SetPlugin(wxGuiPluginBase * value) { m_Plugin = value ; } + + /// Retrieves bitmap resources + wxBitmap GetBitmapResource( const wxString& name ); + + /// Retrieves icon resources + wxIcon GetIconResource( const wxString& name ); +////@end wxGuiPluginWindowBase member function declarations + + /// Should we show tooltips? + static bool ShowToolTips(); + +////@begin wxGuiPluginWindowBase member variables + wxGuiPluginBase * m_Plugin; +////@end wxGuiPluginWindowBase member variables +}; + +#endif + // _WXGUIPLUGINWINDOWBASE_H_ diff --git a/wxModularCore/CMakeLists.txt b/wxModularCore/CMakeLists.txt index 1e6a04b..9d3c97a 100644 --- a/wxModularCore/CMakeLists.txt +++ b/wxModularCore/CMakeLists.txt @@ -1,30 +1,30 @@ -set (SRCS - wxModularCore.cpp - wxModularCoreSettings.cpp) -set (HEADERS - wxModularCore.h - wxModularCoreSettings.h) - -set(LIBRARY_NAME wxModularCore) - -if(WIN32) - set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D__STDC_CONSTANT_MACROS) -endif(WIN32) - -set(SRCS ${SRCS} ${HEADERS} - ${PROJECT_ROOT_DIR}/include/stdwx.h - ${PROJECT_ROOT_DIR}/include/stdwx.cpp) - -add_definitions(${PREPROCESSOR_DEFINITIONS}) - -include_directories(${INCLUDE_DIRECTORIES} ${BASE_INCLUDE_DIRECTORIES}) - -link_directories(${LINK_DIRECTORIES}) - -add_library(${LIBRARY_NAME} STATIC ${SRCS}) - -set(DLL_DIR bin) -set(TARGET_LOCATION ${PROJECT_SOURCE_DIR}/${DLL_DIR}/${CMAKE_CFG_INTDIR}) -set_target_properties(${LIBRARY_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TARGET_LOCATION}) - -target_precompile_headers(${LIBRARY_NAME} PRIVATE ${PROJECT_ROOT_DIR}/include/stdwx.h ${PROJECT_ROOT_DIR}/include/stdwx.cpp) \ No newline at end of file +set (SRCS + wxModularCore.cpp + wxModularCoreSettings.cpp) +set (HEADERS + wxModularCore.h + wxModularCoreSettings.h) + +set(LIBRARY_NAME wxModularCore) + +if(WIN32) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D__STDC_CONSTANT_MACROS) +endif(WIN32) + +set(SRCS ${SRCS} ${HEADERS} + ${PROJECT_ROOT_DIR}/include/stdwx.h + ${PROJECT_ROOT_DIR}/include/stdwx.cpp) + +add_definitions(${PREPROCESSOR_DEFINITIONS}) + +include_directories(${INCLUDE_DIRECTORIES} ${BASE_INCLUDE_DIRECTORIES}) + +link_directories(${LINK_DIRECTORIES}) + +add_library(${LIBRARY_NAME} STATIC ${SRCS}) + +set(DLL_DIR bin) +set(TARGET_LOCATION ${PROJECT_SOURCE_DIR}/${DLL_DIR}/${CMAKE_CFG_INTDIR}) +set_target_properties(${LIBRARY_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TARGET_LOCATION}) + +target_precompile_headers(${LIBRARY_NAME} PRIVATE ${PROJECT_ROOT_DIR}/include/stdwx.h) \ No newline at end of file diff --git a/wxModularCore/Win/wxModularCore.vcxproj b/wxModularCore/Win/wxModularCore.vcxproj new file mode 100644 index 0000000..ed9edcd --- /dev/null +++ b/wxModularCore/Win/wxModularCore.vcxproj @@ -0,0 +1,218 @@ + + + + x64 + + + + Debug + x64 + + + Release + x64 + + + + {746FA12D-51CE-3AA5-90F0-43DD3C32BDA9} + Win32Proj + 10.0.26100.0 + x64 + wxModularCore + NoUpgrade + + + + StaticLibrary + Unicode + v143 + + + StaticLibrary + Unicode + v143 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Debug\ + wxModularCore.dir\Debug\ + wxModularCore + .lib + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\lib\Release\ + wxModularCore.dir\Release\ + wxModularCore + .lib + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + $(IntDir) + EnableFastChecks + + + ProgramDatabase + 4996 + Sync + + + Disabled + stdcpp17 + + true + Disabled + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/CMakeFiles/wxModularCore.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/wxModularCore.dir/Debug//cmake_pch.pch + + MultiThreadedDebugDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;__STDC_CONSTANT_MACROS;CMAKE_INTDIR="Debug" + $(IntDir) + false + + + %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;__STDC_CONSTANT_MACROS;CMAKE_INTDIR=\"Debug\" + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + %(AdditionalOptions) /machine:x64 + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + $(IntDir) + Default + + + 4996 + Sync + + + AnySuitable + stdcpp17 + + true + MaxSpeed + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/CMakeFiles/wxModularCore.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/wxModularCore.dir/Release//cmake_pch.pch + + MultiThreadedDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;__STDC_CONSTANT_MACROS;CMAKE_INTDIR="Release" + $(IntDir) + + + false + + + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;__STDC_CONSTANT_MACROS;CMAKE_INTDIR=\"Release\" + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + %(AdditionalOptions) /machine:x64 + + + + + Always + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\wxModularCore\Win\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\wxModularCore\Win\CMakeFiles\generate.stamp + false + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/CMakeFiles/wxModularCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/CMakeFiles/wxModularCore.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/wxModularCore.dir/Debug//cmake_pch.pch + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/CMakeFiles/wxModularCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/CMakeFiles/wxModularCore.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/wxModularCore.dir/Release//cmake_pch.pch + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/CMakeFiles/wxModularCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/CMakeFiles/wxModularCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/CMakeFiles/wxModularCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/CMakeFiles/wxModularCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/CMakeFiles/wxModularCore.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularCore/Win/CMakeFiles/wxModularCore.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + ZERO_CHECK + false + Never + + + + + + \ No newline at end of file diff --git a/wxModularCore/Win/wxModularCore.vcxproj.filters b/wxModularCore/Win/wxModularCore.vcxproj.filters new file mode 100644 index 0000000..f1b6bd4 --- /dev/null +++ b/wxModularCore/Win/wxModularCore.vcxproj.filters @@ -0,0 +1,48 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Precompile Header File + + + Precompile Header File + + + + + + + + {4951AEE1-75F2-3C38-B593-C6BC8C809FB0} + + + {112D4227-BB51-3360-BB5B-5EA5DBA5A65F} + + + {05450AB2-CB7B-34EA-83DF-1EE86424EDF0} + + + diff --git a/wxModularCore/wxModularCore.cpp b/wxModularCore/wxModularCore.cpp index 7dc009f..d3cea07 100644 --- a/wxModularCore/wxModularCore.cpp +++ b/wxModularCore/wxModularCore.cpp @@ -1,57 +1,57 @@ -#include "stdwx.h" -#include "wxModularCore.h" -#include "wxModularCoreSettings.h" -#include - -WX_DEFINE_LIST(wxDynamicLibraryList); - - -wxModularCore::wxModularCore() - : m_Settings(new wxModularCoreSettings), m_Handler(new wxEvtHandler) -{ - // This will allow to delete all objects from this list automatically - m_DllList.DeleteContents(true); -} - -wxModularCore::~wxModularCore() -{ - wxDELETE(m_Handler); - wxDELETE(m_Settings); -} - -void wxModularCore::Clear() -{ - UnloadAllPlugins(); - // TODO: Add the code which resets the object to initial state -} - -wxString wxModularCore::GetPluginsPath(bool forceProgramPath) const -{ -#if defined(__WXMAC__) - return wxStandardPaths::Get().GetPluginsDir(); -#else - wxString path; - if (m_Settings->GetStoreInAppData() && !forceProgramPath) - path = wxStandardPaths::Get().GetConfigDir(); - else - path = wxPathOnly(wxStandardPaths::Get().GetExecutablePath()); - wxFileName fn; - fn.AssignDir(path); - fn.AppendDir(wxT("plugins")); - return fn.GetFullPath(); -#endif -} - -wxString wxModularCore::GetPluginExt() -{ - return -#if defined(__WXMSW__) - wxT("dll"); -#elif defined(__WXGTK__) - wxT("so"); -#elif defined(__WXMAC__) - wxT("dylib"); -#else - wxEmptyString; -#endif -} +#include "stdwx.h" +#include "wxModularCore.h" +#include "wxModularCoreSettings.h" +#include + +WX_DEFINE_LIST(wxDynamicLibraryList); + + +wxModularCore::wxModularCore() + : m_Settings(new wxModularCoreSettings), m_Handler(new wxEvtHandler) +{ + // This will allow to delete all objects from this list automatically + m_DllList.DeleteContents(true); +} + +wxModularCore::~wxModularCore() +{ + wxDELETE(m_Handler); + wxDELETE(m_Settings); +} + +void wxModularCore::Clear() +{ + UnloadAllPlugins(); + // TODO: Add the code which resets the object to initial state +} + +wxString wxModularCore::GetPluginsPath(bool forceProgramPath) const +{ +#if defined(__WXMAC__) + return wxStandardPaths::Get().GetPluginsDir(); +#else + wxString path; + if (m_Settings->GetStoreInAppData() && !forceProgramPath) + path = wxStandardPaths::Get().GetConfigDir(); + else + path = wxPathOnly(wxStandardPaths::Get().GetExecutablePath()); + wxFileName fn; + fn.AssignDir(path); + fn.AppendDir(wxT("plugins")); + return fn.GetFullPath(); +#endif +} + +wxString wxModularCore::GetPluginExt() +{ + return +#if defined(__WXMSW__) + wxT("dll"); +#elif defined(__WXGTK__) + wxT("so"); +#elif defined(__WXMAC__) + wxT("dylib"); +#else + wxEmptyString; +#endif +} diff --git a/wxModularCore/wxModularCore.h b/wxModularCore/wxModularCore.h index cd6701d..943f15d 100644 --- a/wxModularCore/wxModularCore.h +++ b/wxModularCore/wxModularCore.h @@ -1,140 +1,140 @@ -#pragma once - -// We need to keep the list of loaded DLLs -WX_DECLARE_LIST(wxDynamicLibrary, wxDynamicLibraryList); - -class wxModularCoreSettings; - -class wxModularCore -{ -public: - wxModularCore(); - virtual ~wxModularCore(); - - virtual wxString GetPluginsPath(bool forceProgramPath) const; - virtual wxString GetPluginExt(); - - virtual bool LoadAllPlugins(bool forceProgramPath) = 0; - virtual bool UnloadAllPlugins() = 0; - virtual void Clear(); -protected: - - wxDynamicLibraryList m_DllList; - - wxModularCoreSettings * m_Settings; - wxEvtHandler * m_Handler; - - template - bool RegisterPlugin(PluginType * plugin, - PluginListType & list) - { - list.Append(plugin); - return true; - } - - template - bool UnRegisterPlugin( - PluginType * plugin, - PluginListType & container, - PluginToDllDictionaryType & pluginMap) - { - typename PluginListType::compatibility_iterator it = - container.Find(plugin); - if (it == NULL) - return false; - - do - { - wxDynamicLibrary * dll = (wxDynamicLibrary *)pluginMap[plugin]; - if (!dll) // Probably plugin was not loaded from dll - break; - - wxDYNLIB_FUNCTION(DeletePluginFunctionType, - DeletePlugin, *dll); - if (pfnDeletePlugin) - { - pfnDeletePlugin(plugin); - container.Erase(it); - pluginMap.erase(plugin); - return true; - } - } while (false); - - // If plugin is not loaded from DLL (e.g. embedded into executable) - wxDELETE(plugin); - container.Erase(it); - - return true; - } - - template - bool UnloadPlugins(PluginListType & list, - PluginToDllDictionaryType & pluginDictoonary) - { - bool result = true; - PluginType * plugin = NULL; - while (list.GetFirst() && (plugin = - list.GetFirst()->GetData())) - { - result &= UnRegisterPlugin(plugin, - list, pluginDictoonary); - } - return result; - } - - template - bool LoadPlugins(const wxString & pluginsDirectory, - PluginListType & list, - PluginToDllDictionaryType & pluginDictionary, - const wxString & subFolder) - { - wxFileName fn; - fn.AssignDir(pluginsDirectory); - wxLogDebug(wxT("%s"), fn.GetFullPath().data()); - fn.AppendDir(subFolder); - wxLogDebug(wxT("%s"), fn.GetFullPath().data()); - if (!fn.DirExists()) - return false; - - if(!wxDirExists(fn.GetFullPath())) return false; - wxString wildcard = wxString::Format(wxT("*.%s"), - GetPluginExt().GetData()); - wxArrayString pluginPaths; - wxDir::GetAllFiles(fn.GetFullPath(), - &pluginPaths, wildcard); - for(size_t i = 0; i < pluginPaths.GetCount(); ++i) - { - wxString fileName = pluginPaths[i]; - wxDynamicLibrary * dll = new wxDynamicLibrary(fileName); - if (dll->IsLoaded()) - { - wxDYNLIB_FUNCTION(CreatePluginFunctionType, - CreatePlugin, *dll); - if (pfnCreatePlugin) - { - PluginType * plugin = pfnCreatePlugin(); - RegisterPlugin(plugin, list); - m_DllList.Append(dll); - pluginDictionary[plugin] = dll; - } - else - wxDELETE(dll); - } - } - return true; - } - -}; +#pragma once + +// We need to keep the list of loaded DLLs +WX_DECLARE_LIST(wxDynamicLibrary, wxDynamicLibraryList); + +class wxModularCoreSettings; + +class wxModularCore +{ +public: + wxModularCore(); + virtual ~wxModularCore(); + + virtual wxString GetPluginsPath(bool forceProgramPath) const; + virtual wxString GetPluginExt(); + + virtual bool LoadAllPlugins(bool forceProgramPath) = 0; + virtual bool UnloadAllPlugins() = 0; + virtual void Clear(); +protected: + + wxDynamicLibraryList m_DllList; + + wxModularCoreSettings * m_Settings; + wxEvtHandler * m_Handler; + + template + bool RegisterPlugin(PluginType * plugin, + PluginListType & list) + { + list.Append(plugin); + return true; + } + + template + bool UnRegisterPlugin( + PluginType * plugin, + PluginListType & container, + PluginToDllDictionaryType & pluginMap) + { + typename PluginListType::compatibility_iterator it = + container.Find(plugin); + if (it == nullptr) + return false; + + do + { + wxDynamicLibrary * dll = (wxDynamicLibrary *)pluginMap[plugin]; + if (!dll) // Probably plugin was not loaded from dll + break; + + wxDYNLIB_FUNCTION(DeletePluginFunctionType, + DeletePlugin, *dll); + if (pfnDeletePlugin) + { + pfnDeletePlugin(plugin); + container.Erase(it); + pluginMap.erase(plugin); + return true; + } + } while (false); + + // If plugin is not loaded from DLL (e.g. embedded into executable) + wxDELETE(plugin); + container.Erase(it); + + return true; + } + + template + bool UnloadPlugins(PluginListType & list, + PluginToDllDictionaryType & pluginDictoonary) + { + bool result = true; + PluginType * plugin = NULL; + while (list.GetFirst() && (plugin = + list.GetFirst()->GetData())) + { + result &= UnRegisterPlugin(plugin, + list, pluginDictoonary); + } + return result; + } + + template + bool LoadPlugins(const wxString & pluginsDirectory, + PluginListType & list, + PluginToDllDictionaryType & pluginDictionary, + const wxString & subFolder) + { + wxFileName fn; + fn.AssignDir(pluginsDirectory); + wxLogDebug(wxT("%s"), fn.GetFullPath().data()); + fn.AppendDir(subFolder); + wxLogDebug(wxT("%s"), fn.GetFullPath().data()); + if (!fn.DirExists()) + return false; + + if(!wxDirExists(fn.GetFullPath())) return false; + wxString wildcard = wxString::Format(wxT("*.%s"), + GetPluginExt().GetData()); + wxArrayString pluginPaths; + wxDir::GetAllFiles(fn.GetFullPath(), + &pluginPaths, wildcard); + for(size_t i = 0; i < pluginPaths.GetCount(); ++i) + { + wxString fileName = pluginPaths[i]; + wxDynamicLibrary * dll = new wxDynamicLibrary(fileName); + if (dll->IsLoaded()) + { + wxDYNLIB_FUNCTION(CreatePluginFunctionType, + CreatePlugin, *dll); + if (pfnCreatePlugin) + { + PluginType * plugin = pfnCreatePlugin(); + RegisterPlugin(plugin, list); + m_DllList.Append(dll); + pluginDictionary[plugin] = dll; + } + else + wxDELETE(dll); + } + } + return true; + } + +}; diff --git a/wxModularCore/wxModularCoreSettings.cpp b/wxModularCore/wxModularCoreSettings.cpp index 4761361..5987986 100644 --- a/wxModularCore/wxModularCoreSettings.cpp +++ b/wxModularCore/wxModularCoreSettings.cpp @@ -1,42 +1,42 @@ -#include "stdwx.h" -#include "wxModularCoreSettings.h" - -wxModularCoreSettings::wxModularCoreSettings() - : m_bStoreInAppData(false) -{ - -} - -wxModularCoreSettings::wxModularCoreSettings(const wxModularCoreSettings & settings) -{ - CopyFrom(settings); -} - -wxModularCoreSettings & wxModularCoreSettings::operator = (const wxModularCoreSettings & settings) -{ - if (this != &settings) - { - CopyFrom(settings); - } - return *this; -} - -wxModularCoreSettings::~wxModularCoreSettings() -{ - -} - -void wxModularCoreSettings::CopyFrom(const wxModularCoreSettings & settings) -{ - m_bStoreInAppData = settings.m_bStoreInAppData; -} - -void wxModularCoreSettings::SetStoreInAppData(const bool & value) -{ - m_bStoreInAppData = value; -} - -bool wxModularCoreSettings::GetStoreInAppData() const -{ - return m_bStoreInAppData; +#include "stdwx.h" +#include "wxModularCoreSettings.h" + +wxModularCoreSettings::wxModularCoreSettings() + : m_bStoreInAppData(false) +{ + +} + +wxModularCoreSettings::wxModularCoreSettings(const wxModularCoreSettings & settings) +{ + CopyFrom(settings); +} + +wxModularCoreSettings & wxModularCoreSettings::operator = (const wxModularCoreSettings & settings) +{ + if (this != &settings) + { + CopyFrom(settings); + } + return *this; +} + +wxModularCoreSettings::~wxModularCoreSettings() +{ + +} + +void wxModularCoreSettings::CopyFrom(const wxModularCoreSettings & settings) +{ + m_bStoreInAppData = settings.m_bStoreInAppData; +} + +void wxModularCoreSettings::SetStoreInAppData(const bool & value) +{ + m_bStoreInAppData = value; +} + +bool wxModularCoreSettings::GetStoreInAppData() const +{ + return m_bStoreInAppData; } \ No newline at end of file diff --git a/wxModularCore/wxModularCoreSettings.h b/wxModularCore/wxModularCoreSettings.h index baf7c5f..b970eb4 100644 --- a/wxModularCore/wxModularCoreSettings.h +++ b/wxModularCore/wxModularCoreSettings.h @@ -1,17 +1,17 @@ -#pragma once - -class wxModularCoreSettings -{ -public: - wxModularCoreSettings(); - wxModularCoreSettings(const wxModularCoreSettings & settings); - wxModularCoreSettings & operator = (const wxModularCoreSettings & settings); - virtual ~wxModularCoreSettings(); - - void SetStoreInAppData(const bool & val); - bool GetStoreInAppData() const; -protected: - virtual void CopyFrom(const wxModularCoreSettings & settings); -private: - bool m_bStoreInAppData; // Should we store data in Application Data folder or in .exe folder +#pragma once + +class wxModularCoreSettings +{ +public: + wxModularCoreSettings(); + wxModularCoreSettings(const wxModularCoreSettings & settings); + wxModularCoreSettings & operator = (const wxModularCoreSettings & settings); + virtual ~wxModularCoreSettings(); + + void SetStoreInAppData(const bool & val); + bool GetStoreInAppData() const; +protected: + virtual void CopyFrom(const wxModularCoreSettings & settings); +private: + bool m_bStoreInAppData; // Should we store data in Application Data folder or in .exe folder }; \ No newline at end of file diff --git a/wxModularHost/CMakeLists.txt b/wxModularHost/CMakeLists.txt index a43a247..035ab4c 100644 --- a/wxModularHost/CMakeLists.txt +++ b/wxModularHost/CMakeLists.txt @@ -1,102 +1,106 @@ -set(SRCS - MainFrame.cpp - SampleModularCore.cpp - wxModularHostApp.cpp) -set(HEADERS - MainFrame.h - SampleModularCore.h - wxModularHostApp.h) - - -execute_process( - COMMAND wx-config --libs aui - RESULT_VARIABLE wxWidgets_aui_lib_result - OUTPUT_VARIABLE wxWidgets_aui_lib_output - ERROR_VARIABLE wxWidgets_aui_lib_error - OUTPUT_STRIP_TRAILING_WHITESPACE -) - -if(NOT ${wxWidgets_aui_lib_result} EQUAL 0) - message(FATAL_ERROR "wx-config failed: ${wxWidgets_aui_lib_error}") -else() - message(STATUS "wx-config output: ${wxWidgets_aui_lib_output}") -endif() - -set(INCLUDE_DIRECTORIES ${BASE_INCLUDE_DIRECTORIES} - ${PROJECT_ROOT_DIR}/wxModularCore - ${PROJECT_ROOT_DIR}/wxNonGuiPluginBase - ${PROJECT_ROOT_DIR}/wxGuiPluginBase) - -if(WIN32) - set(SRCS ${SRCS} wxModularHost.rc) - set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS}; - /D_USRDLL; - /DwxUSE_NO_MANIFEST=1; - /D__STDC_CONSTANT_MACROS) - set(LINK_DIRECTORIES - ${PROJECT_ROOT_DIR}/wxNonGuiPluginBase/${OS_BASE_NAME}${LIB_SUFFIX}/$(ConfigurationName) - ${PROJECT_ROOT_DIR}/wxGuiPluginBase/${OS_BASE_NAME}${LIB_SUFFIX}/$(ConfigurationName) - ${PROJECT_ROOT_DIR}/wxModularCore/${OS_BASE_NAME}${LIB_SUFFIX}/$(ConfigurationName)) - set(DEMO_LIBS wxModularCore.lib wxNonGuiPluginBase.lib wxGuiPluginBase.lib) -endif(WIN32) -if(LINUX OR APPLE) - set(LINK_DIRECTORIES - ${PROJECT_ROOT_DIR}/wxNonGuiPluginBase/${OS_BASE_NAME}${LIB_SUFFIX} - ${PROJECT_ROOT_DIR}/wxGuiPluginBase/${OS_BASE_NAME}${LIB_SUFFIX} - ${PROJECT_ROOT_DIR}/wxModularCore/${OS_BASE_NAME}${LIB_SUFFIX}) - set(DEMO_LIBS_SHARED wxNonGuiPluginBase wxGuiPluginBase) - set(DEMO_LIBS wxModularCore ${DEMO_LIBS_SHARED}) -endif(LINUX OR APPLE) - -set(LIBS ${DEMO_LIBS} ${wxWidgets_LIBRARIES} ${wxWidgets_aui_lib_output}) - -set(EXECUTABLE_NAME wxModularHost) - -add_definitions(${PREPROCESSOR_DEFINITIONS}) -include_directories(${INCLUDE_DIRECTORIES} ${BASE_INCLUDE_DIRECTORIES}) -link_directories(${LINK_DIRECTORIES}) - -if(WIN32) - set(EXECUTABLE_TYPE WIN32) -endif(WIN32) -if(APPLE) - set(MACOSX_BUNDLE YES) - set(EXECUTABLE_TYPE MACOSX_BUNDLE) - set(CMAKE_INSTALL_PATH "@loader_path") -endif(APPLE) -if(LINUX) - set(EXECUTABLE_TYPE "") -endif(LINUX) - -set(SRCS ${SRCS} ${HEADERS} - ${PROJECT_ROOT_DIR}/include/stdwx.h - ${PROJECT_ROOT_DIR}/include/stdwx.cpp) - -set(PROJECT_FILES ${SRCS}) -add_executable(${EXECUTABLE_NAME} ${EXECUTABLE_TYPE} ${PROJECT_FILES}) - -set(EXE_DIR bin) -set(TARGET_LOCATION ${PROJECT_SOURCE_DIR}/${EXE_DIR}${LIB_SUFFIX}) -set_target_properties(${EXECUTABLE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TARGET_LOCATION}) -if(APPLE) - set(CMAKE_MACOSX_RPATH 1) - set(MACOSX_RPATH TRUE) - set_target_properties( - ${EXECUTABLE_NAME} PROPERTIES - INSTALL_RPATH "@loader_path/../Frameworks") -endif(APPLE) - -target_link_libraries(${EXECUTABLE_NAME} ${LIBS}) - -add_dependencies(${EXECUTABLE_NAME} wxModularCore) - -target_precompile_headers(${EXECUTABLE_NAME} PRIVATE ${PROJECT_ROOT_DIR}/include/stdwx.h ${PROJECT_ROOT_DIR}/include/stdwx.cpp) - -if(APPLE) - FOREACH(DEP_LIB ${DEMO_LIBS_SHARED}) - get_filename_component(ABS_ROOT_DIR ${PROJECT_ROOT_DIR} ABSOLUTE) - set(LIBNAME_FULL "${ABS_ROOT_DIR}/${DEP_LIB}/${OS_BASE_NAME}${LIB_SUFFIX}/$(CONFIGURATION)/lib${DEP_LIB}.dylib") - add_custom_command(TARGET ${EXECUTABLE_NAME} POST_BUILD - COMMAND install_name_tool -change "${LIBNAME_FULL}" "@executable_path/../Frameworks/lib${DEP_LIB}.dylib" $) - ENDFOREACH(DEP_LIB) -endif(APPLE) +set(SRCS + MainFrame.cpp + SampleModularCore.cpp + wxModularHostApp.cpp) +set(HEADERS + MainFrame.h + SampleModularCore.h + wxModularHostApp.h) + + +if(NOT WIN32) + execute_process( + COMMAND wx-config --libs aui + RESULT_VARIABLE wxWidgets_aui_lib_result + OUTPUT_VARIABLE wxWidgets_aui_lib_output + ERROR_VARIABLE wxWidgets_aui_lib_error + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(NOT ${wxWidgets_aui_lib_result} EQUAL 0) + message(FATAL_ERROR "wx-config failed: ${wxWidgets_aui_lib_error}") + else() + message(STATUS "wx-config output: ${wxWidgets_aui_lib_output}") + endif() +endif(NOT WIN32) + +set(INCLUDE_DIRECTORIES ${BASE_INCLUDE_DIRECTORIES} + ${PROJECT_ROOT_DIR}/wxModularCore + ${PROJECT_ROOT_DIR}/wxNonGuiPluginBase + ${PROJECT_ROOT_DIR}/wxGuiPluginBase) + +if(WIN32) + set(SRCS ${SRCS} wxModularHost.rc) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS}; + /D_USRDLL; + /DwxUSE_NO_MANIFEST=1; + /D__STDC_CONSTANT_MACROS) + set(LINK_DIRECTORIES + ${PROJECT_ROOT_DIR}/wxNonGuiPluginBase/${OS_BASE_NAME}${LIB_SUFFIX}/$(ConfigurationName) + ${PROJECT_ROOT_DIR}/wxGuiPluginBase/${OS_BASE_NAME}${LIB_SUFFIX}/$(ConfigurationName) + ${PROJECT_ROOT_DIR}/wxModularCore/${OS_BASE_NAME}${LIB_SUFFIX}/$(ConfigurationName)) + set(DEMO_LIBS wxModularCore.lib wxNonGuiPluginBase.lib wxGuiPluginBase.lib) +endif(WIN32) +if(LINUX OR APPLE) + set(LINK_DIRECTORIES + ${PROJECT_ROOT_DIR}/wxNonGuiPluginBase/${OS_BASE_NAME}${LIB_SUFFIX} + ${PROJECT_ROOT_DIR}/wxGuiPluginBase/${OS_BASE_NAME}${LIB_SUFFIX} + ${PROJECT_ROOT_DIR}/wxModularCore/${OS_BASE_NAME}${LIB_SUFFIX}) + set(DEMO_LIBS_SHARED wxNonGuiPluginBase wxGuiPluginBase) + set(DEMO_LIBS wxModularCore ${DEMO_LIBS_SHARED}) +endif(LINUX OR APPLE) + +find_package(OpenCV REQUIRED) + +set(LIBS ${DEMO_LIBS} ${wxWidgets_LIBRARIES} ${wxWidgets_aui_lib_output} ${OpenCV_LIBS}) + +set(EXECUTABLE_NAME wxModularHost) + +add_definitions(${PREPROCESSOR_DEFINITIONS}) +include_directories(${INCLUDE_DIRECTORIES} ${BASE_INCLUDE_DIRECTORIES}) +link_directories(${LINK_DIRECTORIES}) + +if(WIN32) + set(EXECUTABLE_TYPE WIN32) +endif(WIN32) +if(APPLE) + set(MACOSX_BUNDLE YES) + set(EXECUTABLE_TYPE MACOSX_BUNDLE) + set(CMAKE_INSTALL_PATH "@loader_path") +endif(APPLE) +if(LINUX) + set(EXECUTABLE_TYPE "") +endif(LINUX) + +set(SRCS ${SRCS} ${HEADERS} + ${PROJECT_ROOT_DIR}/include/stdwx.h + ${PROJECT_ROOT_DIR}/include/stdwx.cpp) + +set(PROJECT_FILES ${SRCS}) +add_executable(${EXECUTABLE_NAME} ${EXECUTABLE_TYPE} ${PROJECT_FILES}) + +set(EXE_DIR bin) +set(TARGET_LOCATION ${PROJECT_SOURCE_DIR}/${EXE_DIR}${LIB_SUFFIX}) +set_target_properties(${EXECUTABLE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TARGET_LOCATION}) +if(APPLE) + set(CMAKE_MACOSX_RPATH 1) + set(MACOSX_RPATH TRUE) + set_target_properties( + ${EXECUTABLE_NAME} PROPERTIES + INSTALL_RPATH "@loader_path/../Frameworks") +endif(APPLE) + +target_link_libraries(${EXECUTABLE_NAME} ${LIBS}) + +add_dependencies(${EXECUTABLE_NAME} wxModularCore) + +target_precompile_headers(${EXECUTABLE_NAME} PRIVATE ${PROJECT_ROOT_DIR}/include/stdwx.h) + +if(APPLE) + FOREACH(DEP_LIB ${DEMO_LIBS_SHARED}) + get_filename_component(ABS_ROOT_DIR ${PROJECT_ROOT_DIR} ABSOLUTE) + set(LIBNAME_FULL "${ABS_ROOT_DIR}/${DEP_LIB}/${OS_BASE_NAME}${LIB_SUFFIX}/$(CONFIGURATION)/lib${DEP_LIB}.dylib") + add_custom_command(TARGET ${EXECUTABLE_NAME} POST_BUILD + COMMAND install_name_tool -change "${LIBNAME_FULL}" "@executable_path/../Frameworks/lib${DEP_LIB}.dylib" $) + ENDFOREACH(DEP_LIB) +endif(APPLE) diff --git a/wxModularHost/MainFrame.cpp b/wxModularHost/MainFrame.cpp index 6c8d050..24ec667 100644 --- a/wxModularHost/MainFrame.cpp +++ b/wxModularHost/MainFrame.cpp @@ -1,195 +1,195 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: MainFrame.cpp -// Purpose: -// Author: Volodymyr (T-Rex) Triapichko -// Modified by: -// Created: 02/08/2013 21:20:05 -// RCS-ID: -// Copyright: Volodymyr (T-Rex) Triapichko, 2013 -// Licence: -///////////////////////////////////////////////////////////////////////////// - -// For compilers that support precompilation, includes "wx/wx.h". -#include "stdwx.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#ifndef WX_PRECOMP -#include "wx/wx.h" -#endif - -////@begin includes -#include "wx/imaglist.h" -////@end includes - -#include "MainFrame.h" -#include "wxModularHostApp.h" -#include "SampleModularCore.h" - -////@begin XPM images -////@end XPM images - - -/* - * MainFrame type definition - */ - -IMPLEMENT_CLASS( MainFrame, wxFrame ) - - -/* - * MainFrame event table definition - */ - -BEGIN_EVENT_TABLE( MainFrame, wxFrame ) - -////@begin MainFrame event table entries -////@end MainFrame event table entries - -END_EVENT_TABLE() - - -/* - * MainFrame constructors - */ - -MainFrame::MainFrame() -{ - Init(); -} - -MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style ) -{ - Init(); - Create( parent, id, caption, pos, size, style ); -} - - -/* - * MainFrame creator - */ - -bool MainFrame::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style ) -{ -////@begin MainFrame creation - wxFrame::Create( parent, id, caption, pos, size, style ); - - CreateControls(); - Centre(); -////@end MainFrame creation - return true; -} - - -/* - * MainFrame destructor - */ - -MainFrame::~MainFrame() -{ -////@begin MainFrame destruction - GetAuiManager().UnInit(); -////@end MainFrame destruction -} - - -/* - * Member initialisation - */ - -void MainFrame::Init() -{ -////@begin MainFrame member initialisation - m_Notebook = NULL; -////@end MainFrame member initialisation -} - - -/* - * Control creation for MainFrame - */ - -void MainFrame::CreateControls() -{ -////@begin MainFrame content construction - MainFrame* itemFrame1 = this; - - GetAuiManager().SetManagedWindow(this); - - wxMenuBar* menuBar = new wxMenuBar; - wxMenu* itemMenu4 = new wxMenu; - itemMenu4->Append(wxID_EXIT, _("Exit\tAlt+F4"), wxEmptyString, wxITEM_NORMAL); - menuBar->Append(itemMenu4, _("File")); - itemFrame1->SetMenuBar(menuBar); - - wxStatusBar* itemStatusBar2 = new wxStatusBar( itemFrame1, ID_STATUSBAR, wxST_SIZEGRIP|wxNO_BORDER ); - itemStatusBar2->SetFieldsCount(2); - itemFrame1->SetStatusBar(itemStatusBar2); - - m_Notebook = new wxAuiNotebook( itemFrame1, ID_AUINOTEBOOK, wxDefaultPosition, wxDefaultSize, wxAUI_NB_DEFAULT_STYLE|wxAUI_NB_TOP|wxNO_BORDER ); - - itemFrame1->GetAuiManager().AddPane(m_Notebook, wxAuiPaneInfo() - .Name(_T("Pane1")).Centre().CaptionVisible(false).CloseButton(false).DestroyOnClose(false).Resizable(true).Floatable(false)); - - GetAuiManager().Update(); - -////@end MainFrame content construction - AddPagesFromGuiPlugins(); - -} - - -/* - * Should we show tooltips? - */ - -bool MainFrame::ShowToolTips() -{ - return true; -} - -/* - * Get bitmap resources - */ - -wxBitmap MainFrame::GetBitmapResource( const wxString& name ) -{ - // Bitmap retrieval -////@begin MainFrame bitmap retrieval - wxUnusedVar(name); - return wxNullBitmap; -////@end MainFrame bitmap retrieval -} - -/* - * Get icon resources - */ - -wxIcon MainFrame::GetIconResource( const wxString& name ) -{ - // Icon retrieval -////@begin MainFrame icon retrieval - wxUnusedVar(name); - return wxNullIcon; -////@end MainFrame icon retrieval -} - -void MainFrame::AddPagesFromGuiPlugins() -{ - SampleModularCore * pluginManager = wxGetApp().GetPluginManager(); - for(wxGuiPluginBaseList::Node * node = pluginManager->GetGuiPlugins().GetFirst(); - node; node = node->GetNext()) - { - wxGuiPluginBase * plugin = node->GetData(); - if(plugin) - { - wxWindow * page = plugin->CreatePanel(m_Notebook); - if(page) - { - m_Notebook->AddPage(page, plugin->GetName()); - } - } - } -} +///////////////////////////////////////////////////////////////////////////// +// Name: MainFrame.cpp +// Purpose: +// Author: Volodymyr (T-Rex) Triapichko +// Modified by: +// Created: 02/08/2013 21:20:05 +// RCS-ID: +// Copyright: Volodymyr (T-Rex) Triapichko, 2013 +// Licence: +///////////////////////////////////////////////////////////////////////////// + +// For compilers that support precompilation, includes "wx/wx.h". +#include "stdwx.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#include "wx/wx.h" +#endif + +////@begin includes +#include "wx/imaglist.h" +////@end includes + +#include "MainFrame.h" +#include "wxModularHostApp.h" +#include "SampleModularCore.h" + +////@begin XPM images +////@end XPM images + + +/* + * MainFrame type definition + */ + +IMPLEMENT_CLASS( MainFrame, wxFrame ) + + +/* + * MainFrame event table definition + */ + +BEGIN_EVENT_TABLE( MainFrame, wxFrame ) + +////@begin MainFrame event table entries +////@end MainFrame event table entries + +END_EVENT_TABLE() + + +/* + * MainFrame constructors + */ + +MainFrame::MainFrame() +{ + Init(); +} + +MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style ) +{ + Init(); + Create( parent, id, caption, pos, size, style ); +} + + +/* + * MainFrame creator + */ + +bool MainFrame::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style ) +{ +////@begin MainFrame creation + wxFrame::Create( parent, id, caption, pos, size, style ); + + CreateControls(); + Centre(); +////@end MainFrame creation + return true; +} + + +/* + * MainFrame destructor + */ + +MainFrame::~MainFrame() +{ +////@begin MainFrame destruction + GetAuiManager().UnInit(); +////@end MainFrame destruction +} + + +/* + * Member initialisation + */ + +void MainFrame::Init() +{ +////@begin MainFrame member initialisation + m_Notebook = NULL; +////@end MainFrame member initialisation +} + + +/* + * Control creation for MainFrame + */ + +void MainFrame::CreateControls() +{ +////@begin MainFrame content construction + MainFrame* itemFrame1 = this; + + GetAuiManager().SetManagedWindow(this); + + wxMenuBar* menuBar = new wxMenuBar; + wxMenu* itemMenu4 = new wxMenu; + itemMenu4->Append(wxID_EXIT, _("Exit\tAlt+F4"), wxEmptyString, wxITEM_NORMAL); + menuBar->Append(itemMenu4, _("File")); + itemFrame1->SetMenuBar(menuBar); + + wxStatusBar* itemStatusBar2 = new wxStatusBar( itemFrame1, ID_STATUSBAR, wxST_SIZEGRIP|wxNO_BORDER ); + itemStatusBar2->SetFieldsCount(2); + itemFrame1->SetStatusBar(itemStatusBar2); + + m_Notebook = new wxAuiNotebook( itemFrame1, ID_AUINOTEBOOK, wxDefaultPosition, wxDefaultSize, wxAUI_NB_DEFAULT_STYLE|wxAUI_NB_TOP|wxNO_BORDER ); + + itemFrame1->GetAuiManager().AddPane(m_Notebook, wxAuiPaneInfo() + .Name(_T("Pane1")).Centre().CaptionVisible(false).CloseButton(false).DestroyOnClose(false).Resizable(true).Floatable(false)); + + GetAuiManager().Update(); + +////@end MainFrame content construction + AddPagesFromGuiPlugins(); + +} + + +/* + * Should we show tooltips? + */ + +bool MainFrame::ShowToolTips() +{ + return true; +} + +/* + * Get bitmap resources + */ + +wxBitmap MainFrame::GetBitmapResource( const wxString& name ) +{ + // Bitmap retrieval +////@begin MainFrame bitmap retrieval + wxUnusedVar(name); + return wxNullBitmap; +////@end MainFrame bitmap retrieval +} + +/* + * Get icon resources + */ + +wxIcon MainFrame::GetIconResource( const wxString& name ) +{ + // Icon retrieval +////@begin MainFrame icon retrieval + wxUnusedVar(name); + return wxNullIcon; +////@end MainFrame icon retrieval +} + +void MainFrame::AddPagesFromGuiPlugins() +{ + SampleModularCore * pluginManager = wxGetApp().GetPluginManager(); + for(wxGuiPluginBaseList::compatibility_iterator node = pluginManager->GetGuiPlugins().GetFirst(); + node; node = node->GetNext()) + { + wxGuiPluginBase* plugin = node->GetData(); + if (plugin) + { + wxWindow* page = plugin->CreatePanel(m_Notebook); + if (page) + { + m_Notebook->AddPage(page, plugin->GetName()); + } + } + } +} diff --git a/wxModularHost/MainFrame.h b/wxModularHost/MainFrame.h index 1c28b12..a3335d1 100644 --- a/wxModularHost/MainFrame.h +++ b/wxModularHost/MainFrame.h @@ -1,107 +1,107 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: MainFrame.h -// Purpose: -// Author: Volodymyr (T-Rex) Triapichko -// Modified by: -// Created: 02/08/2013 21:20:05 -// RCS-ID: -// Copyright: Volodymyr (T-Rex) Triapichko, 2013 -// Licence: -///////////////////////////////////////////////////////////////////////////// - -#ifndef _MAINFRAME_H_ -#define _MAINFRAME_H_ - - -/*! - * Includes - */ - -////@begin includes -#include "wx/aui/framemanager.h" -#include "wx/frame.h" -#include "wx/statusbr.h" -#include "wx/aui/auibook.h" -////@end includes - -/*! - * Forward declarations - */ - -////@begin forward declarations -class wxAuiNotebook; -////@end forward declarations - -/*! - * Control identifiers - */ - -////@begin control identifiers -#define SYMBOL_MAINFRAME_STYLE wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX -#define SYMBOL_MAINFRAME_TITLE _("MainFrame") -#define SYMBOL_MAINFRAME_IDNAME ID_MAINFRAME -#define SYMBOL_MAINFRAME_SIZE wxSize(600, 450) -#define SYMBOL_MAINFRAME_POSITION wxDefaultPosition -////@end control identifiers - - -/*! - * MainFrame class declaration - */ - -class MainFrame: public wxFrame -{ - DECLARE_CLASS( MainFrame ) - DECLARE_EVENT_TABLE() - -public: - /// Constructors - MainFrame(); - MainFrame( wxWindow* parent, wxWindowID id = SYMBOL_MAINFRAME_IDNAME, const wxString& caption = SYMBOL_MAINFRAME_TITLE, const wxPoint& pos = SYMBOL_MAINFRAME_POSITION, const wxSize& size = SYMBOL_MAINFRAME_SIZE, long style = SYMBOL_MAINFRAME_STYLE ); - - bool Create( wxWindow* parent, wxWindowID id = SYMBOL_MAINFRAME_IDNAME, const wxString& caption = SYMBOL_MAINFRAME_TITLE, const wxPoint& pos = SYMBOL_MAINFRAME_POSITION, const wxSize& size = SYMBOL_MAINFRAME_SIZE, long style = SYMBOL_MAINFRAME_STYLE ); - - /// Destructor - ~MainFrame(); - - /// Initialises member variables - void Init(); - - /// Creates the controls and sizers - void CreateControls(); - - void AddPagesFromGuiPlugins(); - -////@begin MainFrame event handler declarations - -////@end MainFrame event handler declarations - -////@begin MainFrame member function declarations - - /// Returns the AUI manager object - wxAuiManager& GetAuiManager() { return m_auiManager; } - - /// Retrieves bitmap resources - wxBitmap GetBitmapResource( const wxString& name ); - - /// Retrieves icon resources - wxIcon GetIconResource( const wxString& name ); -////@end MainFrame member function declarations - - /// Should we show tooltips? - static bool ShowToolTips(); - -////@begin MainFrame member variables - wxAuiManager m_auiManager; - wxAuiNotebook* m_Notebook; - /// Control identifiers - enum { - ID_MAINFRAME = 10000, - ID_STATUSBAR = 10001, - ID_AUINOTEBOOK = 10003 - }; -////@end MainFrame member variables -}; - -#endif - // _MAINFRAME_H_ +///////////////////////////////////////////////////////////////////////////// +// Name: MainFrame.h +// Purpose: +// Author: Volodymyr (T-Rex) Triapichko +// Modified by: +// Created: 02/08/2013 21:20:05 +// RCS-ID: +// Copyright: Volodymyr (T-Rex) Triapichko, 2013 +// Licence: +///////////////////////////////////////////////////////////////////////////// + +#ifndef _MAINFRAME_H_ +#define _MAINFRAME_H_ + + +/*! + * Includes + */ + +////@begin includes +#include "wx/aui/framemanager.h" +#include "wx/frame.h" +#include "wx/statusbr.h" +#include "wx/aui/auibook.h" +////@end includes + +/*! + * Forward declarations + */ + +////@begin forward declarations +class wxAuiNotebook; +////@end forward declarations + +/*! + * Control identifiers + */ + +////@begin control identifiers +#define SYMBOL_MAINFRAME_STYLE wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX +#define SYMBOL_MAINFRAME_TITLE _("MainFrame") +#define SYMBOL_MAINFRAME_IDNAME ID_MAINFRAME +#define SYMBOL_MAINFRAME_SIZE wxSize(600, 450) +#define SYMBOL_MAINFRAME_POSITION wxDefaultPosition +////@end control identifiers + + +/*! + * MainFrame class declaration + */ + +class MainFrame: public wxFrame +{ + DECLARE_CLASS( MainFrame ) + DECLARE_EVENT_TABLE() + +public: + /// Constructors + MainFrame(); + MainFrame( wxWindow* parent, wxWindowID id = SYMBOL_MAINFRAME_IDNAME, const wxString& caption = SYMBOL_MAINFRAME_TITLE, const wxPoint& pos = SYMBOL_MAINFRAME_POSITION, const wxSize& size = SYMBOL_MAINFRAME_SIZE, long style = SYMBOL_MAINFRAME_STYLE ); + + bool Create( wxWindow* parent, wxWindowID id = SYMBOL_MAINFRAME_IDNAME, const wxString& caption = SYMBOL_MAINFRAME_TITLE, const wxPoint& pos = SYMBOL_MAINFRAME_POSITION, const wxSize& size = SYMBOL_MAINFRAME_SIZE, long style = SYMBOL_MAINFRAME_STYLE ); + + /// Destructor + ~MainFrame(); + + /// Initialises member variables + void Init(); + + /// Creates the controls and sizers + void CreateControls(); + + void AddPagesFromGuiPlugins(); + +////@begin MainFrame event handler declarations + +////@end MainFrame event handler declarations + +////@begin MainFrame member function declarations + + /// Returns the AUI manager object + wxAuiManager& GetAuiManager() { return m_auiManager; } + + /// Retrieves bitmap resources + wxBitmap GetBitmapResource( const wxString& name ); + + /// Retrieves icon resources + wxIcon GetIconResource( const wxString& name ); +////@end MainFrame member function declarations + + /// Should we show tooltips? + static bool ShowToolTips(); + +////@begin MainFrame member variables + wxAuiManager m_auiManager; + wxAuiNotebook* m_Notebook; + /// Control identifiers + enum { + ID_MAINFRAME = 10000, + ID_STATUSBAR = 10001, + ID_AUINOTEBOOK = 10003 + }; +////@end MainFrame member variables +}; + +#endif + // _MAINFRAME_H_ diff --git a/wxModularHost/SampleModularCore.cpp b/wxModularHost/SampleModularCore.cpp index cbc8510..0e5d4d3 100644 --- a/wxModularHost/SampleModularCore.cpp +++ b/wxModularHost/SampleModularCore.cpp @@ -1,65 +1,65 @@ -#include "stdwx.h" -#include "SampleModularCore.h" -#include - -WX_DEFINE_LIST(wxNonGuiPluginBaseList); -WX_DEFINE_LIST(wxGuiPluginBaseList); - -SampleModularCore::~SampleModularCore() -{ - Clear(); -} - -bool SampleModularCore::LoadAllPlugins(bool forceProgramPath) -{ - wxString pluginsRootDir = GetPluginsPath(forceProgramPath); - bool result = true; - result &= LoadPlugins(pluginsRootDir, - m_NonGuiPlugins, - m_MapNonGuiPluginsDll, - wxT("nongui")); - result &= LoadPlugins(pluginsRootDir, - m_GuiPlugins, - m_MapGuiPluginsDll, - wxT("gui")); - // You can implement other logic which takes in account - // the result of LoadPlugins() calls - for(wxGuiPluginBaseList::Node * node = m_GuiPlugins.GetFirst(); - node; node = node->GetNext()) - { - wxGuiPluginBase * plugin = node->GetData(); - plugin->SetEventHandler(m_Handler); - } - return true; -} - -bool SampleModularCore::UnloadAllPlugins() -{ - return - UnloadPlugins(m_NonGuiPlugins, - m_MapNonGuiPluginsDll) && - UnloadPlugins(m_GuiPlugins, - m_MapGuiPluginsDll); -} - -const wxNonGuiPluginBaseList & SampleModularCore::GetNonGuiPlugins() const -{ - return m_NonGuiPlugins; -} - -const wxGuiPluginBaseList & SampleModularCore::GetGuiPlugins() const -{ - return m_GuiPlugins; +#include "stdwx.h" +#include "SampleModularCore.h" +#include + +WX_DEFINE_LIST(wxNonGuiPluginBaseList); +WX_DEFINE_LIST(wxGuiPluginBaseList); + +SampleModularCore::~SampleModularCore() +{ + Clear(); +} + +bool SampleModularCore::LoadAllPlugins(bool forceProgramPath) +{ + wxString pluginsRootDir = GetPluginsPath(forceProgramPath); + bool result = true; + result &= LoadPlugins(pluginsRootDir, + m_NonGuiPlugins, + m_MapNonGuiPluginsDll, + wxT("nongui")); + result &= LoadPlugins(pluginsRootDir, + m_GuiPlugins, + m_MapGuiPluginsDll, + wxT("gui")); + // You can implement other logic which takes in account + // the result of LoadPlugins() calls + for(wxGuiPluginBaseList::compatibility_iterator node = m_GuiPlugins.GetFirst(); + node; node = node->GetNext()) + { + wxGuiPluginBase * plugin = node->GetData(); + plugin->SetEventHandler(m_Handler); + } + return true; +} + +bool SampleModularCore::UnloadAllPlugins() +{ + return + UnloadPlugins(m_NonGuiPlugins, + m_MapNonGuiPluginsDll) && + UnloadPlugins(m_GuiPlugins, + m_MapGuiPluginsDll); +} + +const wxNonGuiPluginBaseList & SampleModularCore::GetNonGuiPlugins() const +{ + return m_NonGuiPlugins; +} + +const wxGuiPluginBaseList & SampleModularCore::GetGuiPlugins() const +{ + return m_GuiPlugins; } \ No newline at end of file diff --git a/wxModularHost/SampleModularCore.h b/wxModularHost/SampleModularCore.h index 2048b85..55c2609 100644 --- a/wxModularHost/SampleModularCore.h +++ b/wxModularHost/SampleModularCore.h @@ -1,32 +1,32 @@ -#pragma once - -#include -#include -#include - -// We need to know which DLL produced the specific plugin object. -WX_DECLARE_HASH_MAP(wxNonGuiPluginBase*, wxDynamicLibrary*, \ - wxPointerHash, wxPointerEqual, \ - wxNonGuiPluginToDllDictionary); -WX_DECLARE_HASH_MAP(wxGuiPluginBase*, wxDynamicLibrary*, \ - wxPointerHash, wxPointerEqual, \ - wxGuiPluginToDllDictionary); -// And separate list of loaded plugins for faster access. -WX_DECLARE_LIST(wxNonGuiPluginBase, wxNonGuiPluginBaseList); -WX_DECLARE_LIST(wxGuiPluginBase, wxGuiPluginBaseList); - -class SampleModularCore : public wxModularCore -{ -public: - virtual ~SampleModularCore(); - virtual bool LoadAllPlugins(bool forceProgramPath); - virtual bool UnloadAllPlugins(); - - const wxNonGuiPluginBaseList & GetNonGuiPlugins() const; - const wxGuiPluginBaseList & GetGuiPlugins() const; -private: - wxNonGuiPluginToDllDictionary m_MapNonGuiPluginsDll; - wxNonGuiPluginBaseList m_NonGuiPlugins; - wxGuiPluginToDllDictionary m_MapGuiPluginsDll; - wxGuiPluginBaseList m_GuiPlugins; +#pragma once + +#include +#include +#include + +// We need to know which DLL produced the specific plugin object. +WX_DECLARE_HASH_MAP(wxNonGuiPluginBase*, wxDynamicLibrary*, \ + wxPointerHash, wxPointerEqual, \ + wxNonGuiPluginToDllDictionary); +WX_DECLARE_HASH_MAP(wxGuiPluginBase*, wxDynamicLibrary*, \ + wxPointerHash, wxPointerEqual, \ + wxGuiPluginToDllDictionary); +// And separate list of loaded plugins for faster access. +WX_DECLARE_LIST(wxNonGuiPluginBase, wxNonGuiPluginBaseList); +WX_DECLARE_LIST(wxGuiPluginBase, wxGuiPluginBaseList); + +class SampleModularCore : public wxModularCore +{ +public: + virtual ~SampleModularCore(); + virtual bool LoadAllPlugins(bool forceProgramPath); + virtual bool UnloadAllPlugins(); + + const wxNonGuiPluginBaseList & GetNonGuiPlugins() const; + const wxGuiPluginBaseList & GetGuiPlugins() const; +private: + wxNonGuiPluginToDllDictionary m_MapNonGuiPluginsDll; + wxNonGuiPluginBaseList m_NonGuiPlugins; + wxGuiPluginToDllDictionary m_MapGuiPluginsDll; + wxGuiPluginBaseList m_GuiPlugins; }; \ No newline at end of file diff --git a/wxModularHost/Win/wxModularHost.vcxproj b/wxModularHost/Win/wxModularHost.vcxproj new file mode 100644 index 0000000..6bbaa1e --- /dev/null +++ b/wxModularHost/Win/wxModularHost.vcxproj @@ -0,0 +1,275 @@ + + + + x64 + + + + Debug + x64 + + + Release + x64 + + + + {B4520BB8-638C-30A5-B13E-9F8B09B91B37} + Win32Proj + 10.0.26100.0 + x64 + wxModularHost + NoUpgrade + + + + Application + Unicode + v143 + + + Application + Unicode + v143 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + wxModularHost.dir\Debug\ + wxModularHost + .exe + true + true + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + wxModularHost.dir\Release\ + wxModularHost + .exe + false + true + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxModularCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxNonGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /external:I "C:/Users/Admin/IFloor/libs/opencv/build/include" + $(IntDir) + EnableFastChecks + + + ProgramDatabase + 4996 + Sync + TurnOffAllWarnings + + + Disabled + stdcpp17 + + true + Disabled + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/wxModularHost.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/wxModularHost.dir/Debug//cmake_pch.pch + + MultiThreadedDebugDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;wxUSE_NO_MANIFEST=1;__STDC_CONSTANT_MACROS;CMAKE_INTDIR="Debug" + $(IntDir) + false + + + %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;wxUSE_NO_MANIFEST=1;__STDC_CONSTANT_MACROS;CMAKE_INTDIR=\"Debug\" + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxModularCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxNonGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxModularCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxNonGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + wxModularCore.lib;wxNonGuiPluginBase.lib;wxGuiPluginBase.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120d.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../wxNonGuiPluginBase/Win/$(ConfigurationName);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../wxNonGuiPluginBase/Win/$(ConfigurationName)/$(Configuration);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../wxGuiPluginBase/Win/$(ConfigurationName);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../wxGuiPluginBase/Win/$(ConfigurationName)/$(Configuration);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../wxModularCore/Win/$(ConfigurationName);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../wxModularCore/Win/$(ConfigurationName)/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + true + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Debug/wxModularHost.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/wxModularHost.pdb + + Windows + + + false + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxModularCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxNonGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;%(AdditionalIncludeDirectories) + %(AdditionalOptions) /external:I "C:/Users/Admin/IFloor/libs/opencv/build/include" + $(IntDir) + Default + + + 4996 + Sync + TurnOffAllWarnings + + + AnySuitable + stdcpp17 + + true + MaxSpeed + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/wxModularHost.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/wxModularHost.dir/Release//cmake_pch.pch + + MultiThreadedDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;wxUSE_NO_MANIFEST=1;__STDC_CONSTANT_MACROS;CMAKE_INTDIR="Release" + $(IntDir) + + + false + + + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;wxUSE_NO_MANIFEST=1;__STDC_CONSTANT_MACROS;CMAKE_INTDIR=\"Release\" + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxModularCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxNonGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxModularCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxNonGuiPluginBase;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\wxGuiPluginBase;C:\Users\Admin\IFloor\libs\opencv\build\include;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + wxModularCore.lib;wxNonGuiPluginBase.lib;wxGuiPluginBase.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\opencv_world4120.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../wxNonGuiPluginBase/Win/$(ConfigurationName);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../wxNonGuiPluginBase/Win/$(ConfigurationName)/$(Configuration);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../wxGuiPluginBase/Win/$(ConfigurationName);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../wxGuiPluginBase/Win/$(ConfigurationName)/$(Configuration);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../wxModularCore/Win/$(ConfigurationName);C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/../wxModularCore/Win/$(ConfigurationName)/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + false + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Release/wxModularHost.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/wxModularHost.pdb + + Windows + + + false + + + + + Always + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:\Users\Admin\IFloor\libs\opencv\build\OpenCVConfig-version.cmake;C:\Users\Admin\IFloor\libs\opencv\build\OpenCVConfig.cmake;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\OpenCVConfig.cmake;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\FindPackageHandleStandardArgs.cmake;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\FindPackageMessage.cmake;%(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\wxModularHost\Win\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + C:\Users\Admin\IFloor\libs\opencv\build\OpenCVConfig-version.cmake;C:\Users\Admin\IFloor\libs\opencv\build\OpenCVConfig.cmake;C:\Users\Admin\IFloor\libs\opencv\build\x64\vc16\lib\OpenCVConfig.cmake;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\FindPackageHandleStandardArgs.cmake;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\FindPackageMessage.cmake;%(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\wxModularHost\Win\CMakeFiles\generate.stamp + false + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/wxModularHost.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/wxModularHost.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/wxModularHost.dir/Debug//cmake_pch.pch + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/wxModularHost.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/wxModularHost.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/wxModularHost.dir/Release//cmake_pch.pch + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/wxModularHost.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/wxModularHost.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/wxModularHost.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/wxModularHost.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/wxModularHost.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/wxModularHost.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + NotUsing + NotUsing + + + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/wxModularHost.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxModularHost/Win/CMakeFiles/wxModularHost.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + ZERO_CHECK + false + Never + + + {751A15C0-76C2-3506-AB9D-0CD3545003FA} + CommonPluginBase + + + {14D82890-BB7F-3748-8713-43304E91CFA1} + Utils + + + {746FA12D-51CE-3AA5-90F0-43DD3C32BDA9} + wxModularCore + + + + + + \ No newline at end of file diff --git a/wxModularHost/Win/wxModularHost.vcxproj.filters b/wxModularHost/Win/wxModularHost.vcxproj.filters new file mode 100644 index 0000000..d993b28 --- /dev/null +++ b/wxModularHost/Win/wxModularHost.vcxproj.filters @@ -0,0 +1,59 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Precompile Header File + + + Precompile Header File + + + + + + + + Source Files + + + + + {4951AEE1-75F2-3C38-B593-C6BC8C809FB0} + + + {112D4227-BB51-3360-BB5B-5EA5DBA5A65F} + + + {05450AB2-CB7B-34EA-83DF-1EE86424EDF0} + + + diff --git a/wxModularHost/wxModularHost.pjd b/wxModularHost/wxModularHost.pjd index 8637447..e27afad 100644 --- a/wxModularHost/wxModularHost.pjd +++ b/wxModularHost/wxModularHost.pjd @@ -1,587 +1,587 @@ - - -
- 0 - "" - "" - "" - "" - "" - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - "Volodymyr (T-Rex) Triapichko" - "Volodymyr (T-Rex) Triapichko, 2013" - "" - 0 - 1 - 0 - 0 - "<All platforms>" - "2.9.5" - "Standard" - "///////////////////////////////////////////////////////////////////////////// -// Name: %HEADER-FILENAME% -// Purpose: -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "///////////////////////////////////////////////////////////////////////////// -// Name: %SOURCE-FILENAME% -// Purpose: -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "///////////////////////////////////////////////////////////////////////////// -// Name: %SYMBOLS-FILENAME% -// Purpose: Symbols file -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "" - "// For compilers that support precompilation, includes "wx/wx.h". -#include "wx/wxprec.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#ifndef WX_PRECOMP -#include "wx/wx.h" -#endif - -" - " /// %BODY% -" - " -/* - * %BODY% - */ - -" - "app_resources.h" - "app_resources.cpp" - "AppResources" - "app.h" - "app.cpp" - "Application" - 0 - "" - "<None>" - "iso-8859-1" - "utf-8" - "utf-8" - "" - 0 - 0 - 4 - " " - "" - 0 - 0 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 -
- - - "" - "data-document" - "" - "" - 0 - 1 - 0 - 0 - - "Configurations" - "config-data-document" - "" - "" - 0 - 1 - 0 - 0 - "" - 1 - -8519680 - "" - "Debug" - "Unicode" - "Static" - "Modular" - "GUI" - "wxMSW" - "Default" - "Dynamic" - "Yes" - "No" - "Yes" - "No" - "No" - "Yes" - "Yes" - "Yes" - "Yes" - "Yes" - "builtin" - "Yes" - "%EXECUTABLE%" - "" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%WXVERSION%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - 0 - 1 - - - - - - - "Projects" - "root-document" - "" - "project" - 1 - 1 - 0 - 1 - - "Windows" - "html-document" - "" - "dialogsfolder" - 1 - 1 - 0 - 1 - - "wxModularHostApp" - "dialog-document" - "" - "app" - 0 - 1 - 0 - 0 - "wbAppProxy" - 10000 - 0 - "" - 0 - "" - "Standard" - 0 - 0 - "m_PluginManager|SampleModularCore *|PluginManager|new SampleModularCore|0|0|" - "wxModularHostApp" - "wxApp" - "wxModularHostApp.cpp" - "wxModularHostApp.h" - "" - "ID_MAINFRAME" - "" - - - "MainFrame" - "dialog-document" - "" - "frame" - 0 - 1 - 0 - 0 - "wbFrameProxy" - 10000 - 0 - "" - 0 - "" - "Standard" - 0 - 0 - "ID_MAINFRAME" - 10000 - "MainFrame" - "wxFrame" - "MainFrame.cpp" - "MainFrame.h" - "" - "MainFrame" - 1 - "" - 0 - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - "" - "" - "" - "" - "" - 0 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - "" - 0 - 0 - -1 - -1 - 600 - 450 - 1 - "" - - "wxStatusBar: ID_STATUSBAR" - "dialog-control-document" - "" - "statusbar" - 0 - 1 - 0 - 0 - "wbStatusBarProxy" - "ID_STATUSBAR" - 10001 - "" - "wxStatusBar" - "wxStatusBar" - 1 - 0 - "" - "" - "" - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - 2 - "" - "" - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - "" - -1 - -1 - -1 - -1 - "Centre" - "Centre" - 0 - 5 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - "" - "" - "" - - - "wxMenuBar: ID_MENUBAR" - "dialog-control-document" - "" - "menubar" - 0 - 1 - 0 - 0 - "wbMenuBarProxy" - "ID_MENUBAR" - "<Any platform>" - 10002 - - "File" - "dialog-control-document" - "" - "menu" - 0 - 1 - 0 - 0 - "wbMenuProxy" - "File" - 1 - "" - "<Any platform>" - - "Exit\tAlt+F4: wxID_EXIT" - "dialog-control-document" - "" - "menuitem" - 0 - 1 - 0 - 0 - "wbMenuItemProxy" - "wxID_EXIT" - 5006 - "Exit\tAlt+F4" - "Normal" - 0 - 1 - "" - "" - "" - "<Any platform>" - - - - - "wxAuiNotebook: ID_AUINOTEBOOK" - "dialog-control-document" - "" - "notebook" - 0 - 1 - 0 - 0 - "wbAuiNotebookProxy" - "ID_AUINOTEBOOK" - 10003 - "" - "wxAuiNotebook" - "wxAuiNotebook" - 1 - 0 - "" - "" - "m_Notebook" - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - "" - "" - "" - "" - "" - "" - "" - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - "" - -1 - -1 - -1 - -1 - "Centre" - "Centre" - 0 - 5 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - "" - "" - 1 - "Pane1" - "" - 0 - "Centre" - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - - - - - "Sources" - "html-document" - "" - "sourcesfolder" - 1 - 1 - 0 - 1 - - "wxModularHost.rc" - "source-editor-document" - "wxModularHost.rc" - "source-editor" - 0 - 0 - 1 - 0 - "2/8/2013" - "" - - - - "Images" - "html-document" - "" - "bitmapsfolder" - 1 - 1 - 0 - 1 - - - - -
+ + +
+ 0 + "" + "" + "" + "" + "" + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + "Volodymyr (T-Rex) Triapichko" + "Volodymyr (T-Rex) Triapichko, 2013" + "" + 0 + 1 + 0 + 0 + "<All platforms>" + "2.9.5" + "Standard" + "///////////////////////////////////////////////////////////////////////////// +// Name: %HEADER-FILENAME% +// Purpose: +// Author: %AUTHOR% +// Modified by: +// Created: %DATE% +// RCS-ID: +// Copyright: %COPYRIGHT% +// Licence: +///////////////////////////////////////////////////////////////////////////// + +" + "///////////////////////////////////////////////////////////////////////////// +// Name: %SOURCE-FILENAME% +// Purpose: +// Author: %AUTHOR% +// Modified by: +// Created: %DATE% +// RCS-ID: +// Copyright: %COPYRIGHT% +// Licence: +///////////////////////////////////////////////////////////////////////////// + +" + "///////////////////////////////////////////////////////////////////////////// +// Name: %SYMBOLS-FILENAME% +// Purpose: Symbols file +// Author: %AUTHOR% +// Modified by: +// Created: %DATE% +// RCS-ID: +// Copyright: %COPYRIGHT% +// Licence: +///////////////////////////////////////////////////////////////////////////// + +" + "" + "// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#include "wx/wx.h" +#endif + +" + " /// %BODY% +" + " +/* + * %BODY% + */ + +" + "app_resources.h" + "app_resources.cpp" + "AppResources" + "app.h" + "app.cpp" + "Application" + 0 + "" + "<None>" + "iso-8859-1" + "utf-8" + "utf-8" + "" + 0 + 0 + 4 + " " + "" + 0 + 0 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 +
+ + + "" + "data-document" + "" + "" + 0 + 1 + 0 + 0 + + "Configurations" + "config-data-document" + "" + "" + 0 + 1 + 0 + 0 + "" + 1 + -8519680 + "" + "Debug" + "Unicode" + "Static" + "Modular" + "GUI" + "wxMSW" + "Default" + "Dynamic" + "Yes" + "No" + "Yes" + "No" + "No" + "Yes" + "Yes" + "Yes" + "Yes" + "Yes" + "builtin" + "Yes" + "%EXECUTABLE%" + "" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%WXVERSION%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + "%AUTO%" + 0 + 1 + + + + + + + "Projects" + "root-document" + "" + "project" + 1 + 1 + 0 + 1 + + "Windows" + "html-document" + "" + "dialogsfolder" + 1 + 1 + 0 + 1 + + "wxModularHostApp" + "dialog-document" + "" + "app" + 0 + 1 + 0 + 0 + "wbAppProxy" + 10000 + 0 + "" + 0 + "" + "Standard" + 0 + 0 + "m_PluginManager|SampleModularCore *|PluginManager|new SampleModularCore|0|0|" + "wxModularHostApp" + "wxApp" + "wxModularHostApp.cpp" + "wxModularHostApp.h" + "" + "ID_MAINFRAME" + "" + + + "MainFrame" + "dialog-document" + "" + "frame" + 0 + 1 + 0 + 0 + "wbFrameProxy" + 10000 + 0 + "" + 0 + "" + "Standard" + 0 + 0 + "ID_MAINFRAME" + 10000 + "MainFrame" + "wxFrame" + "MainFrame.cpp" + "MainFrame.h" + "" + "MainFrame" + 1 + "" + 0 + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + 0 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + 0 + 0 + -1 + -1 + 600 + 450 + 1 + "" + + "wxStatusBar: ID_STATUSBAR" + "dialog-control-document" + "" + "statusbar" + 0 + 1 + 0 + 0 + "wbStatusBarProxy" + "ID_STATUSBAR" + 10001 + "" + "wxStatusBar" + "wxStatusBar" + 1 + 0 + "" + "" + "" + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + 2 + "" + "" + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + "" + "" + "" + + + "wxMenuBar: ID_MENUBAR" + "dialog-control-document" + "" + "menubar" + 0 + 1 + 0 + 0 + "wbMenuBarProxy" + "ID_MENUBAR" + "<Any platform>" + 10002 + + "File" + "dialog-control-document" + "" + "menu" + 0 + 1 + 0 + 0 + "wbMenuProxy" + "File" + 1 + "" + "<Any platform>" + + "Exit\tAlt+F4: wxID_EXIT" + "dialog-control-document" + "" + "menuitem" + 0 + 1 + 0 + 0 + "wbMenuItemProxy" + "wxID_EXIT" + 5006 + "Exit\tAlt+F4" + "Normal" + 0 + 1 + "" + "" + "" + "<Any platform>" + + + + + "wxAuiNotebook: ID_AUINOTEBOOK" + "dialog-control-document" + "" + "notebook" + 0 + 1 + 0 + 0 + "wbAuiNotebookProxy" + "ID_AUINOTEBOOK" + 10003 + "" + "wxAuiNotebook" + "wxAuiNotebook" + 1 + 0 + "" + "" + "m_Notebook" + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + "" + "" + 1 + "Pane1" + "" + 0 + "Centre" + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + "Sources" + "html-document" + "" + "sourcesfolder" + 1 + 1 + 0 + 1 + + "wxModularHost.rc" + "source-editor-document" + "wxModularHost.rc" + "source-editor" + 0 + 0 + 1 + 0 + "2/8/2013" + "" + + + + "Images" + "html-document" + "" + "bitmapsfolder" + 1 + 1 + 0 + 1 + + + + +
diff --git a/wxModularHost/wxModularHost.rc b/wxModularHost/wxModularHost.rc old mode 100755 new mode 100644 index f63e693..b86c4e2 --- a/wxModularHost/wxModularHost.rc +++ b/wxModularHost/wxModularHost.rc @@ -1 +1 @@ -#include "wx/msw/wx.rc" +#include "wx/msw/wx.rc" diff --git a/wxModularHost/wxModularHostApp.cpp b/wxModularHost/wxModularHostApp.cpp index 3c6d9cf..fd648a9 100644 --- a/wxModularHost/wxModularHostApp.cpp +++ b/wxModularHost/wxModularHostApp.cpp @@ -1,138 +1,138 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: wxModularHostApp.cpp -// Purpose: -// Author: Volodymyr (T-Rex) Triapichko -// Modified by: -// Created: 02/08/2013 21:14:33 -// RCS-ID: -// Copyright: Volodymyr (T-Rex) Triapichko, 2013 -// Licence: -///////////////////////////////////////////////////////////////////////////// - -// For compilers that support precompilation, includes "wx/wx.h". -#include "stdwx.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#ifndef WX_PRECOMP -#include "wx/wx.h" -#endif - -////@begin includes -////@end includes - -#include "wxModularHostApp.h" -#include "SampleModularCore.h" - -////@begin XPM images -////@end XPM images - - -/* - * Application instance implementation - */ - -////@begin implement app -IMPLEMENT_APP( wxModularHostApp ) -////@end implement app - - -/* - * wxModularHostApp type definition - */ - -IMPLEMENT_CLASS( wxModularHostApp, wxApp ) - - -/* - * wxModularHostApp event table definition - */ - -BEGIN_EVENT_TABLE( wxModularHostApp, wxApp ) - -////@begin wxModularHostApp event table entries -////@end wxModularHostApp event table entries - -END_EVENT_TABLE() - - -/* - * Constructor for wxModularHostApp - */ - -wxModularHostApp::wxModularHostApp() -{ - Init(); -} - - -/* - * Member initialisation - */ - -void wxModularHostApp::Init() -{ -////@begin wxModularHostApp member initialisation - m_PluginManager = new SampleModularCore; -////@end wxModularHostApp member initialisation -} - -/* - * Initialisation for wxModularHostApp - */ - -bool wxModularHostApp::OnInit() -{ -#if wxUSE_XPM - wxImage::AddHandler(new wxXPMHandler); -#endif -#if wxUSE_LIBPNG - wxImage::AddHandler(new wxPNGHandler); -#endif -#if wxUSE_LIBJPEG - wxImage::AddHandler(new wxJPEGHandler); -#endif -#if wxUSE_GIF - wxImage::AddHandler(new wxGIFHandler); -#endif - TestNonGuiPlugins(); - - MainFrame* mainWindow = new MainFrame( NULL ); - mainWindow->Show(true); - - return true; -} - - -/* - * Cleanup for wxModularHostApp - */ - -int wxModularHostApp::OnExit() -{ - wxDELETE(m_PluginManager); -////@begin wxModularHostApp cleanup - return wxApp::OnExit(); -////@end wxModularHostApp cleanup -} - -void wxModularHostApp::TestNonGuiPlugins() -{ - if(m_PluginManager) - { - if(m_PluginManager->LoadAllPlugins(true)) - { - for(wxNonGuiPluginBaseList::Node * node = - m_PluginManager->GetNonGuiPlugins().GetFirst(); node; node = node->GetNext()) - { - wxNonGuiPluginBase * plugin = node->GetData(); - if(plugin) - { - wxLogDebug(wxT("Non-GUI plugin returns %i"), plugin->Work()); - } - } - } - } -} +///////////////////////////////////////////////////////////////////////////// +// Name: wxModularHostApp.cpp +// Purpose: +// Author: Volodymyr (T-Rex) Triapichko +// Modified by: +// Created: 02/08/2013 21:14:33 +// RCS-ID: +// Copyright: Volodymyr (T-Rex) Triapichko, 2013 +// Licence: +///////////////////////////////////////////////////////////////////////////// + +// For compilers that support precompilation, includes "wx/wx.h". +#include "stdwx.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#include "wx/wx.h" +#endif + +////@begin includes +////@end includes + +#include "wxModularHostApp.h" +#include "SampleModularCore.h" + +////@begin XPM images +////@end XPM images + + +/* + * Application instance implementation + */ + +////@begin implement app +IMPLEMENT_APP( wxModularHostApp ) +////@end implement app + + +/* + * wxModularHostApp type definition + */ + +IMPLEMENT_CLASS( wxModularHostApp, wxApp ) + + +/* + * wxModularHostApp event table definition + */ + +BEGIN_EVENT_TABLE( wxModularHostApp, wxApp ) + +////@begin wxModularHostApp event table entries +////@end wxModularHostApp event table entries + +END_EVENT_TABLE() + + +/* + * Constructor for wxModularHostApp + */ + +wxModularHostApp::wxModularHostApp() +{ + Init(); +} + + +/* + * Member initialisation + */ + +void wxModularHostApp::Init() +{ +////@begin wxModularHostApp member initialisation + m_PluginManager = new SampleModularCore; +////@end wxModularHostApp member initialisation +} + +/* + * Initialisation for wxModularHostApp + */ + +bool wxModularHostApp::OnInit() +{ +#if wxUSE_XPM + wxImage::AddHandler(new wxXPMHandler); +#endif +#if wxUSE_LIBPNG + wxImage::AddHandler(new wxPNGHandler); +#endif +#if wxUSE_LIBJPEG + wxImage::AddHandler(new wxJPEGHandler); +#endif +#if wxUSE_GIF + wxImage::AddHandler(new wxGIFHandler); +#endif + TestNonGuiPlugins(); + + MainFrame* mainWindow = new MainFrame( NULL ); + mainWindow->Show(true); + + return true; +} + + +/* + * Cleanup for wxModularHostApp + */ + +int wxModularHostApp::OnExit() +{ + wxDELETE(m_PluginManager); +////@begin wxModularHostApp cleanup + return wxApp::OnExit(); +////@end wxModularHostApp cleanup +} + +void wxModularHostApp::TestNonGuiPlugins() +{ + if(m_PluginManager) + { + if(m_PluginManager->LoadAllPlugins(true)) + { + for(wxNonGuiPluginBaseList::compatibility_iterator node = + m_PluginManager->GetNonGuiPlugins().GetFirst(); node; node = node->GetNext()) + { + wxNonGuiPluginBase * plugin = node->GetData(); + if(plugin) + { + wxLogDebug(wxT("Non-GUI plugin returns %i"), plugin->Work()); + } + } + } + } +} diff --git a/wxModularHost/wxModularHostApp.h b/wxModularHost/wxModularHostApp.h index ac05af6..1f02682 100644 --- a/wxModularHost/wxModularHostApp.h +++ b/wxModularHost/wxModularHostApp.h @@ -1,88 +1,88 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: wxModularHostApp.h -// Purpose: -// Author: Volodymyr (T-Rex) Triapichko -// Modified by: -// Created: 02/08/2013 21:14:33 -// RCS-ID: -// Copyright: Volodymyr (T-Rex) Triapichko, 2013 -// Licence: -///////////////////////////////////////////////////////////////////////////// - -#ifndef _WXMODULARHOSTAPP_H_ -#define _WXMODULARHOSTAPP_H_ - - -/*! - * Includes - */ - -////@begin includes -#include "wx/image.h" -#include "MainFrame.h" -////@end includes - -/*! - * Forward declarations - */ - -////@begin forward declarations -////@end forward declarations -class SampleModularCore; - -/*! - * Control identifiers - */ - -////@begin control identifiers -////@end control identifiers - -/*! - * wxModularHostApp class declaration - */ - -class wxModularHostApp: public wxApp -{ - DECLARE_CLASS( wxModularHostApp ) - DECLARE_EVENT_TABLE() - -public: - /// Constructor - wxModularHostApp(); - - void Init(); - - /// Initialises the application - virtual bool OnInit(); - - void TestNonGuiPlugins(); - - /// Called on exit - virtual int OnExit(); - -////@begin wxModularHostApp event handler declarations - -////@end wxModularHostApp event handler declarations - -////@begin wxModularHostApp member function declarations - - SampleModularCore * GetPluginManager() const { return m_PluginManager ; } - void SetPluginManager(SampleModularCore * value) { m_PluginManager = value ; } - -////@end wxModularHostApp member function declarations - -////@begin wxModularHostApp member variables - SampleModularCore * m_PluginManager; -////@end wxModularHostApp member variables -}; - -/*! - * Application instance declaration - */ - -////@begin declare app -DECLARE_APP(wxModularHostApp) -////@end declare app - -#endif - // _WXMODULARHOSTAPP_H_ +///////////////////////////////////////////////////////////////////////////// +// Name: wxModularHostApp.h +// Purpose: +// Author: Volodymyr (T-Rex) Triapichko +// Modified by: +// Created: 02/08/2013 21:14:33 +// RCS-ID: +// Copyright: Volodymyr (T-Rex) Triapichko, 2013 +// Licence: +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WXMODULARHOSTAPP_H_ +#define _WXMODULARHOSTAPP_H_ + + +/*! + * Includes + */ + +////@begin includes +#include "wx/image.h" +#include "MainFrame.h" +////@end includes + +/*! + * Forward declarations + */ + +////@begin forward declarations +////@end forward declarations +class SampleModularCore; + +/*! + * Control identifiers + */ + +////@begin control identifiers +////@end control identifiers + +/*! + * wxModularHostApp class declaration + */ + +class wxModularHostApp: public wxApp +{ + DECLARE_CLASS( wxModularHostApp ) + DECLARE_EVENT_TABLE() + +public: + /// Constructor + wxModularHostApp(); + + void Init(); + + /// Initialises the application + virtual bool OnInit(); + + void TestNonGuiPlugins(); + + /// Called on exit + virtual int OnExit(); + +////@begin wxModularHostApp event handler declarations + +////@end wxModularHostApp event handler declarations + +////@begin wxModularHostApp member function declarations + + SampleModularCore * GetPluginManager() const { return m_PluginManager ; } + void SetPluginManager(SampleModularCore * value) { m_PluginManager = value ; } + +////@end wxModularHostApp member function declarations + +////@begin wxModularHostApp member variables + SampleModularCore * m_PluginManager; +////@end wxModularHostApp member variables +}; + +/*! + * Application instance declaration + */ + +////@begin declare app +DECLARE_APP(wxModularHostApp) +////@end declare app + +#endif + // _WXMODULARHOSTAPP_H_ diff --git a/wxNonGuiPluginBase/CMakeLists.txt b/wxNonGuiPluginBase/CMakeLists.txt index 4bffebc..a917c4a 100644 --- a/wxNonGuiPluginBase/CMakeLists.txt +++ b/wxNonGuiPluginBase/CMakeLists.txt @@ -1,61 +1,27 @@ -set (SRCS - wxNonGuiPluginBase.cpp) -set (HEADERS - Declarations.h - wxNonGuiPluginBase.h) - -set(LIBRARY_NAME wxNonGuiPluginBase) - -if(WIN32) - # Only for Windows: - # we add additional preprocessor definitons - set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS}; - /D_USRDLL;/DDEMO_PLUGIN_EXPORTS;/D__STDC_CONSTANT_MACROS) -endif(WIN32) - -# Add 2 files for precompiled headers -set(SRCS ${SRCS} ${HEADERS} - ${PROJECT_ROOT_DIR}/include/stdwx.h - ${PROJECT_ROOT_DIR}/include/stdwx.cpp) - -# Set preprocessor definitions -add_definitions(${PREPROCESSOR_DEFINITIONS}) -# Set include directories -include_directories(${INCLUDE_DIRECTORIES} ${BASE_INCLUDE_DIRECTORIES}) -# Set library search paths -link_directories(${LINK_DIRECTORIES}) -# Setup the project name and assign the source files for this project -add_library(${LIBRARY_NAME} SHARED ${SRCS}) - -#Setup the output folder -set(DLL_DIR bin) -set(TARGET_LOCATION ${PROJECT_SOURCE_DIR}/${DLL_DIR}${LIB_SUFFIX}) -if(APPLE) - set(TARGET_LOCATION - ${TARGET_LOCATION}/$(CONFIGURATION)/${PROJECT_NAME}.app/Contents/Frameworks) - set(CMAKE_INSTALL_PATH "@loader_path/../Frameworks") -endif(APPLE) -if(LINUX OR APPLE) - get_target_property(RESULT_FULL_PATH ${LIBRARY_NAME} LOCATION) - get_filename_component(RESULT_FILE_NAME ${RESULT_FULL_PATH} NAME) -endif(LINUX OR APPLE) -set_target_properties(${LIBRARY_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TARGET_LOCATION}) - -# Set additional dependencies -target_link_libraries(${LIBRARY_NAME} ${wxWidgets_LIBRARIES}) - -# Setup precompiled headers -target_precompile_headers(${LIBRARY_NAME} PRIVATE ${PROJECT_ROOT_DIR}/include/stdwx.h ${PROJECT_ROOT_DIR}/include/stdwx.cpp) - -if(APPLE) - get_filename_component(ABSOLUTE_PATH "${RESULT_FULL_PATH}" ABSOLUTE) - add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD - COMMAND install_name_tool -change "${ABSOLUTE_PATH}" "@loader_path/../Frameworks/${RESULT_FILE_NAME}" $ - ) -endif(APPLE) - -if(LINUX OR APPLE) - add_custom_command(TARGET ${LIBRARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy $ ${TARGET_LOCATION}/${RESULT_FILE_NAME} - ) -endif(LINUX OR APPLE) +set(SRCS + wxNonGuiPluginBase.cpp +) +set(HEADERS + Declarations.h + wxNonGuiPluginBase.h +) + +set(LIBRARY_NAME wxNonGuiPluginBase) + +if(WIN32) + set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS}; + /D_USRDLL;/DDEMO_PLUGIN_EXPORTS;/D__STDC_CONSTANT_MACROS) +endif(WIN32) + +set(SRCS ${SRCS} ${HEADERS} + ${PROJECT_ROOT_DIR}/include/stdwx.h + ${PROJECT_ROOT_DIR}/include/stdwx.cpp) + +add_definitions(${PREPROCESSOR_DEFINITIONS}) +include_directories(${INCLUDE_DIRECTORIES} ${BASE_INCLUDE_DIRECTORIES}) + +add_library(${LIBRARY_NAME} SHARED ${SRCS}) + +target_link_libraries(${LIBRARY_NAME} ${wxWidgets_LIBRARIES}) + +target_precompile_headers(${LIBRARY_NAME} PRIVATE ${PROJECT_ROOT_DIR}/include/stdwx.h) \ No newline at end of file diff --git a/wxNonGuiPluginBase/Declarations.h b/wxNonGuiPluginBase/Declarations.h index 13dd0d3..fd08279 100644 --- a/wxNonGuiPluginBase/Declarations.h +++ b/wxNonGuiPluginBase/Declarations.h @@ -1,14 +1,14 @@ -#ifndef _DECLARATIONS_H -#define _DECLARATIONS_H - -#if defined(__WXMSW__) -#ifdef DEMO_PLUGIN_EXPORTS -#define DEMO_API __declspec(dllexport) -#else -#define DEMO_API __declspec(dllimport) -#endif -#else -#define DEMO_API -#endif - -#endif // _DECLARATIONS_H +#ifndef _DECLARATIONS_H +#define _DECLARATIONS_H + +#if defined(__WXMSW__) +#ifdef DEMO_PLUGIN_EXPORTS +#define DEMO_API __declspec(dllexport) +#else +#define DEMO_API __declspec(dllimport) +#endif +#else +#define DEMO_API +#endif + +#endif // _DECLARATIONS_H diff --git a/wxNonGuiPluginBase/Win/wxNonGuiPluginBase.vcxproj b/wxNonGuiPluginBase/Win/wxNonGuiPluginBase.vcxproj new file mode 100644 index 0000000..32c4a2a --- /dev/null +++ b/wxNonGuiPluginBase/Win/wxNonGuiPluginBase.vcxproj @@ -0,0 +1,247 @@ + + + + x64 + + + + Debug + x64 + + + Release + x64 + + + + {0DC8318A-07F9-3AB6-8E65-2642EE273101} + Win32Proj + 10.0.26100.0 + x64 + wxNonGuiPluginBase + NoUpgrade + + + + DynamicLibrary + Unicode + v143 + + + DynamicLibrary + Unicode + v143 + + + + + + + + + + <_ProjectFileVersion>10.0.20506.1 + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + wxNonGuiPluginBase.dir\Debug\ + wxNonGuiPluginBase + .dll + true + true + C:\Users\Admin\IFloor\projects\wxVideoProcessing\bin\ + wxNonGuiPluginBase.dir\Release\ + wxNonGuiPluginBase + .dll + false + true + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + $(IntDir) + EnableFastChecks + + + ProgramDatabase + 4996 + Sync + + + Disabled + stdcpp17 + + true + Disabled + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/CMakeFiles/wxNonGuiPluginBase.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/wxNonGuiPluginBase.dir/Debug//cmake_pch.pch + + MultiThreadedDebugDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;DEMO_PLUGIN_EXPORTS;__STDC_CONSTANT_MACROS;CMAKE_INTDIR="Debug";wxNonGuiPluginBase_EXPORTS + $(IntDir) + false + + + %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;__WXDEBUG__=1;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;DEMO_PLUGIN_EXPORTS;__STDC_CONSTANT_MACROS;CMAKE_INTDIR=\"Debug\";wxNonGuiPluginBase_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33ud_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33ud_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpngd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiffd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpegd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlibd.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexud.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpatd.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + true + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Debug/wxNonGuiPluginBase.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/wxNonGuiPluginBase.pdb + + Console + + + false + + + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + $(IntDir) + Default + + + 4996 + Sync + + + AnySuitable + stdcpp17 + + true + MaxSpeed + Use + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/CMakeFiles/wxNonGuiPluginBase.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/wxNonGuiPluginBase.dir/Release//cmake_pch.pch + + MultiThreadedDLL + true + + + false + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;DEMO_PLUGIN_EXPORTS;__STDC_CONSTANT_MACROS;CMAKE_INTDIR="Release";wxNonGuiPluginBase_EXPORTS + $(IntDir) + + + false + + + %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;WIN32_LEAN_AND_MEAN;WXUSINGDLL;UNICODE;_UNICODE;_CRT_SECURE_NO_DEPRECATE;_USRDLL;DEMO_PLUGIN_EXPORTS;__STDC_CONSTANT_MACROS;CMAKE_INTDIR=\"Release\";wxNonGuiPluginBase_EXPORTS + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\mswu;C:\Users\Admin\IFloor\libs\wxWidgets\include;C:\Users\Admin\IFloor\libs\opencv\build\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\Utils;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\MotionDetectorCore;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxJSON\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer\include;C:\Users\Admin\IFloor\projects\wxVideoProcessing\build\..\ThirdParty\wxxmlserializer;%(AdditionalIncludeDirectories) + $(ProjectDir)/$(IntDir) + %(Filename).h + %(Filename).tlb + %(Filename)_i.c + %(Filename)_p.c + + + C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_core.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_adv.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_aui.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_net.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_gl.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxbase33u_xml.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_propgrid.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxmsw33u_html.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxpng.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxtiff.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxjpeg.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxzlib.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxregexu.lib;C:\Users\Admin\IFloor\libs\wxWidgets\lib\vc_x64_dll\wxexpat.lib;opengl32.lib;glu32.lib;winmm.lib;comctl32.lib;uuid.lib;oleacc.lib;uxtheme.lib;rpcrt4.lib;shlwapi.lib;version.lib;wsock32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib + C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib;C:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win/lib/$(Configuration);%(AdditionalLibraryDirectories) + %(AdditionalOptions) /machine:x64 + + false + %(IgnoreSpecificDefaultLibraries) + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/lib/Release/wxNonGuiPluginBase.lib + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/bin/wxNonGuiPluginBase.pdb + + Console + + + false + + + + + Always + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\wxNonGuiPluginBase\Win\CMakeFiles\generate.stamp + false + Building Custom Rule C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/CMakeLists.txt + setlocal +"C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/Admin/IFloor/projects/wxVideoProcessing/build -BC:/Users/Admin/IFloor/projects/wxVideoProcessing/build/Win --check-stamp-file C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/CMakeFiles/generate.stamp +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + %(AdditionalInputs) + C:\Users\Admin\IFloor\projects\wxVideoProcessing\wxNonGuiPluginBase\Win\CMakeFiles\generate.stamp + false + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/CMakeFiles/wxNonGuiPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/CMakeFiles/wxNonGuiPluginBase.dir/Debug/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/wxNonGuiPluginBase.dir/Debug//cmake_pch.pch + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/CMakeFiles/wxNonGuiPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + Create + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/CMakeFiles/wxNonGuiPluginBase.dir/Release/cmake_pch.hxx + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/wxNonGuiPluginBase.dir/Release//cmake_pch.pch + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/CMakeFiles/wxNonGuiPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/CMakeFiles/wxNonGuiPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/CMakeFiles/wxNonGuiPluginBase.dir/Debug/cmake_pch.hxx;%(ForcedIncludeFiles) + C:/Users/Admin/IFloor/projects/wxVideoProcessing/wxNonGuiPluginBase/Win/CMakeFiles/wxNonGuiPluginBase.dir/Release/cmake_pch.hxx;%(ForcedIncludeFiles) + + + + + + + + {6F4BDD20-5B99-3029-BDF0-7D719B283AF5} + ZERO_CHECK + false + Never + + + + + + \ No newline at end of file diff --git a/wxNonGuiPluginBase/Win/wxNonGuiPluginBase.vcxproj.filters b/wxNonGuiPluginBase/Win/wxNonGuiPluginBase.vcxproj.filters new file mode 100644 index 0000000..f2c2fab --- /dev/null +++ b/wxNonGuiPluginBase/Win/wxNonGuiPluginBase.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Precompile Header File + + + Precompile Header File + + + + + + + + {4951AEE1-75F2-3C38-B593-C6BC8C809FB0} + + + {112D4227-BB51-3360-BB5B-5EA5DBA5A65F} + + + {05450AB2-CB7B-34EA-83DF-1EE86424EDF0} + + + diff --git a/wxNonGuiPluginBase/wxNonGuiPluginBase.cpp b/wxNonGuiPluginBase/wxNonGuiPluginBase.cpp index 78a26ed..18a9db8 100644 --- a/wxNonGuiPluginBase/wxNonGuiPluginBase.cpp +++ b/wxNonGuiPluginBase/wxNonGuiPluginBase.cpp @@ -1,12 +1,12 @@ -#include "stdwx.h" -#include "wxNonGuiPluginBase.h" - -IMPLEMENT_ABSTRACT_CLASS(wxNonGuiPluginBase, wxObject) - -wxNonGuiPluginBase::wxNonGuiPluginBase() -{ -} - -wxNonGuiPluginBase::~wxNonGuiPluginBase() -{ -} +#include "stdwx.h" +#include "wxNonGuiPluginBase.h" + +IMPLEMENT_ABSTRACT_CLASS(wxNonGuiPluginBase, wxObject) + +wxNonGuiPluginBase::wxNonGuiPluginBase() +{ +} + +wxNonGuiPluginBase::~wxNonGuiPluginBase() +{ +} diff --git a/wxNonGuiPluginBase/wxNonGuiPluginBase.h b/wxNonGuiPluginBase/wxNonGuiPluginBase.h index 5d31011..123f12e 100644 --- a/wxNonGuiPluginBase/wxNonGuiPluginBase.h +++ b/wxNonGuiPluginBase/wxNonGuiPluginBase.h @@ -1,16 +1,16 @@ -#pragma once - -#include "Declarations.h" - -class DEMO_API wxNonGuiPluginBase : public wxObject -{ - DECLARE_ABSTRACT_CLASS(wxNonGuiPluginBase) -public: - wxNonGuiPluginBase(); - virtual ~wxNonGuiPluginBase(); - - virtual int Work() = 0; -}; - -typedef wxNonGuiPluginBase * (*CreatePlugin_function)(); +#pragma once + +#include "Declarations.h" + +class DEMO_API wxNonGuiPluginBase : public wxObject +{ + DECLARE_ABSTRACT_CLASS(wxNonGuiPluginBase) +public: + wxNonGuiPluginBase(); + virtual ~wxNonGuiPluginBase(); + + virtual int Work() = 0; +}; + +typedef wxNonGuiPluginBase * (*CreatePlugin_function)(); typedef void (*DeletePlugin_function)(wxNonGuiPluginBase * plugin); \ No newline at end of file