Merge branch 'develop' into master

This commit is contained in:
Charles J. Cliffe 2017-01-02 21:22:13 -05:00 committed by GitHub
commit 5c72b97309
35 changed files with 5567 additions and 572 deletions

View File

@ -6,19 +6,69 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
SET(CUBICSDR_VERSION_MAJOR "0")
SET(CUBICSDR_VERSION_MINOR "2")
SET(CUBICSDR_VERSION_PATCH "0")
SET(CUBICSDR_VERSION_REL "")
SET(CUBICSDR_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}${CUBICSDR_VERSION_REL}")
SET(CUBICSDR_VERSION_PATCH "1")
SET(CUBICSDR_VERSION_SUFFIX "-alpha-bookmark1")
SET(CUBICSDR_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}${CUBICSDR_VERSION_SUFFIX}")
SET(CPACK_PACKAGE_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}")
SET(CPACK_PACKAGE_VERSION_MAJOR ${CUBICSDR_VERSION_MAJOR})
SET(CPACK_PACKAGE_VERSION_MINOR ${CUBICSDR_VERSION_MINOR})
SET(CPACK_PACKAGE_VERSION_PATCH ${CUBICSDR_VERSION_PATCH})
SET (VERSION_SUFFIX "" CACHE STRING "Add custom version suffix to CubicSDR application title.")
SET (CUSTOM_BUILD OFF CACHE BOOL "Enable custom build options")
# Build options for custom deploys, optimization and debugging
IF(CUSTOM_BUILD)
SET (CUBICSDR_BUILD_TITLE CACHE STRING "Custom Title")
# bundle flags
SET (CUBICSDR_INSTALL_NAME CACHE "CubicSDR" "Installation Name")
SET (CUBICSDR_INSTALL_TITLE CACHE "CubicSDR" "Installation Title")
SET (CUBICSDR_HEADER_IMAGE CACHE "" "Image file to display in header")
SET (CUBICSDR_HEADER_BG CACHE "000000" "Background Color (HEX) for header")
# feature flags
SET (CUBICSDR_ENABLE_VIEW_DEMOD ON CACHE BOOL "Enable Second Demodulator Spectrum/Waterfall view.")
SET (CUBICSDR_ENABLE_VIEW_SCOPE ON CACHE BOOL "Enable Demodulator Scope/Spectrum view.")
SET (CUBICSDR_MODEM_EXCLUDE CACHE "" "Comma-separated list of modems to exclude.")
IF (NOT CUBICSDR_HEADER_IMAGE STREQUAL "")
SET(CUBICSDR_HAS_HEADER_IMAGE TRUE)
GET_FILENAME_COMPONENT(CUBICSDR_HEADER_IMAGE_FILE "${CUBICSDR_HEADER_IMAGE}" NAME)
GET_FILENAME_COMPONENT(CUBICSDR_HEADER_IMAGE_DIR "${CUBICSDR_HEADER_IMAGE}" PATH)
ADD_DEFINITIONS(
-DCUBICSDR_HEADER_IMAGE="${CUBICSDR_HEADER_IMAGE_FILE}"
-DCUBICSDR_HEADER_BG="${CUBICSDR_HEADER_BG}"
)
ENDIF()
IF (NOT CUBICSDR_MODEM_EXCLUDE STREQUAL "")
ADD_DEFINITIONS(
-DCUBICSDR_MODEM_EXCLUDE="${CUBICSDR_MODEM_EXCLUDE}"
)
ENDIF()
ELSE()
SET (CUBICSDR_BUILD_TITLE "CubicSDR v${CUBICSDR_VERSION} by Charles J. Cliffe (@ccliffe) :: www.cubicsdr.com")
# bundle flags
SET (CUBICSDR_INSTALL_NAME "CubicSDR")
SET (CUBICSDR_INSTALL_TITLE "CubicSDR ${CUBICSDR_VERSION} Installer")
SET (CUBICSDR_HEADER_IMAGE "")
SET (CUBICSDR_HEADER_BG "")
# feature flags
SET (CUBICSDR_ENABLE_VIEW_DEMOD TRUE)
SET (CUBICSDR_ENABLE_VIEW_SCOPE TRUE)
SET (CUBICSDR_EXCLUDE_MODEM "")
ENDIF()
IF(CUBICSDR_ENABLE_VIEW_DEMOD)
ADD_DEFINITIONS( -DCUBICSDR_ENABLE_VIEW_DEMOD=1 )
ENDIF()
IF(CUBICSDR_ENABLE_VIEW_SCOPE)
ADD_DEFINITIONS( -DCUBICSDR_ENABLE_VIEW_SCOPE=1 )
ENDIF()
ADD_DEFINITIONS(
-DCUBICSDR_VERSION="${CUBICSDR_VERSION}${VERSION_SUFFIX}"
-DCUBICSDR_INSTALL_NAME="${CUBICSDR_INSTALL_NAME}"
-DCUBICSDR_VERSION="${CUBICSDR_VERSION}"
-DCUBICSDR_BUILD_TITLE="${CUBICSDR_BUILD_TITLE}"
)
SET (ENABLE_DIGITAL_LAB OFF CACHE BOOL "Enable 'Digital Lab' testing features.")
@ -27,9 +77,9 @@ ADD_DEFINITIONS(
-DENABLE_DIGITAL_LAB=1
)
IF(MSVC)
SET (ENABLE_LIQUID_EXPERIMENTAL OFF CACHE BOOL "Enable experimental liquid-dsp features (requires latest liquid-dsp installed)")
SET (ENABLE_LIQUID_EXPERIMENTAL OFF CACHE BOOL "Enable experimental liquid-dsp features (requires latest liquid-dsp installed)")
ELSE()
SET (ENABLE_LIQUID_EXPERIMENTAL ON CACHE BOOL "Enable experimental liquid-dsp features (requires latest liquid-dsp installed)")
SET (ENABLE_LIQUID_EXPERIMENTAL ON CACHE BOOL "Enable experimental liquid-dsp features (requires latest liquid-dsp installed)")
ENDIF()
IF(ENABLE_LIQUID_EXPERIMENTAL)
ADD_DEFINITIONS(
@ -50,7 +100,7 @@ if (USE_HAMLIB)
include_directories(${HAMLIB_INCLUDE_DIR})
link_libraries(${HAMLIB_LIBRARY})
ADD_DEFINITIONS(-DUSE_HAMLIB)
ADD_DEFINITIONS(-DUSE_HAMLIB)
endif ()
macro(configure_files srcDir destDir globStr)
@ -103,16 +153,16 @@ SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/${EX_PLATFORM_NA
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/${EX_PLATFORM_NAME})
IF (MSVC)
include_directories ("${PROJECT_SOURCE_DIR}/external/wglext")
SET(LIQUID_INCLUDES "${PROJECT_SOURCE_DIR}/external/liquid-dsp/include/" CACHE STRING "Liquid-DSP include directory")
SET(LIQUID_LIBRARIES "${PROJECT_SOURCE_DIR}/external/liquid-dsp/msvc/${EX_PLATFORM}/libliquid.lib" CACHE STRING "Liquid-DSP Library")
SET(LIQUID_DLL "${PROJECT_SOURCE_DIR}/external/liquid-dsp/msvc/${EX_PLATFORM}/libliquid.dll" CACHE STRING "Liquid-DSP DLL")
SET(HAMLIB_DLLS "${PROJECT_SOURCE_DIR}/external/hamlib/${EX_PLATFORM}/libhamlib-2.dll;${PROJECT_SOURCE_DIR}/external/hamlib/${EX_PLATFORM}/libwinpthread-1.dll" CACHE STRING "HAMLIB DLLS")
include_directories ("${PROJECT_SOURCE_DIR}/external/wglext")
SET(LIQUID_INCLUDES "${PROJECT_SOURCE_DIR}/external/liquid-dsp/include/" CACHE STRING "Liquid-DSP include directory")
SET(LIQUID_LIBRARIES "${PROJECT_SOURCE_DIR}/external/liquid-dsp/msvc/${EX_PLATFORM}/libliquid.lib" CACHE STRING "Liquid-DSP Library")
SET(LIQUID_DLL "${PROJECT_SOURCE_DIR}/external/liquid-dsp/msvc/${EX_PLATFORM}/libliquid.dll" CACHE STRING "Liquid-DSP DLL")
SET(HAMLIB_DLLS "${PROJECT_SOURCE_DIR}/external/hamlib/${EX_PLATFORM}/libhamlib-2.dll;${PROJECT_SOURCE_DIR}/external/hamlib/${EX_PLATFORM}/libwinpthread-1.dll" CACHE STRING "HAMLIB DLLS")
ELSE (MSVC)
ADD_DEFINITIONS(
-std=c++0x
-pthread
)
ADD_DEFINITIONS(
-std=c++0x
-pthread
)
ENDIF(MSVC)
find_package(OpenGL REQUIRED)
@ -128,50 +178,50 @@ find_package(SoapySDR "0.4.0" NO_MODULE REQUIRED)
include_directories(${SOAPY_SDR_INCLUDE_DIR})
SET(OTHER_LIBRARIES ${SOAPY_SDR_LIBRARY} ${OTHER_LIBRARIES})
ADD_DEFINITIONS(
-DUSE_SOAPY_SDR=1
-DUSE_SOAPY_SDR=1
)
IF (WIN32)
set(wxWidgets_USE_STATIC ON)
set(wxWidgets_USE_STATIC ON)
set(BUILD_INSTALLER OFF CACHE BOOL "Build Installer")
# Audio device selection is not mandatory, dummy audio device is used if none are compiled in.
# Can also compile support for more than one simultaneously.
set(USE_AUDIO_DS ON CACHE BOOL "Include support for DirectSound")
set(USE_AUDIO_WASAPI OFF CACHE BOOL "Include support for WASAPI Audio")
# TODO:
# set(USE_AUDIO_ASIO OFF CACHE BOOL "Include support for ASIO Audio")
set(BUILD_INSTALLER OFF CACHE BOOL "Build Installer")
# Audio device selection is not mandatory, dummy audio device is used if none are compiled in.
# Can also compile support for more than one simultaneously.
set(USE_AUDIO_DS ON CACHE BOOL "Include support for DirectSound")
set(USE_AUDIO_WASAPI OFF CACHE BOOL "Include support for WASAPI Audio")
# TODO:
# set(USE_AUDIO_ASIO OFF CACHE BOOL "Include support for ASIO Audio")
# WASAPI
IF(USE_AUDIO_WASAPI)
ADD_DEFINITIONS(-D__WINDOWS_WASAPI__)
IF (NOT MSVC)
SET(OTHER_LIBRARIES ${OTHER_LIBRARIES} -luuid -lksuser)
ENDIF(NOT MSVC)
ENDIF(USE_AUDIO_WASAPI)
# WASAPI
IF(USE_AUDIO_WASAPI)
ADD_DEFINITIONS(-D__WINDOWS_WASAPI__)
IF (NOT MSVC)
SET(OTHER_LIBRARIES ${OTHER_LIBRARIES} -luuid -lksuser)
ENDIF(NOT MSVC)
ENDIF(USE_AUDIO_WASAPI)
# DirectSound
IF (USE_AUDIO_DS)
ADD_DEFINITIONS(-D__WINDOWS_DS__)
IF (MSVC)
SET(OTHER_LIBRARIES ${OTHER_LIBRARIES} dsound.lib)
ELSE (MSVC)
SET(OTHER_LIBRARIES ${OTHER_LIBRARIES} -ldsound)
ENDIF (MSVC)
ENDIF(USE_AUDIO_DS)
# DirectSound
IF (USE_AUDIO_DS)
ADD_DEFINITIONS(-D__WINDOWS_DS__)
IF (MSVC)
SET(OTHER_LIBRARIES ${OTHER_LIBRARIES} dsound.lib)
ELSE (MSVC)
SET(OTHER_LIBRARIES ${OTHER_LIBRARIES} -ldsound)
ENDIF (MSVC)
ENDIF(USE_AUDIO_DS)
SET(USE_MINGW_PATCH OFF CACHE BOOL "Add some missing functions when compiling against mingw liquid-dsp.")
IF (USE_MINGW_PATCH)
SET(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} legacy_stdio_definitions.lib libgcc.a")
ADD_DEFINITIONS(
-DMINGW_PATCH=1
)
SET (GCC_LINKDIR "" CACHE STRING "")
IF (GCC_LINKDIR)
link_directories("${GCC_LINKDIR}")
ENDIF()
ENDIF()
SET(USE_MINGW_PATCH OFF CACHE BOOL "Add some missing functions when compiling against mingw liquid-dsp.")
IF (USE_MINGW_PATCH)
SET(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} legacy_stdio_definitions.lib libgcc.a")
ADD_DEFINITIONS(
-DMINGW_PATCH=1
)
SET (GCC_LINKDIR "" CACHE STRING "")
IF (GCC_LINKDIR)
link_directories("${GCC_LINKDIR}")
ENDIF()
ENDIF()
ENDIF (WIN32)
IF (UNIX AND NOT APPLE)
@ -240,22 +290,23 @@ ENDIF (APPLE)
SET (cubicsdr_sources
src/CubicSDR.cpp
src/AppFrame.cpp
src/AppConfig.cpp
src/FrequencyDialog.cpp
src/CubicSDR.cpp
src/AppFrame.cpp
src/AppConfig.cpp
src/FrequencyDialog.cpp
src/DemodLabelDialog.cpp
src/IOThread.cpp
src/ModemProperties.cpp
src/sdr/SDRDeviceInfo.cpp
src/sdr/SDRPostThread.cpp
src/sdr/SDREnumerator.cpp
src/sdr/SoapySDRThread.h
src/demod/DemodulatorPreThread.cpp
src/demod/DemodulatorThread.cpp
src/demod/DemodulatorWorkerThread.cpp
src/demod/DemodulatorInstance.cpp
src/demod/DemodulatorMgr.cpp
src/BookmarkMgr.cpp
src/sdr/SDRDeviceInfo.cpp
src/sdr/SDRPostThread.cpp
src/sdr/SDREnumerator.cpp
src/sdr/SoapySDRThread.h
src/demod/DemodulatorPreThread.cpp
src/demod/DemodulatorThread.cpp
src/demod/DemodulatorWorkerThread.cpp
src/demod/DemodulatorInstance.cpp
src/demod/DemodulatorMgr.cpp
src/modules/modem/Modem.cpp
src/modules/modem/ModemAnalog.cpp
src/modules/modem/ModemDigital.cpp
@ -267,50 +318,55 @@ SET (cubicsdr_sources
src/modules/modem/analog/ModemIQ.cpp
src/modules/modem/analog/ModemLSB.cpp
src/modules/modem/analog/ModemUSB.cpp
src/audio/AudioThread.cpp
src/util/Gradient.cpp
src/util/Timer.cpp
src/util/MouseTracker.cpp
src/util/GLExt.cpp
src/util/GLFont.cpp
src/util/DataTree.cpp
src/audio/AudioThread.cpp
src/util/Gradient.cpp
src/util/Timer.cpp
src/util/MouseTracker.cpp
src/util/GLExt.cpp
src/util/GLFont.cpp
src/util/DataTree.cpp
src/panel/ScopePanel.cpp
src/panel/SpectrumPanel.cpp
src/panel/WaterfallPanel.cpp
src/panel/MeterPanel.cpp
src/panel/MeterPanel.h
src/visual/ColorTheme.cpp
src/visual/PrimaryGLContext.cpp
src/visual/InteractiveCanvas.cpp
src/visual/MeterCanvas.cpp
src/visual/MeterContext.cpp
src/visual/TuningCanvas.cpp
src/visual/TuningContext.cpp
src/visual/ModeSelectorCanvas.cpp
src/visual/ModeSelectorContext.cpp
src/visual/ScopeCanvas.cpp
src/visual/ScopeContext.cpp
src/visual/SpectrumCanvas.cpp
src/visual/WaterfallCanvas.cpp
src/visual/ColorTheme.cpp
src/visual/PrimaryGLContext.cpp
src/visual/InteractiveCanvas.cpp
src/visual/MeterCanvas.cpp
src/visual/MeterContext.cpp
src/visual/TuningCanvas.cpp
src/visual/TuningContext.cpp
src/visual/ModeSelectorCanvas.cpp
src/visual/ModeSelectorContext.cpp
src/visual/ScopeCanvas.cpp
src/visual/ScopeContext.cpp
src/visual/SpectrumCanvas.cpp
src/visual/WaterfallCanvas.cpp
src/visual/GainCanvas.cpp
src/process/VisualProcessor.cpp
src/process/ScopeVisualProcessor.cpp
src/process/SpectrumVisualProcessor.cpp
src/process/FFTVisualDataThread.cpp
src/process/FFTDataDistributor.cpp
src/visual/ImagePanel.cpp
src/process/VisualProcessor.cpp
src/process/ScopeVisualProcessor.cpp
src/process/SpectrumVisualProcessor.cpp
src/process/FFTVisualDataThread.cpp
src/process/FFTDataDistributor.cpp
src/process/SpectrumVisualDataThread.cpp
src/ui/GLPanel.cpp
src/ui/GLPanel.cpp
src/forms/SDRDevices/SDRDevices.cpp
src/forms/SDRDevices/SDRDevicesForm.cpp
src/forms/SDRDevices/SDRDeviceAdd.cpp
src/forms/SDRDevices/SDRDeviceAddForm.cpp
external/rtaudio/RtAudio.cpp
external/lodepng/lodepng.cpp
external/tinyxml/tinyxml.cpp
external/tinyxml/tinystr.cpp
external/tinyxml/tinyxmlparser.cpp
external/tinyxml/tinyxmlerror.cpp
external/cubicvr2/math/cubic_math.cpp
src/forms/Bookmark/BookmarkPanel.cpp
src/forms/Bookmark/BookmarkView.cpp
src/forms/Dialog/ActionDialogBase.cpp
src/forms/Dialog/ActionDialog.cpp
external/rtaudio/RtAudio.cpp
external/lodepng/lodepng.cpp
external/tinyxml/tinyxml.cpp
external/tinyxml/tinystr.cpp
external/tinyxml/tinyxmlparser.cpp
external/tinyxml/tinyxmlerror.cpp
external/cubicvr2/math/cubic_math.cpp
)
IF(ENABLE_DIGITAL_LAB)
@ -330,33 +386,34 @@ IF(ENABLE_DIGITAL_LAB)
src/modules/modem/digital/ModemQAM.cpp
src/modules/modem/digital/ModemQPSK.cpp
)
IF(ENABLE_LIQUID_EXPERIMENTAL)
IF(ENABLE_LIQUID_EXPERIMENTAL)
SET (cubicsdr_sources
${cubicsdr_sources}
src/modules/modem/digital/ModemFSK.cpp
)
ENDIF()
ENDIF()
ENDIF()
SET (cubicsdr_headers
src/CubicSDRDefs.h
src/CubicSDR.h
src/AppFrame.h
src/AppConfig.h
src/FrequencyDialog.h
src/CubicSDRDefs.h
src/CubicSDR.h
src/AppFrame.h
src/AppConfig.h
src/FrequencyDialog.h
src/DemodLabelDialog.h
src/IOThread.h
src/ModemProperties.h
src/sdr/SDRDeviceInfo.h
src/sdr/SDRPostThread.h
src/sdr/SDREnumerator.h
src/sdr/SoapySDRThread.cpp
src/demod/DemodulatorPreThread.h
src/demod/DemodulatorThread.h
src/demod/DemodulatorWorkerThread.h
src/demod/DemodulatorInstance.h
src/demod/DemodulatorMgr.h
src/demod/DemodDefs.h
src/BookmarkMgr.h
src/sdr/SDRDeviceInfo.h
src/sdr/SDRPostThread.h
src/sdr/SDREnumerator.h
src/sdr/SoapySDRThread.cpp
src/demod/DemodulatorPreThread.h
src/demod/DemodulatorThread.h
src/demod/DemodulatorWorkerThread.h
src/demod/DemodulatorInstance.h
src/demod/DemodulatorMgr.h
src/demod/DemodDefs.h
src/modules/modem/Modem.h
src/modules/modem/ModemAnalog.h
src/modules/modem/ModemDigital.h
@ -368,64 +425,69 @@ SET (cubicsdr_headers
src/modules/modem/analog/ModemIQ.h
src/modules/modem/analog/ModemLSB.h
src/modules/modem/analog/ModemUSB.h
src/audio/AudioThread.h
src/util/Gradient.h
src/util/Timer.h
src/util/ThreadQueue.h
src/util/MouseTracker.h
src/util/GLExt.h
src/util/GLFont.h
src/util/DataTree.h
src/audio/AudioThread.h
src/util/Gradient.h
src/util/Timer.h
src/util/ThreadQueue.h
src/util/MouseTracker.h
src/util/GLExt.h
src/util/GLFont.h
src/util/DataTree.h
src/panel/ScopePanel.h
src/panel/SpectrumPanel.h
src/panel/WaterfallPanel.h
src/visual/ColorTheme.h
src/visual/PrimaryGLContext.h
src/visual/InteractiveCanvas.h
src/visual/MeterCanvas.h
src/visual/MeterContext.h
src/visual/TuningCanvas.h
src/visual/TuningContext.h
src/visual/ModeSelectorCanvas.h
src/visual/ModeSelectorContext.h
src/visual/ScopeCanvas.h
src/visual/ScopeContext.h
src/visual/SpectrumCanvas.h
src/visual/WaterfallCanvas.h
src/visual/ColorTheme.h
src/visual/PrimaryGLContext.h
src/visual/InteractiveCanvas.h
src/visual/MeterCanvas.h
src/visual/MeterContext.h
src/visual/TuningCanvas.h
src/visual/TuningContext.h
src/visual/ModeSelectorCanvas.h
src/visual/ModeSelectorContext.h
src/visual/ScopeCanvas.h
src/visual/ScopeContext.h
src/visual/SpectrumCanvas.h
src/visual/WaterfallCanvas.h
src/visual/GainCanvas.h
src/process/VisualProcessor.h
src/process/ScopeVisualProcessor.h
src/process/SpectrumVisualProcessor.h
src/process/FFTVisualDataThread.h
src/process/FFTDataDistributor.h
src/visual/ImagePanel.h
src/process/VisualProcessor.h
src/process/ScopeVisualProcessor.h
src/process/SpectrumVisualProcessor.h
src/process/FFTVisualDataThread.h
src/process/FFTDataDistributor.h
src/process/SpectrumVisualDataThread.h
src/ui/GLPanel.h
src/ui/UITestCanvas.cpp
src/ui/UITestCanvas.h
src/ui/UITestContext.cpp
src/ui/UITestContext.h
src/ui/GLPanel.h
src/ui/UITestCanvas.cpp
src/ui/UITestCanvas.h
src/ui/UITestContext.cpp
src/ui/UITestContext.h
src/forms/SDRDevices/SDRDevices.h
src/forms/SDRDevices/SDRDevicesForm.h
src/forms/SDRDevices/SDRDeviceAdd.h
src/forms/SDRDevices/SDRDeviceAddForm.h
external/rtaudio/RtAudio.h
external/lodepng/lodepng.h
external/tinyxml/tinyxml.h
external/tinyxml/tinystr.h
external/cubicvr2/math/aabb.h
external/cubicvr2/math/cubic_math.h
external/cubicvr2/math/cubic_types.h
external/cubicvr2/math/frustum.h
external/cubicvr2/math/mat3.h
external/cubicvr2/math/mat4.h
external/cubicvr2/math/plane.h
external/cubicvr2/math/quaternion.h
external/cubicvr2/math/sphere.h
external/cubicvr2/math/transform.h
external/cubicvr2/math/triangle.h
external/cubicvr2/math/vec2.h
external/cubicvr2/math/vec3.h
external/cubicvr2/math/vec4.h
src/forms/Bookmark/BookmarkPanel.h
src/forms/Bookmark/BookmarkView.h
src/forms/Dialog/ActionDialogBase.h
src/forms/Dialog/ActionDialog.h
external/rtaudio/RtAudio.h
external/lodepng/lodepng.h
external/tinyxml/tinyxml.h
external/tinyxml/tinystr.h
external/cubicvr2/math/aabb.h
external/cubicvr2/math/cubic_math.h
external/cubicvr2/math/cubic_types.h
external/cubicvr2/math/frustum.h
external/cubicvr2/math/mat3.h
external/cubicvr2/math/mat4.h
external/cubicvr2/math/plane.h
external/cubicvr2/math/quaternion.h
external/cubicvr2/math/sphere.h
external/cubicvr2/math/transform.h
external/cubicvr2/math/triangle.h
external/cubicvr2/math/vec2.h
external/cubicvr2/math/vec3.h
external/cubicvr2/math/vec4.h
)
IF(ENABLE_DIGITAL_LAB)
@ -495,6 +557,8 @@ set(REG_EXT "[^/]*([.]cpp|[.]c|[.]h|[.]hpp)$")
SOURCE_GROUP("Base" REGULAR_EXPRESSION "src/${REG_EXT}")
SOURCE_GROUP("Forms\\SDRDevices" REGULAR_EXPRESSION "src/forms/SDRDevices/${REG_EXT}")
SOURCE_GROUP("Forms\\Bookmark" REGULAR_EXPRESSION "src/forms/Bookmark/${REG_EXT}")
SOURCE_GROUP("Forms\\Dialog" REGULAR_EXPRESSION "src/forms/Dialog/${REG_EXT}")
SOURCE_GROUP("SDR" REGULAR_EXPRESSION "src/sdr/${REG_EXT}")
IF(USE_HAMLIB)
SOURCE_GROUP("Rig" REGULAR_EXPRESSION "src/rig/${REG_EXT}")
@ -518,26 +582,28 @@ SOURCE_GROUP("_ext-TinyXML" REGULAR_EXPRESSION "external/tinyxml/.*${REG_EXT}")
SOURCE_GROUP("_ext-CubicVR2" REGULAR_EXPRESSION "external/cubicvr2/.*${REG_EXT}")
include_directories (
${PROJECT_SOURCE_DIR}/src/forms/SDRDevices
${PROJECT_SOURCE_DIR}/src/forms/DigitalConsole
${PROJECT_SOURCE_DIR}/src/sdr
${PROJECT_SOURCE_DIR}/src/demod
${PROJECT_SOURCE_DIR}/src/modules
${PROJECT_SOURCE_DIR}/src/modules/modem
${PROJECT_SOURCE_DIR}/src/modules/modem/digital
${PROJECT_SOURCE_DIR}/src/modules/modem/analog
${PROJECT_SOURCE_DIR}/src/audio
${PROJECT_SOURCE_DIR}/src/util
${PROJECT_SOURCE_DIR}/src/panel
${PROJECT_SOURCE_DIR}/src/visual
${PROJECT_SOURCE_DIR}/src/process
${PROJECT_SOURCE_DIR}/src/ui
${PROJECT_SOURCE_DIR}/src/rig
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/external/rtaudio
${PROJECT_SOURCE_DIR}/external/lodepng
${PROJECT_SOURCE_DIR}/external/tinyxml
${PROJECT_SOURCE_DIR}/external/cubicvr2/math
${PROJECT_SOURCE_DIR}/src/forms/SDRDevices
${PROJECT_SOURCE_DIR}/src/forms/DigitalConsole
${PROJECT_SOURCE_DIR}/src/forms/Bookmark
${PROJECT_SOURCE_DIR}/src/forms/Dialog
${PROJECT_SOURCE_DIR}/src/sdr
${PROJECT_SOURCE_DIR}/src/demod
${PROJECT_SOURCE_DIR}/src/modules
${PROJECT_SOURCE_DIR}/src/modules/modem
${PROJECT_SOURCE_DIR}/src/modules/modem/digital
${PROJECT_SOURCE_DIR}/src/modules/modem/analog
${PROJECT_SOURCE_DIR}/src/audio
${PROJECT_SOURCE_DIR}/src/util
${PROJECT_SOURCE_DIR}/src/panel
${PROJECT_SOURCE_DIR}/src/visual
${PROJECT_SOURCE_DIR}/src/process
${PROJECT_SOURCE_DIR}/src/ui
${PROJECT_SOURCE_DIR}/src/rig
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/external/rtaudio
${PROJECT_SOURCE_DIR}/external/lodepng
${PROJECT_SOURCE_DIR}/external/tinyxml
${PROJECT_SOURCE_DIR}/external/cubicvr2/math
)
set(RES_FILES "")
@ -546,11 +612,11 @@ if(MINGW OR MSVC)
set(CMAKE_RC_COMPILER_INIT windres)
ENABLE_LANGUAGE(RC)
IF(EX_PLATFORM EQUAL 64)
SET(RC_TARGET "pe-x86-64")
SET(RC_TARGET "pe-x86-64")
ELSE(EX_PLATFORM EQUAL 64)
SET(RC_TARGET "pe-i386")
SET(RC_TARGET "pe-i386")
ENDIF(EX_PLATFORM EQUAL 64)
SET(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
endif(MINGW OR MSVC)
@ -558,9 +624,12 @@ IF (NOT BUNDLE_APP)
configure_files(${PROJECT_SOURCE_DIR}/font ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME}/fonts "*.fnt")
configure_files(${PROJECT_SOURCE_DIR}/font ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME}/fonts "*.png")
configure_files(${PROJECT_SOURCE_DIR}/icon ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME} CubicSDR.ico)
IF(MSVC)
configure_files(${PROJECT_SOURCE_DIR}/external/liquid-dsp/msvc/${EX_PLATFORM}/ ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME} "*.dll")
ENDIF()
IF(MSVC)
configure_files(${PROJECT_SOURCE_DIR}/external/liquid-dsp/msvc/${EX_PLATFORM}/ ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME} "*.dll")
ENDIF()
IF (CUBICSDR_HAS_HEADER_IMAGE)
configure_files(${CUBICSDR_HEADER_IMAGE_DIR} ${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME} ${CUBICSDR_HEADER_IMAGE_FILE})
ENDIF()
add_executable(CubicSDR ${cubicsdr_sources} ${cubicsdr_headers} ${RES_FILES})
target_link_libraries(CubicSDR ${LIQUID_LIB} ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} ${OTHER_LIBRARIES})
ENDIF (NOT BUNDLE_APP)
@ -575,6 +644,8 @@ IF (MSVC)
set_target_properties(CubicSDR PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
set_target_properties(CubicSDR PROPERTIES COMPILE_DEFINITIONS_MINSIZEREL "_WINDOWS")
set(CMAKE_CREATE_WIN32_EXE "/SUBSYSTEM:WINDOWS /ENTRY:\"mainCRTStartup\"")
set_target_properties (CubicSDR PROPERTIES OUTPUT_NAME "${CUBICSDR_INSTALL_NAME}")
ENDIF(MSVC)
IF (APPLE)
@ -596,20 +667,20 @@ IF (APPLE AND BUNDLE_APP)
set(BUNDLE_MIR_SDR OFF CACHE BOOL "Bundle mir_sdr for personal use only -- do not distribute.")
IF (BUNDLE_SOAPY_MODS)
ADD_DEFINITIONS(
-DBUNDLE_SOAPY_MODS=1
)
set(BUNDLED_MODS_ONLY OFF CACHE BOOL "Use bundled mods only")
IF (BUNDLED_MODS_ONLY)
ADD_DEFINITIONS(
-DBUNDLED_MODS_ONLY=1
)
ENDIF()
ADD_DEFINITIONS(
-DBUNDLE_SOAPY_MODS=1
)
set(BUNDLED_MODS_ONLY OFF CACHE BOOL "Use bundled mods only")
IF (BUNDLED_MODS_ONLY)
ADD_DEFINITIONS(
-DBUNDLED_MODS_ONLY=1
)
ENDIF()
ENDIF()
ADD_DEFINITIONS(
-std=c++0x
-pthread
-std=c++0x
-pthread
-D_OSX_APP_
)
@ -639,7 +710,7 @@ IF (APPLE AND BUNDLE_APP)
MACOSX_BUNDLE_INFO_STRING "CubicSDR Open-Source Software-Defined Radio Application"
MACOSX_BUNDLE_BUNDLE_NAME "CubicSDR"
MACOSX_BUNDLE_BUNDLE_VERSION "${CUBICSDR_VERSION}"
MACOSX_BUNDLE_LONG_VERSION_STRING "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}.${CUBICSDR_VERSION_REL}"
MACOSX_BUNDLE_LONG_VERSION_STRING "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}${CUBICSDR_VERSION_SUFFIX}"
MACOSX_BUNDLE_SHORT_VERSION_STRING "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}"
MACOSX_BUNDLE_GUI_IDENTIFIER "com.cubicproductions.cubicsdr"
MACOSX_BUNDLE_ICON_FILE "CubicSDR.icns"
@ -651,9 +722,10 @@ IF (APPLE AND BUNDLE_APP)
# SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
IF (BUNDLE_SOAPY_MODS)
message(STATUS "SOAPY_ROOT: ${SOAPY_SDR_ROOT}")
file(GLOB SOAPY_MODS ${SOAPY_SDR_ROOT}/lib/SoapySDR/modules/*.so)
SET(SOAPY_SDR_MOD_PATH "${SOAPY_SDR_ROOT}/lib/SoapySDR/modules/${SOAPY_SDR_ABI_VERSION}")
file(GLOB SOAPY_MODS ${SOAPY_MOD_PATH}/*.so)
FOREACH(SOAPY_MOD_FILE ${SOAPY_MODS})
INSTALL( FILES "${SOAPY_MOD_FILE}"
@ -734,25 +806,26 @@ IF (APPLE AND BUNDLE_APP)
include(CPack)
ENDIF()
IF(APPLE AND NOT BUNDLE_APP)
IF (NOT CMAKE_INSTALL_PREFIX)
SET(CMAKE_INSTALL_PREFIX "/usr/")
ENDIF()
ADD_DEFINITIONS(
-DRES_FOLDER="${CMAKE_INSTALL_PREFIX}/share/cubicsdr/"
)
ADD_DEFINITIONS(
-DRES_FOLDER="${CMAKE_INSTALL_PREFIX}/share/cubicsdr/"
)
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,relro")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,relro")
INSTALL(TARGETS CubicSDR DESTINATION bin)
INSTALL(TARGETS CubicSDR DESTINATION bin)
install(FILES
${PROJECT_SOURCE_DIR}/src/CubicSDR.png
DESTINATION share/cubicsdr)
DESTINATION share/cubicsdr)
install(FILES
${CUBICSDR_FONTS}
DESTINATION share/cubicsdr/fonts)
DESTINATION share/cubicsdr/fonts)
CONFIGURE_FILE(
"${PROJECT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
@ -768,181 +841,201 @@ IF (WIN32 AND NOT BUILD_INSTALLER)
ADD_DEFINITIONS(
-DRES_FOLDER="../share/cubicsdr/"
)
INSTALL(TARGETS CubicSDR DESTINATION bin)
INSTALL(FILES
${LIQUID_DLL}
DESTINATION bin)
INSTALL(FILES
${LIQUID_DLL}
DESTINATION bin)
IF(USE_HAMLIB)
FOREACH(HAMLIB_DLL ${HAMLIB_DLLS})
message(STATUS "Copying Hamlib DLL: ${HAMLIB_DLL}")
IF(USE_HAMLIB)
FOREACH(HAMLIB_DLL ${HAMLIB_DLLS})
message(STATUS "Copying Hamlib DLL: ${HAMLIB_DLL}")
INSTALL( FILES "${HAMLIB_DLL}"
DESTINATION bin
)
ENDFOREACH()
ENDIF()
ENDFOREACH()
ENDIF()
INSTALL(FILES
${PROJECT_SOURCE_DIR}/src/CubicSDR.png
DESTINATION share/cubicsdr)
${PROJECT_SOURCE_DIR}/src/CubicSDR.png
DESTINATION share/cubicsdr)
INSTALL(FILES
${CUBICSDR_FONTS}
DESTINATION share/cubicsdr/fonts)
${CUBICSDR_FONTS}
DESTINATION share/cubicsdr/fonts)
IF (CUBICSDR_HAS_HEADER_IMAGE)
INSTALL(FILES
${CUBICSDR_HEADER_IMAGE}
DESTINATION share/cubicsdr/)
ENDIF()
ENDIF()
IF (WIN32 AND BUILD_INSTALLER)
set(BUNDLE_SOAPY_MODS OFF CACHE BOOL "Bundle local SoapySDR modules")
set(CPACK_GENERATOR NSIS)
set(CPACK_PACKAGE_NAME "CubicSDR")
set(CPACK_PACKAGE_VENDOR "cubicsdr.com")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "CubicSDR ${CUBICSDR_VERSION} Installer")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "CubicSDR")
SET(CPACK_NSIS_INSTALLED_ICON_NAME "CubicSDR.ico")
SET(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}/icon\\\\NSIS_Header.bmp")
IF(EX_PLATFORM EQUAL 64)
SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64")
SET(CPACK_NSIS_PACKAGE_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY}")
SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION}")
set(CMAKE_CL_64 TRUE) # This gets around a bug in the CPack installer name generation for MinGW 64-bit since 2.8
ELSE(EX_PLATFORM EQUAL 64)
SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
SET(CPACK_NSIS_PACKAGE_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} (x86)")
SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION} (x86)")
set(CMAKE_CL_64 FALSE)
ENDIF(EX_PLATFORM EQUAL 64)
set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
install(TARGETS CubicSDR RUNTIME DESTINATION .)
set(CPACK_GENERATOR NSIS)
set(CPACK_PACKAGE_NAME "${CUBICSDR_INSTALL_NAME}")
set(CPACK_NSIS_DISPLAY_NAME "${CUBICSDR_INSTALL_TITLE}")
set(CPACK_PACKAGE_VENDOR "cubicsdr.com")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CUBICSDR_INSTALL_NAME}")
SET(CPACK_NSIS_INSTALLED_ICON_NAME "CubicSDR.ico")
SET(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}/icon\\\\NSIS_Header.bmp")
IF(EX_PLATFORM EQUAL 64)
SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64")
SET(CPACK_NSIS_PACKAGE_NAME "${CUBICSDR_INSTALL_NAME}")
SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CUBICSDR_INSTALL_NAME} ${CPACK_PACKAGE_VERSION}")
set(CMAKE_CL_64 TRUE) # This gets around a bug in the CPack installer name generation for MinGW 64-bit since 2.8
ELSE(EX_PLATFORM EQUAL 64)
SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
SET(CPACK_NSIS_PACKAGE_NAME "${CUBICSDR_INSTALL_NAME} (x86)")
SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CUBICSDR_INSTALL_NAME} ${CPACK_PACKAGE_VERSION} (x86)")
set(CMAKE_CL_64 FALSE)
ENDIF(EX_PLATFORM EQUAL 64)
set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
install(TARGETS CubicSDR RUNTIME DESTINATION .)
install(FILES
install(FILES
${PROJECT_SOURCE_DIR}/icon/CubicSDR.ico
${LIQUID_DLL}
DESTINATION .)
${LIQUID_DLL}
DESTINATION .)
install(FILES
install(FILES
${CUBICSDR_FONTS}
DESTINATION fonts)
IF(USE_HAMLIB)
FOREACH(HAMLIB_DLL ${HAMLIB_DLLS})
message(STATUS "Copying Hamlib DLL: ${HAMLIB_DLL}")
DESTINATION fonts)
IF (CUBICSDR_HAS_HEADER_IMAGE)
INSTALL(FILES
${CUBICSDR_HEADER_IMAGE}
DESTINATION .)
ENDIF()
IF(USE_HAMLIB)
FOREACH(HAMLIB_DLL ${HAMLIB_DLLS})
message(STATUS "Copying Hamlib DLL: ${HAMLIB_DLL}")
INSTALL( FILES
${HAMLIB_DLL}
DESTINATION .)
ENDFOREACH()
ENDIF()
${HAMLIB_DLL}
DESTINATION .)
ENDFOREACH()
ENDIF()
IF (BUNDLE_SOAPY_MODS)
ADD_DEFINITIONS(
-DBUNDLE_SOAPY_MODS=1
)
set(BUNDLED_MODS_ONLY OFF CACHE BOOL "Use bundled mods only")
IF (BUNDLED_MODS_ONLY)
ADD_DEFINITIONS(
-DBUNDLED_MODS_ONLY=1
)
ENDIF()
file(GLOB SOAPY_BINS ${SOAPY_SDR_ROOT}/bin/*.dll)
file(GLOB SOAPY_MODS ${SOAPY_SDR_ROOT}/lib/SoapySDR/modules/*.dll)
message(STATUS "SOAPY_BINS: ${SOAPY_BINS}")
message(STATUS "SOAPY_MODS: ${SOAPY_MODS}")
install(FILES ${SOAPY_BINS} DESTINATION .)
install(FILES ${SOAPY_MODS} DESTINATION modules)
ENDIF(BUNDLE_SOAPY_MODS)
IF(MSVC AND EX_PLATFORM EQUAL 32)
install(FILES
${PROJECT_SOURCE_DIR}/external/msvc/${EX_PLATFORM_NAME}/libgcc_s_dw2-1.dll
DESTINATION .)
ENDIF(MSVC AND EX_PLATFORM EQUAL 32)
IF (BUNDLE_SOAPY_MODS)
ADD_DEFINITIONS(
-DBUNDLE_SOAPY_MODS=1
)
set(BUNDLED_MODS_ONLY OFF CACHE BOOL "Use bundled mods only")
IF (BUNDLED_MODS_ONLY)
ADD_DEFINITIONS(
-DBUNDLED_MODS_ONLY=1
)
ENDIF()
file(GLOB SOAPY_BINS ${SOAPY_SDR_ROOT}/bin/*.dll)
file(GLOB SOAPY_MODS ${SOAPY_SDR_ROOT}/lib/SoapySDR/modules${SOAPY_SDR_ABI_VERSION}/*.dll)
message(STATUS "SOAPY_BINS: ${SOAPY_BINS}")
message(STATUS "SOAPY_MODS: ${SOAPY_MODS}")
install(FILES ${SOAPY_BINS} DESTINATION .)
install(FILES ${SOAPY_MODS} DESTINATION modules)
ENDIF(BUNDLE_SOAPY_MODS)
IF(MSVC AND EX_PLATFORM EQUAL 32)
install(FILES
${PROJECT_SOURCE_DIR}/external/msvc/${EX_PLATFORM_NAME}/libgcc_s_dw2-1.dll
DESTINATION .)
ENDIF(MSVC AND EX_PLATFORM EQUAL 32)
set(CPACK_PACKAGE_EXECUTABLES CubicSDR "CubicSDR")
set(CPACK_PACKAGE_EXECUTABLES CubicSDR "CubicSDR")
IF (MSVC)
install(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/external/msvc/${EX_PLATFORM_NAME}/vc_redist.${EX_PLATFORM_NAME}.exe DESTINATION vc_redist)
set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\vc_redist\\\\vc_redist.${EX_PLATFORM_NAME}.exe\\\" /q:a'")
ENDIF (MSVC)
INCLUDE(CPack)
IF (MSVC)
install(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/external/msvc/${EX_PLATFORM_NAME}/vc_redist.${EX_PLATFORM_NAME}.exe DESTINATION vc_redist)
set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\vc_redist\\\\vc_redist.${EX_PLATFORM_NAME}.exe\\\" /q:a'")
ENDIF (MSVC)
INCLUDE(CPack)
ENDIF (WIN32 AND BUILD_INSTALLER)
IF (UNIX AND NOT APPLE AND BUILD_DEB)
set(CPACK_GENERATOR DEB)
set(CPACK_PACKAGE_NAME "CubicSDR")
SET(CPACK_DEBIAN_PACKAGE_DEPENDS " libwxgtk3.0-0, libpulse0")
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Charles J. Cliffe <cj@cubicproductions.com>")
SET(CPACK_DEBIAN_PACKAGE_DESCRIPTION "CubicSDR Software Defined Radio application v${CUBICSDR_VERSION}")
SET(CPACK_DEBIAN_PACKAGE_SECTION "comm")
set(CPACK_PACKAGE_NAME "CubicSDR")
SET(CPACK_DEBIAN_PACKAGE_DEPENDS " libwxgtk3.0-0, libpulse0")
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Charles J. Cliffe <cj@cubicproductions.com>")
SET(CPACK_DEBIAN_PACKAGE_DESCRIPTION "CubicSDR Software Defined Radio application v${CUBICSDR_VERSION}")
SET(CPACK_DEBIAN_PACKAGE_SECTION "comm")
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${EX_PLATFORM_NAME}")
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${EX_PLATFORM_NAME}")
IF (NOT CMAKE_INSTALL_PREFIX)
SET(CMAKE_INSTALL_PREFIX "/usr/")
ENDIF()
ADD_DEFINITIONS(
-DRES_FOLDER="${CMAKE_INSTALL_PREFIX}/share/cubicsdr/"
-D_FORTIFY_SOURCE=2
)
ADD_DEFINITIONS(
-DRES_FOLDER="${CMAKE_INSTALL_PREFIX}/share/cubicsdr/"
-D_FORTIFY_SOURCE=2
)
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,relro")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,relro")
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/external/deb/deb_post.sh.in"
"${CMAKE_CURRENT_BINARY_DIR}/deb_post.sh" @ONLY IMMEDIATE)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/external/deb/deb_post.sh.in"
"${CMAKE_CURRENT_BINARY_DIR}/deb_post.sh" @ONLY IMMEDIATE)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/cmake/CubicSDR.desktop.in"
"${CMAKE_CURRENT_BINARY_DIR}/CubicSDR.desktop" @ONLY IMMEDIATE)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/cmake/CubicSDR.desktop.in"
"${CMAKE_CURRENT_BINARY_DIR}/CubicSDR.desktop" @ONLY IMMEDIATE)
INSTALL(TARGETS CubicSDR DESTINATION bin)
INSTALL(TARGETS CubicSDR DESTINATION bin)
install(FILES
${PROJECT_SOURCE_DIR}/src/CubicSDR.png
DESTINATION share/cubicsdr)
DESTINATION share/cubicsdr)
install(FILES
${CUBICSDR_FONTS}
DESTINATION share/cubicsdr/fonts)
DESTINATION share/cubicsdr/fonts)
INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/CubicSDR.desktop"
DESTINATION share/applications)
INCLUDE(CPack)
INCLUDE(CPack)
ENDIF()
IF(UNIX AND NOT APPLE AND NOT BUILD_DEB)
IF (NOT CMAKE_INSTALL_PREFIX)
SET(CMAKE_INSTALL_PREFIX "/usr/")
ENDIF()
ADD_DEFINITIONS(
-DRES_FOLDER="${CMAKE_INSTALL_PREFIX}/share/cubicsdr/"
)
ADD_DEFINITIONS(
-DRES_FOLDER="${CMAKE_INSTALL_PREFIX}/share/cubicsdr/"
)
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,relro")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,relro")
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/cmake/CubicSDR.desktop.in"
"${CMAKE_CURRENT_BINARY_DIR}/CubicSDR.desktop" @ONLY IMMEDIATE)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/cmake/CubicSDR.desktop.in"
"${CMAKE_CURRENT_BINARY_DIR}/CubicSDR.desktop" @ONLY IMMEDIATE)
INSTALL(TARGETS CubicSDR DESTINATION bin)
INSTALL(TARGETS CubicSDR DESTINATION bin)
INSTALL(FILES
${PROJECT_SOURCE_DIR}/src/CubicSDR.png
DESTINATION share/cubicsdr)
DESTINATION share/cubicsdr)
INSTALL(FILES
${CUBICSDR_FONTS}
DESTINATION share/cubicsdr/fonts)
DESTINATION share/cubicsdr/fonts)
IF (CUBICSDR_HAS_HEADER_IMAGE)
INSTALL(FILES
${CUBICSDR_HEADER_IMAGE}
DESTINATION share/cubicsdr)
ENDIF()
INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/CubicSDR.desktop"
DESTINATION share/applications)
DESTINATION share/applications)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/external/deb/deb_post.sh.in"
"${CMAKE_CURRENT_BINARY_DIR}/deb_post.sh" @ONLY IMMEDIATE)
"${CMAKE_CURRENT_BINARY_DIR}/deb_post.sh" @ONLY IMMEDIATE)
CONFIGURE_FILE(
"${PROJECT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"

View File

@ -31,7 +31,6 @@ long long DeviceConfig::getOffset() {
return offset.load();
}
void DeviceConfig::setSampleRate(long srate) {
sampleRate.store(srate);
}
@ -292,7 +291,13 @@ AppConfig::AppConfig() : configName("") {
centerFreq.store(100000000);
waterfallLinesPerSec.store(DEFAULT_WATERFALL_LPS);
spectrumAvgSpeed.store(0.65f);
dbOffset.store(0);
modemPropsCollapsed.store(false);
mainSplit = -1;
visSplit = -1;
bookmarkSplit = 200;
bookmarksVisible.store(true);
#ifdef USE_HAMLIB
rigEnabled.store(false);
rigModel.store(1);
@ -428,6 +433,14 @@ float AppConfig::getSpectrumAvgSpeed() {
return spectrumAvgSpeed.load();
}
void AppConfig::setDBOffset(int offset) {
this->dbOffset.store(offset);
}
int AppConfig::getDBOffset() {
return dbOffset.load();
}
void AppConfig::setManualDevices(std::vector<SDRManualDef> manuals) {
manualDevices = manuals;
}
@ -436,6 +449,39 @@ std::vector<SDRManualDef> AppConfig::getManualDevices() {
return manualDevices;
}
void AppConfig::setMainSplit(float value) {
mainSplit.store(value);
}
float AppConfig::getMainSplit() {
return mainSplit.load();
}
void AppConfig::setVisSplit(float value) {
visSplit.store(value);
}
float AppConfig::getVisSplit() {
return visSplit.load();
}
void AppConfig::setBookmarkSplit(float value) {
bookmarkSplit.store(value);
}
float AppConfig::getBookmarkSplit() {
return bookmarkSplit.load();
}
void AppConfig::setBookmarksVisible(bool state) {
bookmarksVisible.store(state);
}
bool AppConfig::getBookmarksVisible() {
return bookmarksVisible.load();
}
void AppConfig::setConfigName(std::string configName) {
this->configName = configName;
}
@ -481,6 +527,12 @@ bool AppConfig::save() {
*window_node->newChild("waterfall_lps") = waterfallLinesPerSec.load();
*window_node->newChild("spectrum_avg") = spectrumAvgSpeed.load();
*window_node->newChild("modemprops_collapsed") = modemPropsCollapsed.load();;
*window_node->newChild("db_offset") = dbOffset.load();
*window_node->newChild("main_split") = mainSplit.load();
*window_node->newChild("vis_split") = visSplit.load();
*window_node->newChild("bookmark_split") = bookmarkSplit.load();
*window_node->newChild("bookmark_visible") = bookmarksVisible.load();
}
DataNode *devices_node = cfg.rootNode()->newChild("devices");
@ -631,6 +683,37 @@ bool AppConfig::load() {
win_node->getNext("modemprops_collapsed")->element()->get(mpc);
modemPropsCollapsed.store(mpc?true:false);
}
if (win_node->hasAnother("db_offset")) {
DataNode *offset_node = win_node->getNext("db_offset");
int offsetValue = 0;
offset_node->element()->get(offsetValue);
setDBOffset(offsetValue);
}
if (win_node->hasAnother("main_split")) {
float gVal;
win_node->getNext("main_split")->element()->get(gVal);
mainSplit.store(gVal);
}
if (win_node->hasAnother("vis_split")) {
float gVal;
win_node->getNext("vis_split")->element()->get(gVal);
visSplit.store(gVal);
}
if (win_node->hasAnother("bookmark_split")) {
float gVal;
win_node->getNext("bookmark_split")->element()->get(gVal);
bookmarkSplit.store(gVal);
}
if (win_node->hasAnother("bookmark_visible")) {
int bVal;
win_node->getNext("bookmark_visible")->element()->get(bVal);
bookmarksVisible.store(bVal);
}
}
if (cfg.rootNode()->hasAnother("devices")) {

View File

@ -115,9 +115,25 @@ public:
void setSpectrumAvgSpeed(float avgSpeed);
float getSpectrumAvgSpeed();
void setDBOffset(int offset);
int getDBOffset();
void setManualDevices(std::vector<SDRManualDef> manuals);
std::vector<SDRManualDef> getManualDevices();
void setMainSplit(float value);
float getMainSplit();
void setVisSplit(float value);
float getVisSplit();
void setBookmarkSplit(float value);
float getBookmarkSplit();
void setBookmarksVisible(bool state);
bool getBookmarksVisible();
#if USE_HAMLIB
int getRigModel();
void setRigModel(int rigModel);
@ -160,11 +176,12 @@ private:
std::atomic_llong snap;
std::atomic_llong centerFreq;
std::atomic_int waterfallLinesPerSec;
std::atomic<float> spectrumAvgSpeed;
std::atomic<float> spectrumAvgSpeed, mainSplit, visSplit, bookmarkSplit;
std::atomic_int dbOffset;
std::vector<SDRManualDef> manualDevices;
#if USE_HAMLIB
std::atomic_int rigModel, rigRate;
std::string rigPort;
std::atomic_bool rigEnabled, rigFollowMode, rigControlMode, rigCenterLock, rigFollowModem;
std::atomic_bool rigEnabled, rigFollowMode, rigControlMode, rigCenterLock, rigFollowModem, bookmarksVisible;
#endif
};

View File

@ -23,6 +23,7 @@
#include "DataTree.h"
#include "ColorTheme.h"
#include "DemodulatorMgr.h"
#include "ImagePanel.h"
#include <thread>
@ -46,6 +47,10 @@ wxEND_EVENT_TABLE()
#include "RigThread.h"
#endif
/* split a string by 'seperator' into a vector of string */
std::vector<std::string> str_explode(const std::string &seperator, const std::string &in_str);
#define APPFRAME_MODEMPROPS_MINSIZE 20
#define APPFRAME_MODEMPROPS_MAXSIZE 240
@ -57,7 +62,6 @@ AppFrame::AppFrame() :
#endif
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *demodVisuals = new wxBoxSizer(wxVERTICAL);
demodTray = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *demodScopeTray = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *demodTunerTray = new wxBoxSizer(wxHORIZONTAL);
@ -68,10 +72,30 @@ AppFrame::AppFrame() :
//attribList.PlatformDefaults().MinRGBA(8, 8, 8, 8).DoubleBuffer().Depth(16).EndList();
mainSplitter = new wxSplitterWindow( this, wxID_MAIN_SPLITTER, wxDefaultPosition, wxDefaultSize, wxSP_3DSASH | wxSP_LIVE_UPDATE );
mainSplitter->SetSashGravity(10.0/37.0);
mainSplitter->SetSashGravity(10.0f / 37.0f);
mainSplitter->SetMinimumPaneSize(1);
wxPanel *demodPanel = new wxPanel(mainSplitter, wxID_ANY);
#ifdef CUBICSDR_HEADER_IMAGE
wxFileName exePath = wxFileName(wxStandardPaths::Get().GetExecutablePath());
std::string headerPath = exePath.GetPath().ToStdString();
headerPath += filePathSeparator + std::string("" CUBICSDR_HEADER_IMAGE);
wxInitAllImageHandlers();
ImagePanel *imgPanel = new ImagePanel(demodPanel, headerPath, wxBITMAP_TYPE_ANY);
std::string headerBgColor = "" CUBICSDR_HEADER_BG;
if (headerBgColor != "") {
imgPanel->SetBackgroundColour(wxColour(headerBgColor));
}
imgPanel->SetBestFittingSize(wxSize(200, 0));
demodTray->Add(imgPanel, 0, wxEXPAND | wxALL, 0);
demodTray->AddSpacer(1);
#endif
gainCanvas = new GainCanvas(demodPanel, attribList);
@ -80,16 +104,24 @@ AppFrame::AppFrame() :
gainSpacerItem = demodTray->AddSpacer(1);
gainSpacerItem->Show(false);
std::string modemListArr[] = { "FM", "FMS", "NBFM", "AM", "LSB", "USB", "DSB", "I/Q" };
std::vector<std::string> modemList( modemListArr, modemListArr + 8 );
#ifdef CUBICSDR_MODEM_EXCLUDE
std::string excludeListStr = "" CUBICSDR_MODEM_EXCLUDE;
std::vector<std::string> excludeList = str_explode(",",excludeListStr);
for (auto ex_i : excludeList) {
std::vector<std::string>::iterator found_i = std::find(modemList.begin(),modemList.end(),ex_i);
if (found_i != modemList.end()) {
modemList.erase(found_i);
}
}
#endif
demodModeSelector = new ModeSelectorCanvas(demodPanel, attribList);
demodModeSelector->addChoice("FM");
demodModeSelector->addChoice("FMS");
demodModeSelector->addChoice("NBFM");
demodModeSelector->addChoice("AM");
demodModeSelector->addChoice("LSB");
demodModeSelector->addChoice("USB");
demodModeSelector->addChoice("DSB");
demodModeSelector->addChoice("I/Q");
demodModeSelector->setSelection("FM");
for (auto mt_i : modemList) {
demodModeSelector->addChoice(mt_i);
}
demodModeSelector->setHelpTip("Choose modulation type: Frequency Modulation (Hotkey F), Amplitude Modulation (A) and Lower (L), Upper (U), Double Side-Band and more.");
demodModeSelector->SetMinSize(wxSize(50,-1));
demodModeSelector->SetMaxSize(wxSize(50,-1));
@ -120,13 +152,19 @@ AppFrame::AppFrame() :
modemProps->SetMinSize(wxSize(APPFRAME_MODEMPROPS_MAXSIZE,-1));
modemProps->SetMaxSize(wxSize(APPFRAME_MODEMPROPS_MAXSIZE,-1));
modemProps->Hide();
ModemArgInfoList dummyInfo;
modemProps->initProperties(dummyInfo, nullptr);
modemProps->updateTheme();
demodTray->Add(modemProps, 15, wxEXPAND | wxALL, 0);
#ifndef __APPLE__
demodTray->AddSpacer(1);
#endif
#if CUBICSDR_ENABLE_VIEW_DEMOD
wxBoxSizer *demodVisuals = new wxBoxSizer(wxVERTICAL);
wxGetApp().getDemodSpectrumProcessor()->setup(1024);
demodSpectrumCanvas = new SpectrumCanvas(demodPanel, attribList);
demodSpectrumCanvas->setView(wxGetApp().getConfig()->getCenterFreq(), 300000);
@ -150,7 +188,11 @@ AppFrame::AppFrame() :
demodTray->Add(demodVisuals, 30, wxEXPAND | wxALL, 0);
demodTray->AddSpacer(1);
#else
demodSpectrumCanvas = nullptr;
demodWaterfallCanvas = nullptr;
#endif
demodSignalMeter = new MeterCanvas(demodPanel, attribList);
demodSignalMeter->setMax(DEMOD_SIGNAL_MAX);
demodSignalMeter->setMin(DEMOD_SIGNAL_MIN);
@ -163,6 +205,7 @@ AppFrame::AppFrame() :
demodTray->AddSpacer(1);
#if CUBICSDR_ENABLE_VIEW_SCOPE
scopeCanvas = new ScopeCanvas(demodPanel, attribList);
scopeCanvas->setHelpTip("Audio Visuals, drag left/right to toggle Scope or Spectrum.");
scopeCanvas->SetMinSize(wxSize(128,-1));
@ -171,7 +214,10 @@ AppFrame::AppFrame() :
wxGetApp().getScopeProcessor()->attachOutput(scopeCanvas->getInputQueue());
demodScopeTray->AddSpacer(1);
#else
scopeCanvas = nullptr;
#endif
deltaLockButton = new ModeSelectorCanvas(demodPanel, attribList);
deltaLockButton->addChoice(1, "V");
deltaLockButton->setPadding(-1,-1);
@ -235,10 +281,13 @@ AppFrame::AppFrame() :
// vbox->Add(demodTray, 12, wxEXPAND | wxALL, 0);
// vbox->AddSpacer(1);
mainVisSplitter = new wxSplitterWindow( mainSplitter, wxID_VIS_SPLITTER, wxDefaultPosition, wxDefaultSize, wxSP_3DSASH | wxSP_LIVE_UPDATE );
mainVisSplitter->SetSashGravity(6.0/25.0);
bookmarkSplitter = new wxSplitterWindow( mainSplitter, wxID_BM_SPLITTER, wxDefaultPosition, wxDefaultSize, wxSP_3DSASH | wxSP_LIVE_UPDATE );
bookmarkSplitter->SetMinimumPaneSize(1);
bookmarkSplitter->SetSashGravity(1.0f / 20.0f);
mainVisSplitter = new wxSplitterWindow( bookmarkSplitter, wxID_VIS_SPLITTER, wxDefaultPosition, wxDefaultSize, wxSP_3DSASH | wxSP_LIVE_UPDATE );
mainVisSplitter->SetMinimumPaneSize(1);
mainVisSplitter->SetSashGravity(6.0f / 25.0f);
// mainVisSplitter->Connect( wxEVT_IDLE, wxIdleEventHandler( AppFrame::mainVisSplitterIdle ), NULL, this );
@ -248,6 +297,7 @@ AppFrame::AppFrame() :
wxGetApp().getSpectrumProcessor()->setup(2048);
spectrumCanvas = new SpectrumCanvas(spectrumPanel, attribList);
spectrumCanvas->setShowDb(true);
spectrumCanvas->setUseDBOfs(true);
spectrumCanvas->setScaleFactorEnabled(true);
wxGetApp().getSpectrumProcessor()->attachOutput(spectrumCanvas->getVisualDataQueue());
@ -312,10 +362,19 @@ AppFrame::AppFrame() :
// vbox->Add(wfSizer, 20, wxEXPAND | wxALL, 0);
mainVisSplitter->SplitHorizontally( spectrumPanel, waterfallPanel, 0 );
mainSplitter->SplitHorizontally( demodPanel, mainVisSplitter );
bookmarkView = new BookmarkView(bookmarkSplitter, wxID_ANY, wxDefaultPosition, wxSize(120,-1));
bookmarkSplitter->SplitVertically( bookmarkView, mainVisSplitter );
mainSplitter->SplitHorizontally( demodPanel, bookmarkSplitter );
if (!wxGetApp().getConfig()->getBookmarksVisible()) {
bookmarkSplitter->Unsplit(bookmarkView);
bookmarkSplitter->Layout();
}
vbox->Add(mainSplitter, 1, wxEXPAND | wxALL, 0);
// TODO: refactor these..
waterfallCanvas->attachSpectrumCanvas(spectrumCanvas);
spectrumCanvas->attachWaterfallCanvas(waterfallCanvas);
@ -378,6 +437,8 @@ AppFrame::AppFrame() :
}
i++;
}
wxGetApp().getDemodMgr().setOutputDevices(outputDevices);
//
// for (mdevices_i = outputDevices.begin(); mdevices_i != outputDevices.end(); mdevices_i++) {
// wxMenuItem *itm = menu->AppendRadioItem(wxID_RT_AUDIO_DEVICE + mdevices_i->first, mdevices_i->second.name, wxT("Description?"));
@ -470,6 +531,9 @@ AppFrame::AppFrame() :
themeMenu->AppendRadioItem(wxID_THEME_HD, "HD")->Check(themeId==COLOR_THEME_HD);
displayMenu->AppendSubMenu(themeMenu, wxT("&Color Scheme"));
hideBookmarksItem = displayMenu->AppendCheckItem(wxID_DISPLAY_BOOKMARKS, wxT("Hide Bookmarks"));
hideBookmarksItem->Check(!wxGetApp().getConfig()->getBookmarksVisible());
GLFont::setScale((GLFont::GLFontScale)fontScale);
@ -588,13 +652,27 @@ AppFrame::AppFrame() :
waterfallCanvas->setLinesPerSecond(wflps);
ThemeMgr::mgr.setTheme(wxGetApp().getConfig()->getTheme());
bookmarkView->updateTheme();
int mpc =wxGetApp().getConfig()->getModemPropsCollapsed();
if (mpc) {
modemProps->setCollapsed(true);
}
int msPos = wxGetApp().getConfig()->getMainSplit();
if (msPos != -1) {
mainSplitter->SetSashPosition(msPos);
}
int bsPos = wxGetApp().getConfig()->getBookmarkSplit();
if (bsPos != -1) {
bookmarkSplitter->SetSashPosition(bsPos);
}
int vsPos = wxGetApp().getConfig()->getVisSplit();
if (vsPos != -1) {
mainVisSplitter->SetSashPosition(vsPos);
}
Show();
#ifdef _WIN32
@ -611,6 +689,7 @@ AppFrame::AppFrame() :
deviceChanged.store(false);
devInfo = NULL;
wxGetApp().deviceSelector();
saveDisabled = false;
// static const int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
// wxLogStatus("Double-buffered display %s supported", wxGLCanvas::IsDisplaySupported(attribs) ? "is" : "not");
@ -652,6 +731,7 @@ void AppFrame::updateDeviceParams() {
newSettingsMenu->AppendSeparator();
newSettingsMenu->Append(wxID_SET_DB_OFFSET, "Power Level Offset");
newSettingsMenu->Append(wxID_SET_FREQ_OFFSET, "Frequency Offset");
if (devInfo->hasCORR(SOAPY_SDR_RX, 0)) {
@ -867,6 +947,12 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
if (ofs != -1) {
wxGetApp().setOffset(ofs);
}
} else if (event.GetId() == wxID_SET_DB_OFFSET) {
long ofs = wxGetNumberFromUser("Shift the displayed RF power level by this amount.\ni.e. -30 for -30 dB", "Decibels (dB)",
"Power Level Offset", wxGetApp().getConfig()->getDBOffset(), -1000, 1000, this);
if (ofs != -1) {
wxGetApp().getConfig()->setDBOffset(ofs);
}
} else if (event.GetId() == wxID_AGC_CONTROL) {
if (wxGetApp().getDevice() == NULL) {
agcMenuItem->Check(true);
@ -937,6 +1023,9 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
demodTuner->Refresh();
SetTitle(CUBICSDR_TITLE);
currentSessionFile = "";
bookmarkSplitter->Unsplit(bookmarkView);
bookmarkSplitter->SplitVertically( bookmarkView, mainVisSplitter, wxGetApp().getConfig()->getBookmarkSplit() );
hideBookmarksItem->Check(false);
} else if (event.GetId() == wxID_CLOSE || event.GetId() == wxID_EXIT) {
Close(false);
} else if (event.GetId() == wxID_THEME_DEFAULT) {
@ -969,6 +1058,14 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
GLFont::setScale(GLFont::GLFONT_SCALE_LARGE);
//force all windows refresh
Refresh();
} else if (event.GetId() == wxID_DISPLAY_BOOKMARKS) {
if (hideBookmarksItem->IsChecked()) {
bookmarkSplitter->Unsplit(bookmarkView);
bookmarkSplitter->Layout();
} else {
bookmarkSplitter->SplitVertically( bookmarkView, mainVisSplitter, wxGetApp().getConfig()->getBookmarkSplit() );
bookmarkSplitter->Layout();
}
}
if (event.GetId() >= wxID_SETTINGS_BASE && event.GetId() < settingsIdMax) {
@ -1029,6 +1126,7 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
spectrumAvgMeter->Refresh();
gainCanvas->setThemeColors();
modemProps->updateTheme();
bookmarkView->updateTheme();
}
switch (event.GetId()) {
@ -1212,10 +1310,17 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
void AppFrame::OnClose(wxCloseEvent& event) {
wxGetApp().closeDeviceSelector();
wxGetApp().getDemodSpectrumProcessor()->removeOutput(demodSpectrumCanvas->getVisualDataQueue());
wxGetApp().getDemodSpectrumProcessor()->removeOutput(demodWaterfallCanvas->getVisualDataQueue());
if (wxGetApp().getDemodSpectrumProcessor()) {
wxGetApp().getDemodSpectrumProcessor()->removeOutput(demodSpectrumCanvas->getVisualDataQueue());
wxGetApp().getDemodSpectrumProcessor()->removeOutput(demodWaterfallCanvas->getVisualDataQueue());
}
wxGetApp().getSpectrumProcessor()->removeOutput(spectrumCanvas->getVisualDataQueue());
if (saveDisabled) {
event.Skip();
return;
}
wxGetApp().getConfig()->setWindow(this->GetPosition(), this->GetClientSize());
wxGetApp().getConfig()->setWindowMaximized(this->IsMaximized());
wxGetApp().getConfig()->setTheme(ThemeMgr::mgr.getTheme());
@ -1226,6 +1331,10 @@ void AppFrame::OnClose(wxCloseEvent& event) {
wxGetApp().getConfig()->setWaterfallLinesPerSec(waterfallDataThread->getLinesPerSecond());
wxGetApp().getConfig()->setManualDevices(SDREnumerator::getManuals());
wxGetApp().getConfig()->setModemPropsCollapsed(modemProps->isCollapsed());
wxGetApp().getConfig()->setMainSplit(mainSplitter->GetSashPosition());
wxGetApp().getConfig()->setVisSplit(mainVisSplitter->GetSashPosition());
if (!hideBookmarksItem->IsChecked()) wxGetApp().getConfig()->setBookmarkSplit(bookmarkSplitter->GetSashPosition());
wxGetApp().getConfig()->setBookmarksVisible(!hideBookmarksItem->IsChecked());
#ifdef USE_HAMLIB
wxGetApp().getConfig()->setRigEnabled(rigEnableMenuItem->IsChecked());
wxGetApp().getConfig()->setRigModel(rigModel);
@ -1237,6 +1346,7 @@ void AppFrame::OnClose(wxCloseEvent& event) {
wxGetApp().getConfig()->setRigFollowModem(rigFollowModemMenuItem->IsChecked());
#endif
wxGetApp().getConfig()->save();
wxGetApp().getBookmarkMgr().saveToFile("bookmarks.xml");
event.Skip();
}
@ -1244,6 +1354,7 @@ void AppFrame::OnNewWindow(wxCommandEvent& WXUNUSED(event)) {
new AppFrame();
}
void AppFrame::OnThread(wxCommandEvent& event) {
event.Skip();
}
@ -1284,7 +1395,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
demodGainMeter->setInputValue(demod->getGain());
wxGetApp().getDemodMgr().setLastGain(demod->getGain());
int outputDevice = demod->getOutputDevice();
scopeCanvas->setDeviceName(outputDevices[outputDevice].name);
if (scopeCanvas) scopeCanvas->setDeviceName(outputDevices[outputDevice].name);
// outputDeviceMenuItems[outputDevice]->Check(true);
std::string dType = demod->getDemodulatorType();
demodModeSelector->setSelection(dType);
@ -1296,7 +1407,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
modemPropertiesUpdated.store(true);
demodTuner->setHalfBand(dType=="USB" || dType=="LSB");
}
if (demodWaterfallCanvas->getDragState() == WaterfallCanvas::WF_DRAG_NONE) {
if (!demodWaterfallCanvas || demodWaterfallCanvas->getDragState() == WaterfallCanvas::WF_DRAG_NONE) {
long long centerFreq = demod->getFrequency();
unsigned int demodBw = (unsigned int) ceil((float) demod->getBandwidth() * 2.25);
@ -1317,7 +1428,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
demodBw = 20000;
}
if (centerFreq != demodWaterfallCanvas->getCenterFrequency()) {
if (demodWaterfallCanvas && centerFreq != demodWaterfallCanvas->getCenterFrequency()) {
demodWaterfallCanvas->setCenterFrequency(centerFreq);
demodSpectrumCanvas->setCenterFrequency(centerFreq);
}
@ -1403,8 +1514,10 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
}
}
demodWaterfallCanvas->setBandwidth(demodBw);
demodSpectrumCanvas->setBandwidth(demodBw);
if (demodWaterfallCanvas) {
demodWaterfallCanvas->setBandwidth(demodBw);
demodSpectrumCanvas->setBandwidth(demodBw);
}
}
demodSignalMeter->setLevel(demod->getSignalLevel());
@ -1460,9 +1573,9 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
demodGainMeter->setLevel(demodGainMeter->getInputValue());
}
if (wxGetApp().getFrequency() != demodWaterfallCanvas->getCenterFrequency()) {
if (demodWaterfallCanvas && wxGetApp().getFrequency() != demodWaterfallCanvas->getCenterFrequency()) {
demodWaterfallCanvas->setCenterFrequency(wxGetApp().getFrequency());
demodSpectrumCanvas->setCenterFrequency(wxGetApp().getFrequency());
if (demodSpectrumCanvas) demodSpectrumCanvas->setCenterFrequency(wxGetApp().getFrequency());
}
if (spectrumCanvas->getViewState() && abs(wxGetApp().getFrequency()-spectrumCanvas->getCenterFrequency()) > (wxGetApp().getSampleRate()/2)) {
spectrumCanvas->setCenterFrequency(wxGetApp().getFrequency());
@ -1479,15 +1592,17 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
}
}
scopeCanvas->setPPMMode(demodTuner->isAltDown());
if (scopeCanvas) {
scopeCanvas->setPPMMode(demodTuner->isAltDown());
scopeCanvas->setShowDb(spectrumCanvas->getShowDb());
wxGetApp().getScopeProcessor()->setScopeEnabled(scopeCanvas->scopeVisible());
wxGetApp().getScopeProcessor()->setSpectrumEnabled(scopeCanvas->spectrumVisible());
wxGetApp().getAudioVisualQueue()->set_max_num_items((scopeCanvas->scopeVisible()?1:0) + (scopeCanvas->spectrumVisible()?1:0));
wxGetApp().getScopeProcessor()->run();
}
scopeCanvas->setShowDb(spectrumCanvas->getShowDb());
wxGetApp().getScopeProcessor()->setScopeEnabled(scopeCanvas->scopeVisible());
wxGetApp().getScopeProcessor()->setSpectrumEnabled(scopeCanvas->spectrumVisible());
wxGetApp().getAudioVisualQueue()->set_max_num_items((scopeCanvas->scopeVisible()?1:0) + (scopeCanvas->spectrumVisible()?1:0));
wxGetApp().getScopeProcessor()->run();
SpectrumVisualProcessor *proc = wxGetApp().getSpectrumProcessor();
if (spectrumAvgMeter->inputChanged()) {
@ -1505,9 +1620,11 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
}
SpectrumVisualProcessor *dproc = wxGetApp().getDemodSpectrumProcessor();
dproc->setView(demodWaterfallCanvas->getViewState(), demodWaterfallCanvas->getCenterFrequency(),demodWaterfallCanvas->getBandwidth());
if (dproc) {
dproc->setView(demodWaterfallCanvas->getViewState(), demodWaterfallCanvas->getCenterFrequency(),demodWaterfallCanvas->getBandwidth());
}
SpectrumVisualProcessor *wproc = waterfallDataThread->getProcessor();
if (waterfallSpeedMeter->inputChanged()) {
@ -1539,13 +1656,15 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
ModemDigitalOutputConsole *outp = (ModemDigitalOutputConsole *)demod->getOutput();
if (!outp->getDialog()) {
outp->setTitle(demod->getDemodulatorType() + ": " + frequencyToStr(demod->getFrequency()));
outp->setDialog(new DigitalConsole(this, outp));
outp->setDialog(new DigitalConsole(this, outp)) ;
}
demod->showOutput();
}
#endif
} else if (!demod) {
modemProps->Hide();
} else if (!demod && modemPropertiesUpdated.load()) {
ModemArgInfoList dummyInfo;
modemProps->initProperties(dummyInfo, nullptr);
modemProps->updateTheme();
demodTray->Layout();
}
@ -1566,7 +1685,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
wxGetApp().getSpectrumProcessor()->setPeakHold(peakHoldMode == 1);
//make the peak hold act on the current dmod also, like a zoomed-in version.
wxGetApp().getDemodSpectrumProcessor()->setPeakHold(peakHoldMode == 1);
if (wxGetApp().getDemodSpectrumProcessor()) wxGetApp().getDemodSpectrumProcessor()->setPeakHold(peakHoldMode == 1);
peakHoldButton->clearModeChanged();
}
@ -1580,7 +1699,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
#endif
#ifdef _WIN32
if (scopeCanvas->HasFocus()) {
if (scopeCanvas && scopeCanvas->HasFocus()) {
waterfallCanvas->SetFocus();
}
#endif
@ -1652,35 +1771,10 @@ void AppFrame::saveSession(std::string fileName) {
DataNode *demods = s.rootNode()->newChild("demodulators");
std::vector<DemodulatorInstance *> &instances = wxGetApp().getDemodMgr().getDemodulators();
std::vector<DemodulatorInstance *>::iterator instance_i;
for (instance_i = instances.begin(); instance_i != instances.end(); instance_i++) {
for (auto instance_i : instances) {
DataNode *demod = demods->newChild("demodulator");
*demod->newChild("bandwidth") = (*instance_i)->getBandwidth();
*demod->newChild("frequency") = (*instance_i)->getFrequency();
*demod->newChild("type") = (*instance_i)->getDemodulatorType();
demod->newChild("user_label")->element()->set((*instance_i)->getDemodulatorUserLabel());
*demod->newChild("squelch_level") = (*instance_i)->getSquelchLevel();
*demod->newChild("squelch_enabled") = (*instance_i)->isSquelchEnabled() ? 1 : 0;
*demod->newChild("output_device") = outputDevices[(*instance_i)->getOutputDevice()].name;
*demod->newChild("gain") = (*instance_i)->getGain();
*demod->newChild("muted") = (*instance_i)->isMuted() ? 1 : 0;
if ((*instance_i)->isDeltaLock()) {
*demod->newChild("delta_lock") = (*instance_i)->isDeltaLock() ? 1 : 0;
*demod->newChild("delta_ofs") = (*instance_i)->getDeltaLockOfs();
}
if ((*instance_i) == wxGetApp().getDemodMgr().getLastActiveDemodulator()) {
*demod->newChild("active") = 1;
}
ModemSettings saveSettings = (*instance_i)->readModemSettings();
if (saveSettings.size()) {
DataNode *settingsNode = demod->newChild("settings");
for (ModemSettings::const_iterator msi = saveSettings.begin(); msi != saveSettings.end(); msi++) {
*settingsNode->newChild(msi->first.c_str()) = msi->second;
}
}
wxGetApp().getDemodMgr().saveInstance(demod, instance_i);
} //end for demodulators
// Make sure the file name actually ends in .xml
@ -1754,7 +1848,6 @@ bool AppFrame::loadSession(std::string fileName) {
DataNode *demodulators = l.rootNode()->getNext("demodulators");
int numDemodulators = 0;
std::vector<DemodulatorInstance *> demodsLoaded;
while (demodulators->hasAnother("demodulator")) {
@ -1764,122 +1857,15 @@ bool AppFrame::loadSession(std::string fileName) {
continue;
}
long bandwidth = *demod->getNext("bandwidth");
long long freq = *demod->getNext("frequency");
float squelch_level = demod->hasAnother("squelch_level") ? (float) *demod->getNext("squelch_level") : 0;
int squelch_enabled = demod->hasAnother("squelch_enabled") ? (int) *demod->getNext("squelch_enabled") : 0;
int muted = demod->hasAnother("muted") ? (int) *demod->getNext("muted") : 0;
int delta_locked = demod->hasAnother("delta_lock") ? (int) *demod->getNext("delta_lock") : 0;
int delta_ofs = demod->hasAnother("delta_ofs") ? (int) *demod->getNext("delta_ofs") : 0;
std::string output_device = demod->hasAnother("output_device") ? string(*(demod->getNext("output_device"))) : "";
float gain = demod->hasAnother("gain") ? (float) *demod->getNext("gain") : 1.0;
newDemod = wxGetApp().getDemodMgr().loadInstance(demod);
std::string type = "FM";
DataNode *demodTypeNode = demod->hasAnother("type")?demod->getNext("type"):nullptr;
if (demodTypeNode && demodTypeNode->element()->getDataType() == DATA_INT) {
int legacyType = *demodTypeNode;
int legacyStereo = demod->hasAnother("stereo") ? (int) *demod->getNext("stereo") : 0;
switch (legacyType) { // legacy demod ID
case 1: type = legacyStereo?"FMS":"FM"; break;
case 2: type = "AM"; break;
case 3: type = "LSB"; break;
case 4: type = "USB"; break;
case 5: type = "DSB"; break;
case 6: type = "ASK"; break;
case 7: type = "APSK"; break;
case 8: type = "BPSK"; break;
case 9: type = "DPSK"; break;
case 10: type = "PSK"; break;
case 11: type = "OOK"; break;
case 12: type = "ST"; break;
case 13: type = "SQAM"; break;
case 14: type = "QAM"; break;
case 15: type = "QPSK"; break;
case 16: type = "I/Q"; break;
default: type = "FM"; break;
}
} else if (demodTypeNode && demodTypeNode->element()->getDataType() == DATA_STRING) {
demodTypeNode->element()->get(type);
}
//read the user label associated with the demodulator
std::wstring user_label = L"";
DataNode *demodUserLabel = demod->hasAnother("user_label") ? demod->getNext("user_label") : nullptr;
if (demodUserLabel) {
demodUserLabel->element()->get(user_label);
}
ModemSettings mSettings;
if (demod->hasAnother("settings")) {
DataNode *modemSettings = demod->getNext("settings");
for (int msi = 0, numSettings = modemSettings->numChildren(); msi < numSettings; msi++) {
DataNode *settingNode = modemSettings->child(msi);
std::string keyName = settingNode->getName();
std::string strSettingValue = settingNode->element()->toString();
if (keyName != "" && strSettingValue != "") {
mSettings[keyName] = strSettingValue;
}
}
}
newDemod = wxGetApp().getDemodMgr().newThread();
if (demod->hasAnother("active")) {
loadedActiveDemod = newDemod;
}
numDemodulators++;
newDemod->setDemodulatorType(type);
newDemod->setDemodulatorUserLabel(user_label);
newDemod->writeModemSettings(mSettings);
newDemod->setBandwidth(bandwidth);
newDemod->setFrequency(freq);
newDemod->setGain(gain);
newDemod->updateLabel(freq);
newDemod->setMuted(muted?true:false);
if (delta_locked) {
newDemod->setDeltaLock(true);
newDemod->setDeltaLockOfs(delta_ofs);
}
if (squelch_enabled) {
newDemod->setSquelchEnabled(true);
newDemod->setSquelchLevel(squelch_level);
}
bool found_device = false;
std::map<int, RtAudio::DeviceInfo>::iterator i;
for (i = outputDevices.begin(); i != outputDevices.end(); i++) {
if (i->second.name == output_device) {
newDemod->setOutputDevice(i->first);
found_device = true;
}
}
// if (!found_device) {
// std::cout << "\tWarning: named output device '" << output_device << "' was not found. Using default output.";
// }
newDemod->run();
newDemod->setActive(true);
demodsLoaded.push_back(newDemod);
// wxGetApp().bindDemodulator(newDemod);
std::cout << "\tAdded demodulator at frequency " << newDemod->getFrequency() << " type " << type << std::endl;
// std::cout << "\t\tBandwidth: " << bandwidth << std::endl;
// std::cout << "\t\tSquelch Level: " << squelch_level << std::endl;
// std::cout << "\t\tSquelch Enabled: " << (squelch_enabled ? "true" : "false") << std::endl;
// std::cout << "\t\tOutput Device: " << output_device << std::endl;
}
if (demodsLoaded.size()) {
@ -1925,6 +1911,8 @@ bool AppFrame::loadSession(std::string fileName) {
GetStatusBar()->SetStatusText(wxString::Format(wxT("Loaded session file: %s"), currentSessionFile.c_str()));
SetTitle(wxString::Format(wxT("%s: %s"), CUBICSDR_TITLE, filePart.c_str()));
wxGetApp().getBookmarkMgr().updateActiveList();
return true;
}
@ -1945,7 +1933,7 @@ void AppFrame::setMainWaterfallFFTSize(int fftSize) {
}
void AppFrame::setScopeDeviceName(std::string deviceName) {
scopeCanvas->setDeviceName(deviceName);
if (scopeCanvas) scopeCanvas->setDeviceName(deviceName);
}
@ -1957,12 +1945,20 @@ void AppFrame::refreshGainUI() {
bool AppFrame::isUserDemodBusy() {
return (modemProps && modemProps->isMouseInView())
|| (waterfallCanvas->isMouseInView() && waterfallCanvas->isMouseDown())
|| (demodWaterfallCanvas->isMouseInView() && demodWaterfallCanvas->isMouseDown())
|| (demodWaterfallCanvas && demodWaterfallCanvas->isMouseInView() && demodWaterfallCanvas->isMouseDown())
|| (wxGetApp().getDemodMgr().getLastActiveDemodulator() &&
wxGetApp().getDemodMgr().getActiveDemodulator() &&
wxGetApp().getDemodMgr().getLastActiveDemodulator() != wxGetApp().getDemodMgr().getActiveDemodulator());
}
BookmarkView *AppFrame::getBookmarkView() {
return bookmarkView;
}
void AppFrame::disableSave(bool state) {
saveDisabled = state;
}
#ifdef _WIN32
bool AppFrame::canFocus() {
@ -2022,6 +2018,10 @@ int AppFrame::OnGlobalKeyDown(wxKeyEvent &event) {
return -1;
}
if (bookmarkView && bookmarkView->isMouseInView()) {
return -1;
}
DemodulatorInstance *demod = nullptr, *lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
int snap = wxGetApp().getFrequencySnap();
@ -2123,6 +2123,10 @@ int AppFrame::OnGlobalKeyUp(wxKeyEvent &event) {
return -1;
}
if (bookmarkView && bookmarkView->isMouseInView()) {
return -1;
}
if (event.ControlDown()) {
return 1;
}
@ -2195,7 +2199,7 @@ int AppFrame::OnGlobalKeyUp(wxKeyEvent &event) {
break;
case 'P':
wxGetApp().getSpectrumProcessor()->setPeakHold(!wxGetApp().getSpectrumProcessor()->getPeakHold());
wxGetApp().getDemodSpectrumProcessor()->setPeakHold(wxGetApp().getSpectrumProcessor()->getPeakHold());
if (wxGetApp().getDemodSpectrumProcessor()) wxGetApp().getDemodSpectrumProcessor()->setPeakHold(wxGetApp().getSpectrumProcessor()->getPeakHold());
peakHoldButton->setSelection(wxGetApp().getSpectrumProcessor()->getPeakHold()?1:0);
peakHoldButton->clearModeChanged();
break;
@ -2246,3 +2250,42 @@ void AppFrame::setViewState(long long center_freq) {
spectrumCanvas->disableView();
waterfallCanvas->disableView();
}
long long AppFrame::getViewCenterFreq() {
return waterfallCanvas->getCenterFrequency();
}
int AppFrame::getViewBandwidth() {
return waterfallCanvas->getBandwidth();
}
/* split a string by 'seperator' into a vector of string */
std::vector<std::string> str_explode(const std::string &seperator, const std::string &in_str)
{
std::vector<std::string> vect_out;
int i = 0, j = 0;
int seperator_len = seperator.length();
int str_len = in_str.length();
while(i < str_len)
{
j = in_str.find_first_of(seperator,i);
if (j == std::string::npos && i < str_len) j = str_len;
if (j == std::string::npos) break;
vect_out.push_back(in_str.substr(i,j-i));
i = j;
i+=seperator_len;
}
return vect_out;
}

View File

@ -7,6 +7,8 @@
#include <wx/panel.h>
#include <wx/splitter.h>
#include <wx/sizer.h>
#include <wx/bitmap.h>
#include <wx/statbmp.h>
#include "PrimaryGLContext.h"
@ -22,6 +24,7 @@
#include "ModemProperties.h"
//#include "UITestCanvas.h"
#include "FrequencyDialog.h"
#include "BookmarkView.h"
#include <map>
@ -35,9 +38,11 @@
#define wxID_AGC_CONTROL 2009
#define wxID_SDR_START_STOP 2010
#define wxID_LOW_PERF 2011
#define wxID_SET_DB_OFFSET 2012
#define wxID_MAIN_SPLITTER 2050
#define wxID_VIS_SPLITTER 2051
#define wxID_BM_SPLITTER 2052
#define wxID_THEME_DEFAULT 2100
#define wxID_THEME_SHARP 2101
@ -47,6 +52,8 @@
#define wxID_THEME_HD 2105
#define wxID_THEME_RADAR 2106
#define wxID_DISPLAY_BOOKMARKS 2107
#define wxID_BANDWIDTH_BASE 2150
#define wxID_BANDWIDTH_MANUAL 2200
@ -76,6 +83,7 @@ class AppFrame: public wxFrame {
public:
AppFrame();
~AppFrame();
void OnThread(wxCommandEvent& event);
void OnEventInput(wxThreadEvent& event);
void initDeviceParams(SDRDeviceInfo *devInfo);
@ -103,9 +111,14 @@ public:
void refreshGainUI();
void setViewState(long long center_freq, int bandwidth);
void setViewState(long long center_freq);
long long getViewCenterFreq();
int getViewBandwidth();
bool isUserDemodBusy();
BookmarkView *getBookmarkView();
void disableSave(bool state);
#ifdef _WIN32
bool canFocus();
#endif
@ -136,8 +149,9 @@ private:
ModeSelectorCanvas *demodMuteButton, *peakHoldButton, *soloModeButton, *deltaLockButton;
GainCanvas *gainCanvas;
wxSizerItem *gainSizerItem, *gainSpacerItem;
wxSplitterWindow *mainVisSplitter, *mainSplitter;
wxSplitterWindow *mainVisSplitter, *mainSplitter, *bookmarkSplitter;
wxBoxSizer *demodTray;
BookmarkView *bookmarkView;
DemodulatorInstance *activeDemodulator;
@ -174,7 +188,7 @@ private:
wxMenuItem *showTipMenuItem;
bool lowPerfMode;
#ifdef USE_HAMLIB
void enableRig();
void disableRig();
@ -187,6 +201,7 @@ private:
wxMenuItem *rigCenterLockMenuItem;
wxMenuItem *rigFollowModemMenuItem;
wxMenuItem *sdrIFMenuItem;
wxMenuItem *hideBookmarksItem;
std::map<int, wxMenuItem *> rigSerialMenuItems;
std::map<int, wxMenuItem *> rigModelMenuItems;
int rigModel;
@ -196,6 +211,7 @@ private:
std::string rigPort;
int numRigs;
bool rigInit;
bool saveDisabled;
#endif
wxDECLARE_EVENT_TABLE();

521
src/BookmarkMgr.cpp Normal file
View File

@ -0,0 +1,521 @@
#include "BookmarkMgr.h"
#include "CubicSDR.h"
#include "DataTree.h"
#define BOOKMARK_RECENTS_MAX 25
BookmarkMgr::BookmarkMgr() {
rangesSorted = false;
}
void BookmarkMgr::saveToFile(std::string bookmarkFn, bool backup) {
DataTree s("cubicsdr_bookmarks");
DataNode *header = s.rootNode()->newChild("header");
header->newChild("version")->element()->set(wxString(CUBICSDR_VERSION).ToStdWstring());
DataNode *branches = s.rootNode()->newChild("branches");
*branches->newChild("active") = wxGetApp().getAppFrame()->getBookmarkView()->getExpandState("active")?1:0;
*branches->newChild("range") = wxGetApp().getAppFrame()->getBookmarkView()->getExpandState("range")?1:0;
*branches->newChild("bookmark") = wxGetApp().getAppFrame()->getBookmarkView()->getExpandState("bookmark")?1:0;
*branches->newChild("recent") = wxGetApp().getAppFrame()->getBookmarkView()->getExpandState("recent")?1:0;
DataNode *view_ranges = s.rootNode()->newChild("ranges");
for (auto re_i : ranges) {
DataNode *range = view_ranges->newChild("range");
*range->newChild("label") = re_i->label;
*range->newChild("freq") = re_i->freq;
*range->newChild("start") = re_i->startFreq;
*range->newChild("end") = re_i->endFreq;
}
DataNode *modems = s.rootNode()->newChild("modems");
for (auto &bmd_i : bmData) {
DataNode *group = modems->newChild("group");
*group->newChild("@name") = bmd_i.first;
*group->newChild("@expanded") = (getExpandState(bmd_i.first)?std::string("true"):std::string("false"));
for (auto &bm_i : bmd_i.second ) {
group->newChildCloneFrom("modem", bm_i->node);
}
}
DataNode *recent_modems = s.rootNode()->newChild("recent_modems");
for (auto demod : wxGetApp().getDemodMgr().getDemodulators()) {
wxGetApp().getDemodMgr().saveInstance(recent_modems->newChild("modem"),demod);
}
for (auto &r_i : this->recents) {
recent_modems->newChildCloneFrom("modem", r_i->node);
}
wxFileName saveFile(wxGetApp().getConfig()->getConfigDir(), bookmarkFn);
wxFileName saveFileBackup(wxGetApp().getConfig()->getConfigDir(), bookmarkFn + ".backup");
if (saveFile.IsDirWritable()) {
// Hopefully leave at least a readable backup in case of failure..
if (backup && saveFile.FileExists() && (!saveFileBackup.FileExists() || saveFileBackup.IsFileWritable())) {
wxCopyFile(saveFile.GetFullPath(wxPATH_NATIVE).ToStdString(), saveFileBackup.GetFullPath(wxPATH_NATIVE).ToStdString());
}
s.SaveToFileXML(saveFile.GetFullPath(wxPATH_NATIVE).ToStdString());
}
}
bool BookmarkMgr::loadFromFile(std::string bookmarkFn, bool backup) {
wxFileName loadFile(wxGetApp().getConfig()->getConfigDir(), bookmarkFn);
wxFileName failFile(wxGetApp().getConfig()->getConfigDir(), bookmarkFn + ".failedload");
wxFileName lastLoaded(wxGetApp().getConfig()->getConfigDir(), bookmarkFn + ".lastloaded");
wxFileName backupFile(wxGetApp().getConfig()->getConfigDir(), bookmarkFn + ".backup");
DataTree s;
bool loadStatusOk = true;
// Clear any active data
bmData.erase(bmData.begin(),bmData.end());
recents.erase(recents.begin(),recents.end());
ranges.erase(ranges.begin(),ranges.end());
bmDataSorted.erase(bmDataSorted.begin(),bmDataSorted.end());
// File exists but is not readable
if (loadFile.FileExists() && !loadFile.IsFileReadable()) {
return false;
}
// New instance of bookmark savefiles
if (backup && !loadFile.FileExists() && !lastLoaded.FileExists() && !backupFile.FileExists()) {
wxGetApp().getAppFrame()->getBookmarkView()->loadDefaultRanges();
return true;
}
// Attempt to load file
if (!s.LoadFromFileXML(loadFile.GetFullPath(wxPATH_NATIVE).ToStdString())) {
return false;
}
if (s.rootNode()->hasAnother("branches")) {
DataNode *branches = s.rootNode()->getNext("branches");
int bActive = 1, bRange = 0, bBookmark = 1, bRecent = 1;
if (branches->hasAnother("active")) branches->getNext("active")->element()->get(bActive);
if (branches->hasAnother("range")) branches->getNext("range")->element()->get(bRange);
if (branches->hasAnother("bookmark")) branches->getNext("bookmark")->element()->get(bBookmark);
if (branches->hasAnother("recent")) branches->getNext("recent")->element()->get(bRecent);
wxGetApp().getAppFrame()->getBookmarkView()->setExpandState("active", bActive?true:false);
wxGetApp().getAppFrame()->getBookmarkView()->setExpandState("range", bRange?true:false);
wxGetApp().getAppFrame()->getBookmarkView()->setExpandState("bookmark", bBookmark?true:false);
wxGetApp().getAppFrame()->getBookmarkView()->setExpandState("recent", bRecent?true:false);
}
if (s.rootNode()->hasAnother("ranges")) {
DataNode *view_ranges = s.rootNode()->getNext("ranges");
while (view_ranges->hasAnother("range")) {
DataNode *range = view_ranges->getNext("range");
BookmarkRangeEntry *re = new BookmarkRangeEntry;
if (range->hasAnother("label")) range->getNext("label")->element()->get(re->label);
if (range->hasAnother("freq")) range->getNext("freq")->element()->get(re->freq);
if (range->hasAnother("start")) range->getNext("start")->element()->get(re->startFreq);
if (range->hasAnother("end")) range->getNext("end")->element()->get(re->endFreq);
addRange(re);
}
}
if (s.rootNode()->hasAnother("modems")) {
DataNode *modems = s.rootNode()->getNext("modems");
while (modems->hasAnother("group")) {
DataNode *group = modems->getNext("group");
std::string expandState = "true";
std::string groupName = "Unnamed";
if (group->hasAnother("@name")) {
groupName = group->getNext("@name")->element()->toString();
}
if (group->hasAnother("@expanded")) {
expandState = group->getNext("@expanded")->element()->toString();
}
setExpandState(groupName, (expandState == "true"));
while (group->hasAnother("modem")) {
DataNode *modem = group->getNext("modem");
BookmarkEntry *be = nodeToBookmark("modem", modem);
if (be) {
addBookmark(groupName.c_str(), be);
} else {
std::cout << "error loading bookmarked modem.." << std::endl;
loadStatusOk = false;
}
}
}
}
if (s.rootNode()->hasAnother("recent_modems")) {
DataNode *recent_modems = s.rootNode()->getNext("recent_modems");
while (recent_modems->hasAnother("modem")) {
DataNode *modem = recent_modems->getNext("modem");
BookmarkEntry *be = nodeToBookmark("modem", modem);
if (be) {
addRecent(be);
} else {
std::cout << "error loading recent modem.." << std::endl;
loadStatusOk = false;
}
}
}
if (backup) {
if (loadStatusOk) { // Loaded OK; keep a copy
if (loadFile.IsDirWritable()) {
if (loadFile.FileExists() && (!lastLoaded.FileExists() || lastLoaded.IsFileWritable())) {
wxCopyFile(loadFile.GetFullPath(wxPATH_NATIVE).ToStdString(), lastLoaded.GetFullPath(wxPATH_NATIVE).ToStdString());
}
}
} else if (!loadStatusOk) {
if (loadFile.IsDirWritable()) { // Load failed; keep a copy of the failed bookmark file for analysis?
if (loadFile.FileExists() && (!failFile.FileExists() || failFile.IsFileWritable())) {
wxCopyFile(loadFile.GetFullPath(wxPATH_NATIVE).ToStdString(), failFile.GetFullPath(wxPATH_NATIVE).ToStdString());
}
}
}
}
return loadStatusOk;
}
bool BookmarkMgr::hasLastLoad(std::string bookmarkFn) {
wxFileName lastLoaded(wxGetApp().getConfig()->getConfigDir(), bookmarkFn + ".lastloaded");
return lastLoaded.FileExists() && lastLoaded.IsFileReadable();
}
bool BookmarkMgr::hasBackup(std::string bookmarkFn) {
wxFileName backupFile(wxGetApp().getConfig()->getConfigDir(), bookmarkFn + ".backup");
return backupFile.FileExists() && backupFile.IsFileReadable();
}
void BookmarkMgr::addBookmark(std::string group, DemodulatorInstance *demod) {
std::lock_guard < std::mutex > lock(busy_lock);
BookmarkEntry *be = demodToBookmarkEntry(demod);
wxGetApp().getDemodMgr().saveInstance(be->node, demod);
bmData[group].push_back(be);
bmDataSorted[group] = false;
}
void BookmarkMgr::addBookmark(std::string group, BookmarkEntry *be) {
std::lock_guard < std::mutex > lock(busy_lock);
bmData[group].push_back(be);
bmDataSorted[group] = false;
}
void BookmarkMgr::removeBookmark(std::string group, BookmarkEntry *be) {
std::lock_guard < std::mutex > lockData(busy_lock);
std::lock_guard < std::mutex > lockEnt(be->busy_lock);
if (bmData.find(group) == bmData.end()) {
return;
}
BookmarkList::iterator i = std::find(bmData[group].begin(), bmData[group].end(), be);
if (i != bmData[group].end()) {
delete *i;
bmData[group].erase(i);
}
}
void BookmarkMgr::removeBookmark(BookmarkEntry *be) {
std::lock_guard < std::mutex > lockData(busy_lock);
std::lock_guard < std::mutex > lockEnt(be->busy_lock);
for (auto &bmd_i : bmData) {
BookmarkList::iterator i = std::find(bmd_i.second.begin(), bmd_i.second.end(), be);
if (i != bmd_i.second.end()) {
bmd_i.second.erase(i);
}
}
}
void BookmarkMgr::moveBookmark(BookmarkEntry *be, std::string group) {
std::lock_guard < std::mutex > lockData(busy_lock);
std::lock_guard < std::mutex > lockEnt(be->busy_lock);
for (auto &bmd_i : bmData) {
BookmarkList::iterator i = std::find(bmd_i.second.begin(), bmd_i.second.end(), be);
if (i != bmd_i.second.end()) {
if (bmd_i.first == group) {
return;
}
bmData[group].push_back(*i);
bmd_i.second.erase(i);
bmDataSorted[group] = false;
bmDataSorted[bmd_i.first] = false;
return;
}
}
}
void BookmarkMgr::addGroup(std::string group) {
std::lock_guard < std::mutex > lock(busy_lock);
if (bmData.find(group) == bmData.end()) {
BookmarkList dummy = bmData[group];
}
}
void BookmarkMgr::removeGroup(std::string group) {
std::lock_guard < std::mutex > lock(busy_lock);
BookmarkMap::iterator i = bmData.find(group);
if (i != bmData.end()) {
for (auto ii : bmData[group]) {
delete ii;
}
bmData.erase(group);
}
}
void BookmarkMgr::renameGroup(std::string group, std::string ngroup) {
if (group == ngroup) {
return;
}
std::lock_guard < std::mutex > lock(busy_lock);
BookmarkMap::iterator i = bmData.find(group);
BookmarkMap::iterator it = bmData.find(ngroup);
if (i != bmData.end() && it != bmData.end()) {
for (auto ii : bmData[group]) {
bmData[ngroup].push_back(ii);
}
bmData.erase(group);
} else if (i != bmData.end()) {
bmData[ngroup] = bmData[group];
bmData.erase(group);
}
}
BookmarkList BookmarkMgr::getBookmarks(std::string group) {
std::lock_guard < std::mutex > lock(busy_lock);
if (bmData.find(group) == bmData.end()) {
BookmarkList results;
return results;
}
if (!bmDataSorted[group]) {
std::sort(bmData[group].begin(), bmData[group].end(), BookmarkEntryCompare());
bmDataSorted[group] = true;
}
return bmData[group];
}
void BookmarkMgr::getGroups(BookmarkNames &arr) {
for (BookmarkMap::iterator i = bmData.begin(); i!= bmData.end(); ++i) {
arr.push_back(i->first);
}
}
void BookmarkMgr::getGroups(wxArrayString &arr) {
for (BookmarkMap::iterator i = bmData.begin(); i!= bmData.end(); ++i) {
arr.push_back(i->first);
}
}
void BookmarkMgr::setExpandState(std::string groupName, bool state) {
expandState[groupName] = state;
}
bool BookmarkMgr::getExpandState(std::string groupName) {
if (expandState.find(groupName) == expandState.end()) {
return true;
}
return expandState[groupName];
}
void BookmarkMgr::updateActiveList() {
BookmarkView *bmv = wxGetApp().getAppFrame()->getBookmarkView();
if (bmv) {
bmv->updateActiveList();
}
}
void BookmarkMgr::updateBookmarks() {
BookmarkView *bmv = wxGetApp().getAppFrame()->getBookmarkView();
if (bmv) {
bmv->updateBookmarks();
}
}
void BookmarkMgr::updateBookmarks(std::string group) {
BookmarkView *bmv = wxGetApp().getAppFrame()->getBookmarkView();
if (bmv) {
bmv->updateBookmarks(group);
}
}
void BookmarkMgr::addRecent(DemodulatorInstance *demod) {
std::lock_guard < std::mutex > lock(busy_lock);
recents.push_back(demodToBookmarkEntry(demod));
trimRecents();
}
void BookmarkMgr::addRecent(BookmarkEntry *be) {
std::lock_guard < std::mutex > lock(busy_lock);
recents.push_back(be);
trimRecents();
}
void BookmarkMgr::removeRecent(BookmarkEntry *be) {
std::lock_guard < std::mutex > lock(busy_lock);
BookmarkList::iterator bm_i = std::find(recents.begin(),recents.end(), be);
if (bm_i != recents.end()) {
recents.erase(bm_i);
}
}
BookmarkList BookmarkMgr::getRecents() {
return BookmarkList(recents.rbegin(), recents.rend());
}
void BookmarkMgr::clearRecents() {
std::lock_guard < std::mutex > lock(busy_lock);
recents.erase(recents.begin(),recents.end());
}
void BookmarkMgr::trimRecents() {
if (recents.size() > BOOKMARK_RECENTS_MAX) {
delete *(recents.begin());
recents.erase(recents.begin(), recents.begin()+1);
}
}
void BookmarkMgr::addRange(BookmarkRangeEntry *re) {
std::lock_guard < std::mutex > lock(busy_lock);
ranges.push_back(re);
rangesSorted = false;
}
void BookmarkMgr::removeRange(BookmarkRangeEntry *re) {
std::lock_guard < std::mutex > lock(busy_lock);
BookmarkRangeList::iterator re_i = std::find(ranges.begin(), ranges.end(), re);
if (re_i != ranges.end()) {
ranges.erase(re_i);
}
}
BookmarkRangeList BookmarkMgr::getRanges() {
std::lock_guard < std::mutex > lock(busy_lock);
if (!rangesSorted) {
std::sort(ranges.begin(), ranges.end(), BookmarkRangeEntryCompare());
rangesSorted = true;
}
return ranges;
}
void BookmarkMgr::clearRanges() {
std::lock_guard < std::mutex > lock(busy_lock);
ranges.erase(ranges.begin(),ranges.end());
}
BookmarkEntry *BookmarkMgr::demodToBookmarkEntry(DemodulatorInstance *demod) {
BookmarkEntry *be = new BookmarkEntry;
be->bandwidth = demod->getBandwidth();
be->type = demod->getDemodulatorType();
be->label = demod->getDemodulatorUserLabel();
be->frequency = demod->getFrequency();
be->node = new DataNode;
wxGetApp().getDemodMgr().saveInstance(be->node, demod);
return be;
}
BookmarkEntry *BookmarkMgr::nodeToBookmark(const char *name_in, DataNode *node) {
if (!node->hasAnother("frequency") || !node->hasAnother("type") || !node->hasAnother("bandwidth")) {
return nullptr;
}
BookmarkEntry *be = new BookmarkEntry();
node->getNext("frequency")->element()->get(be->frequency);
node->getNext("type")->element()->get(be->type);
node->getNext("bandwidth")->element()->get(be->bandwidth);
if (node->hasAnother("user_label")) {
node->getNext("user_label")->element()->get(be->label);
}
node->rewindAll();
be->node = new DataNode("node",*node);
return be;
}
std::wstring BookmarkMgr::getBookmarkEntryDisplayName(BookmarkEntry *bmEnt) {
std::wstring dispName = bmEnt->label;
if (dispName == "") {
std::string freqStr = frequencyToStr(bmEnt->frequency) + " " + bmEnt->type;
dispName = wstring(freqStr.begin(),freqStr.end());
}
return dispName;
}
std::wstring BookmarkMgr::getActiveDisplayName(DemodulatorInstance *demod) {
std::wstring activeName = demod->getDemodulatorUserLabel();
if (activeName == "") {
std::string wstr = frequencyToStr(demod->getFrequency()) + " " + demod->getDemodulatorType();
activeName = std::wstring(wstr.begin(),wstr.end());
}
return activeName;
}

129
src/BookmarkMgr.h Normal file
View File

@ -0,0 +1,129 @@
#pragma once
#include <wx/arrstr.h>
#include <vector>
#include <set>
#include "DemodulatorInstance.h"
class DataNode;
class BookmarkEntry {
public:
std::mutex busy_lock;
std::string type;
std::wstring label;
std::wstring userLabel;
long long frequency;
int bandwidth;
DataNode *node;
};
class BookmarkRangeEntry {
public:
BookmarkRangeEntry() : label(L""), freq(0), startFreq(0), endFreq(0) {
}
BookmarkRangeEntry(std::wstring label, long long freq, long long startFreq, long long endFreq) : label(label), freq(freq), startFreq(startFreq), endFreq(endFreq) {
}
std::mutex busy_lock;
std::wstring label;
long long freq;
long long startFreq;
long long endFreq;
};
struct BookmarkEntryCompare : public std::binary_function<BookmarkEntry *,BookmarkEntry *,bool>
{
bool operator()(const BookmarkEntry *a, BookmarkEntry *b) const
{
return a->frequency < b->frequency;
}
};
struct BookmarkRangeEntryCompare : public std::binary_function<BookmarkRangeEntry *,BookmarkRangeEntry *,bool>
{
bool operator()(const BookmarkRangeEntry *a, BookmarkRangeEntry *b) const
{
return a->freq < b->freq;
}
};
typedef std::vector<BookmarkEntry *> BookmarkList;
typedef std::vector<BookmarkRangeEntry *> BookmarkRangeList;
typedef std::map<std::string, BookmarkList > BookmarkMap;
typedef std::map<std::string, bool > BookmarkMapSorted;
typedef std::vector<std::string> BookmarkNames;
typedef std::map<std::string, bool> BookmarkExpandState;
class BookmarkMgr {
public:
BookmarkMgr();
void saveToFile(std::string bookmarkFn, bool backup = true);
bool loadFromFile(std::string bookmarkFn, bool backup = true);
bool hasLastLoad(std::string bookmarkFn);
bool hasBackup(std::string bookmarkFn);
void addBookmark(std::string group, DemodulatorInstance *demod);
void addBookmark(std::string group, BookmarkEntry *be);
void removeBookmark(std::string group, BookmarkEntry *be);
void removeBookmark(BookmarkEntry *be);
void moveBookmark(BookmarkEntry *be, std::string group);
void addGroup(std::string group);
void removeGroup(std::string group);
void renameGroup(std::string group, std::string ngroup);
BookmarkList getBookmarks(std::string group);
void getGroups(BookmarkNames &arr);
void getGroups(wxArrayString &arr);
void setExpandState(std::string groupName, bool state);
bool getExpandState(std::string groupName);
void updateActiveList();
void updateBookmarks();
void updateBookmarks(std::string group);
void addRecent(DemodulatorInstance *demod);
void addRecent(BookmarkEntry *be);
void removeRecent(BookmarkEntry *be);
BookmarkList getRecents();
void clearRecents();
void addRange(BookmarkRangeEntry *re);
void removeRange(BookmarkRangeEntry *re);
BookmarkRangeList getRanges();
void clearRanges();
static std::wstring getBookmarkEntryDisplayName(BookmarkEntry *bmEnt);
static std::wstring getActiveDisplayName(DemodulatorInstance *demod);
protected:
void trimRecents();
BookmarkEntry *demodToBookmarkEntry(DemodulatorInstance *demod);
BookmarkEntry *nodeToBookmark(const char *name_in, DataNode *node);
BookmarkMap bmData;
BookmarkMapSorted bmDataSorted;
BookmarkList recents;
BookmarkRangeList ranges;
bool rangesSorted;
std::mutex busy_lock;
BookmarkExpandState expandState;
};

View File

@ -30,6 +30,9 @@ IMPLEMENT_APP(CubicSDR)
#include <fstream>
#include <clocale>
#include "ActionDialog.h"
//#ifdef ENABLE_DIGITAL_LAB
//// console output buffer for windows
//#ifdef _WINDOWS
@ -136,8 +139,65 @@ long long strToFrequency(std::string freqStr) {
}
CubicSDR::CubicSDR() : frequency(0), offset(0), ppm(0), snap(1), sampleRate(DEFAULT_SAMPLE_RATE),agcMode(false)
{
class ActionDialogBookmarkCatastophe : public ActionDialog {
public:
ActionDialogBookmarkCatastophe() : ActionDialog(wxGetApp().getAppFrame(), wxID_ANY, wxT("Bookmark Last-Loaded Backup Failure :( :( :(")) {
m_questionText->SetLabelText(wxT("All attempts to recover bookmarks have failed. \nWould you like to exit without touching any more save files?\nClick OK to exit without saving; or Cancel to continue anyways."));
}
void doClickOK() {
wxGetApp().getAppFrame()->disableSave(true);
wxGetApp().getAppFrame()->Close(false);
}
};
class ActionDialogBookmarkBackupLoadFailed : public ActionDialog {
public:
ActionDialogBookmarkBackupLoadFailed() : ActionDialog(wxGetApp().getAppFrame(), wxID_ANY, wxT("Bookmark Backup Load Failure :( :(")) {
m_questionText->SetLabelText(wxT("Sorry; unable to load your bookmarks backup file. \nWould you like to attempt to load the last succssfully loaded bookmarks file?"));
}
void doClickOK() {
if (wxGetApp().getBookmarkMgr().hasLastLoad("bookmarks.xml")) {
if (wxGetApp().getBookmarkMgr().loadFromFile("bookmarks.xml.lastloaded",false)) {
wxGetApp().getBookmarkMgr().updateBookmarks();
wxGetApp().getBookmarkMgr().updateActiveList();
} else {
ActionDialog::showDialog(new ActionDialogBookmarkCatastophe());
}
}
}
};
class ActionDialogBookmarkLoadFailed : public ActionDialog {
public:
ActionDialogBookmarkLoadFailed() : ActionDialog(wxGetApp().getAppFrame(), wxID_ANY, wxT("Bookmark Load Failure :(")) {
m_questionText->SetLabelText(wxT("Sorry; unable to load your bookmarks file. \nWould you like to attempt to load the backup file?"));
}
void doClickOK() {
bool loadOk = false;
if (wxGetApp().getBookmarkMgr().hasBackup("bookmarks.xml")) {
loadOk = wxGetApp().getBookmarkMgr().loadFromFile("bookmarks.xml.backup",false);
}
if (loadOk) {
wxGetApp().getBookmarkMgr().updateBookmarks();
wxGetApp().getBookmarkMgr().updateActiveList();
} else if (wxGetApp().getBookmarkMgr().hasLastLoad("bookmarks.xml")) {
ActionDialog::showDialog(new ActionDialogBookmarkBackupLoadFailed());
} else {
ActionDialog::showDialog(new ActionDialogBookmarkCatastophe());
}
}
};
CubicSDR::CubicSDR() : frequency(0), offset(0), ppm(0), snap(1), sampleRate(DEFAULT_SAMPLE_RATE), agcMode(false)
{
sampleRateInitialized.store(false);
agcMode.store(true);
soloMode.store(false);
@ -231,25 +291,16 @@ bool CubicSDR::OnInit() {
// Visual Data
spectrumVisualThread = new SpectrumVisualDataThread();
demodVisualThread = new SpectrumVisualDataThread();
pipeIQVisualData = new DemodulatorThreadInputQueue();
pipeIQVisualData->set_max_num_items(1);
pipeDemodIQVisualData = new DemodulatorThreadInputQueue();
pipeDemodIQVisualData->set_max_num_items(1);
pipeWaterfallIQVisualData = new DemodulatorThreadInputQueue();
pipeWaterfallIQVisualData->set_max_num_items(128);
getDemodSpectrumProcessor()->setInput(pipeDemodIQVisualData);
getSpectrumProcessor()->setInput(pipeIQVisualData);
getSpectrumProcessor()->setHideDC(true);
pipeAudioVisualData = new DemodulatorThreadOutputQueue();
pipeAudioVisualData->set_max_num_items(1);
scopeProcessor.setInput(pipeAudioVisualData);
// I/Q Data
pipeSDRIQData = new SDRThreadIQDataQueue();
@ -263,12 +314,32 @@ bool CubicSDR::OnInit() {
sdrPostThread->setOutputQueue("IQVisualDataOutput", pipeIQVisualData);
sdrPostThread->setOutputQueue("IQDataOutput", pipeWaterfallIQVisualData);
sdrPostThread->setOutputQueue("IQActiveDemodVisualDataOutput", pipeDemodIQVisualData);
t_PostSDR = new std::thread(&SDRPostThread::threadMain, sdrPostThread);
t_SpectrumVisual = new std::thread(&SpectrumVisualDataThread::threadMain, spectrumVisualThread);
#if CUBICSDR_ENABLE_VIEW_SCOPE
pipeAudioVisualData = new DemodulatorThreadOutputQueue();
pipeAudioVisualData->set_max_num_items(1);
scopeProcessor.setInput(pipeAudioVisualData);
#else
pipeAudioVisualData = nullptr;
#endif
#if CUBICSDR_ENABLE_VIEW_DEMOD
demodVisualThread = new SpectrumVisualDataThread();
pipeDemodIQVisualData = new DemodulatorThreadInputQueue();
pipeDemodIQVisualData->set_max_num_items(1);
if (getDemodSpectrumProcessor()) getDemodSpectrumProcessor()->setInput(pipeDemodIQVisualData);
sdrPostThread->setOutputQueue("IQActiveDemodVisualDataOutput", pipeDemodIQVisualData);
t_DemodVisual = new std::thread(&SpectrumVisualDataThread::threadMain, demodVisualThread);
#else
demodVisualThread = nullptr;
pipeDemodIQVisualData = nullptr;
t_DemodVisual = nullptr;
#endif
sdrEnum = new SDREnumerator();
SDREnumerator::setManuals(config.getManualDevices());
@ -286,6 +357,19 @@ bool CubicSDR::OnInit() {
// pthread_setschedparam(pthread_self(), main_policy, &main_param);
//#endif
if (!wxGetApp().getBookmarkMgr().loadFromFile("bookmarks.xml")) {
if (wxGetApp().getBookmarkMgr().hasBackup("bookmarks.xml")) {
ActionDialog::showDialog(new ActionDialogBookmarkLoadFailed());
} else if (wxGetApp().getBookmarkMgr().hasLastLoad("bookmarks.xml")) {
ActionDialog::showDialog(new ActionDialogBookmarkBackupLoadFailed());
} else {
ActionDialog::showDialog(new ActionDialogBookmarkCatastophe());
}
} else {
getBookmarkMgr().updateActiveList();
getBookmarkMgr().updateBookmarks();
}
return true;
}
@ -316,16 +400,20 @@ int CubicSDR::OnExit() {
std::cout << "Terminating Visual Processor threads.." << std::endl;
spectrumVisualThread->terminate();
demodVisualThread->terminate();
if (demodVisualThread) {
demodVisualThread->terminate();
}
//Wait nicely
sdrPostThread->isTerminated(1000);
spectrumVisualThread->isTerminated(1000);
demodVisualThread->isTerminated(1000);
if (demodVisualThread) {
demodVisualThread->isTerminated(1000);
}
//Then join the thread themselves
t_PostSDR->join();
t_DemodVisual->join();
if (t_DemodVisual) t_DemodVisual->join();
t_SpectrumVisual->join();
//Now only we can delete
@ -494,7 +582,9 @@ void CubicSDR::setFrequency(long long freq) {
getSpectrumProcessor()->setPeakHold(getSpectrumProcessor()->getPeakHold());
//make the peak hold act on the current dmod also, like a zoomed-in version.
getDemodSpectrumProcessor()->setPeakHold(getSpectrumProcessor()->getPeakHold());
if (getDemodSpectrumProcessor()) {
getDemodSpectrumProcessor()->setPeakHold(getSpectrumProcessor()->getPeakHold());
}
}
long long CubicSDR::getOffset() {
@ -655,7 +745,11 @@ SpectrumVisualProcessor *CubicSDR::getSpectrumProcessor() {
}
SpectrumVisualProcessor *CubicSDR::getDemodSpectrumProcessor() {
return demodVisualThread->getProcessor();
if (demodVisualThread) {
return demodVisualThread->getProcessor();
} else {
return nullptr;
}
}
DemodulatorThreadOutputQueue* CubicSDR::getAudioVisualQueue() {
@ -674,6 +768,10 @@ DemodulatorMgr &CubicSDR::getDemodMgr() {
return demodMgr;
}
BookmarkMgr &CubicSDR::getBookmarkMgr() {
return bookmarkMgr;
}
SDRPostThread *CubicSDR::getSDRPostThread() {
return sdrPostThread;
}
@ -707,6 +805,7 @@ void CubicSDR::removeDemodulator(DemodulatorInstance *demod) {
}
demod->setActive(false);
sdrPostThread->removeDemodulator(demod);
wxGetApp().getAppFrame()->notifyUpdateModemProperties();
}
std::vector<SDRDeviceInfo*>* CubicSDR::getDevices() {
@ -752,6 +851,7 @@ void CubicSDR::showFrequencyInput(FrequencyDialog::FrequencyDialogTarget targetM
switch (targetMode) {
case FrequencyDialog::FDIALOG_TARGET_DEFAULT:
case FrequencyDialog::FDIALOG_TARGET_FREQ:
title = demodMgr.getActiveDemodulator()?demodTitle:freqTitle;
break;
case FrequencyDialog::FDIALOG_TARGET_BANDWIDTH:

View File

@ -26,6 +26,7 @@
#include "AppFrame.h"
#include "FrequencyDialog.h"
#include "DemodLabelDialog.h"
#include "BookmarkMgr.h"
#include "ScopeVisualProcessor.h"
#include "SpectrumVisualProcessor.h"
@ -96,6 +97,9 @@ public:
void setOffset(long long ofs);
long long getOffset();
void setDBOffset(int ofs);
int getDBOffset();
void setSampleRate(long long rate_in);
long long getSampleRate();
@ -114,6 +118,7 @@ public:
DemodulatorThreadInputQueue* getWaterfallVisualQueue();
DemodulatorThreadInputQueue* getActiveDemodVisualQueue();
DemodulatorMgr &getDemodMgr();
BookmarkMgr &getBookmarkMgr();
SDRPostThread *getSDRPostThread();
SDRThread *getSDRThread();
@ -182,6 +187,7 @@ private:
std::vector<SDRDeviceInfo *> *devs = nullptr;
DemodulatorMgr demodMgr;
BookmarkMgr bookmarkMgr;
std::atomic_llong frequency;
std::atomic_llong offset;

View File

@ -3,7 +3,7 @@
#pragma once
#define CUBICSDR_TITLE "CubicSDR v" CUBICSDR_VERSION " by Charles J. Cliffe (@ccliffe) :: www.cubicsdr.com"
#define CUBICSDR_TITLE "" CUBICSDR_BUILD_TITLE
#ifndef __BYTE_ORDER
#ifdef _WIN32

View File

@ -60,7 +60,7 @@ void DemodLabelDialog::OnChar(wxKeyEvent& event) {
else {
activeDemod->setDemodulatorUserLabel(L"");
}
wxGetApp().getBookmarkMgr().updateActiveList();
Close();
break;
case WXK_ESCAPE:

View File

@ -33,26 +33,10 @@ void ModemProperties::OnShow(wxShowEvent & /* event */) {
}
void ModemProperties::updateTheme() {
wxColour bgColor(
(unsigned char) (ThemeMgr::mgr.currentTheme->generalBackground.r * 255.0),
(unsigned char) (ThemeMgr::mgr.currentTheme->generalBackground.g * 255.0),
(unsigned char) (ThemeMgr::mgr.currentTheme->generalBackground.b * 255.0));
wxColour textColor(
(unsigned char) (ThemeMgr::mgr.currentTheme->text.r * 255.0),
(unsigned char) (ThemeMgr::mgr.currentTheme->text.g * 255.0),
(unsigned char) (ThemeMgr::mgr.currentTheme->text.b * 255.0));
wxColour btn(
(unsigned char) (ThemeMgr::mgr.currentTheme->button.r * 255.0),
(unsigned char) (ThemeMgr::mgr.currentTheme->button.g * 255.0),
(unsigned char) (ThemeMgr::mgr.currentTheme->button.b * 255.0));
wxColour btnHl(
(unsigned char) (ThemeMgr::mgr.currentTheme->buttonHighlight.r * 255.0),
(unsigned char) (ThemeMgr::mgr.currentTheme->buttonHighlight.g * 255.0),
(unsigned char) (ThemeMgr::mgr.currentTheme->buttonHighlight.b * 255.0));
wxColour bgColor(ThemeMgr::mgr.currentTheme->generalBackground);
wxColour textColor(ThemeMgr::mgr.currentTheme->text);
wxColour btn(ThemeMgr::mgr.currentTheme->button);
wxColour btnHl(ThemeMgr::mgr.currentTheme->buttonHighlight);
m_propertyGrid->SetEmptySpaceColour(bgColor);
m_propertyGrid->SetCellBackgroundColour(bgColor);
@ -125,10 +109,8 @@ void ModemProperties::initProperties(ModemArgInfoList newArgs, DemodulatorInstan
m_propertyGrid->Clear();
if (!demodInstance) {
Hide();
m_propertyGrid->Append(new wxPropertyCategory("Modem Settings"));
return;
} else {
Show();
}
m_propertyGrid->Append(new wxPropertyCategory(demodInstance->getDemodulatorType() + " Settings"));

View File

@ -83,6 +83,8 @@ DemodulatorInstance::~DemodulatorInstance() {
delete pipeIQDemodData;
delete threadQueueControl;
delete pipeAudioData;
wxGetApp().getBookmarkMgr().updateActiveList();
}
void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueue *tQueue) {
@ -121,6 +123,7 @@ void DemodulatorInstance::run() {
active = true;
wxGetApp().getBookmarkMgr().updateActiveList();
}
void DemodulatorInstance::updateLabel(long long freq) {
@ -128,6 +131,7 @@ void DemodulatorInstance::updateLabel(long long freq) {
newLabel.precision(3);
newLabel << std::fixed << ((long double) freq / 1000000.0);
setLabel(newLabel.str());
wxGetApp().getBookmarkMgr().updateActiveList();
}
void DemodulatorInstance::terminate() {
@ -230,6 +234,8 @@ void DemodulatorInstance::setActive(bool state) {
tracking = false;
}
active = state;
wxGetApp().getBookmarkMgr().updateActiveList();
}
void DemodulatorInstance::squelchAuto() {
@ -334,7 +340,9 @@ void DemodulatorInstance::setDemodulatorType(std::string demod_type_in) {
outp->setTitle(getDemodulatorType() + ": " + frequencyToStr(getFrequency()));
}
#endif
}
}
wxGetApp().getBookmarkMgr().updateActiveList();
}
std::string DemodulatorInstance::getDemodulatorType() {
@ -394,6 +402,10 @@ void DemodulatorInstance::setFrequency(long long freq) {
wxGetApp().getRigThread()->setFrequency(freq,true);
}
#endif
if (this->isActive()) {
wxGetApp().getBookmarkMgr().updateActiveList();
}
}
long long DemodulatorInstance::getFrequency() {

View File

@ -4,15 +4,18 @@
#include <DemodulatorMgr.h>
#include <sstream>
#include <algorithm>
#include "CubicSDR.h"
#include <string>
#include <sstream>
#include <algorithm>
#include "DemodulatorMgr.h"
#if USE_HAMLIB
#include "RigThread.h"
#endif
#include "DataTree.h"
bool demodFreqCompare (DemodulatorInstance *i, DemodulatorInstance *j) { return (i->getFrequency()<j->getFrequency()); }
bool inactiveCompare (DemodulatorInstance *i, DemodulatorInstance *j) { return (i->isActive()<j->isActive()); }
@ -133,6 +136,8 @@ DemodulatorInstance *DemodulatorMgr::getFirstDemodulator() {
void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) {
std::lock_guard < std::recursive_mutex > lock(demods_busy);
wxGetApp().getBookmarkMgr().addRecent(demod);
std::vector<DemodulatorInstance *>::iterator i;
@ -218,6 +223,7 @@ void DemodulatorMgr::setActiveDemodulator(DemodulatorInstance *demod, bool tempo
wxGetApp().getRigThread()->setFrequency(lastActiveDemodulator.load()->getFrequency(),true);
}
#endif
wxGetApp().getBookmarkMgr().updateActiveList();
} else {
std::lock_guard < std::recursive_mutex > lock(demods_busy);
garbageCollect();
@ -371,3 +377,138 @@ ModemSettings DemodulatorMgr::getLastModemSettings(std::string modemType) {
void DemodulatorMgr::setLastModemSettings(std::string modemType, ModemSettings settings) {
lastModemSettings[modemType] = settings;
}
void DemodulatorMgr::setOutputDevices(std::map<int,RtAudio::DeviceInfo> devs) {
outputDevices = devs;
}
void DemodulatorMgr::saveInstance(DataNode *node, DemodulatorInstance *inst) {
*node->newChild("bandwidth") = inst->getBandwidth();
*node->newChild("frequency") = inst->getFrequency();
*node->newChild("type") = inst->getDemodulatorType();
node->newChild("user_label")->element()->set(inst->getDemodulatorUserLabel());
*node->newChild("squelch_level") = inst->getSquelchLevel();
*node->newChild("squelch_enabled") = inst->isSquelchEnabled() ? 1 : 0;
*node->newChild("output_device") = outputDevices[inst->getOutputDevice()].name;
*node->newChild("gain") = inst->getGain();
*node->newChild("muted") = inst->isMuted() ? 1 : 0;
if (inst->isDeltaLock()) {
*node->newChild("delta_lock") = inst->isDeltaLock() ? 1 : 0;
*node->newChild("delta_ofs") = inst->getDeltaLockOfs();
}
if (inst == getLastActiveDemodulator()) {
*node->newChild("active") = 1;
}
ModemSettings saveSettings = inst->readModemSettings();
if (saveSettings.size()) {
DataNode *settingsNode = node->newChild("settings");
for (ModemSettings::const_iterator msi = saveSettings.begin(); msi != saveSettings.end(); msi++) {
*settingsNode->newChild(msi->first.c_str()) = msi->second;
}
}
}
DemodulatorInstance *DemodulatorMgr::loadInstance(DataNode *node) {
DemodulatorInstance *newDemod = nullptr;
node->rewindAll();
long bandwidth = *node->getNext("bandwidth");
long long freq = *node->getNext("frequency");
float squelch_level = node->hasAnother("squelch_level") ? (float) *node->getNext("squelch_level") : 0;
int squelch_enabled = node->hasAnother("squelch_enabled") ? (int) *node->getNext("squelch_enabled") : 0;
int muted = node->hasAnother("muted") ? (int) *node->getNext("muted") : 0;
int delta_locked = node->hasAnother("delta_lock") ? (int) *node->getNext("delta_lock") : 0;
int delta_ofs = node->hasAnother("delta_ofs") ? (int) *node->getNext("delta_ofs") : 0;
std::string output_device = node->hasAnother("output_device") ? string(*(node->getNext("output_device"))) : "";
float gain = node->hasAnother("gain") ? (float) *node->getNext("gain") : 1.0;
std::string type = "FM";
DataNode *demodTypeNode = node->hasAnother("type")?node->getNext("type"):nullptr;
if (demodTypeNode && demodTypeNode->element()->getDataType() == DATA_INT) {
int legacyType = *demodTypeNode;
int legacyStereo = node->hasAnother("stereo") ? (int) *node->getNext("stereo") : 0;
switch (legacyType) { // legacy demod ID
case 1: type = legacyStereo?"FMS":"FM"; break;
case 2: type = "AM"; break;
case 3: type = "LSB"; break;
case 4: type = "USB"; break;
case 5: type = "DSB"; break;
case 6: type = "ASK"; break;
case 7: type = "APSK"; break;
case 8: type = "BPSK"; break;
case 9: type = "DPSK"; break;
case 10: type = "PSK"; break;
case 11: type = "OOK"; break;
case 12: type = "ST"; break;
case 13: type = "SQAM"; break;
case 14: type = "QAM"; break;
case 15: type = "QPSK"; break;
case 16: type = "I/Q"; break;
default: type = "FM"; break;
}
} else if (demodTypeNode && demodTypeNode->element()->getDataType() == DATA_STRING) {
demodTypeNode->element()->get(type);
}
//read the user label associated with the demodulator
std::wstring user_label = L"";
DataNode *demodUserLabel = node->hasAnother("user_label") ? node->getNext("user_label") : nullptr;
if (demodUserLabel) {
demodUserLabel->element()->get(user_label);
}
ModemSettings mSettings;
if (node->hasAnother("settings")) {
DataNode *modemSettings = node->getNext("settings");
for (int msi = 0, numSettings = modemSettings->numChildren(); msi < numSettings; msi++) {
DataNode *settingNode = modemSettings->child(msi);
std::string keyName = settingNode->getName();
std::string strSettingValue = settingNode->element()->toString();
if (keyName != "" && strSettingValue != "") {
mSettings[keyName] = strSettingValue;
}
}
}
newDemod = wxGetApp().getDemodMgr().newThread();
newDemod->setDemodulatorType(type);
newDemod->setDemodulatorUserLabel(user_label);
newDemod->writeModemSettings(mSettings);
newDemod->setBandwidth(bandwidth);
newDemod->setFrequency(freq);
newDemod->setGain(gain);
newDemod->updateLabel(freq);
newDemod->setMuted(muted?true:false);
if (delta_locked) {
newDemod->setDeltaLock(true);
newDemod->setDeltaLockOfs(delta_ofs);
}
if (squelch_enabled) {
newDemod->setSquelchEnabled(true);
newDemod->setSquelchLevel(squelch_level);
}
bool found_device = false;
std::map<int, RtAudio::DeviceInfo>::iterator i;
for (i = outputDevices.begin(); i != outputDevices.end(); i++) {
if (i->second.name == output_device) {
newDemod->setOutputDevice(i->first);
found_device = true;
}
}
return newDemod;
}

View File

@ -9,6 +9,8 @@
#include "DemodulatorInstance.h"
class DataNode;
class DemodulatorMgr {
public:
DemodulatorMgr();
@ -57,6 +59,10 @@ public:
void updateLastState();
void setOutputDevices(std::map<int,RtAudio::DeviceInfo> devs);
void saveInstance(DataNode *node, DemodulatorInstance *inst);
DemodulatorInstance *loadInstance(DataNode *node);
private:
void garbageCollect();
@ -82,4 +88,5 @@ private:
std::recursive_mutex demods_busy;
std::map<std::string, ModemSettings> lastModemSettings;
std::map<int,RtAudio::DeviceInfo> outputDevices;
};

View File

@ -0,0 +1,136 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "BookmarkPanel.h"
///////////////////////////////////////////////////////////////////////////
BookmarkPanel::BookmarkPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
{
wxBoxSizer* bSizer1;
bSizer1 = new wxBoxSizer( wxVERTICAL );
m_searchText = new wxTextCtrl( this, wxID_ANY, wxT("Search.."), wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
bSizer1->Add( m_searchText, 0, wxALL|wxEXPAND, 5 );
m_clearSearchButton = new wxButton( this, wxID_ANY, wxT("Clear Search"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer1->Add( m_clearSearchButton, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 );
m_treeView = new wxTreeCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTR_DEFAULT_STYLE|wxTR_EDIT_LABELS|wxTR_HAS_VARIABLE_ROW_HEIGHT|wxTR_HIDE_ROOT|wxTR_SINGLE );
bSizer1->Add( m_treeView, 1, wxEXPAND, 5 );
m_propPanel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxFlexGridSizer* fgPropSizer;
fgPropSizer = new wxFlexGridSizer( 0, 2, 0, 0 );
fgPropSizer->AddGrowableCol( 1 );
fgPropSizer->SetFlexibleDirection( wxBOTH );
fgPropSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_labelLabel = new wxStaticText( m_propPanel, wxID_ANY, wxT("Label"), wxDefaultPosition, wxDefaultSize, 0 );
m_labelLabel->Wrap( -1 );
fgPropSizer->Add( m_labelLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 );
m_labelText = new wxTextCtrl( m_propPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER );
fgPropSizer->Add( m_labelText, 0, wxALL|wxEXPAND, 5 );
m_frequencyLabel = new wxStaticText( m_propPanel, wxID_ANY, wxT("Freq"), wxDefaultPosition, wxDefaultSize, 0 );
m_frequencyLabel->Wrap( -1 );
fgPropSizer->Add( m_frequencyLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 );
m_frequencyVal = new wxStaticText( m_propPanel, wxID_ANY, wxT("FrequencyVal"), wxDefaultPosition, wxDefaultSize, 0 );
m_frequencyVal->Wrap( -1 );
fgPropSizer->Add( m_frequencyVal, 0, wxALL, 5 );
m_bandwidthLabel = new wxStaticText( m_propPanel, wxID_ANY, wxT("BW"), wxDefaultPosition, wxDefaultSize, 0 );
m_bandwidthLabel->Wrap( -1 );
fgPropSizer->Add( m_bandwidthLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 );
m_bandwidthVal = new wxStaticText( m_propPanel, wxID_ANY, wxT("BandwidthVal"), wxDefaultPosition, wxDefaultSize, 0 );
m_bandwidthVal->Wrap( -1 );
fgPropSizer->Add( m_bandwidthVal, 0, wxALL, 5 );
m_modulationLabel = new wxStaticText( m_propPanel, wxID_ANY, wxT("Type"), wxDefaultPosition, wxDefaultSize, 0 );
m_modulationLabel->Wrap( -1 );
fgPropSizer->Add( m_modulationLabel, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5 );
m_modulationVal = new wxStaticText( m_propPanel, wxID_ANY, wxT("TypeVal"), wxDefaultPosition, wxDefaultSize, 0 );
m_modulationVal->Wrap( -1 );
fgPropSizer->Add( m_modulationVal, 0, wxALL, 5 );
m_propPanel->SetSizer( fgPropSizer );
m_propPanel->Layout();
fgPropSizer->Fit( m_propPanel );
bSizer1->Add( m_propPanel, 0, wxALL|wxBOTTOM|wxEXPAND|wxTOP, 5 );
m_buttonPanel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* m_buttonPanelSizer;
m_buttonPanelSizer = new wxBoxSizer( wxVERTICAL );
m_buttonPanel->SetSizer( m_buttonPanelSizer );
m_buttonPanel->Layout();
m_buttonPanelSizer->Fit( m_buttonPanel );
bSizer1->Add( m_buttonPanel, 0, wxALL|wxEXPAND, 5 );
this->SetSizer( bSizer1 );
this->Layout();
m_updateTimer.SetOwner( this, wxID_ANY );
// Connect Events
this->Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( BookmarkPanel::onEnterWindow ) );
this->Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( BookmarkPanel::onLeaveWindow ) );
this->Connect( wxEVT_MOTION, wxMouseEventHandler( BookmarkPanel::onMotion ) );
m_searchText->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( BookmarkPanel::onSearchTextFocus ), NULL, this );
m_searchText->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BookmarkPanel::onSearchText ), NULL, this );
m_clearSearchButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BookmarkPanel::onClearSearch ), NULL, this );
m_treeView->Connect( wxEVT_MOTION, wxMouseEventHandler( BookmarkPanel::onMotion ), NULL, this );
m_treeView->Connect( wxEVT_COMMAND_TREE_BEGIN_DRAG, wxTreeEventHandler( BookmarkPanel::onTreeBeginDrag ), NULL, this );
m_treeView->Connect( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, wxTreeEventHandler( BookmarkPanel::onTreeBeginLabelEdit ), NULL, this );
m_treeView->Connect( wxEVT_COMMAND_TREE_END_DRAG, wxTreeEventHandler( BookmarkPanel::onTreeEndDrag ), NULL, this );
m_treeView->Connect( wxEVT_COMMAND_TREE_END_LABEL_EDIT, wxTreeEventHandler( BookmarkPanel::onTreeEndLabelEdit ), NULL, this );
m_treeView->Connect( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, wxTreeEventHandler( BookmarkPanel::onTreeActivate ), NULL, this );
m_treeView->Connect( wxEVT_COMMAND_TREE_ITEM_COLLAPSED, wxTreeEventHandler( BookmarkPanel::onTreeCollapse ), NULL, this );
m_treeView->Connect( wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxTreeEventHandler( BookmarkPanel::onTreeExpanded ), NULL, this );
m_treeView->Connect( wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, wxTreeEventHandler( BookmarkPanel::onTreeItemGetTooltip ), NULL, this );
m_treeView->Connect( wxEVT_COMMAND_TREE_ITEM_MENU, wxTreeEventHandler( BookmarkPanel::onTreeItemMenu ), NULL, this );
m_treeView->Connect( wxEVT_COMMAND_TREE_SEL_CHANGED, wxTreeEventHandler( BookmarkPanel::onTreeSelect ), NULL, this );
m_treeView->Connect( wxEVT_COMMAND_TREE_SEL_CHANGING, wxTreeEventHandler( BookmarkPanel::onTreeSelectChanging ), NULL, this );
m_labelText->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( BookmarkPanel::onLabelText ), NULL, this );
m_frequencyVal->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( BookmarkPanel::onDoubleClickFreq ), NULL, this );
m_bandwidthVal->Connect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( BookmarkPanel::onDoubleClickBandwidth ), NULL, this );
this->Connect( wxID_ANY, wxEVT_TIMER, wxTimerEventHandler( BookmarkPanel::onUpdateTimer ) );
}
BookmarkPanel::~BookmarkPanel()
{
// Disconnect Events
this->Disconnect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( BookmarkPanel::onEnterWindow ) );
this->Disconnect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler( BookmarkPanel::onLeaveWindow ) );
this->Disconnect( wxEVT_MOTION, wxMouseEventHandler( BookmarkPanel::onMotion ) );
m_searchText->Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( BookmarkPanel::onSearchTextFocus ), NULL, this );
m_searchText->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BookmarkPanel::onSearchText ), NULL, this );
m_clearSearchButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BookmarkPanel::onClearSearch ), NULL, this );
m_treeView->Disconnect( wxEVT_MOTION, wxMouseEventHandler( BookmarkPanel::onMotion ), NULL, this );
m_treeView->Disconnect( wxEVT_COMMAND_TREE_BEGIN_DRAG, wxTreeEventHandler( BookmarkPanel::onTreeBeginDrag ), NULL, this );
m_treeView->Disconnect( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, wxTreeEventHandler( BookmarkPanel::onTreeBeginLabelEdit ), NULL, this );
m_treeView->Disconnect( wxEVT_COMMAND_TREE_END_DRAG, wxTreeEventHandler( BookmarkPanel::onTreeEndDrag ), NULL, this );
m_treeView->Disconnect( wxEVT_COMMAND_TREE_END_LABEL_EDIT, wxTreeEventHandler( BookmarkPanel::onTreeEndLabelEdit ), NULL, this );
m_treeView->Disconnect( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, wxTreeEventHandler( BookmarkPanel::onTreeActivate ), NULL, this );
m_treeView->Disconnect( wxEVT_COMMAND_TREE_ITEM_COLLAPSED, wxTreeEventHandler( BookmarkPanel::onTreeCollapse ), NULL, this );
m_treeView->Disconnect( wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxTreeEventHandler( BookmarkPanel::onTreeExpanded ), NULL, this );
m_treeView->Disconnect( wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, wxTreeEventHandler( BookmarkPanel::onTreeItemGetTooltip ), NULL, this );
m_treeView->Disconnect( wxEVT_COMMAND_TREE_ITEM_MENU, wxTreeEventHandler( BookmarkPanel::onTreeItemMenu ), NULL, this );
m_treeView->Disconnect( wxEVT_COMMAND_TREE_SEL_CHANGED, wxTreeEventHandler( BookmarkPanel::onTreeSelect ), NULL, this );
m_treeView->Disconnect( wxEVT_COMMAND_TREE_SEL_CHANGING, wxTreeEventHandler( BookmarkPanel::onTreeSelectChanging ), NULL, this );
m_labelText->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( BookmarkPanel::onLabelText ), NULL, this );
m_frequencyVal->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( BookmarkPanel::onDoubleClickFreq ), NULL, this );
m_bandwidthVal->Disconnect( wxEVT_LEFT_DCLICK, wxMouseEventHandler( BookmarkPanel::onDoubleClickBandwidth ), NULL, this );
this->Disconnect( wxID_ANY, wxEVT_TIMER, wxTimerEventHandler( BookmarkPanel::onUpdateTimer ) );
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __BOOKMARKPANEL_H__
#define __BOOKMARKPANEL_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/string.h>
#include <wx/textctrl.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/button.h>
#include <wx/treectrl.h>
#include <wx/stattext.h>
#include <wx/sizer.h>
#include <wx/panel.h>
#include <wx/timer.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class BookmarkPanel
///////////////////////////////////////////////////////////////////////////////
class BookmarkPanel : public wxPanel
{
private:
protected:
wxTextCtrl* m_searchText;
wxButton* m_clearSearchButton;
wxTreeCtrl* m_treeView;
wxPanel* m_propPanel;
wxStaticText* m_labelLabel;
wxTextCtrl* m_labelText;
wxStaticText* m_frequencyLabel;
wxStaticText* m_frequencyVal;
wxStaticText* m_bandwidthLabel;
wxStaticText* m_bandwidthVal;
wxStaticText* m_modulationLabel;
wxStaticText* m_modulationVal;
wxPanel* m_buttonPanel;
wxTimer m_updateTimer;
// Virtual event handlers, overide them in your derived class
virtual void onEnterWindow( wxMouseEvent& event ) { event.Skip(); }
virtual void onLeaveWindow( wxMouseEvent& event ) { event.Skip(); }
virtual void onMotion( wxMouseEvent& event ) { event.Skip(); }
virtual void onSearchTextFocus( wxMouseEvent& event ) { event.Skip(); }
virtual void onSearchText( wxCommandEvent& event ) { event.Skip(); }
virtual void onClearSearch( wxCommandEvent& event ) { event.Skip(); }
virtual void onTreeBeginDrag( wxTreeEvent& event ) { event.Skip(); }
virtual void onTreeBeginLabelEdit( wxTreeEvent& event ) { event.Skip(); }
virtual void onTreeEndDrag( wxTreeEvent& event ) { event.Skip(); }
virtual void onTreeEndLabelEdit( wxTreeEvent& event ) { event.Skip(); }
virtual void onTreeActivate( wxTreeEvent& event ) { event.Skip(); }
virtual void onTreeCollapse( wxTreeEvent& event ) { event.Skip(); }
virtual void onTreeExpanded( wxTreeEvent& event ) { event.Skip(); }
virtual void onTreeItemGetTooltip( wxTreeEvent& event ) { event.Skip(); }
virtual void onTreeItemMenu( wxTreeEvent& event ) { event.Skip(); }
virtual void onTreeSelect( wxTreeEvent& event ) { event.Skip(); }
virtual void onTreeSelectChanging( wxTreeEvent& event ) { event.Skip(); }
virtual void onLabelText( wxCommandEvent& event ) { event.Skip(); }
virtual void onDoubleClickFreq( wxMouseEvent& event ) { event.Skip(); }
virtual void onDoubleClickBandwidth( wxMouseEvent& event ) { event.Skip(); }
virtual void onUpdateTimer( wxTimerEvent& event ) { event.Skip(); }
public:
BookmarkPanel( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 169,471 ), long style = wxTAB_TRAVERSAL );
~BookmarkPanel();
};
#endif //__BOOKMARKPANEL_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,169 @@
#pragma once
#include "wx/choice.h"
#include "wx/dialog.h"
#include "BookmarkPanel.h"
#include "BookmarkMgr.h"
class TreeViewItem : public wxTreeItemData {
public:
enum TreeViewItemType {
TREEVIEW_ITEM_TYPE_GROUP,
TREEVIEW_ITEM_TYPE_ACTIVE,
TREEVIEW_ITEM_TYPE_RECENT,
TREEVIEW_ITEM_TYPE_BOOKMARK,
TREEVIEW_ITEM_TYPE_RANGE
};
TreeViewItem() {
bookmarkEnt = nullptr;
demod = nullptr;
rangeEnt = nullptr;
};
TreeViewItemType type;
BookmarkEntry *bookmarkEnt;
BookmarkRangeEntry *rangeEnt;
DemodulatorInstance *demod;
std::string groupName;
};
class BookmarkViewVisualDragItem : public wxDialog {
public:
BookmarkViewVisualDragItem(wxString labelValue = L"Popup");
};
class BookmarkView : public BookmarkPanel {
public:
BookmarkView( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxTAB_TRAVERSAL );
void updateActiveList();
void updateBookmarks();
bool isKeywordMatch(std::wstring str, std::vector<std::wstring> &keywords);
void updateBookmarks(std::string group);
wxTreeItemId refreshBookmarks();
void updateTheme();
void onMenuItem(wxCommandEvent& event);
bool isMouseInView();
bool getExpandState(std::string branchName);
void setExpandState(std::string branchName, bool state);
void loadDefaultRanges();
protected:
void activeSelection(DemodulatorInstance *dsel);
void bookmarkSelection(BookmarkEntry *bmSel);
void rangeSelection(BookmarkRangeEntry *re);
void activateBookmark(BookmarkEntry *bmEnt);
void activateRange(BookmarkRangeEntry *rangeEnt);
void recentSelection(BookmarkEntry *bmSel);
void groupSelection(std::string groupName);
void bookmarkBranchSelection();
void recentBranchSelection();
void rangeBranchSelection();
void activeBranchSelection();
void hideProps();
void showProps();
void onUpdateTimer( wxTimerEvent& event );
void doUpdateActiveList();
void onTreeBeginLabelEdit( wxTreeEvent& event );
void onTreeEndLabelEdit( wxTreeEvent& event );
void onTreeActivate( wxTreeEvent& event );
void onTreeCollapse( wxTreeEvent& event );
void onTreeExpanded( wxTreeEvent& event );
void onTreeItemMenu( wxTreeEvent& event );
void onTreeSelect( wxTreeEvent& event );
void onTreeSelectChanging( wxTreeEvent& event );
void onLabelText( wxCommandEvent& event );
void onDoubleClickFreq( wxMouseEvent& event );
void onDoubleClickBandwidth( wxMouseEvent& event );
void onTreeBeginDrag( wxTreeEvent& event );
void onTreeEndDrag( wxTreeEvent& event );
void onTreeItemGetTooltip( wxTreeEvent& event );
void onEnterWindow( wxMouseEvent& event );
void onLeaveWindow( wxMouseEvent& event );
void onMotion( wxMouseEvent& event );
void onSearchTextFocus( wxMouseEvent& event );
void onSearchText( wxCommandEvent& event );
void onClearSearch( wxCommandEvent& event );
void clearButtons();
void showButtons();
void refreshLayout();
wxButton *makeButton(wxWindow *parent, std::string labelVal, wxObjectEventFunction handler);
wxButton *addButton(wxWindow *parent, std::string labelVal, wxObjectEventFunction handler);
void doBookmarkActive(std::string group, DemodulatorInstance *demod);
void doBookmarkRecent(std::string group, BookmarkEntry *be);
void doMoveBookmark(BookmarkEntry *be, std::string group);
void doRemoveActive(DemodulatorInstance *demod);
void doRemoveRecent(BookmarkEntry *be);
void doClearRecents();
void updateBookmarkChoices();
void addBookmarkChoice(wxWindow *parent);
void onBookmarkChoice( wxCommandEvent &event );
void onRemoveActive( wxCommandEvent& event );
void onRemoveBookmark( wxCommandEvent& event );
void onActivateBookmark( wxCommandEvent& event );
void onActivateRecent( wxCommandEvent& event );
void onRemoveRecent ( wxCommandEvent& event );
void onClearRecents ( wxCommandEvent& event );
void onAddGroup( wxCommandEvent& event );
void onRemoveGroup( wxCommandEvent& event );
void onRenameGroup( wxCommandEvent& event );
void onAddRange( wxCommandEvent& event );
void onRemoveRange( wxCommandEvent& event );
void onRenameRange( wxCommandEvent& event );
void onActivateRange( wxCommandEvent& event );
TreeViewItem *itemToTVI(wxTreeItemId item);
std::atomic_bool mouseInView;
wxTreeItemId rootBranch, activeBranch, bookmarkBranch, recentBranch, rangeBranch;
std::map<std::string, bool> expandState;
TreeViewItem *dragItem;
wxTreeItemId dragItemId;
BookmarkViewVisualDragItem *visualDragItem;
bool editingLabel;
// Bookmarks
std::atomic_bool doUpdateBookmarks;
std::set< std::string > doUpdateBookmarkGroup;
BookmarkNames groupNames;
std::map<std::string, wxTreeItemId> groups;
wxArrayString bookmarkChoices;
wxChoice *bookmarkChoice;
// Active
std::atomic_bool doUpdateActive;
// Focus
BookmarkEntry *nextEnt;
BookmarkRangeEntry *nextRange;
DemodulatorInstance *nextDemod;
// Search
std::vector<std::wstring> searchKeywords;
};

View File

@ -0,0 +1,61 @@
#include "ActionDialog.h"
ActionDialog *ActionDialog::activeDialog = nullptr;
ActionDialog::ActionDialog( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style)
: ActionDialogBase(parent, id, title, pos, size, style) {
}
ActionDialog::~ActionDialog() {
}
void ActionDialog::showDialog(ActionDialog *dlg) {
if (activeDialog) { // rejected
delete dlg;
return;
}
activeDialog = dlg;
dlg->Layout();
dlg->Fit();
dlg->ShowModal();
}
ActionDialog *ActionDialog::getActiveDialog() {
return activeDialog;
}
void ActionDialog::setActiveDialog(ActionDialog *dlg) {
activeDialog = dlg;
}
void ActionDialog::onClickCancel( wxCommandEvent& event ) {
ActionDialog *dlg = activeDialog;
ActionDialog::setActiveDialog(nullptr);
dlg->EndModal(0);
doClickCancel();
delete dlg;
}
void ActionDialog::onClickOK( wxCommandEvent& event ) {
ActionDialog *dlg = activeDialog;
ActionDialog::setActiveDialog(nullptr);
dlg->EndModal(0);
doClickOK();
delete dlg;
}
void ActionDialog::doClickCancel() {
}
void ActionDialog::doClickOK() {
}

View File

@ -0,0 +1,21 @@
#include "ActionDialogBase.h"
#include <mutex>
class ActionDialog : public ActionDialogBase {
public:
ActionDialog( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("QuestionTitle"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE );
~ActionDialog();
void onClickCancel( wxCommandEvent& event );
void onClickOK( wxCommandEvent& event );
virtual void doClickCancel();
virtual void doClickOK();
static ActionDialog *getActiveDialog();
static void setActiveDialog(ActionDialog *dlg);
static void showDialog(ActionDialog *dlg);
private:
static ActionDialog *activeDialog;
};

View File

@ -0,0 +1,53 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "ActionDialogBase.h"
///////////////////////////////////////////////////////////////////////////
ActionDialogBase::ActionDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* mainSizer;
mainSizer = new wxBoxSizer( wxVERTICAL );
m_questionText = new wxStaticText( this, wxID_ANY, wxT("Question"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE );
m_questionText->Wrap( -1 );
mainSizer->Add( m_questionText, 1, wxALL|wxEXPAND, 5 );
wxBoxSizer* buttonSizer;
buttonSizer = new wxBoxSizer( wxHORIZONTAL );
m_cancelButton = new wxButton( this, wxID_ANY, wxT("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
buttonSizer->Add( m_cancelButton, 1, wxALL|wxEXPAND, 5 );
m_okButton = new wxButton( this, wxID_ANY, wxT("OK"), wxDefaultPosition, wxDefaultSize, 0 );
buttonSizer->Add( m_okButton, 1, wxALL|wxEXPAND, 5 );
mainSizer->Add( buttonSizer, 1, wxEXPAND, 5 );
this->SetSizer( mainSizer );
this->Layout();
mainSizer->Fit( this );
this->Centre( wxBOTH );
// Connect Events
m_cancelButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ActionDialogBase::onClickCancel ), NULL, this );
m_okButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ActionDialogBase::onClickOK ), NULL, this );
}
ActionDialogBase::~ActionDialogBase()
{
// Disconnect Events
m_cancelButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ActionDialogBase::onClickCancel ), NULL, this );
m_okButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ActionDialogBase::onClickOK ), NULL, this );
}

View File

@ -0,0 +1,369 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="13" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">ActionDialogBase</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="internationalize">0</property>
<property name="name">ActionDialogBase</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property>
<object class="Dialog" expanded="1">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="center">wxBOTH</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="extra_style"></property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">ActionDialogBase</property>
<property name="pos"></property>
<property name="size"></property>
<property name="style">wxDEFAULT_DIALOG_STYLE</property>
<property name="subclass"></property>
<property name="title">QuestionTitle</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnActivate"></event>
<event name="OnActivateApp"></event>
<event name="OnAuiFindManager"></event>
<event name="OnAuiPaneButton"></event>
<event name="OnAuiPaneClose"></event>
<event name="OnAuiPaneMaximize"></event>
<event name="OnAuiPaneRestore"></event>
<event name="OnAuiRender"></event>
<event name="OnChar"></event>
<event name="OnClose"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnHibernate"></event>
<event name="OnIconize"></event>
<event name="OnIdle"></event>
<event name="OnInitDialog"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">mainSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Question</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_questionText</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxALIGN_CENTRE</property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">buttonSizer</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxButton" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Cancel</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_cancelButton</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">onClickCancel</event>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxButton" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">OK</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_okButton</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">onClickOK</event>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

View File

@ -0,0 +1,50 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __ACTIONDIALOGBASE_H__
#define __ACTIONDIALOGBASE_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/string.h>
#include <wx/stattext.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class ActionDialogBase
///////////////////////////////////////////////////////////////////////////////
class ActionDialogBase : public wxDialog
{
private:
protected:
wxStaticText* m_questionText;
wxButton* m_cancelButton;
wxButton* m_okButton;
// Virtual event handlers, overide them in your derived class
virtual void onClickCancel( wxCommandEvent& event ) { event.Skip(); }
virtual void onClickOK( wxCommandEvent& event ) { event.Skip(); }
public:
ActionDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("QuestionTitle"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE );
~ActionDialogBase();
};
#endif //__ACTIONDIALOGBASE_H__

View File

@ -8,7 +8,7 @@
#include "CubicSDR.h"
SDRDevicesDialog::SDRDevicesDialog( wxWindow* parent ): devFrame( parent ) {
SDRDevicesDialog::SDRDevicesDialog( wxWindow* parent ): devFrame( parent, wxID_ANY, wxT(CUBICSDR_INSTALL_NAME " :: SDR Devices")) {
refresh = true;
failed = false;
m_refreshButton->Disable();

View File

@ -6,6 +6,7 @@
#include <sstream>
#include <iostream>
#include <iomanip>
#include "CubicSDR.h"
#include "ColorTheme.h"
#include "CubicSDRDefs.h"
@ -13,6 +14,7 @@ SpectrumPanel::SpectrumPanel() {
floorValue = 0;
ceilValue = 1;
showDb = false;
useDbOfs = false;
fftSize = DEFAULT_FFT_SIZE;
bandwidth = DEFAULT_DEMOD_BW;
freq = 0;
@ -86,6 +88,14 @@ bool SpectrumPanel::getShowDb() {
return showDb;
}
void SpectrumPanel::setUseDBOffset(bool useOfs) {
this->useDbOfs = useOfs;
}
bool SpectrumPanel::getUseDBOffset() {
return useDbOfs;
}
void SpectrumPanel::setPoints(std::vector<float> &points) {
this->points.assign(points.begin(), points.end());
@ -272,11 +282,11 @@ void SpectrumPanel::drawPanelContents() {
if (showDb) {
float dbPanelWidth = (1.0 / viewWidth)*88.0 * GLFont::getScaleFactor();
float dbPanelHeight = (1.0/viewHeight)*14.0 * GLFont::getScaleFactor();
float dbOfs = useDbOfs?wxGetApp().getConfig()->getDBOffset():0;
std::stringstream ssLabel("");
if (getCeilValue() != getFloorValue() && fftSize) {
ssLabel << std::fixed << std::setprecision(1) << (20.0 * log10(2.0*(getCeilValue())/(double)fftSize)) << "dB";
ssLabel << std::fixed << std::setprecision(1) << (dbOfs + 20.0 * log10(2.0*(getCeilValue())/(double)fftSize)) << "dB";
}
dbPanelCeil.setText(ssLabel.str(), GLFont::GLFONT_ALIGN_RIGHT);
dbPanelCeil.setSize(dbPanelWidth, dbPanelHeight);
@ -285,7 +295,7 @@ void SpectrumPanel::drawPanelContents() {
ssLabel.str("");
if (getCeilValue() != getFloorValue() && fftSize) {
ssLabel << (20.0 * log10(2.0*(getFloorValue())/(double)fftSize)) << "dB";
ssLabel << (dbOfs + 20.0 * log10(2.0*(getFloorValue())/(double)fftSize)) << "dB";
}
dbPanelFloor.setText(ssLabel.str(), GLFont::GLFONT_ALIGN_RIGHT);

View File

@ -29,7 +29,10 @@ public:
void setShowDb(bool showDb);
bool getShowDb();
void setUseDBOffset(bool useOfs);
bool getUseDBOffset();
protected:
void drawPanelContents();
@ -43,5 +46,5 @@ private:
GLTextPanel dbPanelCeil;
GLTextPanel dbPanelFloor;
bool showDb;
};
bool showDb, useDbOfs;
};

View File

@ -41,6 +41,14 @@ using namespace std;
DataElement::DataElement() : data_type(DATA_NULL), data_size(0), unit_size(0), data_val(NULL) {
}
DataElement::DataElement(DataElement &cloneFrom) : data_type(cloneFrom.getDataType()), unit_size(cloneFrom.getUnitSize()) {
data_val = NULL;
data_init(cloneFrom.getDataSize());
if (data_size) {
memcpy(data_val, cloneFrom.getDataPointer(), data_size);
}
}
DataElement::~DataElement() {
if (data_val) {
delete[] data_val;
@ -427,7 +435,12 @@ std::string DataElement::toString() {
strValue = std::to_string(floatSettingValue);
} else if (dataType == DATA_NULL) {
strValue = "";
} else {
} else if (dataType == DATA_WSTRING) {
std::wstring wstr;
get(wstr);
strValue = *wstr.c_str();
}
else {
std::cout << "Unhandled DataElement toString for type: " << dataType << std::endl;
}
} catch (DataTypeMismatchException e) {
@ -482,6 +495,22 @@ DataNode::DataNode(const char *name_in): parentNode(NULL), ptr(0) {
data_elem = new DataElement();
}
DataNode::DataNode(const char *name_in, DataNode &cloneFrom): parentNode(NULL), ptr(0) {
node_name = name_in;
data_elem = new DataElement(*cloneFrom.element());
// TODO: stack recursion optimization
while (cloneFrom.hasAnother()) {
DataNode *cNode = cloneFrom.getNext();
newChildCloneFrom(cNode->getName().c_str(), cNode);
}
}
DataNode::DataNode(const char *name_in, DataElement &cloneFrom): parentNode(NULL), ptr(0) {
node_name = name_in;
data_elem = new DataElement(cloneFrom);
}
DataNode::~DataNode() {
while (children.size()) {
DataNode *del = children.back();
@ -510,6 +539,34 @@ DataNode *DataNode::newChild(const char *name_in) {
return children.back();
}
DataNode *DataNode::newChild(const char *name_in, DataNode *otherNode) {
children.push_back(otherNode);
childmap[name_in].push_back(children.back());
children.back()->setParentNode(*this);
return children.back();
}
DataNode *DataNode::newChildCloneFrom(const char *name_in, DataNode *cloneFrom) {
DataNode *cloneNode = new DataNode(name_in, *cloneFrom->element());
children.push_back(cloneNode);
childmap[name_in].push_back(children.back());
children.back()->setParentNode(*this);
// TODO: stack recursion optimization
while (cloneFrom->hasAnother()) {
DataNode *cNode = cloneFrom->getNext();
cloneNode->newChildCloneFrom(cNode->getName().c_str(), cNode);
}
cloneFrom->rewind();
return children.back();
}
DataNode *DataNode::child(const char *name_in, int index) {
DataNode *child_ret;
@ -565,6 +622,7 @@ DataNode *DataNode::getNext(const char *name_in) {
void DataNode::rewind() {
ptr = 0;
childmap_ptr.erase(childmap_ptr.begin(),childmap_ptr.end());
}
void DataNode::rewind(const char *name_in) {
@ -1342,6 +1400,38 @@ long DataTree::getSerializedSize(DataElement &de_node_names, bool debug) /* get
return total_size;
}
void DataNode::rewindAll() {
stack<DataNode *> dn_stack;
/* start at the root */
dn_stack.push(this);
while (!dn_stack.empty()) {
dn_stack.top()->rewind();
/* if it has children, traverse into them */
if (dn_stack.top()->hasAnother()) {
dn_stack.push(dn_stack.top()->getNext());
dn_stack.top()->rewind();
} else {
/* no more children, back out until we have children, then add next child to the top */
while (!dn_stack.empty()) {
if (!dn_stack.top()->hasAnother()) {
dn_stack.top()->rewind();
dn_stack.pop();
} else
break;
}
if (!dn_stack.empty()) {
dn_stack.push(dn_stack.top()->getNext());
dn_stack.top()->rewind();
}
}
}
}
void DataNode::findAll(const char *name_in, vector<DataNode *> &node_list_out) {
stack<DataNode *> dn_stack;

View File

@ -128,6 +128,7 @@ private:
public:
DataElement();
DataElement(DataElement &cloneFrom);
~DataElement();
int getDataType();
@ -235,8 +236,10 @@ private:
public:
DataNode();
DataNode(const char *name_in);
~DataNode();
DataNode(const char *name_in, DataElement &cloneFrom);
DataNode(const char *name_in, DataNode &cloneFrom);
~DataNode();
void setName(const char *name_in);
string &getName() { return node_name; }
@ -250,6 +253,8 @@ public:
DataElement *element(); /* DataElement at this node */
DataNode *newChild(const char *name_in);
DataNode *newChild(const char *name_in, DataNode *otherNode);
DataNode *newChildCloneFrom(const char *name_in, DataNode *cloneFrom);
DataNode *child(const char *name_in, int index = 0);
DataNode *child(int index);
@ -260,7 +265,8 @@ public:
DataNode *getNext(); /* get next child */
void rewind(const char *name_in); /* rewind specific */
void rewind(); /* rewind generic */
void rewindAll();
void findAll(const char *name_in, vector<DataNode *> &node_list_out);
// operator string () { string s; element()->get(s); return s; }
@ -287,6 +293,7 @@ public:
operator vector<long double> () { vector<long double> v; element()->get(v); return v; }
const string &operator= (const string &s) { element()->set(s); return s; }
const wstring &operator= (const wstring &s) { element()->set(s); return s; }
char operator= (char i) { element()->set(i); return i; }
unsigned char operator= (unsigned char i) { element()->set(i); return i; }
@ -316,7 +323,6 @@ public:
bool operator() () { return hasAnother(); }
DataNode *operator ^(const char *name_in) { return newChild(name_in); }
};

View File

@ -8,6 +8,7 @@
#include <map>
#include <vector>
#include <string>
#include <wx/colour.h>
#define COLOR_THEME_DEFAULT 0
#define COLOR_THEME_BW 1
@ -41,6 +42,14 @@ public:
}
RGBA4f operator*(float v) { return RGBA4f(r*v, g*v, b*v); }
operator wxColour() {
return wxColour(
(unsigned char) std::min((r * 255.0), 255.0),
(unsigned char) std::min((g * 255.0), 255.0),
(unsigned char) std::min((b * 255.0), 255.0));
}
};

50
src/visual/ImagePanel.cpp Normal file
View File

@ -0,0 +1,50 @@
#include "ImagePanel.h"
BEGIN_EVENT_TABLE(ImagePanel, wxPanel)
EVT_PAINT(ImagePanel::paintEvent)
END_EVENT_TABLE()
ImagePanel::ImagePanel(wxPanel * parent, wxString file, wxBitmapType format) :
wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE) {
image.LoadFile(file, format);
}
void ImagePanel::paintEvent(wxPaintEvent & evt) {
wxPaintDC dc(this);
render(dc);
}
void ImagePanel::paintNow() {
wxClientDC dc(this);
render(dc);
}
void ImagePanel::render(wxDC& dc) {
double imagew = image.GetWidth();
double imageh = image.GetHeight();
wxSize destSize = dc.GetSize();
double destw = destSize.GetWidth();
double desth = destSize.GetHeight();
double sf = 1.0, wf, hf;
wf = destw / imagew;
hf = desth / imageh;
sf = (wf < hf)?wf:hf;
double resulth = imageh * sf;
double resultw = imagew * sf;
dc.SetUserScale(sf, sf);
dc.DrawBitmap( image, (destw/2 - resultw/2)/sf, (desth/2 - resulth/2)/sf, false );
}

16
src/visual/ImagePanel.h Normal file
View File

@ -0,0 +1,16 @@
#include <wx/wx.h>
#include <wx/sizer.h>
class ImagePanel : public wxPanel {
wxBitmap image;
public:
ImagePanel(wxPanel* parent, wxString file, wxBitmapType format);
void paintEvent(wxPaintEvent & evt);
void paintNow();
void render(wxDC& dc);
DECLARE_EVENT_TABLE()
};

View File

@ -177,6 +177,14 @@ bool SpectrumCanvas::getShowDb() {
return spectrumPanel.getShowDb();
}
void SpectrumCanvas::setUseDBOfs(bool showDb) {
spectrumPanel.setUseDBOffset(showDb);
}
bool SpectrumCanvas::getUseDBOfs() {
return spectrumPanel.getUseDBOffset();
}
void SpectrumCanvas::setView(long long center_freq_in, int bandwidth_in) {
bwChange += bandwidth_in-bandwidth;
#define BW_RESET_TH 400000
@ -296,7 +304,9 @@ void SpectrumCanvas::OnMouseRightReleased(wxMouseEvent& event) {
wxGetApp().getSpectrumProcessor()->setPeakHold(wxGetApp().getSpectrumProcessor()->getPeakHold());
//make the peak hold act on the current dmod also, like a zoomed-in version.
wxGetApp().getDemodSpectrumProcessor()->setPeakHold(wxGetApp().getSpectrumProcessor()->getPeakHold());
if (wxGetApp().getDemodSpectrumProcessor()) {
wxGetApp().getDemodSpectrumProcessor()->setPeakHold(wxGetApp().getSpectrumProcessor()->getPeakHold());
}
}
mouseTracker.OnMouseRightReleased(event);
}

View File

@ -25,6 +25,9 @@ public:
void setShowDb(bool showDb);
bool getShowDb();
void setUseDBOfs(bool showDb);
bool getUseDBOfs();
void setView(long long center_freq_in, int bandwidth_in);
void disableView();