commit 563f8a9a2d56ebf7e0cc1d9914c088f06fcf3327 Author: Ivan Pelipenko Date: Tue Aug 25 23:05:43 2020 +0300 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a2cb3e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.svn +CMakeLists.txt.user* diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..bd49571 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "pip"] + path = pip + url = https://git.shs.tools/SHS/pip.git diff --git a/AUTHORS.txt b/AUTHORS.txt new file mode 100644 index 0000000..7dd5dfb --- /dev/null +++ b/AUTHORS.txt @@ -0,0 +1,2 @@ +peri4 = Пелипенко Иван +andrey = Бычков Андрей diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..0776d3c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,300 @@ +cmake_minimum_required(VERSION 3.0) +cmake_policy(SET CMP0011 NEW) # don`t affect includer policies +cmake_policy(SET CMP0017 NEW) # need include() with .cmake +cmake_policy(SET CMP0020 NEW) # Automatically link Qt executables to qtmain target on Windows +if (POLICY CMP0053) + cmake_policy(SET CMP0053 NEW) # simpler variable expansion and escape sequence evaluation rules +endif() +project(libs) +set(PIP_CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/pip/cmake") +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${PIP_CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/qad/cmake") +set(LIBPROJECT 1) +set(_qt_libs ) +set(_qt_apps ) +set(_qt_plugs) +include(GenerateExportHeader) +include(SDKMacros) +include(QADMacros) +include(DeployMacros) + +if(NOT DEFINED BUILD_NUMBER) + set(BUILD_NUMBER 9999) +endif() +if("x${BUILD_NUMBER}" STREQUAL "x") + set(BUILD_NUMBER 0) +endif() + + +if(STATIC_LIB) + set(QAD_LIB_TYPE STATIC) + add_definitions(-DQAD_STATIC_DEFINE) + set(QAD_LIB_TYPE_MSG "Static") +else() + set(QAD_LIB_TYPE SHARED) + set(QAD_LIB_TYPE_MSG "Shared") +endif() + +set(_QAD_MAJOR 1) +set(_QAD_MINOR 7) +set(_QAD_REVISION 0) +set(_QAD_SUFFIX ) +set(_QAD_COMPANY SHS) +set(_QAD_DOMAIN org.SHS) +set(QAD_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/qad/qad_version.h") +set_version(QAD + MAJOR "${_QAD_MAJOR}" + MINOR "${_QAD_MINOR}" + REVISION "${_QAD_REVISION}" + BUILD "${BUILD_NUMBER}" + SUFFIX "${_QAD_SUFFIX}" + OUTPUT "${QAD_VERSION_FILE}") +set_deploy_property(QAD ${QAD_LIB_TYPE} + FULLNAME "${_QAD_DOMAIN}.*" + COMPANY "${_QAD_COMPANY}") + + +if(STATIC_LIB) + set(PIQt_LIB_TYPE STATIC) + add_definitions(-DPIQt_STATIC_DEFINE) + set(PIQt_LIB_TYPE_MSG "Static") +else() + set(PIQt_LIB_TYPE SHARED) + set(PIQt_LIB_TYPE_MSG "Shared") +endif() + +set(_PIQt_MAJOR 1) +set(_PIQt_MINOR 0) +set(_PIQt_REVISION 0) +set(_PIQt_SUFFIX ) +set(_PIQt_COMPANY SHS) +set(_PIQt_DOMAIN org.SHS) +if(NOT DEFINED BUILD_NUMBER) + set(BUILD_NUMBER 9999) +endif() +set(PIQt_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/piqt/piqt_version.h") +set_version(PIQt + MAJOR "${_PIQt_MAJOR}" + MINOR "${_PIQt_MINOR}" + REVISION "${_PIQt_REVISION}" + BUILD "${BUILD_NUMBER}" + SUFFIX "${_PIQt_SUFFIX}" + OUTPUT "${PIQt_VERSION_FILE}") +set_deploy_property(PIQt ${_PIQt_LIB_TYPE} + FULLNAME "${_PIQt_DOMAIN}.*" + COMPANY "${_PIQt_COMPANY}") + + +include_directories(${CMAKE_CURRENT_BINARY_DIR}/pip) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/qad) +include_directories(${CMAKE_CURRENT_BINARY_DIR}/piqt) +if(MINGW) + find_package(MinGW REQUIRED) +else() + if(APPLE) + set(CMAKE_INSTALL_RPATH "@executable_path/../Frameworks;@executable_path/lib;@loader_path/../lib") + set(CMAKE_MACOSX_RPATH TRUE) + if(CMAKE_CROSSCOMPILING) + set(CMAKE_INSTALL_NAME_DIR "@rpath") + else() + include_directories(/usr/local/include) + link_directories(/usr/local/lib) + endif() + else() + set(CMAKE_INSTALL_RPATH "\$ORIGIN;\$ORIGIN/lib") + endif() +endif() +if (DEFINED ANDROID_PLATFORM) + include_directories(${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include) + #set(TARGET_INSTALL_PATH "${ANDROID_SYSTEM_LIBRARY_PATH}/usr/") + #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${ANDROID_NDK}/sysroot/usr/include") + #message("${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include") + #message("${ANDROID_NDK}/sysroot/usr/include") +endif() +set(INSTALL_PREFIX "") +set(_plugins_default_ ON) +if(CMAKE_CROSSCOMPILING) + if (DEFINED ANDROID_PLATFORM) + set(_plugins_default_ OFF) + set(INSTALL_PREFIX "${CMAKE_FIND_ROOT_PATH}/") + else() + set(INSTALL_PREFIX "${CMAKE_STAGING_PREFIX}") + endif() +endif() +option(CROSSTOOLS "Crosstools minimal build" OFF) +option(LIB "System install" ON) +option(QGLVIEW "Build QGLview library and utils" OFF) +option(QGLENGINE "Build QGLENGINE library and utils" OFF) +option(UTILS "Build various utils" ${_plugins_default_}) +option(DESIGNER_PLUGINS "Build qt designer plugins" ${_plugins_default_}) +option(STATIC_LIB OFF) +if (CROSSTOOLS) + set(LIB 1) + set(QGLVIEW 0) + set(QGLENGINE 0) + set(UTILS 0) + set(DESIGNER_PLUGINS 0) +endif() +if (CMAKE_BUILD_TYPE MATCHES Debug) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3 -Wall") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3 -Wall") +else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wall") +endif() +set(CMAKE_CXX_STANDARD 11) + +set(PIP_LIBRARY pip) +set(PIP_INCLUDES) + +if(LIB) + if(WIN32) + if(MINGW) + set(CMAKE_INSTALL_PREFIX ${MINGW_DIR}) + endif() + else() + if (DEFINED ANDROID_PLATFORM) + set(CMAKE_INSTALL_PREFIX ${ANDROID_SYSTEM_LIBRARY_PATH}/usr) + else() + if(CMAKE_CROSSCOMPILING) + set(CMAKE_INSTALL_PREFIX ${CMAKE_STAGING_PREFIX}) + else() + set(CMAKE_INSTALL_PREFIX ${INSTALL_PREFIX}/usr/local) + endif() + endif() + endif() + message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"") +else() + message(STATUS "Install ${PROJECT_NAME} to local \"bin\", \"lib\" and \"include\"") +endif() + +#message(${PIP_INCLUDES}) +if(CMAKE_CROSSCOMPILING OR (DEFINED ANDROID_PLATFORM)) + set(PIP_CMG "pip_cmg") + set(PIP_RC "pip_rc") + set(PIP_DEPLOY_TOOL "deploy_tool") +else() + set(PIP_CMG "${CMAKE_CURRENT_BINARY_DIR}/pip/utils/code_model_generator/pip_cmg") + set(PIP_RC "${CMAKE_CURRENT_BINARY_DIR}/pip/utils/resources_compiler/pip_rc") + set(PIP_DEPLOY_TOOL "${CMAKE_CURRENT_BINARY_DIR}/pip/utils/deploy_tool/deploy_tool") +endif() +if(WIN32) + set(PIP_DLL_DIR "${CMAKE_CURRENT_BINARY_DIR}/pip") +endif() + +set(QAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/qad) +set(ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + +if (CROSSTOOLS) + + add_subdirectory(pip) + file(GLOB CMAKES "qad/cmake/*.cmake" "qad/cmake/*.in") + install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules) + +else() + + include(QtWraps) + find_qt(Core QUIET) + set(QtVersions) + set(SomeQtFound 0) + foreach(_v ${_QT_VERSIONS_}) + option(Qt${_v} "Build for Qt${_v}" 1) + if (Qt${_v}) + #message("Qt${_v} -> ${LOCAL_FOUND${_v}}") + if (LOCAL_FOUND${_v}) + list(APPEND QtVersions Qt${_v}) + set(SomeQtFound 1) + endif() + endif() + endforeach() + + #if(UTILS) + # message(STATUS "Building with utils") + #else() + # message(STATUS "Building only libraries") + #endif() + + add_subdirectory(pip) + foreach(F ${PIP_MAIN_FOLDERS}) + list(APPEND PIP_INCLUDES "${F}") + endforeach(F) + add_subdirectory(cd_utils) + include_directories("${CMAKE_CURRENT_SOURCE_DIR}/cd_utils" "${CMAKE_CURRENT_BINARY_DIR}/cd_utils") + set(_DIRS) + if (SomeQtFound) + #message(STATUS "Building Qt-derived targets for ${QtVersions}") + add_subdirectory(qad) + include_directories(${qad_includes}) + add_subdirectory(piqt) + include_directories(${piqt_includes}) + set(_DIRS) + if (Qt5) + if (QGLVIEW) + list(APPEND _DIRS qglview) + endif() + if (QGLENGINE) + list(APPEND _DIRS qglengine) + endif() + endif() + foreach(_D ${_DIRS}) + list(APPEND QT_MULTILIB_LIST ${_D}) + add_subdirectory(${_D}) + endforeach(_D) + + macro(align_list _list _out) + set(_max_len 0) + foreach(_m ${_list}) + string(LENGTH "${_m}" _clen) + if (_clen GREATER _max_len) + set(_max_len ${_clen}) + endif() + endforeach() + set(${_out}) + foreach(_m ${_list}) + set(_am "${_m}") + while(TRUE) + string(LENGTH "${_am}" _clen) + if (_clen GREATER_EQUAL ${_max_len}) + break() + endif() + string(APPEND _am " ") + endwhile() + list(APPEND ${_out} "${_am}") + endforeach() + endmacro() + + macro(print_list _list _name) + if (NOT "x${_list}" STREQUAL "x") + message("") + message(" ${_name}:") + #align_list("${_list}" _alist) + foreach(_m ${_list}) + message(" * ${_m}") + endforeach() + endif() + endmacro() + + message("----------QAD-----------") + message(" Build for ${QtVersions}") + message(" QAD Version: ${QAD_VERSION}") + message(" QAD Linkage: ${QAD_LIB_TYPE_MSG}") + message(" PIQt Version: ${PIQt_VERSION}") + message(" PIQt Linkage: ${PIQt_LIB_TYPE_MSG}") + print_list("${_qt_libs}" "Libraries") + print_list("${_qt_apps}" "Applications") + print_list("${_qt_plugs}" "Plugins") + message("-----------------------") + message("") + + else() + message(STATUS "None of Qt found, skip Qt-derived targets") + endif() + +endif() + +if(WIN32) + foreach(PIP_LT ${PIP_MODULES}) + if (SomeQtFound) + qt_install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pip/lib${PIP_LT}.dll" DESTINATION QtBin) + endif() + endforeach() +endif() diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..aa1dfb8 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,62 @@ +def build_docker(name) { + def image = "${name}-libs" + echo "Build image ${image}" + def pref = "" + if (env.DOCKER_PREFIX) { + pref = "--build-arg DOCKER_PREFIX=${env.DOCKER_PREFIX}/" + } + def jobs = 4 + if (env.JOBS_COUNT) { + jobs = "${env.JOBS_COUNT}" + } + def args = "${pref} --build-arg LIBS_BUILD_NUMBER=${env.BUILD_NUMBER} --build-arg JOBS_COUNT=${jobs}" + dir ("docker/${image}") { + sh "docker build ${args} --no-cache -t ${image} ." + } + return "\n - ${image}" +} +node { + stage("checkout") { + checkout scm + } + def _envmap = [:] + def _env = sh(script: "env", returnStdout: true).trim().split("\n") + _env.each{ l -> + def _ind = l.indexOf('='); + def _n = l.substring(0, _ind); + def _v = l.substring(_ind + 1); + _envmap["${_n}"] = "${_v}"; + } + def _msg = "Built images:" + def platforms = ['debian', 'osx', 'windows', 'android', 'pi'] + for (int i = 0; i < platforms.size(); ++i) { + if (_envmap["BUILD_${platforms[i]}"] == "1") { + stage("${platforms[i]}-libs") { + _msg += build_docker("${platforms[i]}") + } + } + } + sh "docker system prune -f" + echo "${_msg}" +} +pipeline { + agent { + label 'master' + } + stages { + stage("PIP doc") { + steps { + checkout scm + sh "rm -rf share" + sh "rm -vf *.zip" + sh "mkdir -p build" + sh "cd build && cmake -DLIB=0 -DCMAKE_INSTALL_PREFIX=`pwd` ../" + sh "cd build && make doc" + sh "cd share/doc && zip -r ../../pip_doc.zip pip" + sh "cp share/doc/pip/html/pip.qch ./" + archiveArtifacts 'pip_doc.zip' + archiveArtifacts 'pip.qch' + } + } + } +} diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + 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 that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU 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 as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/README.md b/README.md new file mode 100644 index 0000000..58a2a1c --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# Main SHS Toolkit repo + +## Introduction + +This repo contains PIP, QAD and derived projects: +* cd_utils - PIP-based client/server library for read, transmit and use custom structures of coefficients +* qcd_utils - Qt bindings to CDUtils and "CD Pult" executable - full-featured CD client +* piqt - helpers to convert PIP <-> Qt types +* piqt_utils - Gui libraries and executables to edit PIConnection configs and watch PIIntrospection +* qglview - old Qt-base OpenGL engine +* qglengine - new Qt-base OpenGL engine + +## Compile +This repo can be compile with GCC/MinGW/Clang, for Qt 4/5. + +If there is no Qt found, builds only PIP and cd_utils. + +CMake options: +* **LIB** - if 1 then install to system directories: MinGW on Windows, /usr/local on Linux/MacOS, ${ANDROID_SYSTEM_LIBRARY_PATH} on Android. If 0 then install to ${CMAKE_INSTALL_PREFIX}. Enabled by default +* **UTILS** - build or not executable utilites, enabled by default +* **DESIGNER_PLUGINS** - build or not Qt Designer plugins, enabled by default +* **QGLVIEW** - build or not QGLView, disabled by default +* **QGLENGINE** - build or not QGLEngine, disabled by default + +## Windows scripts +Build steps for i686 architecture: +1. unzip mingw.7z to C:\mingw +2. unzip qt.7z to C:\qt +3. download and install cmake from https://cmake.org/download/ +4. Prepare environment + - set prefix for mingw e.g.: for C:\mingw\7_1_x32\ + set SDK_MINGW_DIR=C:\mingw\7_1_x + - set prefix for Qt5 e.g.: for C:\qt\qt5120_win32\ + set SDK_QT5_DIR=C:\qt\qt5120_win + - set SDK_CMAKE_DIR=C:\cmake +5. run make_libs32.bat + +Build steps for amd64 architecture: + -- follow previos steps, but replace '32' to '64' + +Build steps for both architectures: + -- follow previos steps, but on '4' state run make_libs_all.bat + +## Non-Windows scripts +Script "make_libs.sh" compile and install SDK for current environment, e.g. +`./make_libs.sh -j4` + +## Docker +This repo provide Dockerfile, so you can exec `docker build -t libs .` in this directory +and make docker image "libs" with installed SHS SDK for: +* Debian 10 +* Windows x64 +* MacOS +* Android ndk 21 armeabi-v71, arm64-v8a, x86, x86_64 diff --git a/cd_utils/CMakeLists.txt b/cd_utils/CMakeLists.txt new file mode 100644 index 0000000..e399d88 --- /dev/null +++ b/cd_utils/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 3.0) +project(cd_utils) +find_package(MinGW REQUIRED) +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES}) +file(GLOB CPPS_UTILS "cdutils_*.cpp") +file(GLOB HDRS_UTILS "cdutils_*.h") +add_library(${PROJECT_NAME} SHARED ${CPPS_UTILS} ${HDRS_UTILS}) +target_link_libraries(${PROJECT_NAME} ${PIP_LIBRARY}) +generate_export_header(${PROJECT_NAME}) +list(APPEND HDRS_UTILS "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_export.h") + +add_executable(cdutilstest "cdutilstest.cpp" "cdtest.h") +target_link_libraries(cdutilstest ${PIP_LIBRARY} ${PROJECT_NAME}) +message(STATUS "Building ${PROJECT_NAME}") + +if(LIB) + list(APPEND _ALL_TARGETS ${PROJECT_NAME}) + set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE) + if(WIN32) + install(FILES ${HDRS_UTILS} DESTINATION ${MINGW_INCLUDE}) + install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION ${MINGW_LIB}) + install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${MINGW_BIN}) + else() + install(FILES ${HDRS_UTILS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include) + install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) + endif() + #message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"") +else() + if(WIN32) + install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) + install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION lib) + else() + install(TARGETS ${PROJECT_NAME} DESTINATION lib) + endif() + install(FILES ${HDRS_UTILS} DESTINATION include) + #message(STATUS "Install ${PROJECT_NAME} to local \"bin\"") +endif() diff --git a/cd_utils/LICENSE.txt b/cd_utils/LICENSE.txt new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/cd_utils/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + 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 that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU 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 as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/cd_utils/cdtest.h b/cd_utils/cdtest.h new file mode 100644 index 0000000..f707548 --- /dev/null +++ b/cd_utils/cdtest.h @@ -0,0 +1,10 @@ +#ifndef CDTEST_H +#define CDTEST_H + + +enum KDescription { + First, //f Первый + Second, //b Второй +}; + +#endif // CDTEST_H diff --git a/cd_utils/cdutils_c.cpp b/cd_utils/cdutils_c.cpp new file mode 100644 index 0000000..6ff28ac --- /dev/null +++ b/cd_utils/cdutils_c.cpp @@ -0,0 +1,41 @@ +#include "cdutils_c.h" +#include "cdutils_core.h" + +using namespace CDUtils; + +CInterface C; + + +CInterface::CInterface(): Interface(CDType::cdC) { +} + + +void CInterface::sendCommand(const CDType & c) { + core->sendCommand(c); +} + + +void CInterface::connect(const CDType & c, PIObject * o, Handler eh) { + core->registerCHandler(c, o, eh); +} + + +void CInterface::autoConnect(PIObject * o, const PIString & prefix) { + if (!o) return; + uint cid = o->classNameID(); + if (!PIObject::__meta_data().contains(cid)) return; + PIMap eh_map; + PIObject::__MetaData & md(PIObject::__meta_data()[cid]); + PIMap::const_iterator it; + for (it = md.eh_func.constBegin(); it != md.eh_func.constEnd(); ++it) { + eh_map[it.value().func_name] = (Handler)it.value().addr; + //piCout << "func" << it.value().func_name; + } + PIVector cl = C.root().children(); + piForeachC (CDType * c, cl) { + PIString cp = prefix + c->pathString().join("_"); + if (cp.isEmpty()) continue; + if (!eh_map.contains(cp)) continue; + connect(*c, o, eh_map[cp]); + } +} diff --git a/cd_utils/cdutils_c.h b/cd_utils/cdutils_c.h new file mode 100644 index 0000000..80082f9 --- /dev/null +++ b/cd_utils/cdutils_c.h @@ -0,0 +1,46 @@ +/* + CD Utils - Control-Debug utilites + + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + + This program 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 3 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef CDUTILS_C_H +#define CDUTILS_C_H + +#include "cdutils_interface.h" +#include "cd_utils_export.h" + + +namespace CDUtils { + + +class CD_UTILS_EXPORT CInterface: public Interface +{ + PIOBJECT_SUBCLASS(CInterface, Interface) +public: + CInterface(); + + void sendCommand(const CDType & c); + void connect(const CDType & c, PIObject * o, Handler eh); + void autoConnect(PIObject * o, const PIString & prefix = PIStringAscii("c_")); + +}; + +} + +extern CD_UTILS_EXPORT CDUtils::CInterface C; + +#endif // CDUTILS_C_H diff --git a/cd_utils/cdutils_core.cpp b/cd_utils/cdutils_core.cpp new file mode 100644 index 0000000..685694d --- /dev/null +++ b/cd_utils/cdutils_core.cpp @@ -0,0 +1,606 @@ +#include "cdutils_core.h" +#include "cdutils_parser.h" +#include "piconfig.h" +#include "piiobytearray.h" +#include "piiostring.h" +#include "pifile.h" + +using namespace CDUtils; + +const char CDCore::app_config[] = + "include = cd_ip.conf\n\ + port_rec = 2\n\ + port_send = 1\n\ + [connection]\n\ + device.cd = peer://cd_app:cd_pult #s\n\ + []\n\ + connectionmodel = AAAM2Xja7VXLTttAFD12QpsikKjUSixYlLbKEpIUtVIlVEfqhk2FWuiGRRolUYtoHgrmpYiv6IItf8AveMMH9E/YsG6Ph3sde5hGoQoblLGuPHfunTPjc49nADxDA110+LTYC7FrPCAPeAO+vZu+aX7c/8PGd45WCJC0OGcfT6FDnmfSTPtwhZFt3HjgDs/Qtu5jPbZHtI/x50XfIzMQbdwEolbg9INP4ku++myPaUtCHYRaT2j1ldIh3VP60/Qff8vSfXLu9BP6JX9K/0TVH6jqVe22P1X/fao/oddWu/paDs1vBf9Jv/EZ91clbyHqv7BL6sscDOd4v4WTqs6jzaHGJ8QJerxlpJSpdZ7IWFJvDW7I2JxZqIM62k6A57RZmMQGmlyrxdV+WGBnmR01mXPI267hBKwp4FeBeo9VPtssxyb7rzHg1B7T9nCMU45U8BZlWuVWtIcD/CRGOqtsbW09851tXsHN0UTlLIAdASjSXnLyLn+H7L2+xbGYvC63Ezqg543egkLmn8qnRF6USbM4Qp9godkhzI777Ne5bCIt/5UtGz2o/yGby0nKpjqmbOa1ynkjmyzIrzvIZUeBPjvlUmbh32EFJbGyJZhR8YcvlS+3TpjhqeWSyvUkpbI9plSWtcKLcsK05beOJVEnhaEFfHEH+RwpeMcpn1JKGqWMNOL+G6wZyahlpdVOtufKfbDS+guLke9O\n\ + "; + +const char CDCore::pult_config[] = + "include = cd_ip.conf\n\ + port_rec = 1\n\ + port_send = 2\n\ + [connection]\n\ + device.cd = peer://cd_pult:cd_app #s\n\ + []\n\ + connectionmodel = AAAM2Xja7VXLTttAFD12QpsikKjUSixYlLbKEpIUtVIlVEfqhk2FWuiGRRolUYtoHgrmpYiv6IItf8AveMMH9E/YsG6Ph3sde5hGoQoblLGuPHfunTPjc49nADxDA110+LTYC7FrPCAPeAO+vZu+aX7c/8PGd45WCJC0OGcfT6FDnmfSTPtwhZFt3HjgDs/Qtu5jPbZHtI/x50XfIzMQbdwEolbg9INP4ku++myPaUtCHYRaT2j1ldIh3VP60/Qff8vSfXLu9BP6JX9K/0TVH6jqVe22P1X/fao/oddWu/paDs1vBf9Jv/EZ91clbyHqv7BL6sscDOd4v4WTqs6jzaHGJ8QJerxlpJSpdZ7IWFJvDW7I2JxZqIM62k6A57RZmMQGmlyrxdV+WGBnmR01mXPI267hBKwp4FeBeo9VPtssxyb7rzHg1B7T9nCMU45U8BZlWuVWtIcD/CRGOqtsbW09851tXsHN0UTlLIAdASjSXnLyLn+H7L2+xbGYvC63Ezqg543egkLmn8qnRF6USbM4Qp9godkhzI777Ne5bCIt/5UtGz2o/yGby0nKpjqmbOa1ynkjmyzIrzvIZUeBPjvlUmbh32EFJbGyJZhR8YcvlS+3TpjhqeWSyvUkpbI9plSWtcKLcsK05beOJVEnhaEFfHEH+RwpeMcpn1JKGqWMNOL+G6wZyahlpdVOtufKfbDS+guLke9O\n\ + "; + + +int __Core_Initializer__::count_(0); +CDCore * __Core_Initializer__::__instance__(0); +const uchar header_direct = 0x80; +const uchar header_transfer = 0x81; + + +__Core_Initializer__::__Core_Initializer__() { + count_++; + if (count_ > 1) return; + __instance__ = new CDCore(); +} + + +__Core_Initializer__::~__Core_Initializer__() { + count_--; + if (count_ < 0) { + count_ = 0; + return; + } + if (count_ > 0) return; + if (__instance__) { + delete __instance__; + __instance__ = 0; + } +} + + + + +CDCore::CDCore() { + setName("CDCore"); + x_timer.setName("__S__.CDCore.x_timer"); + datatr.setPacketSize(960); + CONNECTU(&connection, dataReceivedEvent, this, dataReceived); + CONNECTU(PICout::Notifier::object(), finished, this, piCoutFinished); + /*PIString s(app_config); + connection.configureFromString(&s); + connection.start();*/ + need_rebuild_x = x_pult_side = false; + k_.cd_type_ = CDType::cdK; + x_.cd_type_ = CDType::cdX; + c_.cd_type_ = CDType::cdC; + m_.cd_type_ = CDType::cdM; + initRoot(&k_); + initRoot(&x_); + initRoot(&c_); + initRoot(&m_); + + CONNECTU(&sendt, started, this, sendThread) + CONNECTU(&datatr, sendRequest, this, dtSendRequest) + CONNECTU(&datatr, receiveFinished, this, dtReceiveFinished) + CONNECTU(&x_timer, tickEvent, this, xTimerTick) + + /*k_[1] = KType(1, "123", "120+3", "comment"); + k_[2] = KType(2, "1", "2", "comm"); + k_[4] = KType(4, "-0.6", "-6/10", "mment"); + k_.section(10)[5] = KType(5, "8", "2*2*2", "88"); + k_.section(10).section(50)[100] = KType(100, "8", "2*2*2", "88"); + k_.section(11)[3] = KType(3, "1", "1", "88"); + k_.section(11)[4] = KType(4, "0", "0", "88"); + k_.section(11)[6] = KType(6, "0", "0", "88");*/ + //piCout << s; +} + + +CDCore::~CDCore() { + x_timer.stop(true); + datatr.stop(); + sendt.stop(); + sendt.waitForFinish(10); + connection.stop(); +} + + +void CDCore::cd_write(CDSection * cd, PIIODevice * d) { + cd->write(d, PIString()); +} + + +void CDCore::cd_read(CDSection * cd, PIIODevice * d) { + PIConfig conf(d, PIIODevice::ReadOnly); + cd->read(&(conf.rootEntry())); + if (cd->cd_type_ == CDType::cdX) + x_selected = cd->collectX(); + initRoot(cd); + raiseChangedGlobal(cd->cd_type_); + /*PIVector ds = connection.allDevices(); + piForeach(PIIODevice * d, ds) { + if (d) + piCoutObj << d->constructFullPath() << d->isOpened(); + }*/ +} + + +void CDCore::cd_parse(CDSection * cd, PIIODevice * d) { + *cd = CDParser::parse(d, cd->cd_type_); + initRoot(cd); + raiseChangedGlobal(cd->cd_type_); +} + + +void CDCore::cd_update(CDSection * cd, PIIODevice * d, UpdateModeFlags mode) { + CDSection ucd = *cd; + cd_parse(cd, d); + /*bool kn = true; + if (!ucd.isEmpty()) + if (!ucd.isSameStructure(k_)) { + piCout << "ask for save names"; + K_KeepNamesRequest(&kn); + }*/ + ucd.update(*cd, mode); + //piCout << k_.count() << ucd.count(); + *cd = ucd; + initRoot(cd); + raiseChangedGlobal(cd->cd_type_); +} + + +void CDCore::cd_calculate(CDSection * cd) { + cd->calculate(); + raiseChangedGlobal(cd->cd_type_); +} + + +void CDCore::cd_send(CDSection * cd, CDPacketType pt, bool direct) { + if (!cd) return; + PIByteArray ba, sba; + PIIOByteArray iob(&ba, PIIODevice::ReadWrite); + cd_write(cd, &iob); + //piCoutObj << PIString(ba); + sba = makeHeader(pt, 0); + sba << ba; + if (direct) + sendDirect(sba); + else + sendThreaded(sba); +} + + +void CDCore::send(CDType::cdT cdt) { + CDPacketType pt = CD_Ping; + switch (cdt) { + case CDType::cdK: pt = CD_KSend; break; + case CDType::cdX: pt = CD_XSend; break; + case CDType::cdC: pt = CD_CSend; break; + case CDType::cdM: pt = CD_MSend; break; + default: break; + } + piCoutObj << "send" << typeLetter(cdt); + cd_send(root(cdt), pt); +} + + +void CDCore::request(CDType::cdT cdt) { + CDPacketType pt = CD_Ping; + switch (cdt) { + case CDType::cdK: pt = CD_KQuery; break; + case CDType::cdX: pt = CD_XQuery; break; + case CDType::cdC: pt = CD_CQuery; break; + case CDType::cdM: pt = CD_MQuery; break; + default: break; + } + piCoutObj << "request" << typeLetter(cdt); + PIByteArray sba = makeHeader(pt, 0); + sendThreaded(sba); +} + + +void CDCore::initApp() { + init(appConfig(), false); +} + + +void CDCore::initPult() { + init(pultConfig(), true); +} + + +void CDCore::init(const PIString & configuration, bool pult) { + PIString c = configuration; + //piCoutObj << "init" << c; + connection.stop(); + connection.removeAllDevices(); + connection.configureFromString(&c); + connection.start(); + x_pult_side = pult; +} + + +void CDCore::stop() { + x_timer.stop(); + x_timer.waitForFinish(1000); + connection.stop(); +} + + +void CDCore::release() { + stop(); + connection.removeAllDevices(); +} + + +void CDCore::startX(double freq) { + //piCout << "start x" << x_timer.isRunning() << freq; + if (!x_timer.isRunning()) + x_timer.start(1000. / piMaxd(freq, 0.01)); +} + + +void CDCore::stopX() { + x_timer.stop(); + x_timer.waitForFinish(1000); +} + + +void CDCore::sendCommand(const CDType & c) { + //piCoutObj << "C_sendCommand" << c; + PIByteArray sba = makeHeader(CD_Command, 0); + sba << c.path(); + sendDirect(sba); +} + + +void CDCore::registerCHandler(const CDType & c, PIObject * o, Handler h) { + PIString sp = pathToString(c.path()); + if (sp.isEmpty() || !h) return; + //piCout << "register" << sp; + c_handlers[sp] = OHPair(o, h); +} + + +void CDCore::sendMessage(const CDType & m, MessageType mt, const PIString & msg) { + if (msg.isEmpty() || (m.cd_type() != CDType::cdM)) return; + PIByteArray sba = makeHeader(CD_Message, 0); + sba << m.path() << int(mt) << msg; + sendDirect(sba); +} + + +CDSection * CDCore::root(CDType::cdT cdt) { + switch (cdt) { + case CDType::cdK: return &k_; break; + case CDType::cdX: return &x_; break; + case CDType::cdC: return &c_; break; + case CDType::cdM: return &m_; break; + default: break; + } + return 0; +} + + +PIString CDCore::typeLetter(CDType::cdT cdt) { + switch (cdt) { + case CDType::cdK: return PIStringAscii("k"); break; + case CDType::cdX: return PIStringAscii("x"); break; + case CDType::cdC: return PIStringAscii("c"); break; + case CDType::cdM: return PIStringAscii("m"); break; + default: break; + } + return PIString(); +} + + +CDCore * CDCore::instance() { + /*static CDCore * ret = new CDCore(); + return ret;*/ + return __Core_Initializer__::__instance__; +} + + +bool CDCore::destroy() { + if (!__Core_Initializer__::__instance__) return false; +// piCout << "delete Core ..."; + delete __Core_Initializer__::__instance__; +// piCout << "delete Core ok"; + __Core_Initializer__::__instance__ = 0; + __Core_Initializer__::count_ = 0; + return true; +} + + +void CDUtils::CDCore::K_DirectChange(PIDeque path, PIString value) { +// piCoutObj << "K_DirectChange"; + PacketKDirectChange p; + p.path = path; + p.value = value; + PIByteArray sba = makeHeader(CD_KDirectChange, 0); + sba << p; + sendDirect(sba); +} + + +void CDCore::sendThread() { + if (send_data.size_s() < 4) return; + PacketHeader h; + memcpy(&h, send_data.data(), sizeof(h)); + bool ok = datatr.send(send_data); + switch (h.type) { + case CD_KSend: + if (ok) K_Sended(); + else K_SendFail(); + break; + case CD_KQuery: + if (!ok) K_ReceiveFail(); + break; + case CD_XSend: + if (ok) X_Sended(); + else X_SendFail(); + break; + case CD_XQuery: + if (!ok) X_ReceiveFail(); + break; + case CD_CSend: + if (ok) C_Sended(); + else C_SendFail(); + break; + case CD_CQuery: + if (!ok) C_ReceiveFail(); + break; + case CD_MSend: + if (ok) M_Sended(); + else M_SendFail(); + break; + case CD_MQuery: + if (!ok) M_ReceiveFail(); + break; + default: break; + } +} + + +void CDCore::xTimerTick() { + //piCout << "x tick" << x_pult_side; + PIByteArray ba; + x_mutex.lock(); + if (x_pult_side) { + ba = makeHeader(CD_XRequest, 0); + if (need_rebuild_x) { + x_selected = x_.collectX(); + //piCout << "collectX" << x_selected.size(); + need_rebuild_x = false; + } + ba << x_selected; + //piCout << "x pult send" << x_selected.size(); + } else { + ba = makeHeader(CD_XValues, 0); + ba << x_selected; + piForeachC (PIDeque & p, x_selected) { + x_[p].writeX(ba); + } + //piCout << "x app" << x_selected.size(); + } + x_mutex.unlock(); + sendDirect(ba); +} + + +void CDCore::piCoutFinished(int id, PIString * buffer) { + if (!buffer || !(id == 1)) return; + PIString sp = buffer->takeRange("[", "]"); + PIDeque p = CDCore::stringToPath(sp); + sendMessage(m_[p], Log, *buffer); + delete buffer; +} + + +void CDCore::initRoot(CDSection * r) { + r->name = "__root__"; + r->alias = "root"; + r->makePath(); + r->calculate(); +} + + +PIByteArray CDCore::makeHeader(CDPacketType type, int session_id) const { + PacketHeader h; + h.type = type; + h.session_id = session_id; + PIByteArray ret; ret << h; + return ret; +} + + +void CDCore::sendDirect(PIByteArray & ba) { + ba.push_front(header_direct); + connection.writeByName("cd", ba); +} + + +void CDCore::sendThreaded(PIByteArray & ba) { + if (sendt.isRunning()) { + piCoutObj << "Send in process, abort"; + return; + } + send_data = ba; + sendt.startOnce(); +} + + +void CDCore::procReceivedPacket(PIByteArray & ba) { + PacketHeader h; + ba >> h; + switch(h.type) { + case CD_Ping: + //piCoutObj << "ping"; + break; + case CD_KQuery: + send(CDType::cdK); + break; + case CD_KSend: { + PIByteArray k; + ba >> k; + k << uchar(0); + PIString s = PIString::fromUTF8((const char *)k.data()); + PIIOString ios(&s); + cd_read(&k_, &ios); + K_Received(); + piCoutObj << "K received"; + } break; + case CD_KDirectChange: { + PacketKDirectChange p; + ba >> p; + k_[p.path].setValue(p.value); + } break; + case CD_XQuery: + send(CDType::cdX); + break; + case CD_XSend: { + PIByteArray x; + ba >> x; + x << uchar(0); + PIString s = PIString::fromUTF8((const char *)x.data()); + PIIOString ios(&s); + cd_read(&x_, &ios); + x_selected = x_.collectX(); + X_Received(); + piCoutObj << "X received"; + } break; + case CD_XRequest: { + if (x_pult_side) break; + //break; + x_mutex.lock(); + x_selected.clear(); + ba >> x_selected; + //piCout << "X req" << x_selected.size(); + x_.setSelectedX(false); + piForeachC (PIDeque & p, x_selected) { + x_[p].x_enabled = true; + } + x_mutex.unlock(); + } break; + case CD_XValues: { + if (!x_pult_side) break; + PIVector > x_vals; + ba >> x_vals; + x_mutex.lock(); + piForeachC (PIDeque & p, x_vals) { + x_[p].readX(ba); + } + x_mutex.unlock(); + X_ReceivedX(x_vals); + } break; + case CD_CQuery: + send(CDType::cdC); + break; + case CD_CSend: { + piCoutObj << "C received"; + PIByteArray c; + ba >> c; + c << uchar(0); + PIString s = PIString::fromUTF8((const char *)c.data()); + PIIOString ios(&s); + cd_read(&c_, &ios); + C_Received(); + } break; + case CD_Command: { + piCoutObj << "C command"; + PIDeque p; + ba >> p; + if (p.isEmpty()) return; + PIString sp = pathToString(p); + OHPair h = c_handlers.value(sp, OHPair(0, 0)); + //piCoutObj << "found" << sp << h.first; + if (h.first && h.second) h.second(h.first); + } break; + case CD_MQuery: + send(CDType::cdM); + break; + case CD_MSend: { + piCoutObj << "M received"; + PIByteArray c; + ba >> c; + c << uchar(0); + PIString s = PIString::fromUTF8((const char *)c.data()); + PIIOString ios(&s); + cd_read(&m_, &ios); + M_Received(); + } break; + case CD_Message: { + PIDeque p; + ba >> p; + piCoutObj << "M message" << p; + if (p.isEmpty()) return; + int t = 0; + PIString msg; + ba >> t >> msg; + //piCoutObj << "found" << sp << h.first; + //piCoutObj << "M message invoke"; + M_Message(p, t, msg); + } break; + default: break; + } +} + + +void CDCore::raiseChangedGlobal(CDType::cdT cdt) { + switch (cdt) { + case CDType::cdK: K_ChangedGlobal(); break; + case CDType::cdX: X_ChangedGlobal(); break; + case CDType::cdC: C_ChangedGlobal(); break; + case CDType::cdM: M_ChangedGlobal(); break; + default: break; + } +} + + +PIString CDCore::pathToString(const PIDeque & p) { + PIString ret; + for (int i = 0; i < p.size_s(); ++i) { + if (!ret.isEmpty()) ret += "."; + ret << p[i]; + } + return ret; +} + + +PIDeque CDCore::stringToPath(const PIString & p) { + PIDeque ret; + PIStringList sl = p.split("."); + piForeachC (PIString & s, sl) + ret << s.toInt(); + return ret; +} + + +void CDUtils::CDCore::dataReceived(const PIString & from, const PIByteArray & data) { + //piCoutObj << "dataReceived" << from << data.size(); + PIIODevice * d = connection.deviceByName("cd"); + if (d && d == connection.deviceByFullPath(from)) { + if (data.size() >= sizeof(4)) { + PIByteArray ba = data; + uchar header = ba.take_front(); + if (header == header_transfer) { + datatr.received(ba); + } + if (header == header_direct) { + procReceivedPacket(ba); + } + } + } +} + + +void CDCore::dtSendRequest(PIByteArray & data) { + data.push_front(header_transfer); + connection.writeByName("cd", data); + //piCoutObj << "send" << data.size() << ret; +} + + +void CDCore::dtReceiveFinished(bool ok) { + if (!ok) return; + PIByteArray ba = datatr.data(); + procReceivedPacket(ba); +} + diff --git a/cd_utils/cdutils_core.h b/cd_utils/cdutils_core.h new file mode 100644 index 0000000..d7c357f --- /dev/null +++ b/cd_utils/cdutils_core.h @@ -0,0 +1,147 @@ +/* + CD Utils - Control-Debug utilites + + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + + This program 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 3 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef CDUTILS_CORE_H +#define CDUTILS_CORE_H + +#include "cdutils_types.h" +#include "cdutils_protocol.h" +#include "piconnection.h" +#include "pidatatransfer.h" +#include "cd_utils_export.h" + + +namespace CDUtils { + +class CDCore; + + +class CD_UTILS_EXPORT __Core_Initializer__ { +public: + __Core_Initializer__(); + ~__Core_Initializer__(); + static int count_; + static CDCore * __instance__; +}; + + +class CD_UTILS_EXPORT CDCore: public PIObject +{ + PIOBJECT(CDUtils::CDCore) + friend class __Core_Initializer__; + friend class CDSection; + friend class Interface; + friend class XInterface; +public: + static CDCore * instance(); + static bool destroy(); + + EVENT(K_Sended) + EVENT(K_SendFail) + EVENT(K_Received) + EVENT(K_ReceiveFail) + EVENT(K_ChangedGlobal) + EVENT_HANDLER2(void, K_DirectChange, PIDeque, path, PIString, value); + + EVENT(X_Sended) + EVENT(X_SendFail) + EVENT(X_Received) + EVENT(X_ReceiveFail) + EVENT(X_ChangedGlobal) + EVENT1(X_ReceivedX, PIVector >, pathes) + + EVENT(C_Sended) + EVENT(C_SendFail) + EVENT(C_Received) + EVENT(C_ReceiveFail) + EVENT(C_ChangedGlobal) + + EVENT(M_Sended) + EVENT(M_SendFail) + EVENT(M_Received) + EVENT(M_ReceiveFail) + EVENT(M_ChangedGlobal) + EVENT3(M_Message, PIDeque, path, int, type, PIString, msg) + + void cd_write (CDSection * cd, PIIODevice * d); + void cd_read (CDSection * cd, PIIODevice * d); + void cd_parse (CDSection * cd, PIIODevice * d); + void cd_update (CDSection * cd, PIIODevice * d, UpdateModeFlags mode); + void cd_calculate(CDSection * cd); + void cd_send (CDSection * cd, CDPacketType pt, bool direct = false); + void send(CDType::cdT cdt); + void request(CDType::cdT cdt); + void initApp(); + void initPult(); + void init(const PIString & configuration, bool pult = false); + void stop(); + void release(); + void startX(double freq = 20.); + void stopX(); + void sendCommand(const CDType & c); + void registerCHandler(const CDType & c, PIObject * o, Handler h); + bool inProgress() {return sendt.isRunning();} + void sendMessage(const CDType & m, MessageType mt, const PIString & msg); + + CDSection * root(CDType::cdT cdt); + PIString typeLetter(CDType::cdT cdt); + static PIString pathToString(const PIDeque & p); + static PIDeque stringToPath(const PIString & p); + + static PIString pultConfig() {return PIString(pult_config);} + static PIString appConfig() {return PIString(app_config);} + +private: + CDCore(); + ~CDCore(); + EVENT_HANDLER2(void, dataReceived, const PIString &, from, const PIByteArray &, data); + EVENT_HANDLER1(void, dtSendRequest, PIByteArray &, data); + EVENT_HANDLER1(void, dtReceiveFinished, bool, ok); + EVENT_HANDLER(void, sendThread); + EVENT_HANDLER(void, xTimerTick); + EVENT_HANDLER2(void, piCoutFinished, int, id, PIString*, buffer); + void initRoot(CDSection * r); + PIByteArray makeHeader(CDPacketType type, int session_id = 0) const; + void sendDirect(PIByteArray & ba); + void sendThreaded(PIByteArray & ba); + void procReceivedPacket(PIByteArray & ba); + void raiseChangedGlobal(CDType::cdT cdt); + + typedef PIPair OHPair; + + static const char app_config[], pult_config[]; + PIConnection connection; + PIDataTransfer datatr; + PIByteArray send_data; + PIThread sendt; + PITimer x_timer; + CDSection k_, x_, c_, m_; + PIMutex x_mutex; + PIVector > x_selected; + PIMap c_handlers; + bool need_rebuild_x, x_pult_side; + +}; + + +static __Core_Initializer__ __Core_initializer__; + +} + +#endif // CDUTILS_CORE_H diff --git a/cd_utils/cdutils_interface.cpp b/cd_utils/cdutils_interface.cpp new file mode 100644 index 0000000..e1688c4 --- /dev/null +++ b/cd_utils/cdutils_interface.cpp @@ -0,0 +1,217 @@ +#include "cdutils_interface.h" +#include "cdutils_core.h" +#include "piconfig.h" +#include "pifile.h" + +using namespace CDUtils; + + +Interface::Interface(CDType::cdT type_) { + core = CDCore::instance(); + s = core->root(type_); + type = type_; + //piCoutObj << (void*)this << core; + file_ = core->typeLetter(type_) + PIStringAscii(".dat"); + file_size = 0; + switch (type) { + case CDType::cdK: + CONNECTU(core, K_Sended, this, sended); + CONNECTU(core, K_SendFail, this, sendFailed); + CONNECTU(core, K_Received, this, received); + CONNECTU(core, K_ReceiveFail, this, receiveFailed); + CONNECTU(core, K_ChangedGlobal, this, changedGlobal); + break; + case CDType::cdX: + CONNECTU(core, X_Sended, this, sended); + CONNECTU(core, X_SendFail, this, sendFailed); + CONNECTU(core, X_Received, this, received); + CONNECTU(core, X_ReceiveFail, this, receiveFailed); + CONNECTU(core, X_ChangedGlobal, this, changedGlobal); + break; + case CDType::cdC: + CONNECTU(core, C_Sended, this, sended); + CONNECTU(core, C_SendFail, this, sendFailed); + CONNECTU(core, C_Received, this, received); + CONNECTU(core, C_ReceiveFail, this, receiveFailed); + CONNECTU(core, C_ChangedGlobal, this, changedGlobal); + break; + case CDType::cdM: + CONNECTU(core, M_Sended, this, sended); + CONNECTU(core, M_SendFail, this, sendFailed); + CONNECTU(core, M_Received, this, received); + CONNECTU(core, M_ReceiveFail, this, receiveFailed); + CONNECTU(core, M_ChangedGlobal, this, changedGlobal); + break; + default: break; + } +} + + +bool Interface::test(int v) { + return s->test(v); +} + + +CDType & Interface::operator [](const PIString & name_) { + return (*s)[name_]; +} + + +const CDType Interface::operator [](const PIString & name_) const { + return (*s)[name_]; +} + + +CDType & Interface::operator [](const PIDeque & path_) { + return (*s)[path_]; +} + + +const CDType Interface::operator [](const PIDeque & path_) const { + return (*s)[path_]; +} + + +CDType & Interface::operator [](int v) { + //piCout << (void*)this << "[]" << core; + return (*s)[v]; +} + + +const CDType Interface::operator [](int v) const { + //piCout << (void*)this << "[]" << core; + return (*s)[v]; +} + + +CDSection & Interface::section(int v) { +// CDSection & ret = s->section(v); +// piCout << "[get section]" << v << ret.name; + return s->section(v); +} + + +const CDSection Interface::section(int v) const { + return s->section(v); +} + + +CDSection & Interface::section(const PIDeque &path) { + PIDeque spath = path; + CDSection * rs = s; + while (!spath.isEmpty()) { + rs = &(rs->section(spath.take_front())); + } + return *rs; +} + + +CDSection & Interface::root() { + return *s; +} + + +const CDSection & Interface::root() const { + return *s; +} + + +int Interface::count(bool recursive) const { + return s->count(recursive); +} + + +bool Interface::exists(PIDeque path) const { + return s->exists(path); +} + + +void Interface::setFileName(const PIString & _file) { + file_ = _file; +} + + +bool Interface::configure(const PIString & config) { + PIConfig conf(config, PIIODevice::ReadOnly); + PIConfig::Entry & e(conf.getValue(core->typeLetter(s->cd_type_))); + bool ret = false; + setFileName(e.getValue("file", file(), &ret).toString()); + return ret; +} + + +void Interface::reinitConnection(const PIString & configuration) { + core->init(configuration); +} + + +void Interface::releaseConnection() { + core->release(); +} + + +void Interface::write(PIIODevice * d) { + core->cd_write(s, d); +} + + +void Interface::read(PIIODevice * d) { + core->cd_read(s, d); +} + + +void Interface::parse(PIIODevice * d) { + core->cd_parse(s, d); +} + + +void Interface::update(PIIODevice * d, UpdateModeFlags mode) { + core->cd_update(s, d, mode); +} + + +void Interface::calculate() { + core->cd_calculate(s); +} + + +PIString Interface::appConfig() { + return core->appConfig(); +} + + +PIString Interface::pultConfig() { + return core->pultConfig(); +} + + +void Interface::readFile() { + if (file_.isEmpty()) return; + PIFile f(file_, PIIODevice::ReadOnly); + read(&f); + file_size = f.size(); +} + + +void Interface::writeFile() { + if (file_.isEmpty()) return; + PIFile f(file_, PIIODevice::ReadWrite); + f.clear(); + write(&f); + file_size = f.size(); +} + + +bool Interface::inProgress() { + return core->inProgress(); +} + + +void Interface::send() { + core->send(type); +} + + +void Interface::request() { + core->request(type); +} diff --git a/cd_utils/cdutils_interface.h b/cd_utils/cdutils_interface.h new file mode 100644 index 0000000..79f0aa1 --- /dev/null +++ b/cd_utils/cdutils_interface.h @@ -0,0 +1,96 @@ +/* + CD Utils - Control-Debug utilites + + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + + This program 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 3 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef CDUTILS_INTERFACE_H +#define CDUTILS_INTERFACE_H + +#include "cdutils_types.h" +#include "piobject.h" +#include "cd_utils_export.h" + + +namespace CDUtils { + +class CDCore; + + +class CD_UTILS_EXPORT Interface: public PIObject +{ + PIOBJECT(CDUtils::Interface) +public: + Interface(CDType::cdT type_); + + bool test(int v); + CDType & operator [](int v); + const CDType operator [](int v) const; + CDType & operator [](const PIString & name_); + const CDType operator [](const PIString & name_) const; + CDType & operator [](const PIDeque & path_); + const CDType operator [](const PIDeque & path_) const; + CDSection & section(int v); + const CDSection section(int v) const; + CDSection & section(const PIDeque & path); + CDSection & root(); + const CDSection & root() const; + + int count(bool recursive = true) const; + const PIString file() const {return file_;} + int fileSize() const {return file_size;} + CDType::cdT cdType() const {return type;} + bool exists(PIDeque path) const; + + void setFileName(const PIString & _file); + bool configure(const PIString & config); + void reinitConnection(const PIString & configuration); + void releaseConnection(); + void write(PIIODevice * d); + void read(PIIODevice * d); + void parse(PIIODevice * d); + void update(PIIODevice * d, UpdateModeFlags mode = SaveByName); + void calculate(); + + PIString appConfig(); + PIString pultConfig(); + + void readFile(); + void writeFile(); + bool inProgress(); + + EVENT(sended) + EVENT(sendFailed) + EVENT(received) + EVENT(receiveFailed) + EVENT(changedGlobal) + EVENT_HANDLER(void, send); + EVENT_HANDLER(void, request); + +protected: + CDCore * core; + CDSection * s; + CDType::cdT type; + PIString file_; + int file_size; + +}; + + +} + + +#endif // CDUTILS_INTERFACE_H diff --git a/cd_utils/cdutils_k.cpp b/cd_utils/cdutils_k.cpp new file mode 100644 index 0000000..313a6fe --- /dev/null +++ b/cd_utils/cdutils_k.cpp @@ -0,0 +1,20 @@ +#include "cdutils_k.h" +#include "cdutils_core.h" + +using namespace CDUtils; + +KInterface K; + + +KInterface::KInterface(): Interface(CDType::cdK) { +} + + +void KInterface::directChange(const CDType & k) { + core->K_DirectChange(k.path(), k.value()); +} + + +void KInterface::directChange(const CDType & k, double v) { + core->K_DirectChange(k.path(), PIString::fromNumber(v)); +} diff --git a/cd_utils/cdutils_k.h b/cd_utils/cdutils_k.h new file mode 100644 index 0000000..e699f07 --- /dev/null +++ b/cd_utils/cdutils_k.h @@ -0,0 +1,47 @@ +/* + CD Utils - Control-Debug utilites + + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + + This program 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 3 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef CDUTILS_K_H +#define CDUTILS_K_H + +#include "cdutils_interface.h" +#include "cd_utils_export.h" + + +namespace CDUtils { + + +class CD_UTILS_EXPORT KInterface: public Interface +{ + PIOBJECT_SUBCLASS(KInterface, Interface) +public: + KInterface(); + + EVENT1(keepNamesRequest, bool*, kn) + + void directChange(const CDType & k); + void directChange(const CDType & k, double v); + +}; + +} + +extern CD_UTILS_EXPORT CDUtils::KInterface K; + +#endif // CDUTILS_K_H diff --git a/cd_utils/cdutils_m.cpp b/cd_utils/cdutils_m.cpp new file mode 100644 index 0000000..95c4151 --- /dev/null +++ b/cd_utils/cdutils_m.cpp @@ -0,0 +1,22 @@ +#include "cdutils_m.h" +#include "cdutils_core.h" + +using namespace CDUtils; + +MInterface M; + + +MInterface::MInterface(): Interface(CDType::cdM) { + CONNECTU(core, M_Message, this, messageReceived); +} + + +void MInterface::messageBox(const CDType & m, const PIString & msg) { + core->sendMessage(m, MessageBox, msg); +} + + +PICout MInterface::createPICout(const CDType & m) const { + PIString * buff = new PIString("[" + CDCore::pathToString(m.path()) + "]"); + return PICout(buff, 1); +} diff --git a/cd_utils/cdutils_m.h b/cd_utils/cdutils_m.h new file mode 100644 index 0000000..9d9a00c --- /dev/null +++ b/cd_utils/cdutils_m.h @@ -0,0 +1,56 @@ +/* + CD Utils - Control-Debug utilites + + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + + This program 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 3 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef CDUTILS_M_H +#define CDUTILS_M_H + +#include "cdutils_interface.h" +#include "cd_utils_export.h" + + +namespace CDUtils { + + +class CD_UTILS_EXPORT MInterface: public Interface +{ + PIOBJECT_SUBCLASS(MInterface, Interface) +public: + MInterface(); + + PICout operator [](int v) {return createPICout((*s)[v]);} + PICout operator [](int v) const {return createPICout((*s)[v]);} + PICout operator [](const PIString & name_) {return createPICout((*s)[name_]);} + PICout operator [](const PIString & name_) const {return createPICout((*s)[name_]);} + PICout operator [](const PIDeque & path_) {return createPICout((*s)[path_]);} + PICout operator [](const PIDeque & path_) const {return createPICout((*s)[path_]);} + + void messageBox(const CDType & m, const PIString & msg); + + EVENT3(messageReceived, PIDeque, path, int, type, PIString, msg) + +private: + PICout createPICout(const CDType & m) const; + +}; + +} + +extern CD_UTILS_EXPORT CDUtils::MInterface M; + +#endif // CDUTILS_M_H diff --git a/cd_utils/cdutils_parser.cpp b/cd_utils/cdutils_parser.cpp new file mode 100644 index 0000000..2a41c07 --- /dev/null +++ b/cd_utils/cdutils_parser.cpp @@ -0,0 +1,196 @@ +#include "cdutils_parser.h" +#include "cdutils_types.h" +#include "piiostring.h" +#include "piiobytearray.h" +#include "pifile.h" + +using namespace CDUtils; + +enum Phase { + eName = 1, + eBracketOpen, + eBracketClose, + eMemberName, + eMemberEqual, + eMemberValue, + eMemberComma, + eComment, + eMultiComment +}; + + +void removeComment(PIString & line, PIString * type, PIString * comment) { + int ci = line.find("//"); + if (ci >= 0) { + if (comment) *comment = line.right(line.size_s() - ci - 2); + line.cutRight(line.size_s() - ci).trim(); + if (type && comment && !line.isEmpty()) { + *type = comment->takeLeft(1); + comment->trim(); + } + } +} + + +void parseEnumLine(PIString & line, int * value, PIString * type, PIString * comment) { + removeComment(line, type, comment); + int ci = line.find("="); + if (ci >= 0) { + if (value) *value = line.right(line.size_s() - ci - 1).trim().toInt(); + line.cutRight(line.size_s() - ci).trim(); + } + if (line.trim().endsWith(",")) line.cutRight(1); +} + + +void parseInsert(PIString line, PIString & alias, PIStringList & out) { + out.clear(); + int ci = line.find("="); + if (ci < 0) return; + alias = line.right(line.size_s() - ci - 1).trim(); + line.cutRight(line.size_s() - ci).trim(); + while (line.find("[") > 0) { + int is = line.find("["), ie = line.find("]"); + PIString arr = line.mid(is + 1, ie - is - 1); + out << arr; + line.cutMid(is, ie - is + 1); + } + if (!line.isEmpty()) out.insert(0, line); +} + + +PIVector enumValues(const PIString & e, const PIMap & sections, PIStringList & enames) { + PIVector ret; + enames.clear(); + if (sections.contains(e)) { + ret = sections[e].indexes(); + enames = sections[e].index_names(); + } else { + int v = e.toInt(); + if (v < 2) return ret; + for (int i = 0; i < v; ++i) { + ret << i; + enames << "";//PIString::fromNumber(i); + } + } + return ret; +} + + +CDSection CDParser::parse(PIIODevice * d, int cdsection_type) { + CDType::cdT et = (CDType::cdT)cdsection_type; + if (!d) return CDSection(et); + if (!d->canRead()) return CDSection(et); + //piCout << "[CDSection] parse start"; + CDSection cs(et); + CDType ck; + PIMap sections; + PIMap enum_values; + PIString content, line, alias, type, comment; + PIStringList iarr; + if (PIStringAscii(d->className()) == PIStringAscii("PIFile")) { + PIByteArray c = ((PIFile*)d)->readAll(); + c << uchar(0); + content = PIString::fromUTF8((const char *)c.data()); + } + if (PIStringAscii(d->className()) == PIStringAscii("PIIOString")) content = *(((PIIOString*)d)->string()); + if (PIStringAscii(d->className()) == PIStringAscii("PIIOByteArray")) content = PIString(*(((PIIOByteArray*)d)->byteArray())); + PIIOString ios(&content); + //int phase = 0; + int cind = -1; + while ((cind = content.find("enum", cind)) >= 0) { + ios.seek(cind); + line = ios.readLine().trim(); + type.clear(); + comment.clear(); + removeComment(line, &type, &comment); + if (line.find("{") < 0) { + cind += 4; + continue; + } + line.cutLeft(line.find("enum") + 4).trim(); + line.cutRight(line.size_s() - line.find("{")).trim(); + if (line.isEmpty()) { + cind += 4; + continue; + } + cs = CDSection(et); + cs.name = line; + //piCout << "enum" << cs.name; + int cev = 0; +// cevalues.clear(); + while (!ios.isEnd()) { + line = ios.readLine().trim(); + comment.clear(); + removeComment(line, &type, &comment); + if (line.find("}") >= 0) break; + if (line.isEmpty()) { + if (comment.find("=") >= 0) { + parseInsert(comment, alias, iarr); + if (!iarr.isEmpty()) { +// piCout << "#" << enum_values; + if (!enum_values.contains(alias)) { + piCout << "Parse error: can`t find section alias \"" << alias << "\"!"; + return CDSection(et); + } + if (!sections.contains(iarr.front())) { + piCout << "Parse error: can`t find section \"" << iarr.front() << "\"!"; + return CDSection(et); + } + //piCout << "insert" << alias << iarr; + int aval = enum_values.value(alias); + CDSection is = sections.value(iarr.take_front()), ts; + int ibpos = is.name.size_s(); + piForeachRC (PIString & a, iarr) { + PIStringList enames; + PIVector evals = enumValues(a, sections, enames); + //piCout << a << evals; + for (int i = 0; i < evals.size_s(); ++i) { + ts.section(evals[i]) = is; + ts.section(evals[i]).alias = enames[i]; + } + ts.name = is.name; + ts.name.insert(ibpos, PIString("[") << a << "]"); + is = ts; + ts = CDSection(et); + } + is.alias = alias; + cs.section(aval) = is; + } + } + } else { + parseEnumLine(line, &cev, &type, &comment); + //piCout << line << "=" << cev << "//" << type << comment; + ck = CDType(cev, line, type, "", "", comment, et); + if (type == "e") { + if (comment.startsWith("${")) { + comment.cutLeft(1); + PIString en = comment.inBrackets('{', '}'); + comment.cutLeft(en.size_s() + 2).trim(); + ck.setEnumValues(sections.value(en).enumValues()); + ck.setComment(comment); + //piCout << "enum" << en << ck.enumValues(); + } + } + cs[cev] = ck; + //cevalues[line] = cev; + enum_values[line] = cev; + ++cev; + } + } + //piCout << cs.name << cs.k; + sections[cs.name] = cs; +// piCout << "#" << cevalues; +// enum_values << cevalues; + cind += 4; + } +// piCout << "[CDSection] parse end"; + switch (et) { + case CDType::cdK: return sections.value("KDescription"); + case CDType::cdX: return sections.value("XDescription"); + case CDType::cdC: return sections.value("CDescription"); + case CDType::cdM: return sections.value("MDescription"); + default: return CDSection(et); + } + return CDSection(et); +} diff --git a/cd_utils/cdutils_parser.h b/cd_utils/cdutils_parser.h new file mode 100644 index 0000000..d85d609 --- /dev/null +++ b/cd_utils/cdutils_parser.h @@ -0,0 +1,39 @@ +/* + CD Utils - Control-Debug utilites + + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + + This program 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 3 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef CDUTILS_PARSER_H +#define CDUTILS_PARSER_H + +#include "cd_utils_export.h" + +class PIIODevice; + +namespace CDUtils { + +class CDSection; + +namespace CDParser { + +CD_UTILS_EXPORT CDSection parse(PIIODevice * d, int cdsection_type); + +} + +} + +#endif // CDUTILS_PARSER_H diff --git a/cd_utils/cdutils_protocol.h b/cd_utils/cdutils_protocol.h new file mode 100644 index 0000000..18b9164 --- /dev/null +++ b/cd_utils/cdutils_protocol.h @@ -0,0 +1,73 @@ +/* + CD Utils - Control-Debug utilites + + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + + This program 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 3 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef CDUTILS_PROTOCOL_H +#define CDUTILS_PROTOCOL_H + +#include "pistring.h" +#include "cd_utils_export.h" + +namespace CDUtils { + + enum CDPacketType { + CD_Ping, + CD_Pong, + + CD_KQuery, + CD_KSend, + CD_KDirectChange, + + CD_XQuery, + CD_XSend, + CD_XRequest, + CD_XValues, + + CD_CQuery, + CD_CSend, + CD_Command, + + CD_MQuery, + CD_MSend, + CD_Message, + }; + +# pragma pack(push,1) + + struct CD_UTILS_EXPORT PacketHeader { + int type; // CDPacketType + int session_id; + }; + + struct CD_UTILS_EXPORT PacketKDirectChange { + PIDeque path; + PIString value; + }; + +# pragma pack(pop) + + +inline PIByteArray & operator <<(PIByteArray & s, const PacketHeader & v) {s << v.type << v.session_id; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PacketHeader & v) {s >> v.type >> v.session_id; return s;} + +inline PIByteArray & operator <<(PIByteArray & s, const PacketKDirectChange & v) {s << v.path << v.value; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PacketKDirectChange & v) {s >> v.path >> v.value; return s;} + +} + +#endif // CDUTILS_PROTOCOL_H diff --git a/cd_utils/cdutils_types.cpp b/cd_utils/cdutils_types.cpp new file mode 100644 index 0000000..c722270 --- /dev/null +++ b/cd_utils/cdutils_types.cpp @@ -0,0 +1,762 @@ +#include "cdutils_types.h" +#include "piconfig.h" +#include "pifile.h" +#include "pievaluator.h" +#include "cdutils_core.h" + +using namespace CDUtils; + +//int cdtype_debug_cnt = 1; + +const int cd_x_history_max_size = 4000; + +CDType::CDType() { + index_ = -1; + value_d = 0.; + value_i = 0; + value_b = calculated = x_enabled = false; + cd_type_ = cdNull; + parent = 0; + avg_size = 1; + mode_ = rmode_ = X_Current; +// debug_cnt = cdtype_debug_cnt; +// cdtype_debug_cnt++; +// piCout << "[CDType]" << "create Null" << debug_cnt; +} + + + + +CDType::CDType(int i, const PIString & n, const PIString & t, const PIString & v, const PIString & f, const PIString & c, cdT cd_t) { + index_ = i; + name_ = n.trimmed(); + type_ = t.trimmed(); + value_s = v.trimmed(); + formula_ = f.trimmed(); + comment_ = c.trimmed(); + value_d = v.toDouble(); + value_i = v.toInt(); + value_b = v.toBool(); + cd_type_ = cd_t; + calculated = x_enabled = false; + parent = 0; + avg_size = 1; + mode_ = rmode_ = X_Current; + if (type_ == "e") { + enum_values = parseEnumComment(comment_); +// piCout << enum_values.size() << enum_values; + } +// piCout << type_.size() << type_.toUTF8(); +// piCout << formula_.size() << formula_.toUTF8(); +// piCout << comment_.size() << comment_.toUTF8(); +// debug_cnt = cdtype_debug_cnt; +// cdtype_debug_cnt++; +// piCout << "[CDType] create" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK); +} + + +CDType & CDType::operator =(double x) { + value_d = x; + value_i = x; + value_b = x > 0.; + if (mode_ == X_All_Avg) { + avg_h << x; + double val = 0; + if (avg_h.size_s() >= avg_size) { + for (int i = 0; i < avg_h.size_s(); i++) + val += avg_h[i]; + val /= avg_h.size(); + avg_h.clear(); + if (history.size() < cd_x_history_max_size) + history << val; + } + } + return *this; +} + + +PIString CDType::type() const { + if (type_.trimmed().isEmpty()) return "f"; + // piCout << "type =" << type_.trimmed() << ";" << type_ << "#"; + return type_; +} + + +PIString CDType::value() const { + if (type_ == "b") return PIString::fromBool(value_b); + return value_s; +} + + +PIVariant CDType::variantValue() const { + if (type_.isEmpty()) return PIVariant(value()); + switch (type_[0].toAscii()) { + case 'b': return PIVariant(toBool()); break; + case 'n': return PIVariant(toInt()); break; + case 'f': return PIVariant(toDouble()); break; + case 'c': return PIVariant(PIVariantTypes::Color(toInt())); break; + case 'e': { + PIVariantTypes::Enum e = enum_values; + e.selectValue(toInt()); + return PIVariant(e); + break; + } + default: break; + } + return PIVariant(value()); +} + + +void CDType::setValue(const PIString & value_) { + formula_ = value_; + value_d = formula_.toDouble(); + value_i = formula_.toInt(); + value_b = formula_.toBool(); +} + + +void CDType::setVariantValue(const PIVariant & value_) { + setValue(PIString::fromNumber(value_.toDouble())); +} + + +void CDType::setFormula(const PIString & f) { + formula_ = f; + calculated = false; + //PIEvaluator e; + //calculate(&e); +} + + +PIStringList CDType::pathString() const { + PIStringList ret; + CDSection * ps = CDCore::instance()->root(cd_type_); + if (!ps) return ret; + for (int i = 0; i < path_.size_s() - 1; ++i) { + ps = &(ps->section(path_[i])); + if (!ps->alias.isEmpty()) ret << ps->alias; + else ret << PIString::fromNumber(path_[i]); + } + if (!name_.isEmpty()) ret << name_; + else ret << PIString::fromNumber(index_); + return ret; +} + + +void CDType::readX(PIByteArray & ba) { + if (ba.size() < 5) return; + uchar t(0); ba >> t; + rmode_ = (XMode)t; + switch (rmode_) { + case X_Current: + ba >> value_d; + break; + case X_All_Avg: { + PIVector ah; + ba >> ah; + history << ah; + if (!history.isEmpty()) + value_d = history.back(); + } break; + default: break; + } + value_i = value_d; + value_b = value_d > 0.; +} + + +void CDType::writeX(PIByteArray & ba) { + ba << uchar(mode_); + switch (mode_) { + case X_Current: + ba << value_d; + break; + case X_All_Avg: + ba << history; + history.clear(); + break; + default: break; + } +} + + +bool CDType::calculate(PIEvaluator * e, PIVector stack) { + if (stack.contains(this)) { + error_ = "Circular dependencies: "; + piForeachC (CDType * k, stack) + error_ << k->name() << " -> "; + error_ << name(); + //piCout << error_; + return false; + } + stack << this; + if (calculated) return true; + calculated = true; + error_.clear(); + if (!parent) return true; + //piCout << "calc" << name_ << (parent ? parent->alias : "root"); + value_s = formula_.trimmed(); + for (;;) { + int ki = value_s.find("K["); + if (ki < 0) break; + int ke = value_s.find("]", ki + 2); + if (ke < 0) break; + PIString kp = value_s.mid(ki + 2, ke - ki - 2); + //piCout << kp; + CDType & k((*parent)[kp]); + k.calculate(e, stack); + value_s.replace(ki, ke - ki + 1, PIString::fromNumber(k.value_d)); + } + value_d = formula_.toDouble(); + value_i = formula_.toInt(); + value_b = formula_.toBool(); + double ev = 0.; + if (!e->check(value_s) && value_d == 0. && value_i == 0 && !value_b) { + PIString f = formula_.trimmed().toLowerCase(); + if (f != "off" && f != "false" && f != "no" && !value_b) { + error_ = e->error(); + return false; + } + } else + if (e->isCorrect()) + ev = e->evaluate().real(); + //piCout << value_s << value_i << value_d << ev; + //if ((value_d == 0.) || (piAbsd(value_d) < piAbsd(ev))) value_d = ev; + //if ((value_i == 0) || (piAbsd(value_i) < piAbsd(ev))) value_i = int(ev); + if ((value_d == 0.) || (ev != 0.)) value_d = ev; + if ((value_i == 0) || (ev != 0.)) value_i = int(ev); + value_b = value_b || (ev > 0.); + if (value_i != 0) { + if (value_d == 0.) value_d = value_i; + value_b = value_i > 0; + } + if (value_d != 0.) { + if (value_i == 0) value_i = value_d; + value_b = value_d > 0.; + } + if (value_b) { + if (value_d == 0.) value_d = 1.; + if (value_i == 0) value_i = 1; + } + value_s = PIString::fromNumber(value_d); + return true; +} + + +PIVariantTypes::Enum CDType::parseEnumComment(PIString c) { + PIVariantTypes::Enum ret; + if (c.isEmpty()) return ret; + if (type_ == "e") { + PIStringList sl = c.inBrackets('{', '}').split(","); + int cval = 0; + piForeach (PIString & s, sl) { + s.trim(); + if (s.isEmpty()) continue; + if (s[0].isDigit()) { + int ind = s.find("-"); + if (ind > 0) { + cval = s.left(ind).toInt(); + s.cutLeft(ind + 1).trim(); + } + } + ret << PIVariantTypes::Enumerator(cval, s); + ++cval; + } + } + //piCout << c << "=" << ret; + return ret; +} + + +//CDType::CDType(const CDType &cdt) { +// index_ = cdt.index_; +// name_ = cdt.name_; +// type_ = cdt.type_; +// value_s = cdt.value_s; +// formula_ = cdt.formula_; +// comment_ = cdt.comment_; +// value_d = cdt.value_d; +// value_i = cdt.value_i; +// value_b = cdt.value_b; +// cd_type_ = cdt.cd_type_; +// debug_cnt = cdtype_debug_cnt; +// cdtype_debug_cnt++; +// piCout << "[CDType] copy" << debug_cnt << "->" << cdt.debug_cnt << index_ << ":" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK); +//} + + +//CDType &CDType::operator =(const CDType &cdt) { +// index_ = cdt.index_; +// name_ = cdt.name_; +// type_ = cdt.type_; +// value_s = cdt.value_s; +// formula_ = cdt.formula_; +// comment_ = cdt.comment_; +// value_d = cdt.value_d; +// value_i = cdt.value_i; +// value_b = cdt.value_b; +// cd_type_ = cdt.cd_type_; +// piCout << "[CDType] assign" << debug_cnt << "=" << cdt.debug_cnt << index_ << ":" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK); +// //debug_cnt = cdt.debug_cnt; +// return *this; +//} + + +//CDType::~CDType() { +// piCout << "[CDType] delete" << debug_cnt << index_ << ":" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK); +//} + + + +CDSection::CDSection(CDType::cdT type_) { + cd_type_ = type_; + null.cd_type_ = type_; +} + + +CDSection & CDSection::section(int v) { + CDSection & ret(s[v]); + ret.cd_type_ = cd_type_; + return ret; +} + + +const CDSection CDSection::section(int v) const { + CDSection & ret(s[v]); + ret.cd_type_ = cd_type_; + return s[v]; +} + + +bool CDSection::exists(PIDeque path) const { + if (path.isEmpty()) return false; + if (path.size_s() == 1) return cd.contains(path[0]); + int si = path[0]; + if (!s.contains(si)) return false; + path.remove(0, 1); + return s[si].exists(path); +} + + +int CDSection::count(bool recursive) const { + int ret = cd.size_s(); + if (recursive) { + PIMap::const_iterator i; + for (i = s.constBegin(); i != s.constEnd(); ++i) + ret += i->second.count(recursive); + } + return ret; +} + + +int CDSection::sectionsCount() const { + return s.size(); +} + + +PIStringList CDSection::index_names() const { + PIStringList ret; + auto i = cd.makeIterator(); + while (i.next()) + ret << i.value().name(); + return ret; +} + + +void CDSection::calculate() { + prepareCalculate(); + if (cd_type_ != CDType::cdK) return; + PIEvaluator e; + calculateRecursive(&e); +} + + +CDType & CDSection::getByName(const PIString & name_) { + PIStringList np = name_.split("."); + if (np.isEmpty()) return null; + //piCout << np; + CDSection * cs = this, * ns = 0; + if (np.front().isEmpty()) { + if (np.size_s() < 2) return null; + cs = CDCore::instance()->root(cd_type_); + np.pop_front(); + } + for (int i = 0; i < np.size_s() - 1; ++i) { + if (np[i].isEmpty()) return null; + bool isd = np[i][0].isDigit() || (np[i][0] == '-'); + int dv = 0; + if (isd) dv = np[i].toInt(); + ns = 0; + auto it = cs->s.makeIterator(); + while (it.next()) { + bool f = false; + if (isd) f = (dv == it.key()); + else f = (np[i] == it.value().alias); + //piCout << "s..." << it.key() << it.value().alias << f; + if (f) { + ns = &(it.valueRef()); + break; + } + } + //piCout << ns; + if (!ns) return null; + cs = ns; + } + if (np.back().isEmpty()) return null; + bool isd = np.back()[0].isDigit() || (np.back()[0] == '-'); + int dv = 0; + if (isd) dv = np.back().toInt(); + //piCout << np.back() << isd << dv; + auto it = cs->cd.makeIterator(); + while (it.next()) { + bool f = false; + if (isd) f = (dv == it.key()); + else f = (np.back() == it.value().name()); + //piCout << "k..." << it.key() << it.value().name() << f; + if (f) + return cs->cd[it.key()]; + } + return null; +} + + +CDType & CDSection::getByPath(const PIDeque & path_) { + if (path_.isEmpty()) return null; + CDSection * s = this; + for (int i = 0; i < path_.size_s() - 1; ++i) + s = &(s->section(path_[i])); + if (!s) return null; + return (*s)[path_.back()]; +} + + +void CDSection::write(PIIODevice * d, const PIString & prefix) { + if (!d) return; + if (cd.isEmpty() && s.isEmpty()) return; +// piCout << "[CDSection] write start"; + PIString l; + PIStringList cdtl; + cdtl << "null" << "k" << "x" << "c" << "m"; + if (prefix.isEmpty()) l = "[" + cdtl[cd_type_] + "]"; + else l = "[" + prefix + "." + cdtl[cd_type_] + "]"; + l += "\n"; + d->write(l.toUTF8()); + l = "name = " + name + " \n"; + d->write(l.toUTF8()); + l = "alias = " + alias + " \n"; + d->write(l.toUTF8()); + auto i = cd.makeIterator(); + while (i.next()) { + const CDType & ck(i.value()); + if (ck.cd_type() != cd_type_) continue; + switch (cd_type_) { + case CDType::cdNull: break; + case CDType::cdK: + l.clear(); l << ck.index() << ".f = " << ck.formula() << " #s " << ck.comment() << " \n"; + d->write(l.toUTF8()); + l.clear(); l << ck.index() << ".v = " << ck.value() << " #" << ck.type() << " " << ck.name() << " \n"; + d->write(l.toUTF8()); + if (!ck.enumValues().enum_list.isEmpty()) { + l.clear(); l << ck.index() << ".ev = {"; + //PIVector el = ck.enumValues(); + piForeachC (PIVariantTypes::Enumerator & e, ck.enumValues().enum_list) + l << e.value << " - " << e.name << ", "; + l.cutRight(2); + l << "} \n"; + d->write(l.toUTF8()); + } + break; + case CDType::cdX: + l.clear(); l << ck.index() << ".name = " << ck.name() << " #s " << ck.comment() << " \n"; + d->write(l.toUTF8()); + l.clear(); l << ck.index() << ".mode = " << ck.xmode() << " #e (0 - cur, 1 - all_avg) " << "\n"; + d->write(l.toUTF8()); + l.clear(); l << ck.index() << ".avg = " << ck.avg() << " #n " << "\n"; + d->write(l.toUTF8()); + l.clear(); l << ck.index() << ".sel = " << (ck.isSelectedX() ? "1" : "0") << " #n " << "\n"; + d->write(l.toUTF8()); + break; + case CDType::cdC: + case CDType::cdM: + l.clear(); l << ck.index() << ".name = " << ck.name() << " #s " << ck.comment() << " \n"; + d->write(l.toUTF8()); + break; + } + } + if (!s.isEmpty()) { + if (prefix.isEmpty()) l = "s"; + else l = prefix + ".s"; + auto j = s.makeIterator(); + while (j.next()) { + j.valueRef().write(d, l + "." + PIString::fromNumber(j.key())); + } + } + if (prefix.isEmpty()) { + l = "[]\n"; + d->write(l.toUTF8()); + } +// piCout << "[CDSection] write end"; +} + + +void CDSection::read(const void * ep) { +// piCout << "[CDSection] read start"; + PIStringList cdtl; + cdtl << "null" << "k" << "x" << "c" << "m"; + cd.clear(); + s.clear(); + PIConfig::Entry & e(*(PIConfig::Entry*)ep); + name = e.getValue(cdtl[cd_type_] + ".name").value(); + alias = e.getValue(cdtl[cd_type_] + ".alias").value(); + PIConfig::Entry & cdl = e.getValue(cdtl[cd_type_]); + for (int i = 0; i < cdl.childCount(); ++i) { + const PIConfig::Entry * e(cdl.child(i)); + bool ok = false; + int id = e->name().toInt(-1, &ok); +// piCout << "[read]" << ke->name() << ke->value() << ok; +// PIString n = ke->getValue("v").comment(); +// PIString t = n.takeLeft(1); + if (ok) { + CDType c; + PIString ev; + switch (cd_type_) { + case CDType::cdNull: break; + case CDType::cdK: + c = CDType(id, e->getValue("v").comment(), e->getValue("v").type(), e->getValue("v").value(), e->getValue("f").value(), e->getValue("f").comment(), cd_type_); + ev = e->getValue("ev", "").value(); + if (!ev.isEmpty()) + c.enum_values = c.parseEnumComment(ev); + break; + case CDType::cdX: + c = CDType(id, e->getValue("name").value(), PIString(), PIString(), PIString() , e->getValue("name").comment(), cd_type_); + c.setXMode((CDType::XMode)e->getValue("mode", int(CDType::X_Current)).value().toInt()); + c.setAvg((CDType::XMode)e->getValue("avg", 1).value().toInt()); + c.x_enabled = e->getValue("sel", false).value().toBool(); + break; + case CDType::cdC: + case CDType::cdM: + c = CDType(id, e->getValue("name").value(), PIString(), PIString(), PIString() , e->getValue("name").comment(), cd_type_); + break; + } + cd[id] = c; + } + } + PIConfig::Entry & sl = e.getValue("s"); + for (int i = 0; i < sl.childCount(); ++i) { + const PIConfig::Entry * se(sl.child(i)); + int sid = se->name().toInt(); + CDSection & rs(s[sid]); + rs.cd_type_ = cd_type_; + rs.read(se); + } +// piCout << "[CDSection] read end"; +} + + +void CDSection::update(CDSection & v, UpdateModeFlags mode) { + if (mode[SaveByIndex] && mode[SaveByName]) { + piCout << "[CDSection] update error: SaveByIndex | SaveByName mode is denied!"; + return; + } + //piCout << "[CDSection] update start"; + //piCout << "before" << k.size() << v.k.size(); + + PIMap prev_cd_f_bi; + PIMap prev_cd_f_bn; + PIMap::iterator i; + if (mode[SaveByIndex]) { + for (i = cd.begin(); i != cd.end(); ++i) + prev_cd_f_bi[i.key()] = i.value().formula(); + } + if (mode[SaveByName]) { + for (i = cd.begin(); i != cd.end(); ++i) + prev_cd_f_bn[i.value().name_] = i.value().formula(); + } + if (!mode[Merge]) + cd.clear(); + for (i = v.cd.begin(); i != v.cd.end(); ++i) { + int id = i.key(); + PIString n = i.value().name(); + cd[id] = i.value(); + if (mode[SaveByIndex]) { + if (prev_cd_f_bi.contains(id)) + cd[id].setFormula(prev_cd_f_bi[id]); + } + if (mode[SaveByName]) { + if (prev_cd_f_bn.contains(n)) + cd[id].setFormula(prev_cd_f_bn[n]); + } + } + + PIMap prev_s_bi; + PIMap prev_s_bn; + PIMap::iterator j; + if (mode[SaveByIndex]) { + for (j = s.begin(); j != s.end(); ++j) + prev_s_bi[j.key()] = j.value(); + } + if (mode[SaveByName]) { + for (j = s.begin(); j != s.end(); ++j) + prev_s_bn[j.value().alias] = j.value(); + } + if (!mode[Merge]) + s.clear(); + for (j = v.s.begin(); j != v.s.end(); ++j) { + int id = j.key(); + PIString n = j.value().alias; + s[id] = j.value(); + if (mode[SaveByIndex]) { + if (prev_s_bi.contains(id)) + s[id] = prev_s_bi[id]; + } + if (mode[SaveByName]) { + if (prev_s_bn.contains(n)) + s[id] = prev_s_bn[n]; + } + s[id].update(j.value(), mode); + } + + /*PISet used; + for (i = k.begin(); i != k.end(); ++i) { + if (v.k.contains(i.key())) { + PIString f = k[i.key()].formula_; + CDType & cdt = v.k[i.key()]; + cdt.formula_ = f; + k[i.key()] = cdt; + used << i.key(); + } + if (mode) { + CDType & ck(k[i.key()]); + if (prev_k_f_bn.contains(ck.name_)) + ck.setFormula(prev_k_f_bn[ck.name_]); + } + } + //piCout << " after" << k.size(); + for (i = v.k.begin(); i != v.k.end(); ++i) { + if (!used.contains(i.key())) + k[i.key()] = i.value(); + CDType & ck(k[i.key()]); + ck.setFormula(prev_k_f_bn.value(ck.name_)); + } + used.clear(); + PIMap::iterator j; + for (j = s.begin(); j != s.end(); ++j) { + if (v.s.contains(j.key())) + j.value().update(v.s[j.key()], mode); + used << j.key(); + } + for (j = v.s.begin(); j != v.s.end(); ++j) { + if (!used.contains(j.key())) + s[j.key()] = j.value(); + }*/ +// piCout << "[CDSection] update end"; +} + + +bool CDSection::isSameStructure(CDSection & v) { + PIMap cd_ids; + PIMap::iterator i; + for (i = cd.begin(); i != cd.end(); ++i) + cd_ids[i.value().name()] = i.key(); + for (i = v.cd.begin(); i != v.cd.end(); ++i) { + if (!cd_ids.contains(i.value().name())) continue; + //piCout << i.key() << k[i.key()].name() << i.value().name(); + if (cd[cd_ids[i.value().name()]].index() != i.key()) + return false; + } + PIMap::iterator j; + for (j = v.s.begin(); j != v.s.end(); ++j) { + if (!s.contains(j.key())) continue; + if (!s[j.key()].isSameStructure(j.value())) + return false; + } + return true; +} + + +void CDSection::prepareCalculate() { + PIMap::iterator i; + for (i = cd.begin(); i != cd.end(); ++i) { + i.value().parent = this; + i.value().calculated = false; + } + PIMap::iterator j; + for (j = s.begin(); j != s.end(); ++j) + j.value().prepareCalculate(); +} + + +void CDSection::calculateRecursive(PIEvaluator * e) { + PIMap::iterator i; + for (i = cd.begin(); i != cd.end(); ++i) + i.value().calculate(e); + PIMap::iterator j; + for (j = s.begin(); j != s.end(); ++j) + j.value().calculateRecursive(e); +} + + +void CDSection::setSelectedX(bool yes) { + PIMap::iterator i; + for (i = cd.begin(); i != cd.end(); ++i) + i.value().x_enabled = yes; + PIMap::iterator j; + for (j = s.begin(); j != s.end(); ++j) + j.value().setSelectedX(yes); +} + + +PIVector > CDSection::collectX() const { + PIVector > ret; + PIMap::const_iterator i; + for (i = cd.begin(); i != cd.end(); ++i) { + if (i.value().x_enabled) + ret << i.value().path(); + } + PIMap::const_iterator j; + for (j = s.constBegin(); j != s.constEnd(); ++j) + ret << j.value().collectX(); + return ret; +} + + +void CDSection::makePath(PIDeque p) { + PIDeque tp; + PIMap::iterator i; + for (i = cd.begin(); i != cd.end(); ++i) { + tp = p; + tp << i.key(); + i.value().path_ = tp; + //piCout << "path for" << i.value().name() << tp; + } + PIMap::iterator j; + for (j = s.begin(); j != s.end(); ++j) { + tp = p; + tp << j.key(); + j.value().makePath(tp); + } +} + + +PIVector CDSection::children(bool recursive) const { + PIVector ret; + PIMap::const_iterator i; + for (i = cd.begin(); i != cd.end(); ++i) + ret << const_cast(&(i.value())); + if (!recursive) return ret; + PIMap::const_iterator j; + for (j = s.constBegin(); j != s.constEnd(); ++j) + ret << j.value().children(true); + return ret; +} + + +PIVariantTypes::Enum CDSection::enumValues() const { + PIVariantTypes::Enum ret; + PIMap::const_iterator i; + for (i = cd.constBegin(); i != cd.constEnd(); ++i) + ret << PIVariantTypes::Enumerator(i.key(), i.value().name()); + return ret; +} + + diff --git a/cd_utils/cdutils_types.h b/cd_utils/cdutils_types.h new file mode 100644 index 0000000..f2fd7fe --- /dev/null +++ b/cd_utils/cdutils_types.h @@ -0,0 +1,193 @@ +/* + CD Utils - Control-Debug utilites + + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + + This program 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 3 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef CDUTILS_TYPES_H +#define CDUTILS_TYPES_H + +#include "pistring.h" +#include "pimap.h" +#include "pivariant.h" +#include "cd_utils_export.h" + +class PIIODevice; +class PIEvaluator; +class CD_Pult; +class CDItem; +class CDItemModel; + +namespace CDUtils { + +class CDSection; + +enum UpdateMode { + SaveByIndex = 0x01, + SaveByName = 0x02, + Merge = 0x04 +}; + +enum MessageType { + Log = 1, + MessageBox, +}; + +typedef PIFlags UpdateModeFlags; + +class CD_UTILS_EXPORT CDType { + friend class CDSection; + friend class CDCore; + friend class Interface; + friend class XInterface; +public: + enum cdT {cdNull, cdK, cdX, cdC, cdM}; + enum XMode {X_Current, X_All_Avg}; + + CDType(); + CDType(int i, const PIString & n, const PIString & t, const PIString & v, const PIString & f, const PIString & c, cdT cd_t); + + CDType & operator =(double x); + int index() const {return index_;} + PIString name() const {return name_;} + PIString type() const; + PIString value() const; + PIVariant variantValue() const; + PIString formula() const {return formula_;} + PIString comment() const {return comment_;} + double toDouble() const {return value_d;} + int toInt() const {return value_i;} + bool toBool() const {return value_b;} + cdT cd_type() const {return cd_type_;} + void setValue(const PIString & value_); + void setVariantValue(const PIVariant & value_); + void setFormula(const PIString & formula); + void setComment(const PIString & comment) {comment_ = comment;} + operator double() const {return value_d;} + const PIVariantTypes::Enum & enumValues() const {return enum_values;} + void setEnumValues(const PIVariantTypes::Enum & ev) {enum_values = ev;} + const PIString & errorString() const {return error_;} + PIDeque path() const {return path_;} + PIStringList pathString() const; + + void setXMode(XMode mode) {mode_ = mode;} + void setAvg(int avg) {avg_size = avg;} + XMode xmode() const {return mode_;} + XMode xmode_rec() const {return rmode_;} + int avg() const {return avg_size;} + bool isSelectedX() const {return x_enabled;} + void readX(PIByteArray & ba); + void writeX(PIByteArray & ba); + + PIVector history; + +protected: + bool calculate(PIEvaluator * e, PIVector stack = PIVector()); + PIVariantTypes::Enum parseEnumComment(PIString c); + cdT cd_type_; + int index_; + PIString name_, type_; + PIString value_s, formula_, comment_, error_; + PIVariantTypes::Enum enum_values; + CDSection * parent; + PIDeque path_; + double value_d; + int value_i; + bool value_b, calculated, x_enabled; + PIVector avg_h; + int avg_size; + XMode mode_, rmode_; +}; + + +class CD_UTILS_EXPORT CDSection { + friend class CDCore; + friend class Interface; + friend class XInterface; + friend class ::CD_Pult; + friend class ::CDItem; + friend class ::CDItemModel; +public: + + CDSection(CDType::cdT type_ = CDType::cdNull); + + bool test(int v) {return cd.value(v).toBool();} +// CDType & operator [](int v) {if (!k.contains(v)) k[v].index_ = v; return k[v];} + CDType & operator [](int v) {return cd[v];} + const CDType operator [](int v) const {return cd[v];} + CDType & operator [](const PIString & name_) {return getByName(name_);} + const CDType operator [](const PIString & name_) const {return const_cast(this)->getByName(name_);} + CDType & operator [](const PIDeque & path_) {return getByPath(path_);} + const CDType operator [](const PIDeque & path_) const {return const_cast(this)->getByPath(path_);} + CDSection & section(int v); + const CDSection section(int v) const; + + bool isEmpty() const {return cd.isEmpty() && s.isEmpty();} + bool exists(PIDeque path) const; + int count(bool recursive = true) const; + int sectionsCount() const; + PIVector indexes() const {return cd.keys();} + PIStringList index_names() const; + void calculate(); + void makePath(PIDeque p = PIDeque()); + PIVector children(bool recursive = true) const; + PIVariantTypes::Enum enumValues() const; + + PIString name; + PIString alias; + +protected: + CDSection(PIMap k_, PIMap s_) { + cd = k_; + s = s_; + } + CDType & getByName(const PIString & name_); + CDType & getByPath(const PIDeque & path_); + void write(PIIODevice * d, const PIString & prefix = PIString()); + void read(const void * ep); + void update(CDSection & v, UpdateModeFlags mode = SaveByName); + bool isSameStructure(CDSection & v); + void prepareCalculate(); + void calculateRecursive(PIEvaluator * e); + void setSelectedX(bool yes); + PIVector > collectX() const; + + PIMap cd; + mutable PIMap s; + CDType null; + CDType::cdT cd_type_; +}; + +} + + +inline PICout operator <<(PICout s, const CDUtils::CDType & v) { + s.space(); + s.setControl(0, true); + switch (v.cd_type()) { + case CDUtils::CDType::cdK : s << "K["; break; + case CDUtils::CDType::cdX : s << "X["; break; + case CDUtils::CDType::cdC : s << "C["; break; + case CDUtils::CDType::cdM : s << "M["; break; + default : s << "Null["; break; + } + s << v.name() << "(" << v.index() << ")] = " << v.value(); + s.restoreControl(); + return s; +} + + +#endif // CDUTILS_TYPES_H diff --git a/cd_utils/cdutils_x.cpp b/cd_utils/cdutils_x.cpp new file mode 100644 index 0000000..e647377 --- /dev/null +++ b/cd_utils/cdutils_x.cpp @@ -0,0 +1,55 @@ +#include "cdutils_x.h" +#include "cdutils_core.h" + +using namespace CDUtils; + +XInterface X; + + +XInterface::XInterface(): Interface(CDType::cdX) { + CONNECTU(core, X_ReceivedX, this, receivedX); +} + + +void XInterface::setEnabled(const CDType & x, bool en) { + core->x_mutex.lock(); + CDType & t((*s)[x.path()]); + if (t.cd_type() != CDType::cdX) { + core->x_mutex.unlock(); + return; + } + t.x_enabled = en; + //piCout << t << "x_enabled" << en; + core->need_rebuild_x = true; + core->x_mutex.unlock(); +} + + +PIVector > XInterface::enabledList() const { + return CDCore::instance()->x_selected; +} + + +void XInterface::setEnabledList(const PIVector > & l) { + CDCore::instance()->x_selected = l; +} + + +void XInterface::lock() { + CDCore::instance()->x_mutex.lock(); +} + + +void XInterface::unlock() { + CDCore::instance()->x_mutex.unlock(); +} + + +void XInterface::start(double freq) { + core->startX(freq); +} + + +void XInterface::stop() { + core->stopX(); +} diff --git a/cd_utils/cdutils_x.h b/cd_utils/cdutils_x.h new file mode 100644 index 0000000..72e9974 --- /dev/null +++ b/cd_utils/cdutils_x.h @@ -0,0 +1,57 @@ +/* + CD Utils - Control-Debug utilites + + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + + This program 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 3 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef CDUTILS_X_H +#define CDUTILS_X_H + +#include "cdutils_interface.h" +#include "cd_utils_export.h" + + +namespace CDUtils { + + +class CD_UTILS_EXPORT XInterface: public Interface +{ + PIOBJECT_SUBCLASS(XInterface, Interface) +public: + XInterface(); + + EVENT1(keepNamesRequest, bool*, xn) + EVENT1(receivedX, PIVector >, pathes) + + void enable(const CDType & x) {setEnabled(x, true);} + void disable(const CDType & x) {setEnabled(x, false);} + void setEnabled(const CDType & x, bool en); + void setDisabled(const CDType & x, bool dis) {setEnabled(x, !dis);} + PIVector > enabledList() const; + void setEnabledList(const PIVector > & l); + void lock(); + void unlock(); + + void start(double freq = 20.); + void stop(); + +}; + +} + +extern CD_UTILS_EXPORT CDUtils::XInterface X; + +#endif // CDUTILS_X_H diff --git a/cd_utils/cdutilstest.cpp b/cd_utils/cdutilstest.cpp new file mode 100644 index 0000000..d284b49 --- /dev/null +++ b/cd_utils/cdutilstest.cpp @@ -0,0 +1,97 @@ +#include "cdutils_k.h" +#include "cdutils_x.h" +#include "cdutils_c.h" +#include "cdutils_m.h" +#include "cdutils_core.h" +#include "cdtest.h" +#include "pip.h" +#include "k_description.h" + +using namespace CDUtils; + +class Core : public PIObject +{ + PIOBJECT(Core) + public: + Core() { + CDCore::instance()->initApp(); +// piCout << "testCore"; + CONNECTU(&timer, tickEvent, this, timerDone); + CONNECTU(&X, received, this, xrecv); + CONNECTU(&C, received, this, crecv); + t = 0.; + } + + void load() { + rf.open("k.dat", PIIODevice::ReadWrite); + K.read(&rf); + rf.close(); + } + + void save() { + rf.open("k_out.txt", PIIODevice::ReadWrite); + rf.resize(0); + K.write(&rf); + rf.close(); +// rf.open("k_out.txt", PIIODevice::ReadWrite); +// K.read(&rf); +// rf.close(); +// rf.open("k_out2.txt", PIIODevice::ReadWrite); +// rf.resize(0); +// K.write(&rf); +// rf.close(); +// rf.open("k_out2.txt", PIIODevice::ReadWrite); +// K.read(&rf); +// rf.close(); +// rf.open("k_out3.txt", PIIODevice::ReadWrite); +// rf.resize(0); +// K.write(&rf); +// rf.close(); + } + + void test() { + X.lock(); + X[KD::Frequency] = 100; + X.section(KD::Spectrometer)[KD::Temperature_default] = sin(t); + t += 0.01; + X.unlock(); + /*piCout << "count" << K.count(); + piCout << K[First]; + piCout << K[Second];*/ + } + + EVENT_HANDLER(void, ksend) {piCout << "sended k";} + EVENT_HANDLER(void, crecv) { + piCout << "received c"; + C.connect(C.section(KD::Logs).section(KD::Spec).section(KD::Formats)[KD::Binary], this, HANDLER(cmd)); + C.autoConnect(this); + } + EVENT_HANDLER(void, xrecv) { + piCout << "received x"; + if (!timer.isRunning()) timer.start(10); + X.start(); + } + EVENT_HANDLER(void, timerDone) {test();} + EVENT_HANDLER(void, cmd) {piCout << "command cmd";} + EVENT_HANDLER(void, c_Pause) { + piCout << "command pause"; + M[KD::Main] << "rec command" << C[KD::Pause]; + M.messageBox(M.root()[KD::Core], "init successfull"); + } + EVENT_HANDLER(void, c_Spectrometer_Connection) {piCout << "command spec_conn";} + +private: + PIFile rf; + PITimer timer; + double t; +}; + + +int main(int argc, char *argv[]) { + X.start(); + piSleep(1); + //CDCore::instance()->destroy(); + piCout << "DELETED"; + return 0; +} + diff --git a/cd_utils/k_description.h b/cd_utils/k_description.h new file mode 100644 index 0000000..09d53ce --- /dev/null +++ b/cd_utils/k_description.h @@ -0,0 +1,147 @@ +#ifndef K_DESCRIPTION_H +#define K_DESCRIPTION_H + +namespace KD { + +enum Sections { + Startup, + Spectrometer, + Switch, + Formats, + Logs, + Detector, + CoreOutput, +}; + +enum LogFormat { + Text, //b text + Binary, //b binary +}; + +enum LogType { + Data, //b write data logs + Spec, //b write spectrogram logs + ARINC, //b ARINC +}; + +enum KLogConfig { + // LogFormat = Formats + StartupWrite, //b + ApplyBinaryLogHeader, //b Apply settings under ID = 255 for binary log + MaximumWriteFrequency, //f Maximum frequency for log in Hz, or 0 for unlimited +}; + +enum SwitchType { + BaySpec, + DiCon, +}; + +enum SpectrometerConnection { + TCP, + USB, +}; + +enum PeakSearchMode { + Left, + Max, + Right, +}; + +enum CoreMode { + ModeSpectrometer, + ModePlayer, + ModePeaks, +}; + +enum KSpectrometer { + Connection, //e ${SpectrometerConnection} + Temperature_compensation, //b Use temperature sensor or default temperature witout compensation + Temperature_default, //f Default temperature using if compensation disabled +}; + +enum KSwitch { + Enabled, //b 0 or 1 Use optical switch or not + Wait, //n Delay after switching channel, ms + Autoscan, //e {0 - scan with our forces, 1 - SDK autoscan} + Autoscan_offset, //n Offset for SDK autoscan + Type, //e ${SwitchType} +}; + +enum KDetector { + Threshold_Min, //f + Threshold_Max, //f + SideSize, //f + SideOffset, //f + PeaksSearch, //e ${PeakSearchMode} +}; + +enum KCoreOutput { + SendSpectrum, //b Send spectrum data or empty vector + SendOnlyCurrentValue, //b Send current values or all stored in 20Hz +}; + +enum CoreOutputChannel { + GUI, + SecGUI, + ThirdGUI, +}; + +enum KDescription { + // KSpectrometer = Spectrometer + // KSwitch = Switch + // KDetector = Detector + // KCoreOutput[CoreOutputChannel] = CoreOutput + // KLogConfig[LogType] = Logs + Gratings_history, //n Gratings peak values history, count + Amplitude_history_size, //n Count of history values to calculate sensors amplitude + Fourier_enabled, //b Global fourier enable flag + Fourier_size, //n Size of fourier window, in counts + Fourier_YScale, //f scale for fourier amplitude + Fourier_Max_or_Density, //n 0 - Maximum in fourier window, 1 - Density of fourier window + Mode, //e ${CoreMode} Work mode + SynchronizationEnabled, //b When enabled, start logs and reset time when sync signal received + SynchronizationMode, //e {0 - disabled, 1 - new file, 2 - column in log} + LambdasAutoReset, //b Set lambdas_0 to grating values on first data receive + Gauss_size, //n + //Peak_max_offset, //f in pixels + //Peak_LF_coeff, //f 1. - no filtering + GratingOverloadMax, //n + GratingOverloadMin, //n + SendLED, //b Send to LED Arduino serial port current state + SynchronizationClearValues, //b clear gratings and sensors values and history on sync + PeaksModeFrequency, //f + PeaksModeAdditionNm_1, //f Addition nm to peaks in ModePeaks, channel 1 + PeaksModeAdditionNm_2, //f Addition nm to peaks in ModePeaks, channel 2 + PeaksModeAdditionNm_3, //f Addition nm to peaks in ModePeaks, channel 3 + PeaksModeAdditionNm_4, //f Addition nm to peaks in ModePeaks, channel 4 +}; + +enum XDescription { + // KSpectrometer = Spectrometer + // KSwitch = Switch + // KDetector = Detector + // KCoreOutput[CoreOutputChannel] = CoreOutput + // KLogConfig[LogType] = Logs + State, //b + Frequency, //n cur freq + //Fourier_enabled, //b Global fourier enable flag +}; + +enum CDescription { + // KSpectrometer = Spectrometer + // KCoreOutput[CoreOutputChannel] = CoreOutput + // KLogConfig[LogType] = Logs + Halt, //b + Reboot, //n cur freq + Pause, //b Global fourier enable flag +}; + +enum MDescription { + Main, //b + Core, //s + Warnings, //b Global fourier enable flag +}; + +} + +#endif // K_DESCRIPTION_H diff --git a/docker/android-libs/Dockerfile b/docker/android-libs/Dockerfile new file mode 100644 index 0000000..e94bc3f --- /dev/null +++ b/docker/android-libs/Dockerfile @@ -0,0 +1,43 @@ +ARG DOCKER_PREFIX=wapmobil/ +FROM ${DOCKER_PREFIX}android + +ARG LIBS_BUILD_NUMBER=9999 +ARG JOBS_COUNT=4 +ENV PATH=/opt/cmake/bin:$PATH +ENV ANDROID_HOME=/usr/lib/android-sdk +ENV ANDROID_NDK_HOME=${ANDROID_HOME}/ndk-bundle +ENV ANDROID_TOOLCHAIN=${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake +ENV NDK_PLATFORM="android-21" + +WORKDIR /soft +RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git + +WORKDIR /soft/libs_build_host +RUN cmake -DICU=0 -DCROSSTOOLS=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \ + && make install -j${JOBS_COUNT} \ + && rm -rf * \ + && ldconfig + +WORKDIR /soft/libs_build_anroid +ENV _ANDROID_TOOLCHAIN=/usr/lib/android-sdk/ndk-bundle/build/cmake/android.toolchain.cmake + +ENV _CUR_ABI=armeabi-v7a +RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/android/${_CUR_ABI} -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=${_ANDROID_TOOLCHAIN} -DQt5_DIR=/soft/android/qt/lib/cmake/Qt5 -DANDROID_PLATFORM=${NDK_PLATFORM} -DANDROID_ABI=${_CUR_ABI} ../libs/ \ + && make install -j${JOBS_COUNT} && rm -rf * + +ENV _CUR_ABI=arm64-v8a +WORKDIR /soft/libs_build_android_${_CUR_ABI} +RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/android/${_CUR_ABI} -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=${_ANDROID_TOOLCHAIN} -DQt5_DIR=/soft/android/qt/lib/cmake/Qt5 -DANDROID_PLATFORM=${NDK_PLATFORM} -DANDROID_ABI=${_CUR_ABI} ../libs/ \ + && make install -j${JOBS_COUNT} && rm -rf * + +ENV _CUR_ABI=x86 +WORKDIR /soft/libs_build_android_${_CUR_ABI} +RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/android/${_CUR_ABI} -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=${_ANDROID_TOOLCHAIN} -DQt5_DIR=/soft/android/qt/lib/cmake/Qt5 -DANDROID_PLATFORM=${NDK_PLATFORM} -DANDROID_ABI=${_CUR_ABI} ../libs/ \ + && make install -j${JOBS_COUNT} && rm -rf * + +ENV _CUR_ABI=x86_64 +WORKDIR /soft/libs_build_android_${_CUR_ABI} +RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/android/${_CUR_ABI} -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=${_ANDROID_TOOLCHAIN} -DQt5_DIR=/soft/android/qt/lib/cmake/Qt5 -DANDROID_PLATFORM=${NDK_PLATFORM} -DANDROID_ABI=${_CUR_ABI} ../libs/ \ + && make install -j${JOBS_COUNT} && rm -rf * + +WORKDIR /soft/src diff --git a/docker/debian-libs/Dockerfile b/docker/debian-libs/Dockerfile new file mode 100644 index 0000000..0a85c7f --- /dev/null +++ b/docker/debian-libs/Dockerfile @@ -0,0 +1,17 @@ +ARG DOCKER_PREFIX=wapmobil/ +FROM ${DOCKER_PREFIX}debian + +ARG LIBS_BUILD_NUMBER=9999 +ARG JOBS_COUNT=4 +ENV PATH=/opt/cmake/bin:$PATH + +WORKDIR /soft +RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git + +WORKDIR /soft/libs_build_debian +RUN cmake -DICU=0 -DLIB=1 -DQGLENGINE=1 -DQGLVIEW=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \ + && make install -j${JOBS_COUNT} \ + && rm -rf * \ + && ldconfig + +WORKDIR /soft/src diff --git a/docker/osx-libs/Dockerfile b/docker/osx-libs/Dockerfile new file mode 100644 index 0000000..5a496e4 --- /dev/null +++ b/docker/osx-libs/Dockerfile @@ -0,0 +1,21 @@ +ARG DOCKER_PREFIX=wapmobil/ +FROM ${DOCKER_PREFIX}osx + +ARG LIBS_BUILD_NUMBER=9999 +ARG JOBS_COUNT=4 +ENV PATH=/soft/osxcross/target/bin:/opt/cmake/bin:$PATH + +WORKDIR /soft +RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git + +WORKDIR /soft/libs_build_host +RUN cmake -DICU=0 -DCROSSTOOLS=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \ + && make install -j${JOBS_COUNT} \ + && rm -rf * \ + && ldconfig + +WORKDIR /soft/libs_build_osx +RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/osx -DICU=0 -DLIB=0 -DQGLENGINE=1 -DQGLVIEW=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=/soft/toolchain-Darwin.cmake ../libs/ \ + && make install -j${JOBS_COUNT} && rm -rf * + +WORKDIR /soft/src diff --git a/docker/pi-libs/Dockerfile b/docker/pi-libs/Dockerfile new file mode 100644 index 0000000..666e20c --- /dev/null +++ b/docker/pi-libs/Dockerfile @@ -0,0 +1,21 @@ +ARG DOCKER_PREFIX=wapmobil/ +FROM ${DOCKER_PREFIX}pi + +ARG LIBS_BUILD_NUMBER=9999 +ARG JOBS_COUNT=4 +ENV PATH=/opt/cmake/bin:$PATH + +WORKDIR /soft +RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git + +WORKDIR /soft/libs_build_host +RUN cmake -DICU=0 -DCROSSTOOLS=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \ + && make install -j${JOBS_COUNT} \ + && rm -rf * \ + && ldconfig + +WORKDIR /soft/libs_build_pi +RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/pi/usr -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=/soft/toolchain-RPi.cmake ../libs/ \ + && make install -j${JOBS_COUNT} && rm -rf * + +WORKDIR /soft/src diff --git a/docker/windows-libs/Dockerfile b/docker/windows-libs/Dockerfile new file mode 100644 index 0000000..82be301 --- /dev/null +++ b/docker/windows-libs/Dockerfile @@ -0,0 +1,21 @@ +ARG DOCKER_PREFIX=wapmobil/ +FROM ${DOCKER_PREFIX}windows + +ARG LIBS_BUILD_NUMBER=9999 +ARG JOBS_COUNT=4 +ENV PATH=/opt/cmake/bin:$PATH + +WORKDIR /soft +RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git + +WORKDIR /soft/libs_build_host +RUN cmake -DICU=0 -DCROSSTOOLS=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \ + && make install -j${JOBS_COUNT} \ + && rm -rf * \ + && ldconfig + +WORKDIR /soft/libs_build_windows +RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/windows -DICU=0 -DLIB=0 -DQGLENGINE=1 -DQGLVIEW=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=/soft/toolchain-Windows.cmake ../libs/ \ + && make install -j${JOBS_COUNT} && rm -rf * + +WORKDIR /soft/src diff --git a/logo.png b/logo.png new file mode 100644 index 0000000..e08b36a Binary files /dev/null and b/logo.png differ diff --git a/make_libs.bat b/make_libs.bat new file mode 100644 index 0000000..d530e09 --- /dev/null +++ b/make_libs.bat @@ -0,0 +1,6 @@ +@echo off +set ARCH=%~1 +set PATH=%SDK_MINGW_DIR%%ARCH%\bin;%SDK_QT4_DIR%%ARCH%\bin;%SDK_CMAKE_DIR%\bin +if defined SDK_QT5_DIR set Qt5_DIR=%SDK_QT5_DIR%%ARCH% +mkdir ..\libs_build_win%ARCH% +cd ../libs_build_win%ARCH% && cmake_mgw -Wno-dev -DQGLVIEW=1 -DQGLENGINE=1 -DQT4=0 ../libs && make install -j4 && cd ../libs && pause diff --git a/make_libs.sh b/make_libs.sh new file mode 100644 index 0000000..ec03987 --- /dev/null +++ b/make_libs.sh @@ -0,0 +1,6 @@ +#! /bin/bash +cd .. +mkdir libs_build_linux +cd libs_build_linux +cmake ../libs +make install $@ diff --git a/make_libs32.bat b/make_libs32.bat new file mode 100644 index 0000000..c1103ef --- /dev/null +++ b/make_libs32.bat @@ -0,0 +1 @@ +make_libs.bat 32 \ No newline at end of file diff --git a/make_libs64.bat b/make_libs64.bat new file mode 100644 index 0000000..f12abc1 --- /dev/null +++ b/make_libs64.bat @@ -0,0 +1 @@ +make_libs.bat 64 \ No newline at end of file diff --git a/make_libs_all.bat b/make_libs_all.bat new file mode 100644 index 0000000..b6bd18b --- /dev/null +++ b/make_libs_all.bat @@ -0,0 +1,2 @@ +start cmd /C make_libs32.bat +start cmd /C make_libs64.bat diff --git a/make_libs_android.bat b/make_libs_android.bat new file mode 100644 index 0000000..4abfcbb --- /dev/null +++ b/make_libs_android.bat @@ -0,0 +1,6 @@ +@echo off +mkdir ..\libs_build_android_%~1 +cd ..\libs_build_android_%~1 +call ..\libs\cmake_android 21 %~1 ..\libs "-DUTILS=0 -DDEBUG=0 -DCMAKE_BUILD_TYPE=Release" +call make install -j4 +cd ..\libs diff --git a/make_libs_android_all.bat b/make_libs_android_all.bat new file mode 100644 index 0000000..b15632e --- /dev/null +++ b/make_libs_android_all.bat @@ -0,0 +1,4 @@ +@echo off +for %%a in (x86,x86_64,arm,arm64) do ( + call .\make_libs_android %%a +)