Compare commits

..

11 Commits
dev ... gr-3.8

  1. 1
      .gitignore
  2. 70
      CMakeLists.txt
  3. 8937
      apps/fft-multi-decoder_fixed_dual-rtlsdr.grc
  4. 4
      apps/fft-multi-decoder_fixed_rtlsdr.grc
  5. 4556
      apps/ifft-RDS-decoder_hier-block.grc
  6. 1005
      apps/read_sync_decim.grc
  7. 4
      cmake/Modules/.directory
  8. 2
      cmake/Modules/CMakeParseArgumentsCopy.cmake
  9. 36
      cmake/Modules/FindGnuradioRuntime.cmake
  10. 528
      cmake/Modules/GrMiscUtils.cmake
  11. 54
      cmake/Modules/GrPlatform.cmake
  12. 241
      cmake/Modules/GrPython.cmake
  13. 251
      cmake/Modules/GrSwig.cmake
  14. 143
      cmake/Modules/GrTest.cmake
  15. 304
      cmake/Modules/UseSWIG.cmake
  16. 5
      cmake/Modules/multirdsConfig.cmake
  17. 28
      grc/CMakeLists.txt
  18. 25
      grc/multirds_decoder_compare.block.yml
  19. 28
      grc/multirds_decoder_compare.xml
  20. 57
      grc/multirds_pilot_SNR.block.yml
  21. 84
      grc/multirds_pilot_SNR.xml
  22. 136
      grc/multirds_qtgui_range.xml
  23. 32
      grc/multirds_rds_decoder.block.yml
  24. 45
      grc/multirds_rds_decoder.xml
  25. 32
      grc/multirds_rds_decoder_redsea.block.yml
  26. 45
      grc/multirds_rds_decoder_redsea.xml
  27. 96
      grc/multirds_rds_parser_table_qt.block.yml
  28. 141
      grc/multirds_rds_parser_table_qt.xml
  29. 37
      grc/multirds_rds_table_qt.block.yml
  30. 46
      grc/multirds_rds_table_qt.xml
  31. 52
      grc/multirds_station_search.block.yml
  32. 78
      grc/multirds_station_search.xml
  33. 29
      grc/multirds_stream_router.block.yml
  34. 54
      grc/multirds_stream_router.xml
  35. 30
      grc/multirds_stream_selector.block.yml
  36. 38
      grc/multirds_stream_selector.xml
  37. 30
      grc/multirds_symbol_combiner.block.yml
  38. 70
      grc/multirds_symbol_combiner.xml
  39. 62
      grc/multirds_tmc_parser.block.yml
  40. 112
      grc/multirds_tmc_parser.xml
  41. 37
      grc/multirds_variable_setter.block.yml
  42. 59
      grc/multirds_variable_setter.xml
  43. 55
      grc/multirds_vector_cutter.block.yml
  44. 87
      grc/multirds_vector_cutter.xml
  45. 4
      python/CMakeLists.txt
  46. 25
      python/__init__.py
  47. 226
      python/build_utils.py
  48. 52
      python/build_utils_codes.py
  49. 2
      python/chart.py
  50. 4
      python/decoder_compare.py
  51. 2
      python/qa_rds_parser_table_qt.py
  52. 2
      python/qa_tmc_parser.py
  53. 279
      python/qtgui_range.py
  54. 176
      python/rds_parser_table_qt.py
  55. 8
      python/rds_table_qt.py
  56. 2
      python/station_search.py
  57. 2
      python/stream_selector.py
  58. 13
      python/tmc_classes.py
  59. 8
      python/tmc_parser.py
  60. 105
      python/top_block.py
  61. 2
      python/variable_setter.py
  62. 4
      python/vector_cutter.py

1
.gitignore vendored

@ -6,3 +6,4 @@ apps/*.pyc
build-manlap build-manlap
*.bak *.bak
directory_writable directory_writable
data/LCL

70
CMakeLists.txt

@ -24,7 +24,7 @@ add_definitions(-std=c++11)
######################################################################## ########################################################################
# Project setup # Project setup
######################################################################## ########################################################################
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 3.8)
project(gr-multirds CXX C) project(gr-multirds CXX C)
enable_testing() enable_testing()
@ -53,11 +53,33 @@ set(VERSION_INFO_MAINT_VERSION git)
######################################################################## ########################################################################
# Compiler specific setup # Compiler specific setup
######################################################################## ########################################################################
if(CMAKE_COMPILER_IS_GNUCXX AND NOT WIN32) if((CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR
CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
AND NOT WIN32)
#http://gcc.gnu.org/wiki/Visibility #http://gcc.gnu.org/wiki/Visibility
add_definitions(-fvisibility=hidden) add_definitions(-fvisibility=hidden)
endif() endif()
IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
SET(CMAKE_CXX_STANDARD 11)
ELSEIF(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
SET(CMAKE_CXX_STANDARD 11)
ELSEIF(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
SET(CMAKE_CXX_STANDARD 11)
ELSE()
message(WARNING "C++ standard could not be set because compiler is not GNU, Clang or MSVC.")
ENDIF()
IF(CMAKE_C_COMPILER_ID STREQUAL "GNU")
SET(CMAKE_C_STANDARD 11)
ELSEIF(CMAKE_C_COMPILER_ID MATCHES "Clang")
SET(CMAKE_C_STANDARD 11)
ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
SET(CMAKE_C_STANDARD 11)
ELSE()
message(WARNING "C standard could not be set because compiler is not GNU, Clang or MSVC.")
ENDIF()
######################################################################## ########################################################################
# Find boost # Find boost
######################################################################## ########################################################################
@ -82,19 +104,21 @@ endif()
######################################################################## ########################################################################
# Install directories # Install directories
######################################################################## ########################################################################
find_package(Gnuradio "3.8" REQUIRED)
include(GrVersion)
include(GrPlatform) #define LIB_SUFFIX include(GrPlatform) #define LIB_SUFFIX
set(GR_RUNTIME_DIR bin)
set(GR_LIBRARY_DIR lib${LIB_SUFFIX}) if(NOT CMAKE_MODULES_DIR)
set(CMAKE_MODULES_DIR lib${LIB_SUFFIX}/cmake)
endif(NOT CMAKE_MODULES_DIR)
set(GR_INCLUDE_DIR include/multirds) set(GR_INCLUDE_DIR include/multirds)
set(GR_DATA_DIR share) set(GR_CMAKE_DIR ${CMAKE_MODULES_DIR}/multirds)
set(GR_PKG_DATA_DIR ${GR_DATA_DIR}/${CMAKE_PROJECT_NAME}) set(GR_PKG_DATA_DIR ${GR_DATA_DIR}/${CMAKE_PROJECT_NAME})
set(GR_DOC_DIR ${GR_DATA_DIR}/doc)
set(GR_PKG_DOC_DIR ${GR_DOC_DIR}/${CMAKE_PROJECT_NAME}) set(GR_PKG_DOC_DIR ${GR_DOC_DIR}/${CMAKE_PROJECT_NAME})
set(GR_CONF_DIR etc)
set(GR_PKG_CONF_DIR ${GR_CONF_DIR}/${CMAKE_PROJECT_NAME}/conf.d) set(GR_PKG_CONF_DIR ${GR_CONF_DIR}/${CMAKE_PROJECT_NAME}/conf.d)
set(GR_LIBEXEC_DIR libexec)
set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME}) set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME})
set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks)
######################################################################## ########################################################################
# On Apple only, set install name and use rpath correctly, if not already set # On Apple only, set install name and use rpath correctly, if not already set
@ -116,24 +140,12 @@ if(APPLE)
endif(NOT CMAKE_BUILD_WITH_INSTALL_RPATH) endif(NOT CMAKE_BUILD_WITH_INSTALL_RPATH)
endif(APPLE) endif(APPLE)
######################################################################## ########################################################################
# Find gnuradio build dependencies # Find gnuradio build dependencies
######################################################################## ########################################################################
find_package(CppUnit)
find_package(Doxygen) find_package(Doxygen)
find_package(CppUnit)
# Search for GNU Radio and its components and versions. Add any
# components required to the list of GR_REQUIRED_COMPONENTS (in all
# caps such as FILTER or FFT) and change the version to the minimum
# API compatible version required.
set(GR_REQUIRED_COMPONENTS RUNTIME)
find_package(Gnuradio "3.7.2" REQUIRED)
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules)
include(GrVersion)
if(NOT CPPUNIT_FOUND)
message(FATAL_ERROR "CppUnit required to compile multirds")
endif()
######################################################################## ########################################################################
# Setup doxygen option # Setup doxygen option
@ -166,7 +178,6 @@ link_directories(
# Set component parameters # Set component parameters
set(GR_MULTIRDS_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE INTERNAL "" FORCE) set(GR_MULTIRDS_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE INTERNAL "" FORCE)
set(GR_MULTIRDS_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/swig CACHE INTERNAL "" FORCE) set(GR_MULTIRDS_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/swig CACHE INTERNAL "" FORCE)
######################################################################## ########################################################################
# Create uninstall target # Create uninstall target
######################################################################## ########################################################################
@ -177,25 +188,22 @@ configure_file(
add_custom_target(uninstall add_custom_target(uninstall
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
) )
######################################################################## ########################################################################
# Add subdirectories # Add subdirectories
######################################################################## ########################################################################
add_subdirectory(include/multirds) add_subdirectory(include/multirds)
add_subdirectory(lib) add_subdirectory(lib)
add_subdirectory(apps)
add_subdirectory(docs)
add_subdirectory(swig) add_subdirectory(swig)
add_subdirectory(python) add_subdirectory(python)
add_subdirectory(grc) add_subdirectory(grc)
add_subdirectory(apps)
add_subdirectory(docs)
######################################################################## ########################################################################
# Install cmake search helper for this library # Install cmake search helper for this library
######################################################################## ########################################################################
if(NOT CMAKE_MODULES_DIR)
set(CMAKE_MODULES_DIR lib${LIB_SUFFIX}/cmake)
endif(NOT CMAKE_MODULES_DIR)
install(FILES cmake/Modules/multirdsConfig.cmake install(FILES cmake/Modules/multirdsConfig.cmake
DESTINATION ${CMAKE_MODULES_DIR}/multirds DESTINATION ${CMAKE_MODULES_DIR}/multirds

8937
apps/fft-multi-decoder_fixed_dual-rtlsdr.grc

File diff suppressed because it is too large Load Diff

4
apps/fft-multi-decoder_fixed_rtlsdr.grc

@ -2282,7 +2282,7 @@ class blk(gr.sync_block): # other base classes are basic_block, decim_block, in
</param> </param>
<param> <param>
<key>workdir</key> <key>workdir</key>
<value>/media/clemens/intdaten/uni_bulk/forschungsarbeit/data/</value> <value>/media/clemens/teratemp/tmp/gr-multirds/data/</value>
</param> </param>
<param> <param>
<key>writeDB</key> <key>writeDB</key>
@ -2341,7 +2341,7 @@ class blk(gr.sync_block): # other base classes are basic_block, decim_block, in
</param> </param>
<param> <param>
<key>workdir</key> <key>workdir</key>
<value>/media/clemens/intdaten/uni_bulk/forschungsarbeit/data/</value> <value>/media/clemens/teratemp/tmp/gr-multirds/data/</value>
</param> </param>
<param> <param>
<key>writeDB</key> <key>writeDB</key>

4556
apps/ifft-RDS-decoder_hier-block.grc

File diff suppressed because it is too large Load Diff

1005
apps/read_sync_decim.grc

File diff suppressed because it is too large Load Diff

4
cmake/Modules/.directory

@ -1,4 +0,0 @@
[Dolphin]
Timestamp=2016,12,6,13,18,42
Version=3
ViewMode=2

2
cmake/Modules/CMakeParseArgumentsCopy.cmake

@ -58,7 +58,7 @@
# the new option. # the new option.
# E.g. my_install(TARGETS foo DESTINATION OPTIONAL) would result in # E.g. my_install(TARGETS foo DESTINATION OPTIONAL) would result in
# MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION would # MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION would
# be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor. # be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefore.
#============================================================================= #=============================================================================
# Copyright 2010 Alexander Neundorf <neundorf@kde.org> # Copyright 2010 Alexander Neundorf <neundorf@kde.org>

36
cmake/Modules/FindGnuradioRuntime.cmake

@ -1,36 +0,0 @@
INCLUDE(FindPkgConfig)
PKG_CHECK_MODULES(PC_GNURADIO_RUNTIME gnuradio-runtime)
if(PC_GNURADIO_RUNTIME_FOUND)
# look for include files
FIND_PATH(
GNURADIO_RUNTIME_INCLUDE_DIRS
NAMES gnuradio/top_block.h
HINTS $ENV{GNURADIO_RUNTIME_DIR}/include
${PC_GNURADIO_RUNTIME_INCLUDE_DIRS}
${CMAKE_INSTALL_PREFIX}/include
PATHS /usr/local/include
/usr/include
)
# look for libs
FIND_LIBRARY(
GNURADIO_RUNTIME_LIBRARIES
NAMES gnuradio-runtime
HINTS $ENV{GNURADIO_RUNTIME_DIR}/lib
${PC_GNURADIO_RUNTIME_LIBDIR}
${CMAKE_INSTALL_PREFIX}/lib/
${CMAKE_INSTALL_PREFIX}/lib64/
PATHS /usr/local/lib
/usr/local/lib64
/usr/lib
/usr/lib64
)
set(GNURADIO_RUNTIME_FOUND ${PC_GNURADIO_RUNTIME_FOUND})
endif(PC_GNURADIO_RUNTIME_FOUND)
INCLUDE(FindPackageHandleStandardArgs)
# do not check GNURADIO_RUNTIME_INCLUDE_DIRS, is not set when default include path us used.
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_RUNTIME DEFAULT_MSG GNURADIO_RUNTIME_LIBRARIES)
MARK_AS_ADVANCED(GNURADIO_RUNTIME_LIBRARIES GNURADIO_RUNTIME_INCLUDE_DIRS)

528
cmake/Modules/GrMiscUtils.cmake

@ -1,528 +0,0 @@
# Copyright 2010-2011,2014 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
if(DEFINED __INCLUDED_GR_MISC_UTILS_CMAKE)
return()
endif()
set(__INCLUDED_GR_MISC_UTILS_CMAKE TRUE)
########################################################################
# Set global variable macro.
# Used for subdirectories to export settings.
# Example: include and library paths.
########################################################################
function(GR_SET_GLOBAL var)
set(${var} ${ARGN} CACHE INTERNAL "" FORCE)
endfunction(GR_SET_GLOBAL)
########################################################################
# Set the pre-processor definition if the condition is true.
# - def the pre-processor definition to set and condition name
########################################################################
function(GR_ADD_COND_DEF def)
if(${def})
add_definitions(-D${def})
endif(${def})
endfunction(GR_ADD_COND_DEF)
########################################################################
# Check for a header and conditionally set a compile define.
# - hdr the relative path to the header file
# - def the pre-processor definition to set
########################################################################
function(GR_CHECK_HDR_N_DEF hdr def)
include(CheckIncludeFileCXX)
CHECK_INCLUDE_FILE_CXX(${hdr} ${def})
GR_ADD_COND_DEF(${def})
endfunction(GR_CHECK_HDR_N_DEF)
########################################################################
# Include subdirectory macro.
# Sets the CMake directory variables,
# includes the subdirectory CMakeLists.txt,
# resets the CMake directory variables.
#
# This macro includes subdirectories rather than adding them
# so that the subdirectory can affect variables in the level above.
# This provides a work-around for the lack of convenience libraries.
# This way a subdirectory can append to the list of library sources.
########################################################################
macro(GR_INCLUDE_SUBDIRECTORY subdir)
#insert the current directories on the front of the list
list(INSERT _cmake_source_dirs 0 ${CMAKE_CURRENT_SOURCE_DIR})
list(INSERT _cmake_binary_dirs 0 ${CMAKE_CURRENT_BINARY_DIR})
#set the current directories to the names of the subdirs
set(CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${subdir})
set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${subdir})
#include the subdirectory CMakeLists to run it
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
include(${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt)
#reset the value of the current directories
list(GET _cmake_source_dirs 0 CMAKE_CURRENT_SOURCE_DIR)
list(GET _cmake_binary_dirs 0 CMAKE_CURRENT_BINARY_DIR)
#pop the subdir names of the front of the list
list(REMOVE_AT _cmake_source_dirs 0)
list(REMOVE_AT _cmake_binary_dirs 0)
endmacro(GR_INCLUDE_SUBDIRECTORY)
########################################################################
# Check if a compiler flag works and conditionally set a compile define.
# - flag the compiler flag to check for
# - have the variable to set with result
########################################################################
macro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE flag have)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG(${flag} ${have})
if(${have})
if(${CMAKE_VERSION} VERSION_GREATER "2.8.4")
STRING(FIND "${CMAKE_CXX_FLAGS}" "${flag}" flag_dup)
if(${flag_dup} EQUAL -1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}")
endif(${flag_dup} EQUAL -1)
endif(${CMAKE_VERSION} VERSION_GREATER "2.8.4")
endif(${have})
endmacro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE)
########################################################################
# Generates the .la libtool file
# This appears to generate libtool files that cannot be used by auto*.
# Usage GR_LIBTOOL(TARGET [target] DESTINATION [dest])
# Notice: there is not COMPONENT option, these will not get distributed.
########################################################################
function(GR_LIBTOOL)
if(NOT DEFINED GENERATE_LIBTOOL)
set(GENERATE_LIBTOOL OFF) #disabled by default
endif()
if(GENERATE_LIBTOOL)
include(CMakeParseArgumentsCopy)
CMAKE_PARSE_ARGUMENTS(GR_LIBTOOL "" "TARGET;DESTINATION" "" ${ARGN})
find_program(LIBTOOL libtool)
if(LIBTOOL)
include(CMakeMacroLibtoolFile)
CREATE_LIBTOOL_FILE(${GR_LIBTOOL_TARGET} /${GR_LIBTOOL_DESTINATION})
endif(LIBTOOL)
endif(GENERATE_LIBTOOL)
endfunction(GR_LIBTOOL)
########################################################################
# Do standard things to the library target
# - set target properties
# - make install rules
# Also handle gnuradio custom naming conventions w/ extras mode.
########################################################################
function(GR_LIBRARY_FOO target)
#parse the arguments for component names
include(CMakeParseArgumentsCopy)
CMAKE_PARSE_ARGUMENTS(GR_LIBRARY "" "RUNTIME_COMPONENT;DEVEL_COMPONENT" "" ${ARGN})
#set additional target properties
set_target_properties(${target} PROPERTIES SOVERSION ${LIBVER})
#install the generated files like so...
install(TARGETS ${target}
LIBRARY DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} # .so/.dylib file
ARCHIVE DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_DEVEL_COMPONENT} # .lib file
RUNTIME DESTINATION ${GR_RUNTIME_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} # .dll file
)
#extras mode enabled automatically on linux
if(NOT DEFINED LIBRARY_EXTRAS)
set(LIBRARY_EXTRAS ${LINUX})
endif()
#special extras mode to enable alternative naming conventions
if(LIBRARY_EXTRAS)
#create .la file before changing props
GR_LIBTOOL(TARGET ${target} DESTINATION ${GR_LIBRARY_DIR})
#give the library a special name with ultra-zero soversion
set_target_properties(${target} PROPERTIES OUTPUT_NAME ${target}-${LIBVER} SOVERSION "0.0.0")
set(target_name lib${target}-${LIBVER}.so.0.0.0)
#custom command to generate symlinks
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}.so
COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}-${LIBVER}.so.0
COMMAND ${CMAKE_COMMAND} -E touch ${target_name} #so the symlinks point to something valid so cmake 2.6 will install
)
#and install the extra symlinks
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/lib${target}.so
${CMAKE_CURRENT_BINARY_DIR}/lib${target}-${LIBVER}.so.0
DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT}
)
endif(LIBRARY_EXTRAS)
endfunction(GR_LIBRARY_FOO)
########################################################################
# Create a dummy custom command that depends on other targets.
# Usage:
# GR_GEN_TARGET_DEPS(unique_name target_deps <target1> <target2> ...)
# ADD_CUSTOM_COMMAND(<the usual args> ${target_deps})
#
# Custom command cant depend on targets, but can depend on executables,
# and executables can depend on targets. So this is the process:
########################################################################
function(GR_GEN_TARGET_DEPS name var)
file(
WRITE ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp.in
"int main(void){return 0;}\n"
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp.in
${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp
)
add_executable(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp)
if(ARGN)
add_dependencies(${name} ${ARGN})
endif(ARGN)
if(CMAKE_CROSSCOMPILING)
set(${var} "DEPENDS;${name}" PARENT_SCOPE) #cant call command when cross
else()
set(${var} "DEPENDS;${name};COMMAND;${name}" PARENT_SCOPE)
endif()
endfunction(GR_GEN_TARGET_DEPS)
########################################################################
# Control use of gr_logger
# Usage:
# GR_LOGGING()
#
# Will set ENABLE_GR_LOG to 1 by default.
# Can manually set with -DENABLE_GR_LOG=0|1
########################################################################
function(GR_LOGGING)
find_package(Log4cpp)
OPTION(ENABLE_GR_LOG "Use gr_logger" ON)
if(ENABLE_GR_LOG)
# If gr_logger is enabled, make it usable
add_definitions( -DENABLE_GR_LOG )
# also test LOG4CPP; if we have it, use this version of the logger
# otherwise, default to the stdout/stderr model.
if(LOG4CPP_FOUND)
SET(HAVE_LOG4CPP True CACHE INTERNAL "" FORCE)
add_definitions( -DHAVE_LOG4CPP )
else(not LOG4CPP_FOUND)
SET(HAVE_LOG4CPP False CACHE INTERNAL "" FORCE)
SET(LOG4CPP_INCLUDE_DIRS "" CACHE INTERNAL "" FORCE)
SET(LOG4CPP_LIBRARY_DIRS "" CACHE INTERNAL "" FORCE)
SET(LOG4CPP_LIBRARIES "" CACHE INTERNAL "" FORCE)
endif(LOG4CPP_FOUND)
SET(ENABLE_GR_LOG ${ENABLE_GR_LOG} CACHE INTERNAL "" FORCE)
else(ENABLE_GR_LOG)
SET(HAVE_LOG4CPP False CACHE INTERNAL "" FORCE)
SET(LOG4CPP_INCLUDE_DIRS "" CACHE INTERNAL "" FORCE)
SET(LOG4CPP_LIBRARY_DIRS "" CACHE INTERNAL "" FORCE)
SET(LOG4CPP_LIBRARIES "" CACHE INTERNAL "" FORCE)
endif(ENABLE_GR_LOG)
message(STATUS "ENABLE_GR_LOG set to ${ENABLE_GR_LOG}.")
message(STATUS "HAVE_LOG4CPP set to ${HAVE_LOG4CPP}.")
message(STATUS "LOG4CPP_LIBRARIES set to ${LOG4CPP_LIBRARIES}.")
endfunction(GR_LOGGING)
########################################################################
# Run GRCC to compile .grc files into .py files.
#
# Usage: GRCC(filename, directory)
# - filenames: List of file name of .grc file
# - directory: directory of built .py file - usually in
# ${CMAKE_CURRENT_BINARY_DIR}
# - Sets PYFILES: output converted GRC file names to Python files.
########################################################################
function(GRCC)
# Extract directory from list of args, remove it for the list of filenames.
list(GET ARGV -1 directory)
list(REMOVE_AT ARGV -1)
set(filenames ${ARGV})
file(MAKE_DIRECTORY ${directory})
SET(GRCC_COMMAND ${CMAKE_SOURCE_DIR}/gr-utils/python/grcc)
# GRCC uses some stuff in grc and gnuradio-runtime, so we force
# the known paths here
list(APPEND PYTHONPATHS
${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/gnuradio-runtime/python
${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib/swig
${CMAKE_BINARY_DIR}/gnuradio-runtime/lib/swig
)
if(WIN32)
#SWIG generates the python library files into a subdirectory.
#Therefore, we must append this subdirectory into PYTHONPATH.
#Only do this for the python directories matching the following:
foreach(pydir ${PYTHONPATHS})
get_filename_component(name ${pydir} NAME)
if(name MATCHES "^(swig|lib|src)$")
list(APPEND PYTHONPATHS ${pydir}/${CMAKE_BUILD_TYPE})
endif()
endforeach(pydir)
endif(WIN32)
file(TO_NATIVE_PATH "${PYTHONPATHS}" pypath)
if(UNIX)
list(APPEND pypath "$PYTHONPATH")
string(REPLACE ";" ":" pypath "${pypath}")
set(ENV{PYTHONPATH} ${pypath})
endif(UNIX)
if(WIN32)
list(APPEND pypath "%PYTHONPATH%")
string(REPLACE ";" "\\;" pypath "${pypath}")
#list(APPEND environs "PYTHONPATH=${pypath}")
set(ENV{PYTHONPATH} ${pypath})
endif(WIN32)
foreach(f ${filenames})
execute_process(
COMMAND ${GRCC_COMMAND} -d ${directory} ${f}
)
string(REPLACE ".grc" ".py" pyfile "${f}")
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" pyfile "${pyfile}")
list(APPEND pyfiles ${pyfile})
endforeach(f)
set(PYFILES ${pyfiles} PARENT_SCOPE)
endfunction(GRCC)
########################################################################
# Check if HAVE_PTHREAD_SETSCHEDPARAM and HAVE_SCHED_SETSCHEDULER
# should be defined
########################################################################
macro(GR_CHECK_LINUX_SCHED_AVAIL)
set(CMAKE_REQUIRED_LIBRARIES -lpthread)
CHECK_CXX_SOURCE_COMPILES("
#include <pthread.h>
int main(){
pthread_t pthread;
pthread_setschedparam(pthread, 0, 0);
return 0;
} " HAVE_PTHREAD_SETSCHEDPARAM
)
GR_ADD_COND_DEF(HAVE_PTHREAD_SETSCHEDPARAM)
CHECK_CXX_SOURCE_COMPILES("
#include <sched.h>
int main(){
pid_t pid;
sched_setscheduler(pid, 0, 0);
return 0;
} " HAVE_SCHED_SETSCHEDULER
)
GR_ADD_COND_DEF(HAVE_SCHED_SETSCHEDULER)
endmacro(GR_CHECK_LINUX_SCHED_AVAIL)
########################################################################
# Macros to generate source and header files from template
########################################################################
macro(GR_EXPAND_X_H component root)
include(GrPython)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
"#!${PYTHON_EXECUTABLE}
import sys, os, re
sys.path.append('${GR_RUNTIME_PYTHONPATH}')
sys.path.append('${CMAKE_SOURCE_DIR}/python')
os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
if __name__ == '__main__':
import build_utils
root, inp = sys.argv[1:3]
for sig in sys.argv[3:]:
name = re.sub ('X+', sig, root)
d = build_utils.standard_dict2(name, sig, '${component}')
build_utils.expand_template(d, inp)
")
#make a list of all the generated headers
unset(expanded_files_h)
foreach(sig ${ARGN})
string(REGEX REPLACE "X+" ${sig} name ${root})
list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/${name}.h)
endforeach(sig)
unset(name)
#create a command to generate the headers
add_custom_command(
OUTPUT ${expanded_files_h}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t
COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
${root} ${root}.h.t ${ARGN}
)
#install rules for the generated headers
list(APPEND generated_includes ${expanded_files_h})
endmacro(GR_EXPAND_X_H)
macro(GR_EXPAND_X_CC_H component root)
include(GrPython)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
"#!${PYTHON_EXECUTABLE}
import sys, os, re
sys.path.append('${GR_RUNTIME_PYTHONPATH}')
sys.path.append('${CMAKE_SOURCE_DIR}/python')
os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
if __name__ == '__main__':
import build_utils
root, inp = sys.argv[1:3]
for sig in sys.argv[3:]:
name = re.sub ('X+', sig, root)
d = build_utils.standard_impl_dict2(name, sig, '${component}')
build_utils.expand_template(d, inp)
")
#make a list of all the generated files
unset(expanded_files_cc)
unset(expanded_files_h)
foreach(sig ${ARGN})
string(REGEX REPLACE "X+" ${sig} name ${root})
list(APPEND expanded_files_cc ${CMAKE_CURRENT_BINARY_DIR}/${name}.cc)
list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/${name}.h)
endforeach(sig)
unset(name)
#create a command to generate the source files
add_custom_command(
OUTPUT ${expanded_files_cc}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.cc.t
COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
${root} ${root}.cc.t ${ARGN}
)
#create a command to generate the header files
add_custom_command(
OUTPUT ${expanded_files_h}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t
COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
${root} ${root}.h.t ${ARGN}
)
#make source files depends on headers to force generation
set_source_files_properties(${expanded_files_cc}
PROPERTIES OBJECT_DEPENDS "${expanded_files_h}"
)
#install rules for the generated files
list(APPEND generated_sources ${expanded_files_cc})
list(APPEND generated_headers ${expanded_files_h})
endmacro(GR_EXPAND_X_CC_H)
macro(GR_EXPAND_X_CC_H_IMPL component root)
include(GrPython)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
"#!${PYTHON_EXECUTABLE}
import sys, os, re
sys.path.append('${GR_RUNTIME_PYTHONPATH}')
sys.path.append('${CMAKE_SOURCE_DIR}/python')
os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
if __name__ == '__main__':
import build_utils
root, inp = sys.argv[1:3]
for sig in sys.argv[3:]:
name = re.sub ('X+', sig, root)
d = build_utils.standard_dict(name, sig, '${component}')
build_utils.expand_template(d, inp, '_impl')
")
#make a list of all the generated files
unset(expanded_files_cc_impl)
unset(expanded_files_h_impl)
unset(expanded_files_h)
foreach(sig ${ARGN})
string(REGEX REPLACE "X+" ${sig} name ${root})
list(APPEND expanded_files_cc_impl ${CMAKE_CURRENT_BINARY_DIR}/${name}_impl.cc)
list(APPEND expanded_files_h_impl ${CMAKE_CURRENT_BINARY_DIR}/${name}_impl.h)
list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/../include/gnuradio/${component}/${name}.h)
endforeach(sig)
unset(name)
#create a command to generate the _impl.cc files
add_custom_command(
OUTPUT ${expanded_files_cc_impl}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}_impl.cc.t
COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
${root} ${root}_impl.cc.t ${ARGN}
)
#create a command to generate the _impl.h files
add_custom_command(
OUTPUT ${expanded_files_h_impl}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}_impl.h.t
COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
${root} ${root}_impl.h.t ${ARGN}
)
#make _impl.cc source files depend on _impl.h to force generation
set_source_files_properties(${expanded_files_cc_impl}
PROPERTIES OBJECT_DEPENDS "${expanded_files_h_impl}"
)
#make _impl.h source files depend on headers to force generation
set_source_files_properties(${expanded_files_h_impl}
PROPERTIES OBJECT_DEPENDS "${expanded_files_h}"
)
#install rules for the generated files
list(APPEND generated_sources ${expanded_files_cc_impl})
list(APPEND generated_headers ${expanded_files_h_impl})
endmacro(GR_EXPAND_X_CC_H_IMPL)

54
cmake/Modules/GrPlatform.cmake

@ -1,54 +0,0 @@
# Copyright 2011 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
if(DEFINED __INCLUDED_GR_PLATFORM_CMAKE)
return()
endif()
set(__INCLUDED_GR_PLATFORM_CMAKE TRUE)
########################################################################
# Setup additional defines for OS types
########################################################################
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(LINUX TRUE)
endif()
if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/debian_version")
set(DEBIAN TRUE)
endif()
if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/redhat-release")
set(REDHAT TRUE)
endif()
if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/slackware-version")
set(SLACKWARE TRUE)
endif()
########################################################################
# when the library suffix should be 64 (applies to redhat linux family)
########################################################################
if (REDHAT OR SLACKWARE)
set(LIB64_CONVENTION TRUE)
endif()
if(NOT DEFINED LIB_SUFFIX AND LIB64_CONVENTION AND CMAKE_SYSTEM_PROCESSOR MATCHES "64$")
set(LIB_SUFFIX 64)
endif()
set(LIB_SUFFIX ${LIB_SUFFIX} CACHE STRING "lib directory suffix")

241
cmake/Modules/GrPython.cmake

@ -1,241 +0,0 @@
# Copyright 2010-2011 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
if(DEFINED __INCLUDED_GR_PYTHON_CMAKE)
return()
endif()
set(__INCLUDED_GR_PYTHON_CMAKE TRUE)
########################################################################
# Setup the python interpreter:
# This allows the user to specify a specific interpreter,
# or finds the interpreter via the built-in cmake module.
########################################################################
#this allows the user to override PYTHON_EXECUTABLE
if(PYTHON_EXECUTABLE)
set(PYTHONINTERP_FOUND TRUE)
#otherwise if not set, try to automatically find it
else(PYTHON_EXECUTABLE)
#use the built-in find script
find_package(PythonInterp 2)
#and if that fails use the find program routine
if(NOT PYTHONINTERP_FOUND)
find_program(PYTHON_EXECUTABLE NAMES python python2 python2.7 python2.6 python2.5)
if(PYTHON_EXECUTABLE)
set(PYTHONINTERP_FOUND TRUE)
endif(PYTHON_EXECUTABLE)
endif(NOT PYTHONINTERP_FOUND)
endif(PYTHON_EXECUTABLE)
if (CMAKE_CROSSCOMPILING)
set(QA_PYTHON_EXECUTABLE "/usr/bin/python")
else (CMAKE_CROSSCOMPILING)
set(QA_PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE})
endif(CMAKE_CROSSCOMPILING)
#make the path to the executable appear in the cmake gui
set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter")
set(QA_PYTHON_EXECUTABLE ${QA_PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter for QA tests")
#make sure we can use -B with python (introduced in 2.6)
if(PYTHON_EXECUTABLE)
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -B -c ""
OUTPUT_QUIET ERROR_QUIET
RESULT_VARIABLE PYTHON_HAS_DASH_B_RESULT
)
if(PYTHON_HAS_DASH_B_RESULT EQUAL 0)
set(PYTHON_DASH_B "-B")
endif()
endif(PYTHON_EXECUTABLE)
########################################################################
# Check for the existence of a python module:
# - desc a string description of the check
# - mod the name of the module to import
# - cmd an additional command to run
# - have the result variable to set
########################################################################
macro(GR_PYTHON_CHECK_MODULE desc mod cmd have)
message(STATUS "")
message(STATUS "Python checking for ${desc}")
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "
#########################################
try:
import ${mod}
assert ${cmd}
except ImportError, AssertionError: exit(-1)
except: pass
#########################################"
RESULT_VARIABLE ${have}
)
if(${have} EQUAL 0)
message(STATUS "Python checking for ${desc} - found")
set(${have} TRUE)
else(${have} EQUAL 0)
message(STATUS "Python checking for ${desc} - not found")
set(${have} FALSE)
endif(${have} EQUAL 0)
endmacro(GR_PYTHON_CHECK_MODULE)
########################################################################
# Sets the python installation directory GR_PYTHON_DIR
########################################################################
if(NOT DEFINED GR_PYTHON_DIR)
execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "
from distutils import sysconfig
print sysconfig.get_python_lib(plat_specific=True, prefix='')
" OUTPUT_VARIABLE GR_PYTHON_DIR OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()
file(TO_CMAKE_PATH ${GR_PYTHON_DIR} GR_PYTHON_DIR)
########################################################################
# Create an always-built target with a unique name
# Usage: GR_UNIQUE_TARGET(<description> <dependencies list>)
########################################################################
function(GR_UNIQUE_TARGET desc)
file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR})
execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib
unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5]
print(re.sub('\\W', '_', '${desc} ${reldir} ' + unique))"
OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE)
add_custom_target(${_target} ALL DEPENDS ${ARGN})
endfunction(GR_UNIQUE_TARGET)
########################################################################
# Install python sources (also builds and installs byte-compiled python)
########################################################################
function(GR_PYTHON_INSTALL)
include(CMakeParseArgumentsCopy)
CMAKE_PARSE_ARGUMENTS(GR_PYTHON_INSTALL "" "DESTINATION;COMPONENT" "FILES;PROGRAMS" ${ARGN})
####################################################################
if(GR_PYTHON_INSTALL_FILES)
####################################################################
install(${ARGN}) #installs regular python files
#create a list of all generated files
unset(pysrcfiles)
unset(pycfiles)
unset(pyofiles)
foreach(pyfile ${GR_PYTHON_INSTALL_FILES})
get_filename_component(pyfile ${pyfile} ABSOLUTE)
list(APPEND pysrcfiles ${pyfile})
#determine if this file is in the source or binary directory
file(RELATIVE_PATH source_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${pyfile})
string(LENGTH "${source_rel_path}" source_rel_path_len)
file(RELATIVE_PATH binary_rel_path ${CMAKE_CURRENT_BINARY_DIR} ${pyfile})
string(LENGTH "${binary_rel_path}" binary_rel_path_len)
#and set the generated path appropriately
if(${source_rel_path_len} GREATER ${binary_rel_path_len})
set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${binary_rel_path})
else()
set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${source_rel_path})
endif()
list(APPEND pycfiles ${pygenfile}c)
list(APPEND pyofiles ${pygenfile}o)
#ensure generation path exists
get_filename_component(pygen_path ${pygenfile} PATH)
file(MAKE_DIRECTORY ${pygen_path})
endforeach(pyfile)
#the command to generate the pyc files
add_custom_command(
DEPENDS ${pysrcfiles} OUTPUT ${pycfiles}
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pycfiles}
)
#the command to generate the pyo files
add_custom_command(
DEPENDS ${pysrcfiles} OUTPUT ${pyofiles}
COMMAND ${PYTHON_EXECUTABLE} -O ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pyofiles}
)
#create install rule and add generated files to target list
set(python_install_gen_targets ${pycfiles} ${pyofiles})
install(FILES ${python_install_gen_targets}
DESTINATION ${GR_PYTHON_INSTALL_DESTINATION}
COMPONENT ${GR_PYTHON_INSTALL_COMPONENT}
)
####################################################################
elseif(GR_PYTHON_INSTALL_PROGRAMS)
####################################################################
file(TO_NATIVE_PATH ${PYTHON_EXECUTABLE} pyexe_native)
if (CMAKE_CROSSCOMPILING)
set(pyexe_native "/usr/bin/env python")
endif()
foreach(pyfile ${GR_PYTHON_INSTALL_PROGRAMS})
get_filename_component(pyfile_name ${pyfile} NAME)
get_filename_component(pyfile ${pyfile} ABSOLUTE)
string(REPLACE "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" pyexefile "${pyfile}.exe")
list(APPEND python_install_gen_targets ${pyexefile})
get_filename_component(pyexefile_path ${pyexefile} PATH)
file(MAKE_DIRECTORY ${pyexefile_path})
add_custom_command(
OUTPUT ${pyexefile} DEPENDS ${pyfile}
COMMAND ${PYTHON_EXECUTABLE} -c
"import re; R=re.compile('^\#!.*$\\n',flags=re.MULTILINE); open('${pyexefile}','w').write('\#!${pyexe_native}\\n'+R.sub('',open('${pyfile}','r').read()))"
COMMENT "Shebangin ${pyfile_name}"
VERBATIM
)
#on windows, python files need an extension to execute
get_filename_component(pyfile_ext ${pyfile} EXT)
if(WIN32 AND NOT pyfile_ext)
set(pyfile_name "${pyfile_name}.py")
endif()
install(PROGRAMS ${pyexefile} RENAME ${pyfile_name}
DESTINATION ${GR_PYTHON_INSTALL_DESTINATION}
COMPONENT ${GR_PYTHON_INSTALL_COMPONENT}
)
endforeach(pyfile)
endif()
GR_UNIQUE_TARGET("pygen" ${python_install_gen_targets})
endfunction(GR_PYTHON_INSTALL)
########################################################################
# Write the python helper script that generates byte code files
########################################################################
file(WRITE ${CMAKE_BINARY_DIR}/python_compile_helper.py "
import sys, py_compile
files = sys.argv[1:]
srcs, gens = files[:len(files)/2], files[len(files)/2:]
for src, gen in zip(srcs, gens):
py_compile.compile(file=src, cfile=gen, doraise=True)
")

251
cmake/Modules/GrSwig.cmake

@ -1,251 +0,0 @@
# Copyright 2010-2011 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
if(DEFINED __INCLUDED_GR_SWIG_CMAKE)
return()
endif()
set(__INCLUDED_GR_SWIG_CMAKE TRUE)
include(GrPython)
########################################################################
# Builds a swig documentation file to be generated into python docstrings
# Usage: GR_SWIG_MAKE_DOCS(output_file input_path input_path....)
#
# Set the following variable to specify extra dependent targets:
# - GR_SWIG_DOCS_SOURCE_DEPS
# - GR_SWIG_DOCS_TARGET_DEPS
########################################################################
function(GR_SWIG_MAKE_DOCS output_file)
if(ENABLE_DOXYGEN)
#setup the input files variable list, quote formated
set(input_files)
unset(INPUT_PATHS)
foreach(input_path ${ARGN})
if(IS_DIRECTORY ${input_path}) #when input path is a directory
file(GLOB input_path_h_files ${input_path}/*.h)
else() #otherwise its just a file, no glob
set(input_path_h_files ${input_path})
endif()
list(APPEND input_files ${input_path_h_files})
set(INPUT_PATHS "${INPUT_PATHS} \"${input_path}\"")
endforeach(input_path)
#determine the output directory
get_filename_component(name ${output_file} NAME_WE)
get_filename_component(OUTPUT_DIRECTORY ${output_file} PATH)
set(OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY}/${name}_swig_docs)
make_directory(${OUTPUT_DIRECTORY})
#generate the Doxyfile used by doxygen
configure_file(
${CMAKE_SOURCE_DIR}/docs/doxygen/Doxyfile.swig_doc.in
${OUTPUT_DIRECTORY}/Doxyfile
@ONLY)
#Create a dummy custom command that depends on other targets
include(GrMiscUtils)
GR_GEN_TARGET_DEPS(_${name}_tag tag_deps ${GR_SWIG_DOCS_TARGET_DEPS})
#call doxygen on the Doxyfile + input headers
add_custom_command(
OUTPUT ${OUTPUT_DIRECTORY}/xml/index.xml
DEPENDS ${input_files} ${GR_SWIG_DOCS_SOURCE_DEPS} ${tag_deps}
COMMAND ${DOXYGEN_EXECUTABLE} ${OUTPUT_DIRECTORY}/Doxyfile
COMMENT "Generating doxygen xml for ${name} docs"
)
#call the swig_doc script on the xml files
add_custom_command(
OUTPUT ${output_file}
DEPENDS ${input_files} ${stamp-file} ${OUTPUT_DIRECTORY}/xml/index.xml
COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
${CMAKE_SOURCE_DIR}/docs/doxygen/swig_doc.py
${OUTPUT_DIRECTORY}/xml
${output_file}
COMMENT "Generating python docstrings for ${name}"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs/doxygen
)
else(ENABLE_DOXYGEN)
file(WRITE ${output_file} "\n") #no doxygen -> empty file
endif(ENABLE_DOXYGEN)
endfunction(GR_SWIG_MAKE_DOCS)
########################################################################
# Build a swig target for the common gnuradio use case. Usage:
# GR_SWIG_MAKE(target ifile ifile ifile...)
#
# Set the following variables before calling:
# - GR_SWIG_FLAGS
# - GR_SWIG_INCLUDE_DIRS
# - GR_SWIG_LIBRARIES
# - GR_SWIG_SOURCE_DEPS
# - GR_SWIG_TARGET_DEPS
# - GR_SWIG_DOC_FILE
# - GR_SWIG_DOC_DIRS
########################################################################
macro(GR_SWIG_MAKE name)
set(ifiles ${ARGN})
# Shimming this in here to take care of a SWIG bug with handling
# vector<size_t> and vector<unsigned int> (on 32-bit machines) and
# vector<long unsigned int> (on 64-bit machines). Use this to test
# the size of size_t, then set SIZE_T_32 if it's a 32-bit machine
# or not if it's 64-bit. The logic in gr_type.i handles the rest.
INCLUDE(CheckTypeSize)
CHECK_TYPE_SIZE("size_t" SIZEOF_SIZE_T)
CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT)
if(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT})
list(APPEND GR_SWIG_FLAGS -DSIZE_T_32)
endif(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT})
#do swig doc generation if specified
if(GR_SWIG_DOC_FILE)
set(GR_SWIG_DOCS_SOURCE_DEPS ${GR_SWIG_SOURCE_DEPS})
list(APPEND GR_SWIG_DOCS_TARGET_DEPS ${GR_SWIG_TARGET_DEPS})
GR_SWIG_MAKE_DOCS(${GR_SWIG_DOC_FILE} ${GR_SWIG_DOC_DIRS})
add_custom_target(${name}_swig_doc DEPENDS ${GR_SWIG_DOC_FILE})
list(APPEND GR_SWIG_TARGET_DEPS ${name}_swig_doc ${GR_RUNTIME_SWIG_DOC_FILE})
endif()
#append additional include directories
find_package(PythonLibs 2)
list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_PATH}) #deprecated name (now dirs)
list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS})
#prepend local swig directories
list(INSERT GR_SWIG_INCLUDE_DIRS 0 ${CMAKE_CURRENT_SOURCE_DIR})
list(INSERT GR_SWIG_INCLUDE_DIRS 0 ${CMAKE_CURRENT_BINARY_DIR})
#determine include dependencies for swig file
execute_process(
COMMAND ${PYTHON_EXECUTABLE}
${CMAKE_BINARY_DIR}/get_swig_deps.py
"${ifiles}" "${GR_SWIG_INCLUDE_DIRS}"
OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE SWIG_MODULE_${name}_EXTRA_DEPS
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
#Create a dummy custom command that depends on other targets
include(GrMiscUtils)
GR_GEN_TARGET_DEPS(_${name}_swig_tag tag_deps ${GR_SWIG_TARGET_DEPS})
set(tag_file ${CMAKE_CURRENT_BINARY_DIR}/${name}.tag)
add_custom_command(
OUTPUT ${tag_file}
DEPENDS ${GR_SWIG_SOURCE_DEPS} ${tag_deps}
COMMAND ${CMAKE_COMMAND} -E touch ${tag_file}
)
#append the specified include directories
include_directories(${GR_SWIG_INCLUDE_DIRS})
list(APPEND SWIG_MODULE_${name}_EXTRA_DEPS ${tag_file})
#setup the swig flags with flags and include directories
set(CMAKE_SWIG_FLAGS -fvirtual -modern -keyword -w511 -module ${name} ${GR_SWIG_FLAGS})
foreach(dir ${GR_SWIG_INCLUDE_DIRS})
list(APPEND CMAKE_SWIG_FLAGS "-I${dir}")
endforeach(dir)
#set the C++ property on the swig .i file so it builds
set_source_files_properties(${ifiles} PROPERTIES CPLUSPLUS ON)
#setup the actual swig library target to be built
include(UseSWIG)
SWIG_ADD_MODULE(${name} python ${ifiles})
SWIG_LINK_LIBRARIES(${name} ${PYTHON_LIBRARIES} ${GR_SWIG_LIBRARIES})
if(${name} STREQUAL "runtime_swig")
SET_TARGET_PROPERTIES(${SWIG_MODULE_runtime_swig_REAL_NAME} PROPERTIES DEFINE_SYMBOL "gnuradio_runtime_EXPORTS")
endif(${name} STREQUAL "runtime_swig")
endmacro(GR_SWIG_MAKE)
########################################################################
# Install swig targets generated by GR_SWIG_MAKE. Usage:
# GR_SWIG_INSTALL(
# TARGETS target target target...
# [DESTINATION destination]
# [COMPONENT component]
# )
########################################################################
macro(GR_SWIG_INSTALL)
include(CMakeParseArgumentsCopy)
CMAKE_PARSE_ARGUMENTS(GR_SWIG_INSTALL "" "DESTINATION;COMPONENT" "TARGETS" ${ARGN})
foreach(name ${GR_SWIG_INSTALL_TARGETS})
install(TARGETS ${SWIG_MODULE_${name}_REAL_NAME}
DESTINATION ${GR_SWIG_INSTALL_DESTINATION}
COMPONENT ${GR_SWIG_INSTALL_COMPONENT}
)
include(GrPython)
GR_PYTHON_INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}.py
DESTINATION ${GR_SWIG_INSTALL_DESTINATION}
COMPONENT ${GR_SWIG_INSTALL_COMPONENT}
)
GR_LIBTOOL(
TARGET ${SWIG_MODULE_${name}_REAL_NAME}
DESTINATION ${GR_SWIG_INSTALL_DESTINATION}
)
endforeach(name)
endmacro(GR_SWIG_INSTALL)
########################################################################
# Generate a python file that can determine swig dependencies.
# Used by the make macro above to determine extra dependencies.
# When you build C++, CMake figures out the header dependencies.
# This code essentially performs that logic for swig includes.
########################################################################
file(WRITE ${CMAKE_BINARY_DIR}/get_swig_deps.py "
import os, sys, re
i_include_matcher = re.compile('%(include|import)\\s*[<|\"](.*)[>|\"]')
h_include_matcher = re.compile('#(include)\\s*[<|\"](.*)[>|\"]')
include_dirs = sys.argv[2].split(';')
def get_swig_incs(file_path):
if file_path.endswith('.i'): matcher = i_include_matcher
else: matcher = h_include_matcher
file_contents = open(file_path, 'r').read()
return matcher.findall(file_contents, re.MULTILINE)
def get_swig_deps(file_path, level):
deps = [file_path]
if level == 0: return deps
for keyword, inc_file in get_swig_incs(file_path):
for inc_dir in include_dirs:
inc_path = os.path.join(inc_dir, inc_file)
if not os.path.exists(inc_path): continue
deps.extend(get_swig_deps(inc_path, level-1))
break #found, we dont search in lower prio inc dirs
return deps
if __name__ == '__main__':
ifiles = sys.argv[1].split(';')
deps = sum([get_swig_deps(ifile, 3) for ifile in ifiles], [])
#sys.stderr.write(';'.join(set(deps)) + '\\n\\n')
print(';'.join(set(deps)))
")

143
cmake/Modules/GrTest.cmake

@ -1,143 +0,0 @@
# Copyright 2010-2011 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
if(DEFINED __INCLUDED_GR_TEST_CMAKE)
return()
endif()
set(__INCLUDED_GR_TEST_CMAKE TRUE)
########################################################################
# Add a unit test and setup the environment for a unit test.
# Takes the same arguments as the ADD_TEST function.
#
# Before calling set the following variables:
# GR_TEST_TARGET_DEPS - built targets for the library path
# GR_TEST_LIBRARY_DIRS - directories for the library path
# GR_TEST_PYTHON_DIRS - directories for the python path
# GR_TEST_ENVIRONS - other environment key/value pairs
########################################################################
function(GR_ADD_TEST test_name)
#Ensure that the build exe also appears in the PATH.
list(APPEND GR_TEST_TARGET_DEPS ${ARGN})
#In the land of windows, all libraries must be in the PATH.
#Since the dependent libraries are not yet installed,
#we must manually set them in the PATH to run tests.
#The following appends the path of a target dependency.
foreach(target ${GR_TEST_TARGET_DEPS})
get_target_property(location ${target} LOCATION)
if(location)
get_filename_component(path ${location} PATH)
string(REGEX REPLACE "\\$\\(.*\\)" ${CMAKE_BUILD_TYPE} path ${path})
list(APPEND GR_TEST_LIBRARY_DIRS ${path})
endif(location)
endforeach(target)
if(WIN32)
#SWIG generates the python library files into a subdirectory.
#Therefore, we must append this subdirectory into PYTHONPATH.
#Only do this for the python directories matching the following:
foreach(pydir ${GR_TEST_PYTHON_DIRS})
get_filename_component(name ${pydir} NAME)
if(name MATCHES "^(swig|lib|src)$")
list(APPEND GR_TEST_PYTHON_DIRS ${pydir}/${CMAKE_BUILD_TYPE})
endif()
endforeach(pydir)
endif(WIN32)
file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR} srcdir)
file(TO_NATIVE_PATH "${GR_TEST_LIBRARY_DIRS}" libpath) #ok to use on dir list?
file(TO_NATIVE_PATH "${GR_TEST_PYTHON_DIRS}" pypath) #ok to use on dir list?
set(environs "VOLK_GENERIC=1" "GR_DONT_LOAD_PREFS=1" "srcdir=${srcdir}")
list(APPEND environs ${GR_TEST_ENVIRONS})
#http://www.cmake.org/pipermail/cmake/2009-May/029464.html
#Replaced this add test + set environs code with the shell script generation.
#Its nicer to be able to manually run the shell script to diagnose problems.
#ADD_TEST(${ARGV})
#SET_TESTS_PROPERTIES(${test_name} PROPERTIES ENVIRONMENT "${environs}")
if(UNIX)
set(LD_PATH_VAR "LD_LIBRARY_PATH")
if(APPLE)
set(LD_PATH_VAR "DYLD_LIBRARY_PATH")
endif()
set(binpath "${CMAKE_CURRENT_BINARY_DIR}:$PATH")
list(APPEND libpath "$${LD_PATH_VAR}")
list(APPEND pypath "$PYTHONPATH")
#replace list separator with the path separator
string(REPLACE ";" ":" libpath "${libpath}")
string(REPLACE ";" ":" pypath "${pypath}")
list(APPEND environs "PATH=${binpath}" "${LD_PATH_VAR}=${libpath}" "PYTHONPATH=${pypath}")
#generate a bat file that sets the environment and runs the test
if (CMAKE_CROSSCOMPILING)
set(SHELL "/bin/sh")
else(CMAKE_CROSSCOMPILING)
find_program(SHELL sh)
endif(CMAKE_CROSSCOMPILING)
set(sh_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.sh)
file(WRITE ${sh_file} "#!${SHELL}\n")
#each line sets an environment variable
foreach(environ ${environs})
file(APPEND ${sh_file} "export ${environ}\n")
endforeach(environ)
#load the command to run with its arguments
foreach(arg ${ARGN})
file(APPEND ${sh_file} "${arg} ")
endforeach(arg)
file(APPEND ${sh_file} "\n")
#make the shell file executable
execute_process(COMMAND chmod +x ${sh_file})
add_test(${test_name} ${SHELL} ${sh_file})
endif(UNIX)
if(WIN32)
list(APPEND libpath ${DLL_PATHS} "%PATH%")
list(APPEND pypath "%PYTHONPATH%")
#replace list separator with the path separator (escaped)
string(REPLACE ";" "\\;" libpath "${libpath}")
string(REPLACE ";" "\\;" pypath "${pypath}")
list(APPEND environs "PATH=${libpath}" "PYTHONPATH=${pypath}")
#generate a bat file that sets the environment and runs the test
set(bat_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.bat)
file(WRITE ${bat_file} "@echo off\n")
#each line sets an environment variable
foreach(environ ${environs})
file(APPEND ${bat_file} "SET ${environ}\n")
endforeach(environ)
#load the command to run with its arguments
foreach(arg ${ARGN})
file(APPEND ${bat_file} "${arg} ")
endforeach(arg)
file(APPEND ${bat_file} "\n")
add_test(${test_name} ${bat_file})
endif(WIN32)
endfunction(GR_ADD_TEST)

304
cmake/Modules/UseSWIG.cmake

@ -1,304 +0,0 @@
# - SWIG module for CMake
# Defines the following macros:
# SWIG_ADD_MODULE(name language [ files ])
# - Define swig module with given name and specified language
# SWIG_LINK_LIBRARIES(name [ libraries ])
# - Link libraries to swig module
# All other macros are for internal use only.
# To get the actual name of the swig module,
# use: ${SWIG_MODULE_${name}_REAL_NAME}.
# Set Source files properties such as CPLUSPLUS and SWIG_FLAGS to specify
# special behavior of SWIG. Also global CMAKE_SWIG_FLAGS can be used to add
# special flags to all swig calls.
# Another special variable is CMAKE_SWIG_OUTDIR, it allows one to specify
# where to write all the swig generated module (swig -outdir option)
# The name-specific variable SWIG_MODULE_<name>_EXTRA_DEPS may be used
# to specify extra dependencies for the generated modules.
# If the source file generated by swig need some special flag you can use
# set_source_files_properties( ${swig_generated_file_fullname}
# PROPERTIES COMPILE_FLAGS "-bla")
#=============================================================================
# Copyright 2004-2009 Kitware, Inc.
# Copyright 2009 Mathieu Malaterre <mathieu.malaterre@gmail.com>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
set(SWIG_CXX_EXTENSION "cxx")
set(SWIG_EXTRA_LIBRARIES "")
set(SWIG_PYTHON_EXTRA_FILE_EXTENSION "py")
#
# For given swig module initialize variables associated with it
#
macro(SWIG_MODULE_INITIALIZE name language)
string(TOUPPER "${language}" swig_uppercase_language)
string(TOLOWER "${language}" swig_lowercase_language)
set(SWIG_MODULE_${name}_LANGUAGE "${swig_uppercase_language}")
set(SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG "${swig_lowercase_language}")
set(SWIG_MODULE_${name}_REAL_NAME "${name}")
if("${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "UNKNOWN")
message(FATAL_ERROR "SWIG Error: Language \"${language}\" not found")
elseif("${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "PYTHON")
# when swig is used without the -interface it will produce in the module.py
# a 'import _modulename' statement, which implies having a corresponding
# _modulename.so (*NIX), _modulename.pyd (Win32).
set(SWIG_MODULE_${name}_REAL_NAME "_${name}")
elseif("${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "PERL")
set(SWIG_MODULE_${name}_EXTRA_FLAGS "-shadow")
endif()
endmacro()
#
# For a given language, input file, and output file, determine extra files that
# will be generated. This is internal swig macro.
#
macro(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile)
set(${outfiles} "")
get_source_file_property(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename
${infile} SWIG_MODULE_NAME)
if(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename STREQUAL "NOTFOUND")
get_filename_component(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename "${infile}" NAME_WE)
endif()
foreach(it ${SWIG_${language}_EXTRA_FILE_EXTENSION})
set(${outfiles} ${${outfiles}}
"${generatedpath}/${SWIG_GET_EXTRA_OUTPUT_FILES_module_basename}.${it}")
endforeach()
endmacro()
#
# Take swig (*.i) file and add proper custom commands for it
#
macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
set(swig_full_infile ${infile})
get_filename_component(swig_source_file_path "${infile}" PATH)
get_filename_component(swig_source_file_name_we "${infile}" NAME_WE)
get_source_file_property(swig_source_file_generated ${infile} GENERATED)
get_source_file_property(swig_source_file_cplusplus ${infile} CPLUSPLUS)
get_source_file_property(swig_source_file_flags ${infile} SWIG_FLAGS)
if("${swig_source_file_flags}" STREQUAL "NOTFOUND")
set(swig_source_file_flags "")
endif()
set(swig_source_file_fullname "${infile}")
if(${swig_source_file_path} MATCHES "^${CMAKE_CURRENT_SOURCE_DIR}")
string(REGEX REPLACE
"^${CMAKE_CURRENT_SOURCE_DIR}" ""
swig_source_file_relative_path
"${swig_source_file_path}")
else()
if(${swig_source_file_path} MATCHES "^${CMAKE_CURRENT_BINARY_DIR}")
string(REGEX REPLACE
"^${CMAKE_CURRENT_BINARY_DIR}" ""
swig_source_file_relative_path
"${swig_source_file_path}")
set(swig_source_file_generated 1)
else()
set(swig_source_file_relative_path "${swig_source_file_path}")
if(swig_source_file_generated)
set(swig_source_file_fullname "${CMAKE_CURRENT_BINARY_DIR}/${infile}")
else()
set(swig_source_file_fullname "${CMAKE_CURRENT_SOURCE_DIR}/${infile}")
endif()
endif()
endif()
set(swig_generated_file_fullname
"${CMAKE_CURRENT_BINARY_DIR}")
if(swig_source_file_relative_path)
set(swig_generated_file_fullname
"${swig_generated_file_fullname}/${swig_source_file_relative_path}")
endif()
# If CMAKE_SWIG_OUTDIR was specified then pass it to -outdir
if(CMAKE_SWIG_OUTDIR)
set(swig_outdir ${CMAKE_SWIG_OUTDIR})
else()
set(swig_outdir ${CMAKE_CURRENT_BINARY_DIR})
endif()
SWIG_GET_EXTRA_OUTPUT_FILES(${SWIG_MODULE_${name}_LANGUAGE}
swig_extra_generated_files
"${swig_outdir}"
"${infile}")
set(swig_generated_file_fullname
"${swig_generated_file_fullname}/${swig_source_file_name_we}")
# add the language into the name of the file (i.e. TCL_wrap)
# this allows for the same .i file to be wrapped into different languages
set(swig_generated_file_fullname
"${swig_generated_file_fullname}${SWIG_MODULE_${name}_LANGUAGE}_wrap")
if(swig_source_file_cplusplus)
set(swig_generated_file_fullname
"${swig_generated_file_fullname}.${SWIG_CXX_EXTENSION}")
else()
set(swig_generated_file_fullname
"${swig_generated_file_fullname}.c")
endif()
# Shut up some warnings from poor SWIG code generation that we
# can do nothing about, when this flag is available
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-Wno-unused-but-set-variable" HAVE_WNO_UNUSED_BUT_SET_VARIABLE)
if(HAVE_WNO_UNUSED_BUT_SET_VARIABLE)
set_source_files_properties(${swig_generated_file_fullname}
PROPERTIES COMPILE_FLAGS "-Wno-unused-but-set-variable")
endif(HAVE_WNO_UNUSED_BUT_SET_VARIABLE)
get_directory_property(cmake_include_directories INCLUDE_DIRECTORIES)
set(swig_include_dirs)
foreach(it ${cmake_include_directories})
set(swig_include_dirs ${swig_include_dirs} "-I${it}")
endforeach()
set(swig_special_flags)
# default is c, so add c++ flag if it is c++
if(swig_source_file_cplusplus)
set(swig_special_flags ${swig_special_flags} "-c++")
endif()
set(swig_extra_flags)
if(SWIG_MODULE_${name}_EXTRA_FLAGS)
set(swig_extra_flags ${swig_extra_flags} ${SWIG_MODULE_${name}_EXTRA_FLAGS})
endif()
# hack to work around CMake bug in add_custom_command with multiple OUTPUT files
file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR})
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib
unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5]
print(re.sub('\\W', '_', '${name} ${reldir} ' + unique))"
OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE
)
file(
WRITE ${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp.in
"int main(void){return 0;}\n"
)
# create dummy dependencies
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp.in
${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp
DEPENDS "${swig_source_file_fullname}" ${SWIG_MODULE_${name}_EXTRA_DEPS}
COMMENT ""
)
# create the dummy target
add_executable(${_target} ${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp)
# add a custom command to the dummy target
add_custom_command(
TARGET ${_target}
# Let's create the ${swig_outdir} at execution time, in case dir contains $(OutDir)
COMMAND ${CMAKE_COMMAND} -E make_directory ${swig_outdir}
COMMAND "${SWIG_EXECUTABLE}"
ARGS "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
${swig_source_file_flags}
${CMAKE_SWIG_FLAGS}
-outdir ${swig_outdir}
${swig_special_flags}
${swig_extra_flags}
${swig_include_dirs}
-o "${swig_generated_file_fullname}"
"${swig_source_file_fullname}"
COMMENT "Swig source"
)
#add dummy independent dependencies from the _target to each file
#that will be generated by the SWIG command above
set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files})
foreach(swig_gen_file ${${outfiles}})
add_custom_command(
OUTPUT ${swig_gen_file}
COMMAND ""
DEPENDS ${_target}
COMMENT ""
)
endforeach()
set_source_files_properties(
${outfiles} PROPERTIES GENERATED 1
)
endmacro()
#
# Create Swig module
#
macro(SWIG_ADD_MODULE name language)
SWIG_MODULE_INITIALIZE(${name} ${language})
set(swig_dot_i_sources)
set(swig_other_sources)
foreach(it ${ARGN})
if(${it} MATCHES ".*\\.i$")
set(swig_dot_i_sources ${swig_dot_i_sources} "${it}")
else()
set(swig_other_sources ${swig_other_sources} "${it}")
endif()
endforeach()
set(swig_generated_sources)
foreach(it ${swig_dot_i_sources})
SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source ${it})
set(swig_generated_sources ${swig_generated_sources} "${swig_generated_source}")
endforeach()
get_directory_property(swig_extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES)
set_directory_properties(PROPERTIES
ADDITIONAL_MAKE_CLEAN_FILES "${swig_extra_clean_files};${swig_generated_sources}")
add_library(${SWIG_MODULE_${name}_REAL_NAME}
MODULE
${swig_generated_sources}
${swig_other_sources})
string(TOLOWER "${language}" swig_lowercase_language)
if ("${swig_lowercase_language}" STREQUAL "java")
if (APPLE)
# In java you want:
# System.loadLibrary("LIBRARY");
# then JNI will look for a library whose name is platform dependent, namely
# MacOS : libLIBRARY.jnilib
# Windows: LIBRARY.dll
# Linux : libLIBRARY.so
set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".jnilib")
endif ()
endif ()
if ("${swig_lowercase_language}" STREQUAL "python")
# this is only needed for the python case where a _modulename.so is generated
set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
# Python extension modules on Windows must have the extension ".pyd"
# instead of ".dll" as of Python 2.5. Older python versions do support
# this suffix.
# http://docs.python.org/whatsnew/ports.html#SECTION0001510000000000000000
# <quote>
# Windows: .dll is no longer supported as a filename extension for extension modules.
# .pyd is now the only filename extension that will be searched for.
# </quote>
if(WIN32 AND NOT CYGWIN)
set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".pyd")
endif()
endif ()
endmacro()
#
# Like TARGET_LINK_LIBRARIES but for swig modules
#
macro(SWIG_LINK_LIBRARIES name)
if(SWIG_MODULE_${name}_REAL_NAME)
target_link_libraries(${SWIG_MODULE_${name}_REAL_NAME} ${ARGN})
else()
message(SEND_ERROR "Cannot find Swig library \"${name}\".")
endif()
endmacro()

5
cmake/Modules/multirdsConfig.cmake

@ -22,9 +22,10 @@ FIND_LIBRARY(
/usr/local/lib64 /usr/local/lib64
/usr/lib /usr/lib
/usr/lib64 /usr/lib64
) )
include("${CMAKE_CURRENT_LIST_DIR}/multirdsTarget.cmake")
INCLUDE(FindPackageHandleStandardArgs) INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MULTIRDS DEFAULT_MSG MULTIRDS_LIBRARIES MULTIRDS_INCLUDE_DIRS) FIND_PACKAGE_HANDLE_STANDARD_ARGS(MULTIRDS DEFAULT_MSG MULTIRDS_LIBRARIES MULTIRDS_INCLUDE_DIRS)
MARK_AS_ADVANCED(MULTIRDS_LIBRARIES MULTIRDS_INCLUDE_DIRS) MARK_AS_ADVANCED(MULTIRDS_LIBRARIES MULTIRDS_INCLUDE_DIRS)

28
grc/CMakeLists.txt

@ -17,18 +17,18 @@
# the Free Software Foundation, Inc., 51 Franklin Street, # the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA. # Boston, MA 02110-1301, USA.
install(FILES install(FILES
multirds_rds_table_qt.xml multirds_rds_table_qt.block.yml
multirds_rds_parser_table_qt.xml multirds_rds_parser_table_qt.block.yml
multirds_rds_decoder.xml multirds_rds_decoder.block.yml
multirds_station_search.xml multirds_station_search.block.yml
multirds_stream_selector.xml multirds_stream_selector.block.yml
multirds_vector_cutter.xml multirds_vector_cutter.block.yml
multirds_decoder_compare.xml multirds_decoder_compare.block.yml
multirds_symbol_combiner.xml multirds_symbol_combiner.block.yml
multirds_rds_decoder_redsea.xml multirds_rds_decoder_redsea.block.yml
multirds_qtgui_range.xml multirds_variable_setter.block.yml
multirds_variable_setter.xml multirds_tmc_parser.block.yml
multirds_tmc_parser.xml multirds_pilot_SNR.block.yml
multirds_pilot_SNR.xml multirds_stream_router.block.yml
multirds_stream_router.xml DESTINATION share/gnuradio/grc/blocks DESTINATION share/gnuradio/grc/blocks
) )

25
grc/multirds_decoder_compare.block.yml

@ -0,0 +1,25 @@
# auto-generated by grc.converter
id: multirds_decoder_compare
label: decoder_compare
category: '[multirds]'
parameters:
- id: nPorts
label: Number of Ports
dtype: int
default: '2'
hide: part
inputs:
- domain: message
id: in
multiplicity: ${ nPorts }
asserts:
- ${ nPorts > 0 }
templates:
imports: import multirds
make: multirds.decoder_compare(${nPorts})
file_format: 1

28
grc/multirds_decoder_compare.xml

@ -1,28 +0,0 @@
<?xml version="1.0"?>
<block>
<name>decoder_compare</name>
<key>multirds_decoder_compare</key>
<category>[multirds]</category>
<import>import multirds</import>
<make>multirds.decoder_compare($nPorts)</make>
<!-- Make one 'param' node for every Parameter you want settable from the GUI.
Sub-nodes:
* name
* key (makes the value accessible as $keyname, e.g. in the make node)
* type -->
<param>
<name>Number of Ports</name>
<key>nPorts</key>
<value>2</value>
<type>int</type>
<hide>part</hide>
</param>
<check>$nPorts &gt; 0</check>
<sink>
<name>in</name>
<type>message</type>
<nports>$nPorts</nports>
<!-- <optional>1</optional> -->
</sink>
</block>

57
grc/multirds_pilot_SNR.block.yml

@ -0,0 +1,57 @@
# auto-generated by grc.converter
id: multirds_pilot_SNR
label: pilot_SNR
category: '[multirds]'
parameters:
- id: debug
label: Debug
dtype: bool
default: 'False'
options: ['True', 'False']
option_labels: [Enable, Disable]
- id: carrier_freq
label: carrier_freq
dtype: float
default: 19e3
- id: gap_width
label: gap_width
dtype: float
default: 4e3
- id: update_period
label: update_period
dtype: float
default: '0.2'
- id: samp_rate
label: samp_rate
dtype: int
default: '240000'
- id: fft_len
label: fft_len
dtype: int
default: '2048'
- id: msg_adr
label: msg_adr
dtype: int
default: '3'
inputs:
- domain: stream
dtype: float
vlen: ${ fft_len }
outputs:
- domain: message
id: out
optional: true
templates:
imports: import multirds
make: multirds.pilot_SNR(${debug}, ${samp_rate}, ${fft_len}, ${carrier_freq},${gap_width},
${msg_adr},${update_period})
documentation: |-
outputs PMT pair of longs (msg_adr . SNR) SNR is calculated as difference (in dB) between the 19k carrier power and the average power between carrier_freq-gap_width and carrier_freq+gap_width \
file_format: 1

84
grc/multirds_pilot_SNR.xml

@ -1,84 +0,0 @@
<?xml version="1.0"?>
<block>
<name>pilot_SNR</name>
<key>multirds_pilot_SNR</key>
<category>[multirds]</category>
<import>import multirds</import>
<make>multirds.pilot_SNR($debug, $samp_rate, $fft_len, $carrier_freq,$gap_width, $msg_adr,$update_period)</make>
<!-- Make one 'param' node for every Parameter you want settable from the GUI.
Sub-nodes:
* name
* key (makes the value accessible as $keyname, e.g. in the make node)
* type -->
<param>
<name>Debug</name>
<key>debug</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<param>
<name>carrier_freq</name>
<key>carrier_freq</key>
<value>19e3</value>
<type>float</type>
</param>
<param>
<name>gap_width</name>
<key>gap_width</key>
<value>4e3</value>
<type>float</type>
</param>
<param>
<name>update_period</name>
<key>update_period</key>
<value>0.2</value>
<type>float</type>
</param>
<param>
<name>samp_rate</name>
<key>samp_rate</key>
<value>240000</value>
<type>int</type>
</param>
<param>
<name>fft_len</name>
<key>fft_len</key>
<value>2048</value>
<type>int</type>
</param>
<param>
<name>msg_adr</name>
<key>msg_adr</key>
<value>3</value>
<type>int</type>
</param>
<!-- Make one 'sink' node per input. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<sink>
<name>in</name>
<type>float</type>
<vlen>$fft_len</vlen>
</sink>
<source>
<name>out</name>
<type>message</type>
<optional>1</optional>
</source>
<doc>outputs PMT pair of longs (msg_adr . SNR) \
SNR is calculated as difference (in dB)\
between the 19k carrier power and the \
average power between carrier_freq-gap_width and carrier_freq+gap_width \
</doc>
</block>

136
grc/multirds_qtgui_range.xml

@ -1,136 +0,0 @@
<?xml version="1.0"?>
<block>
<name>qtgui_range (cr)</name>
<key>variable_multirds_qtgui_range</key>
<category>[multirds]</category>
<import>import multirds</import>
<import>from multirds.qtgui_range import qtgui_range, RangeWidget</import>
<var_make>self.$(id) = $(id) = $value</var_make>
<make>#set $win = 'self._%s_win'%$id
#set $range = 'self.%s_range'%$id
#if not $label()
#set $label = '"%s"'%$id
#end if
$(range) = qtgui_range($start, $stop, $step, $value, $min_len)
$(win) = RangeWidget($range, self.set_$(id), $label, "$widget", $rangeType)
$(gui_hint()($win))</make>
<!--<callback>self.freq2_range.set_test($value);</callback>-->
<!-- <callback>self.set_$(id)($value)</callback> -->
<!-- <callback>set_test($(id));</callback> -->
<!-- <callback>self._$(id)_win.set_test($(id));</callback>-->
<param>
<name>Label</name>
<key>label</key>
<value></value>
<type>string</type>
<hide>#if $label() then 'none' else 'part'#</hide>
</param>
<param>
<name>Type</name>
<key>rangeType</key>
<value>"float"</value>
<type>enum</type>
<hide>part</hide>
<option><name>Float</name><key>float</key><opt>type:float</opt></option>
<option><name>Int</name><key>int</key><opt>type:int</opt></option>
</param>
<param>
<name>Default Value</name>
<key>value</key>
<value>50</value>
<type>$rangeType.type</type>
</param>
<param>
<name>Start</name>
<key>start</key>
<value>0</value>
<type>$rangeType.type</type>
</param>
<param>
<name>Stop</name>
<key>stop</key>
<value>100</value>
<type>$rangeType.type</type>
</param>
<param>
<name>Step</name>
<key>step</key>
<value>1</value>
<type>$rangeType.type</type>
</param>
<param>
<name>Widget</name>
<key>widget</key>
<value>counter_slider</value>
<type>enum</type>
<hide>part</hide>
<option><name>Counter + Slider</name><key>counter_slider</key></option>
<option><name>Counter</name><key>counter</key></option>
<option><name>Slider</name><key>slider</key></option>
<option><name>Knob</name><key>dial</key></option>
</param>
<param>
<name>Orientation</name>
<key>orient</key>
<value>Qt.Horizontal</value>
<type>enum</type>
<hide>#if $widget() == "slider" then 'part' else 'all'#</hide>
<option>
<name>Horizontal</name>
<key>Qt.Horizontal</key>
<opt>scalepos:BottomScale</opt>
<opt>minfcn:setMinimumWidth</opt>
</option>
<option>
<name>Vertical</name>
<key>Qt.Vertical</key>
<opt>scalepos:LeftScale</opt>
<opt>minfcn:setMinimumHeight</opt>
</option>
</param>
<param>
<name>Minimum Length</name>
<key>min_len</key>
<value>200</value>
<type>int</type>
<hide>part</hide>
</param>
<!-- from min_len <hide>#if $widget().split('_')[0] in ("slider", "counter") then 'part' else 'all'#</hide>-->
<param>
<name>GUI Hint</name>
<key>gui_hint</key>
<value></value>
<type>gui_hint</type>
<hide>part</hide>
</param>
<check>$start &lt;= $value &lt;= $stop</check>
<check>$start &lt; $stop</check>
<!-- <sink>
<name>set</name>
<type>message</type>
<optional>1</optional>
</sink>-->
<doc>
This block creates a variable with a slider. \
Leave the label blank to use the variable id as the label. \
The value must be a real number. \
The value must be between the start and the stop.
The GUI hint can be used to position the widget within the application. \
The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. \
Both the tab specification and the grid position are optional.
</doc>
</block>

32
grc/multirds_rds_decoder.block.yml

@ -0,0 +1,32 @@
# auto-generated by grc.converter
id: multirds_rds_decoder
label: multirds Rds decoder
category: '[multirds]'
parameters:
- id: log
label: Log
dtype: bool
default: 'False'
options: ['True', 'False']
option_labels: [Enable, Disable]
- id: debug
label: Debug
dtype: bool
default: 'False'
options: ['True', 'False']
option_labels: [Enable, Disable]
inputs:
- domain: stream
dtype: byte
outputs:
- domain: message
optional: true
templates:
imports: import multirds
make: multirds.rds_decoder(${log}, ${debug})
file_format: 1

45
grc/multirds_rds_decoder.xml

@ -1,45 +0,0 @@
<?xml version="1.0"?>
<block>
<name>RDS Decoder (cr)</name>
<key>multirds_rds_decoder</key>
<category>[multirds]</category>
<import>import multirds</import>
<make>multirds.rds_decoder($log, $debug)</make>
<param>
<name>Log</name>
<key>log</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<param>
<name>Debug</name>
<key>debug</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<sink>
<name>in</name>
<type>byte</type>
</sink>
<source>
<name>out</name>
<type>message</type>
<optional>1</optional>
</source>
</block>

32
grc/multirds_rds_decoder_redsea.block.yml

@ -0,0 +1,32 @@
# auto-generated by grc.converter
id: multirds_rds_decoder_redsea
label: multirds Rds decoder redsea
category: '[multirds]'
parameters:
- id: log
label: Log
dtype: bool
default: 'False'
options: ['True', 'False']
option_labels: [Enable, Disable]
- id: debug
label: Debug
dtype: bool
default: 'False'
options: ['True', 'False']
option_labels: [Enable, Disable]
inputs:
- domain: stream
dtype: byte
outputs:
- domain: message
optional: true
templates:
imports: import multirds
make: multirds.rds_decoder_redsea(${log}, ${debug})
file_format: 1

45
grc/multirds_rds_decoder_redsea.xml

@ -1,45 +0,0 @@
<?xml version="1.0"?>
<block>
<name>RDS Decoder (redsea)</name>
<key>multirds_rds_decoder_redsea</key>
<category>[multirds]</category>
<import>import multirds</import>
<make>multirds.rds_decoder_redsea($log, $debug)</make>
<param>
<name>Log</name>
<key>log</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<param>
<name>Debug</name>
<key>debug</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<sink>
<name>in</name>
<type>byte</type>
</sink>
<source>
<name>out</name>
<type>message</type>
<optional>1</optional>
</source>
</block>

96
grc/multirds_rds_parser_table_qt.block.yml

@ -0,0 +1,96 @@
# auto-generated by grc.converter
id: multirds_rds_parser_table_qt
label: RDS Parser Table (qt)
category: '[multirds]'
parameters:
- id: freq_tune
label: tuned frequency
dtype: float
- id: label
label: Label
dtype: string
hide: ${ ('none' if label else 'part') }
- id: workdir
label: work directory
dtype: string
hide: part
- id: gui_hint
label: GUI Hint
dtype: gui_hint
hide: part
- id: nPorts
label: Number of Ports
dtype: int
default: '2'
hide: part
- id: log
label: Log
dtype: bool
default: 'False'
options: ['True', 'False']
option_labels: [Enable, Disable]
- id: debug
label: Debug
dtype: bool
default: 'False'
options: ['True', 'False']
option_labels: [Enable, Disable]
- id: writeDB
label: write Database
dtype: bool
default: 'False'
options: ['True', 'False']
option_labels: [Enable, Disable]
inputs:
- domain: message
id: in
multiplicity: ${ nPorts }
- domain: message
id: freq
optional: true
outputs:
- domain: message
id: ctrl
optional: true
- domain: message
id: tmc_raw
optional: true
asserts:
- ${ open(workdir+"pty-list.csv").close() or True }
- ${ open(workdir+"directory_writable","w").close() or True }
- ${ nPorts > 0 }
templates:
imports: |-
import multirds
from multirds.rds_parser_table_qt import rds_parser_table_qt, rds_parser_table_qt_Widget,rds_parser_table_qt_Signals
make: "<% win = 'self._%s_win'%id %>\n\t\t<% signals = 'self._%s_signals'%id %>\n\
% if not label:\n\t<% label = '\"%s\"'%id %>\n% endif\n${signals} = rds_parser_table_qt_Signals()\n\
self.${id} = multirds.rds_parser_table_qt(${signals},${nPorts},self.set_${freq_tune},${freq_tune},${log},\
\ ${debug},${workdir},${writeDB})\n${win} = rds_parser_table_qt_Widget(${signals},\
\ ${label},self.${id})\n${gui_hint(in)}"
make: |-
<%
win = 'self._%s_win'%id
signals = 'self._%s_signals'%id
%>\
${signals} = rds_parser_table_qt_Signals()
self.${id} = multirds.rds_parser_table_qt(${signals},${nPorts},self.set_${freq_tune},${freq_tune},${log},${debug},${workdir},${writeDB})
${win} = rds_parser_table_qt_Widget(${signals},${label},self.${id})
${gui_hint() % win}
callbacks:
- set_freq_tune(${freq_tune});
documentation: "show RDS data from multiple stations in QT table input: raw group\
\ data (array of ints) 4x2 raw block data, 4x1 offset chars, 1x1 number of valid\
\ blocks (of last 50) [block1_upper,block1_lower,block2_upper,block2_lower,...,offset1,offset2,offset3,offset4,numerrors]\\\
\ \n The GUI hint can be used to position the widget within the application.\
\ The hint is of the form \"tab_id@tab_index: row, col, row_span, col_span\"\
\ Both the tab specification and the grid position are optional."
file_format: 1

141
grc/multirds_rds_parser_table_qt.xml

@ -1,141 +0,0 @@
<?xml version="1.0"?>
<block>
<name>RDS Parser Table (qt)</name>
<key>multirds_rds_parser_table_qt</key>
<category>[multirds]</category>
<import>import multirds</import>
<import>from multirds.rds_parser_table_qt import rds_parser_table_qt, rds_parser_table_qt_Widget,rds_parser_table_qt_Signals</import>
<!--
<var_make>self.$(id) = $(id) = $value</var_make>
-->
<make>#set $win = 'self._%s_win'%$id
#set $signals = 'self._%s_signals'%$id
#if not $label()
#set $label = '"%s"'%$id
#end if
$(signals) = rds_parser_table_qt_Signals()
self.$(id) = multirds.rds_parser_table_qt($(signals),$nPorts,self.set_$(freq_tune),$freq_tune,$log, $debug,$workdir,$writeDB)
$(win) = rds_parser_table_qt_Widget($signals, $label,self.$(id))
$(gui_hint()($win))</make>
<callback>set_freq_tune($freq_tune);</callback>
<param>
<name>tuned frequency</name>
<key>freq_tune</key>
<value></value>
<type>float</type>
</param>
<param>
<name>Label</name>
<key>label</key>
<value></value>
<type>string</type>
<hide>#if $label() then 'none' else 'part'#</hide>
</param>
<param>
<name>work directory</name>
<key>workdir</key>
<value></value>
<type>string</type>
<hide>part</hide>
</param>
<param>
<name>GUI Hint</name>
<key>gui_hint</key>
<value></value>
<type>gui_hint</type>
<hide>part</hide>
</param>
<param>
<name>Number of Ports</name>
<key>nPorts</key>
<value>2</value>
<type>int</type>
<hide>part</hide>
</param>
<param>
<name>Log</name>
<key>log</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<param>
<name>Debug</name>
<key>debug</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<param>
<name>write Database</name>
<key>writeDB</key>
<value>False</value>
<type>bool</type>
<!--<hide>part</hide>-->
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<!--
check if pty list file exists
check directory doesnt work:
<check>os.path.isdir($workdir)</check>
-->
<check>open($workdir+"pty-list.csv").close() or True</check>
<!--
check if workdir is writable
-->
<check>open($workdir+"directory_writable","w").close() or True</check>
<check>$nPorts &gt; 0</check>
<sink>
<name>in</name>
<type>message</type>
<nports>$nPorts</nports>
<!-- <optional>1</optional> -->
</sink>
<sink>
<name>freq</name>
<type>message</type>
<optional>1</optional>
</sink>
<source>
<name>ctrl</name>
<type>message</type>
<optional>1</optional>
</source>
<source>
<name>tmc_raw</name>
<type>message</type>
<optional>1</optional>
</source>
<doc>show RDS data from multiple stations in QT table \
input: raw group data (array of ints) \
4x2 raw block data, 4x1 offset chars, 1x1 number of valid blocks (of last 50) \
[block1_upper,block1_lower,block2_upper,block2_lower,...,offset1,offset2,offset3,offset4,numerrors]\\
The GUI hint can be used to position the widget within the application. \
The hint is of the form "tab_id@tab_index: row, col, row_span, col_span" \
Both the tab specification and the grid position are optional.
</doc>
</block>

37
grc/multirds_rds_table_qt.block.yml

@ -0,0 +1,37 @@
# auto-generated by grc.converter
id: multirds_rds_table_qt
label: RDS Table (qt)
category: '[multirds]'
parameters:
- id: label
label: Label
dtype: string
hide: ${ ('none' if label else 'part') }
- id: gui_hint
label: GUI Hint
dtype: gui_hint
hide: part
- id: nPorts
label: Number of Ports
dtype: int
default: '2'
hide: part
inputs:
- domain: message
id: in
multiplicity: ${ nPorts }
templates:
imports: |-
import multirds
from multirds.rds_table_qt import rds_table_qt, rds_table_qt_Widget,rds_table_qt_Signals
var_make: self.${id} = ${id} = ${value}
make: "<% win = 'self._%s_win'%id %>\n\t\t<% signals = 'self._%s_signals'%id %>\n\
% if not label:\n\t<% label = '\"%s\"'%id %>\n% endif\n${signals} = rds_table_qt_Signals()\n\
self.${id} = multirds.rds_table_qt(${signals},${nPorts})\n${win} = rds_table_qt_Widget(${signals},\
\ ${label})\n${gui_hint(in)}"
file_format: 1

46
grc/multirds_rds_table_qt.xml

@ -1,46 +0,0 @@
<?xml version="1.0"?>
<block>
<name>RDS Table (qt)</name>
<key>multirds_rds_table_qt</key>
<category>[multirds]</category>
<import>import multirds</import>
<import>from multirds.rds_table_qt import rds_table_qt, rds_table_qt_Widget,rds_table_qt_Signals</import>
<var_make>self.$(id) = $(id) = $value</var_make>
<make>#set $win = 'self._%s_win'%$id
#set $signals = 'self._%s_signals'%$id
#if not $label()
#set $label = '"%s"'%$id
#end if
$(signals) = rds_table_qt_Signals()
self.$(id) = multirds.rds_table_qt($(signals),$nPorts)
$(win) = rds_table_qt_Widget($signals, $label)
$(gui_hint()($win))</make>
<param>
<name>Label</name>
<key>label</key>
<value></value>
<type>string</type>
<hide>#if $label() then 'none' else 'part'#</hide>
</param>
<param>
<name>GUI Hint</name>
<key>gui_hint</key>
<value></value>
<type>gui_hint</type>
<hide>part</hide>
</param>
<param>
<name>Number of Ports</name>
<key>nPorts</key>
<value>2</value>
<type>int</type>
<hide>part</hide>
</param>
<sink>
<name>in</name>
<type>message</type>
<nports>$nPorts</nports>
<!--<optional>1</optional>-->
</sink>
</block>

52
grc/multirds_station_search.block.yml

@ -0,0 +1,52 @@
# auto-generated by grc.converter
id: multirds_station_search
label: station_search
category: '[multirds]'
parameters:
- id: fft_len
label: fft lenngth
dtype: int
hide: ${ 'part' if vlen == 1 else 'none' }
- id: round_to
label: round to (in hz)
dtype: int
- id: num_decoders
label: number of decoders
dtype: int
hide: part
- id: center_freq
label: center frequency
dtype: float
- id: samp_rate
label: sample rate
dtype: int
- id: debug
label: Debug
dtype: bool
default: 'False'
options: ['True', 'False']
option_labels: [Enable, Disable]
hide: part
inputs:
- domain: stream
dtype: float
vlen: ${ fft_len }
- domain: message
id: ctrl
optional: true
outputs:
- domain: message
id: out
optional: true
templates:
imports: import multirds
make: multirds.station_search(${fft_len}, ${num_decoders}, ${center_freq}, ${samp_rate},${round_to},${debug})
callbacks:
- set_center_freq(${center_freq});
file_format: 1

78
grc/multirds_station_search.xml

@ -1,78 +0,0 @@
<?xml version="1.0"?>
<block>
<name>station_search</name>
<key>multirds_station_search</key>
<category>[multirds]</category>
<import>import multirds</import>
<make>multirds.station_search($fft_len, $num_decoders, $center_freq, $samp_rate,$round_to,$debug)</make>
<!-- Make one 'param' node for every Parameter you want settable from the GUI.
Sub-nodes:
* name
* key (makes the value accessible as $keyname, e.g. in the make node)
* type -->
<callback>set_center_freq($center_freq);</callback>
<param>
<name>fft lenngth</name>
<key>fft_len</key>
<type>int</type>
</param>
<param>
<name>round to (in hz)</name>
<key>round_to</key>
<type>int</type>
</param>
<param>
<name>number of decoders</name>
<key>num_decoders</key>
<type>int</type>
<hide>part</hide>
</param>
<param>
<name>center frequency</name>
<key>center_freq</key>
<type>float</type>
</param>
<param>
<name>sample rate</name>
<key>samp_rate</key>
<type>int</type>
</param>
<param>
<name>Debug</name>
<key>debug</key>
<value>False</value>
<type>bool</type>
<hide>part</hide>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<!-- Make one 'sink' node per input. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<sink>
<name>in</name>
<type>float</type>
<vlen>$fft_len</vlen>
</sink>
<sink>
<name>ctrl</name>
<type>message</type>
<optional>1</optional>
</sink>
<source>
<name>out</name>
<type>message</type>
<optional>1</optional>
</source>
</block>

29
grc/multirds_stream_router.block.yml

@ -0,0 +1,29 @@
# auto-generated by grc.converter
id: multirds_stream_router
label: Stream router
category: '[MULTIRDS]'
parameters:
- id: ninputs
label: Ninputs
dtype: int
- id: noutputs
label: Noutputs
dtype: int
inputs:
- domain: stream
dtype: float
multiplicity: '9'
outputs:
- domain: stream
dtype: float
multiplicity: '3'
templates:
imports: import multirds
make: multirds.stream_router(${ninputs}, ${noutputs})
file_format: 1

54
grc/multirds_stream_router.xml

@ -1,54 +0,0 @@
<?xml version="1.0"?>
<block>
<name>stream_router</name>
<key>multirds_stream_router</key>
<category>[multirds]</category>
<import>import multirds</import>
<make>multirds.stream_router($ninputs, $noutputs)</make>
<param>
<name>Type</name>
<key>type</key>
<value>float</value>
<type>enum</type>
<option><name>Complex</name><key>complex</key><opt>fcn:sink_c</opt></option>
<option><name>Float</name><key>float</key><opt>fcn:sink_f</opt></option>
</param>
<param>
<name>Number of inputs</name>
<key>ninputs</key>
<value>9</value>
<type>int</type>
</param>
<param>
<name>Number of outputs</name>
<key>noutputs</key>
<value>3</value>
<type>int</type>
</param>
<!-- Make one 'sink' node per input. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<sink>
<name>in</name>
<type>$type</type>
<nports>$ninputs</nports>
</sink>
<sink>
<name>ctrl</name>
<type>message</type>
</sink>
<!-- Make one 'source' node per output. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<source>
<name>out</name>
<type>$type</type>
<nports>$noutputs</nports>
</source>
</block>

30
grc/multirds_stream_selector.block.yml

@ -0,0 +1,30 @@
# auto-generated by grc.converter
id: multirds_stream_selector
label: stream_selector
category: '[multirds]'
inputs:
- label: in_re
domain: stream
dtype: float
- label: in_arg
domain: stream
dtype: float
- domain: message
id: rds_re
optional: true
- domain: message
id: rds_arg
optional: true
outputs:
- domain: message
id: rds_out
optional: true
templates:
imports: import multirds
make: multirds.stream_selector()
file_format: 1

38
grc/multirds_stream_selector.xml

@ -1,38 +0,0 @@
<?xml version="1.0"?>
<block>
<name>stream_selector</name>
<key>multirds_stream_selector</key>
<category>[multirds]</category>
<import>import multirds</import>
<make>multirds.stream_selector()</make>
<!-- <param>
<name>...</name>
<key>...</key>
<type>...</type>
</param>-->
<sink>
<name>in_re</name>
<type>float</type>
</sink>
<sink>
<name>in_arg</name>
<type>float</type>
</sink>
<sink>
<name>rds_re</name>
<type>message</type>
<optional>1</optional>
</sink>
<sink>
<name>rds_arg</name>
<type>message</type>
<optional>1</optional>
</sink>
<source>
<name>rds_out</name>
<type>message</type>
<optional>1</optional>
</source>
</block>

30
grc/multirds_symbol_combiner.block.yml

@ -0,0 +1,30 @@
# auto-generated by grc.converter
id: multirds_symbol_combiner
label: Symbol combiner
category: '[MULTIRDS]'
parameters:
- id: threshold
label: Threshold
dtype: float
- id: min_diff
label: Min_diff
dtype: float
- id: log
label: Log
dtype: raw
inputs:
- domain: stream
dtype: float
outputs:
- domain: stream
dtype: float
templates:
imports: import multirds
make: multirds.symbol_combiner(${threshold}, ${min_diff}, ${log})
file_format: 1

70
grc/multirds_symbol_combiner.xml

@ -1,70 +0,0 @@
<?xml version="1.0"?>
<block>
<name>symbol_combiner</name>
<key>multirds_symbol_combiner</key>
<category>[multirds]</category>
<import>import multirds</import>
<make>multirds.symbol_combiner($threshold, $min_diff, $log)</make>
<!-- Make one 'param' node for every Parameter you want settable from the GUI.
Sub-nodes:
* name
* key (makes the value accessible as $keyname, e.g. in the make node)
* type -->
<param>
<name>Log</name>
<key>log</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<param>
<name>Threshold</name>
<key>threshold</key>
<value>0.25</value>
<type>float</type>
</param>
<param>
<name>min_diff</name>
<key>min_diff</key>
<value>0.2</value>
<type>float</type>
</param>
<check>0 &lt; $min_diff &lt; 1</check>
<!-- Make one 'sink' node per input. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<sink>
<name>in</name>
<type>float</type>
</sink>
<sink>
<name>ctrl</name>
<type>message</type>
<optional>1</optional>
</sink>
<!-- Make one 'source' node per output. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<source>
<name>ctrl</name>
<type>message</type>
<optional>1</optional>
</source>
<source>
<name>out</name>
<type>float</type>
</source>
</block>

62
grc/multirds_tmc_parser.block.yml

@ -0,0 +1,62 @@
# auto-generated by grc.converter
id: multirds_tmc_parser
label: tmc_parser
category: '[multirds]'
parameters:
- id: maxheight
label: maxheight
dtype: int
default: '160'
hide: part
- id: workdir
label: work directory
dtype: string
hide: part
- id: label
label: Label
dtype: string
hide: ${ ('none' if label else 'part') }
- id: log
label: Log
dtype: bool
default: 'False'
options: ['True', 'False']
option_labels: [Enable, Disable]
- id: debug
label: Debug
dtype: bool
default: 'False'
options: ['True', 'False']
option_labels: [Enable, Disable]
- id: writeDB
label: write Database
dtype: bool
default: 'False'
options: ['True', 'False']
option_labels: [Enable, Disable]
- id: gui_hint
label: GUI Hint
dtype: gui_hint
hide: part
inputs:
- domain: message
id: in
optional: true
asserts:
- ${ open(workdir+"event-list_with_forecast_sort.csv").close() or True }
- ${ open(workdir+"directory_writable","w").close() or True }
templates:
imports: import multirds
make: "<% win = 'self._%s_win'%id %>\n <% parser = 'self.%s_parser'%id\
\ %>\n% if not label:\n\t<% label = '\"%s\"'%id %>\n% endif\n${parser} = multirds.tmc_parser(${workdir},\
\ ${log}, ${debug}, ${writeDB},${maxheight})\n${win} = ${parser}.getqtwidget()\n\
${gui_hint(in)}\n "
documentation: "maxheight = max height of widget in pixels\n\t maxheight == 0 ->\
\ no restriction"
file_format: 1

112
grc/multirds_tmc_parser.xml

@ -1,112 +0,0 @@
<?xml version="1.0"?>
<block>
<name>tmc_parser</name>
<key>multirds_tmc_parser</key>
<category>[multirds]</category>
<import>import multirds</import>
<make>#set $win = 'self._%s_win'%$id
#set $parser = 'self.%s_parser'%$id
#if not $label()
#set $label = '"%s"'%$id
#end if
$(parser) = multirds.tmc_parser($workdir, $log, $debug, $writeDB,$maxheight)
$(win) = $(parser).getqtwidget()
$(gui_hint()($win))
</make>
<!--
multirds.tmc_parser($workdir, $log, $debug, $writeDB)
-->
<param>
<name>maxheight</name>
<key>maxheight</key>
<value>160</value>
<type>int</type>
<hide>part</hide>
</param>
<param>
<name>work directory</name>
<key>workdir</key>
<value></value>
<type>string</type>
<hide>part</hide>
</param>
<param>
<name>Label</name>
<key>label</key>
<value></value>
<type>string</type>
<hide>#if $label() then 'none' else 'part'#</hide>
</param>
<param>
<name>Log</name>
<key>log</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<param>
<name>Debug</name>
<key>debug</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<param>
<name>write Database</name>
<key>writeDB</key>
<value>False</value>
<type>bool</type>
<!--<hide>part</hide>-->
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<param>
<name>GUI Hint</name>
<key>gui_hint</key>
<value></value>
<type>gui_hint</type>
<hide>part</hide>
</param>
<!--
check if event-list file exists
check directory doesnt work:
<check>os.path.isdir($workdir)</check>
-->
<check>open($workdir+"event-list_with_forecast_sort.csv").close() or True</check>
<!--
check if workdir is writable
-->
<check>open($workdir+"directory_writable","w").close() or True</check>
<sink>
<name>in</name>
<type>message</type>
<optional>1</optional>
</sink>
<doc>
maxheight = max height of widget in pixels
maxheight == 0 -> no restriction
</doc>
</block>

37
grc/multirds_variable_setter.block.yml

@ -0,0 +1,37 @@
# auto-generated by grc.converter
id: multirds_variable_setter
label: variable_setter
category: '[multirds]'
parameters:
- id: varname
label: varname
dtype: raw
- id: is_pair
label: Pair Mode
dtype: enum
default: 'False'
options: ['False', 'True']
- id: msgkey
label: Key
dtype: string
hide: ${ ('none' if is_pair == 'True' else 'all') }
inputs:
- domain: message
id: in
templates:
imports: import multirds
make: |-
<% block = 'self.%s'%id %>
<% varsetter = 'self.set_%s'%varname %>
<% guiupdater = 'self._%s_win.update_gui'%varname %>
multirds.variable_setter("$varname",${varsetter},${guiupdater},${is_pair},${msgkey})
documentation: |-
in pair mode this block only accepts PMT pairs that have a matching CAR
no pair mode: block accepts pmt symbols directly
file_format: 1

59
grc/multirds_variable_setter.xml

@ -1,59 +0,0 @@
<?xml version="1.0"?>
<block>
<name>variable_setter</name>
<key>multirds_variable_setter</key>
<category>[multirds]</category>
<import>import multirds</import>
<make>#set $block = 'self.%s'%$id
#set $varsetter = 'self.set_%s'%$varname
#set $guiupdater = 'self._%s_win.update_gui'%$varname
multirds.variable_setter("$varname",$varsetter,$guiupdater,$is_pair,$msgkey)</make>
<!--$(block) = multirds.variable_setter($varname,$varsetter) -->
<param>
<name>varname</name>
<key>varname</key>
<value></value>
<type>raw</type>
</param>
<param>
<name>Pair Mode</name>
<key>is_pair</key>
<value>False</value>
<type>enum</type>
<option>
<name>False</name>
<key>False</key>
</option>
<option>
<name>True</name>
<key>True</key>
</option>
</param>
<param>
<name>Key</name>
<key>msgkey</key>
<value></value>
<type>string</type>
<hide>#if $is_pair() == 'True' then 'none' else 'all'#</hide>
</param>
<!-- Make one 'sink' node per input. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<sink>
<name>in</name>
<type>message</type>
</sink>
<!-- Make one 'source' node per output. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<doc>
in pair mode this block only accepts PMT pairs that have a matching CAR
no pair mode: block accepts pmt symbols directly
</doc>
</block>

55
grc/multirds_vector_cutter.block.yml

@ -0,0 +1,55 @@
# auto-generated by grc.converter
id: multirds_vector_cutter
label: vector_cutter
category: '[multirds]'
parameters:
- id: pad_out
label: padded output
dtype: enum
default: 'False'
options: ['True', 'False']
option_labels: ['Yes', 'No']
hide: part
- id: zero_len
label: num-zeros
dtype: int
default: '0'
- id: insize
label: insize
dtype: int
default: '2048'
- id: outsize
label: outsize
dtype: int
default: '1024'
- id: cutpoint
label: cutpoint
dtype: int
default: '512'
inputs:
- domain: stream
dtype: complex
vlen: ${ insize }
outputs:
- domain: stream
dtype: complex
vlen: ${ outsize }
- label: out_padded
domain: stream
dtype: complex
vlen: ${ insize }
optional: true
hide: ${ ('False' if pad_out == 'True' else 'True') }
templates:
imports: import multirds
make: multirds.vector_cutter(${insize}, ${outsize}, ${cutpoint},${pad_out},${zero_len})
callbacks:
- set_cutpoint(${cutpoint});
- set_zero_len(${zero_len});
file_format: 1

87
grc/multirds_vector_cutter.xml

@ -1,87 +0,0 @@
<?xml version="1.0"?>
<block>
<name>vector_cutter</name>
<key>multirds_vector_cutter</key>
<category>[multirds]</category>
<import>import multirds</import>
<make>multirds.vector_cutter($insize, $outsize, $cutpoint,$pad_out,$zero_len)</make>
<!-- Make one 'param' node for every Parameter you want settable from the GUI.
Sub-nodes:
* name
* key (makes the value accessible as $keyname, e.g. in the make node)
* type -->
<callback>set_cutpoint($cutpoint);</callback>
<callback>set_zero_len($zero_len);</callback>
<!-- <param>
<name>padded output</name>
<key>pad_out</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>-->
<param>
<name>padded output</name>
<key>pad_out</key>
<value>False</value>
<type>enum</type>
<hide>part</hide>
<option>
<name>Yes</name>
<key>True</key>
</option>
<option>
<name>No</name>
<key>False</key>
</option>
</param>
<param>
<name>num-zeros</name>
<key>zero_len</key>
<value>0</value>
<type>int</type>
</param>
<param>
<name>insize</name>
<key>insize</key>
<value>2048</value>
<type>int</type>
</param>
<param>
<name>outsize</name>
<key>outsize</key>
<value>1024</value>
<type>int</type>
</param>
<param>
<name>cutpoint</name>
<key>cutpoint</key>
<value>512</value>
<type>int</type>
</param>
<sink>
<name>in</name>
<type>complex</type>
<vlen>$insize</vlen>
</sink>
<source>
<name>out</name>
<type>complex</type>
<vlen>$outsize</vlen>
</source>
<source>
<name>out_padded</name>
<type>complex</type>
<vlen>$insize</vlen>
<optional>#if $pad_out() == 'True' then 'False' else 'True'#</optional>
<!--<optional>#if $pad_out==True then '1' else '0'#</optional>-->
<hide>#if $pad_out() == 'True' then 'False' else 'True'#</hide>
</source>
</block>

4
python/CMakeLists.txt

@ -38,11 +38,11 @@ GR_PYTHON_INSTALL(
stream_selector.py stream_selector.py
vector_cutter.py vector_cutter.py
decoder_compare.py decoder_compare.py
qtgui_range.py
variable_setter.py variable_setter.py
tmc_classes.py tmc_classes.py
tmc_parser.py tmc_parser.py
pilot_SNR.py DESTINATION ${GR_PYTHON_DIR}/multirds pilot_SNR.py
DESTINATION ${GR_PYTHON_DIR}/multirds
) )
######################################################################## ########################################################################

25
python/__init__.py

@ -33,16 +33,17 @@ except ImportError:
# import any pure python here # import any pure python here
from rds_table_qt import rds_table_qt from .rds_table_qt import rds_table_qt
from rds_parser_table_qt import rds_parser_table_qt from .rds_parser_table_qt import rds_parser_table_qt
from station_search import station_search from .station_search import station_search
from chart import Chart from .chart import Chart
from stream_selector import stream_selector from .stream_selector import stream_selector
from vector_cutter import vector_cutter from .vector_cutter import vector_cutter
from decoder_compare import decoder_compare from .decoder_compare import decoder_compare
from qtgui_range import qtgui_range
from variable_setter import variable_setter from .variable_setter import variable_setter
from tmc_parser import tmc_parser from .tmc_parser import tmc_parser
from pilot_SNR import pilot_SNR from .pilot_SNR import pilot_SNR
# #

226
python/build_utils.py

@ -1,226 +0,0 @@
#
# Copyright 2004,2009,2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
"""Misc utilities used at build time
"""
import re, os, os.path
from build_utils_codes import *
# set srcdir to the directory that contains Makefile.am
try:
srcdir = os.environ['srcdir']
except KeyError, e:
srcdir = "."
srcdir = srcdir + '/'
# set do_makefile to either true or false dependeing on the environment
try:
if os.environ['do_makefile'] == '0':
do_makefile = False
else:
do_makefile = True
except KeyError, e:
do_makefile = False
# set do_sources to either true or false dependeing on the environment
try:
if os.environ['do_sources'] == '0':
do_sources = False
else:
do_sources = True
except KeyError, e:
do_sources = True
name_dict = {}
def log_output_name (name):
(base, ext) = os.path.splitext (name)
ext = ext[1:] # drop the leading '.'
entry = name_dict.setdefault (ext, [])
entry.append (name)
def open_and_log_name (name, dir):
global do_sources
if do_sources:
f = open (name, dir)
else:
f = None
log_output_name (name)
return f
def expand_template (d, template_filename, extra = ""):
'''Given a dictionary D and a TEMPLATE_FILENAME, expand template into output file
'''
global do_sources
output_extension = extract_extension (template_filename)
template = open_src (template_filename, 'r')
output_name = d['NAME'] + extra + '.' + output_extension
log_output_name (output_name)
if do_sources:
output = open (output_name, 'w')
do_substitution (d, template, output)
output.close ()
template.close ()
def output_glue (dirname):
output_makefile_fragment ()
output_ifile_include (dirname)
def output_makefile_fragment ():
global do_makefile
if not do_makefile:
return
# overwrite the source, which must be writable; this should have been
# checked for beforehand in the top-level Makefile.gen.gen .
f = open (os.path.join (os.environ.get('gendir', os.environ.get('srcdir', '.')), 'Makefile.gen'), 'w')
f.write ('#\n# This file is machine generated. All edits will be overwritten\n#\n')
output_subfrag (f, 'h')
output_subfrag (f, 'i')
output_subfrag (f, 'cc')
f.close ()
def output_ifile_include (dirname):
global do_sources
if do_sources:
f = open ('%s_generated.i' % (dirname,), 'w')
f.write ('//\n// This file is machine generated. All edits will be overwritten\n//\n')
files = name_dict.setdefault ('i', [])
files.sort ()
f.write ('%{\n')
for file in files:
f.write ('#include <%s>\n' % (file[0:-1] + 'h',))
f.write ('%}\n\n')
for file in files:
f.write ('%%include <%s>\n' % (file,))
def output_subfrag (f, ext):
files = name_dict.setdefault (ext, [])
files.sort ()
f.write ("GENERATED_%s =" % (ext.upper ()))
for file in files:
f.write (" \\\n\t%s" % (file,))
f.write ("\n\n")
def extract_extension (template_name):
# template name is something like: GrFIRfilterXXX.h.t
# we return everything between the penultimate . and .t
mo = re.search (r'\.([a-z]+)\.t$', template_name)
if not mo:
raise ValueError, "Incorrectly formed template_name '%s'" % (template_name,)
return mo.group (1)
def open_src (name, mode):
global srcdir
return open (os.path.join (srcdir, name), mode)
def do_substitution (d, in_file, out_file):
def repl (match_obj):
key = match_obj.group (1)
# print key
return d[key]
inp = in_file.read ()
out = re.sub (r"@([a-zA-Z0-9_]+)@", repl, inp)
out_file.write (out)
copyright = '''/* -*- c++ -*- */
/*
* Copyright 2003,2004 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
'''
def is_complex (code3):
if i_code (code3) == 'c' or o_code (code3) == 'c':
return '1'
else:
return '0'
def standard_dict (name, code3, package='gr'):
d = {}
d['NAME'] = name
d['NAME_IMPL'] = name+'_impl'
d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
d['GUARD_NAME_IMPL'] = 'INCLUDED_%s_%s_IMPL_H' % (package.upper(), name.upper())
d['BASE_NAME'] = re.sub ('^' + package + '_', '', name)
d['SPTR_NAME'] = '%s_sptr' % name
d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
d['COPYRIGHT'] = copyright
d['TYPE'] = i_type (code3)
d['I_TYPE'] = i_type (code3)
d['O_TYPE'] = o_type (code3)
d['TAP_TYPE'] = tap_type (code3)
d['IS_COMPLEX'] = is_complex (code3)
return d
def standard_dict2 (name, code3, package):
d = {}
d['NAME'] = name
d['BASE_NAME'] = name
d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
d['COPYRIGHT'] = copyright
d['TYPE'] = i_type (code3)
d['I_TYPE'] = i_type (code3)
d['O_TYPE'] = o_type (code3)
d['TAP_TYPE'] = tap_type (code3)
d['IS_COMPLEX'] = is_complex (code3)
return d
def standard_impl_dict2 (name, code3, package):
d = {}
d['NAME'] = name
d['IMPL_NAME'] = name
d['BASE_NAME'] = name.rstrip("impl").rstrip("_")
d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
d['COPYRIGHT'] = copyright
d['FIR_TYPE'] = "fir_filter_" + code3
d['CFIR_TYPE'] = "fir_filter_" + code3[0:2] + 'c'
d['TYPE'] = i_type (code3)
d['I_TYPE'] = i_type (code3)
d['O_TYPE'] = o_type (code3)
d['TAP_TYPE'] = tap_type (code3)
d['IS_COMPLEX'] = is_complex (code3)
return d

52
python/build_utils_codes.py

@ -1,52 +0,0 @@
#
# Copyright 2004 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
def i_code (code3):
return code3[0]
def o_code (code3):
if len (code3) >= 2:
return code3[1]
else:
return code3[0]
def tap_code (code3):
if len (code3) >= 3:
return code3[2]
else:
return code3[0]
def i_type (code3):
return char_to_type[i_code (code3)]
def o_type (code3):
return char_to_type[o_code (code3)]
def tap_type (code3):
return char_to_type[tap_code (code3)]
char_to_type = {}
char_to_type['s'] = 'short'
char_to_type['i'] = 'int'
char_to_type['f'] = 'float'
char_to_type['c'] = 'gr_complex'
char_to_type['b'] = 'unsigned char'

2
python/chart.py

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from gnuradio import gr from gnuradio import gr
from itertools import cycle from itertools import cycle
from PyQt4.Qt import * from PyQt5.Qt import *
DEFAULT_COLORS = [0x3366cc, 0xdc3912, 0xff9900, 0x109618, 0x990099, DEFAULT_COLORS = [0x3366cc, 0xdc3912, 0xff9900, 0x109618, 0x990099,
0x0099c6, 0xdd4477, 0x66aa00, 0xb82e2e, 0x316395, 0x0099c6, 0xdd4477, 0x66aa00, 0xb82e2e, 0x316395,

4
python/decoder_compare.py

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright 2017 <+YOU OR YOUR COMPANY+>. # Copyright 2017 <+YOU OR YOUR COMPANY+>.
@ -46,7 +46,7 @@ class decoder_compare(gr.sync_block):
self.printTime=time.time() self.printTime=time.time()
def handle_msg(self,msg,port): def handle_msg(self,msg,port):
#print("port:%i, msg:%s"%(port,pmt.to_python(msg))) #print("port:%i, msg:%s"%(port,pmt.to_python(msg)))
if pmt.to_long(pmt.car(msg))==1L: if pmt.to_long(pmt.car(msg))==1:
data=pmt.to_python(pmt.cdr(msg)) data=pmt.to_python(pmt.cdr(msg))
#print("port:%i, data: %s"%(port,data)) #print("port:%i, data: %s"%(port,data))
self.synced[port]=data self.synced[port]=data

2
python/qa_rds_parser_table_qt.py

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright 2017 <+YOU OR YOUR COMPANY+>. # Copyright 2017 <+YOU OR YOUR COMPANY+>.

2
python/qa_tmc_parser.py

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright 2017 <+YOU OR YOUR COMPANY+>. # Copyright 2017 <+YOU OR YOUR COMPANY+>.

279
python/qtgui_range.py

@ -1,279 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2015 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
from PyQt4 import Qt, QtCore, QtGui
import pmt
from gnuradio import gr
class qtgui_range(gr.basic_block):
def set_test(self,value):
print("test callback invoked")
print(value)
def __init__(self, minv, maxv, step, default, min_length):
gr.basic_block.__init__(self,
name="qtgui_range",
in_sig=None,
out_sig=None)
self.min = float(minv)
self.max = float(maxv)
self.step = float(step)
self.default = float(default)
self.min_length = min_length
self.find_precision()
self.find_nsteps()
def find_precision(self):
# Get the decimal part of the step
temp = str(float(self.step) - int(self.step))[2:]
precision = len(temp) if temp is not '0' else 0
precision = min(precision, 13)
if precision == 0 and self.max < 100:
self.precision = 1 # Always have a decimal in this case
else:
self.precision = (precision + 2) if precision > 0 else 0
def find_nsteps(self):
self.nsteps = (self.max + self.step - self.min)/self.step
def demap_range(self, val):
if val > self.max:
val = self.max
if val < self.min:
val = self.min
return ((val-self.min)/self.step)
def map_range(self, val):
if val > self.nsteps:
val = self.max
if val < 0:
val = 0
return (val*self.step+self.min)
class RangeWidget(QtGui.QWidget):
def update_gui(self,value):
#print("update_gui called on widget %s"%self.label)
#print(value)
#self.d_widget.slider.setValue(value)
if self.range.min < value < self.range.max:
if self.style=="counter_slider":
self.d_widget.counter.setValue(value)
else:
self.d_widget.setValue(value)
else:
print("value %i not in range %i...%i"%(value,self.range.min,self.range.max))
#self.notifyChanged(self.rangeType(value))
def __init__(self, ranges, slot, label, style, rangeType=float):
""" Creates the QT Range widget """
QtGui.QWidget.__init__(self)
self.range = ranges
self.style = style
self.label=label
# rangeType tells the block how to return the value as a standard
self.rangeType = rangeType
# Top-block function to call when any value changes
# Some widgets call this directly when their value changes.
# Others have intermediate functions to map the value into the right range.
self.notifyChanged = slot
layout = Qt.QHBoxLayout()
label = Qt.QLabel(label)
layout.addWidget(label)
if style == "dial":
self.d_widget = self.Dial(self, self.range, self.notifyChanged, rangeType)
elif style == "slider":
self.d_widget = self.Slider(self, self.range, self.notifyChanged, rangeType)
elif style == "counter":
# The counter widget can be directly wired to the notifyChanged slot
self.d_widget = self.Counter(self, self.range, self.notifyChanged, rangeType)
else:
# The CounterSlider needs its own internal handlers before calling notifyChanged
self.d_widget = self.CounterSlider(self, self.range, self.notifyChanged, rangeType)
layout.addWidget(self.d_widget)
self.setLayout(layout)
class Dial(QtGui.QDial):
""" Creates the range using a dial """
def __init__(self, parent, ranges, slot, rangeType=float):
QtGui.QDial.__init__(self, parent)
self.rangeType = rangeType
# Setup the dial
self.setRange(0, ranges.nsteps-1)
self.setSingleStep(1)
self.setNotchesVisible(True)
self.range = ranges
# Round the initial value to the closest tick
temp = int(round(ranges.demap_range(ranges.default), 0))
self.setValue(temp)
# Setup the slots
self.valueChanged.connect(self.changed)
self.notifyChanged = slot
def changed(self, value):
""" Handles maping the value to the right range before calling the slot. """
val = self.range.map_range(value)
self.notifyChanged(self.rangeType(val))
class Slider(QtGui.QSlider):
""" Creates the range using a slider """
def __init__(self, parent, ranges, slot, rangeType=float):
QtGui.QSlider.__init__(self, QtCore.Qt.Horizontal, parent)
self.rangeType = rangeType
# Setup the slider
#self.setFocusPolicy(QtCore.Qt.NoFocus)
self.setRange(0, ranges.nsteps - 1)
self.setTickPosition(2)
self.setSingleStep(1)
self.range = ranges
# Round the initial value to the closest tick
temp = int(round(ranges.demap_range(ranges.default), 0))
self.setValue(temp)
if ranges.nsteps > ranges.min_length:
interval = int(ranges.nsteps/ranges.min_length)
self.setTickInterval(interval)
self.setPageStep(interval)
else:
self.setTickInterval(1)
self.setPageStep(1)
# Setup the handler function
self.valueChanged.connect(self.changed)
self.notifyChanged = slot
def changed(self, value):
""" Handle the valueChanged signal and map the value into the correct range """
val = self.range.map_range(value)
self.notifyChanged(self.rangeType(val))
def mousePressEvent(self, event):
if((event.button() == QtCore.Qt.LeftButton)):
new = self.minimum() + ((self.maximum()-self.minimum()) * event.x()) / self.width()
self.setValue(new)
event.accept()
# Use repaint rather than calling the super mousePressEvent.
# Calling super causes issue where slider jumps to wrong value.
QtGui.QSlider.repaint(self)
def mouseMoveEvent(self, event):
new = self.minimum() + ((self.maximum()-self.minimum()) * event.x()) / self.width()
self.setValue(new)
event.accept()
QtGui.QSlider.repaint(self)
class Counter(QtGui.QDoubleSpinBox):
""" Creates the range using a counter """
def __init__(self, parent, ranges, slot, rangeType=float):
QtGui.QDoubleSpinBox.__init__(self, parent)
self.rangeType = rangeType
# Setup the counter
self.setRange(ranges.min, ranges.max)
self.setValue(ranges.default)
self.setSingleStep(ranges.step)
self.setKeyboardTracking(False)
self.setDecimals(ranges.precision)
# The counter already handles floats and can be connected directly.
self.valueChanged.connect(self.changed)
self.notifyChanged = slot
def changed(self, value):
""" Handle the valueChanged signal by converting to the right type """
self.notifyChanged(self.rangeType(value))
class CounterSlider(QtGui.QWidget):
""" Creates the range using a counter and slider """
def __init__(self, parent, ranges, slot, rangeType=float):
QtGui.QWidget.__init__(self, parent)
self.rangeType = rangeType
# Slot to call in the parent
self.notifyChanged = slot
self.slider = RangeWidget.Slider(parent, ranges, self.sliderChanged, rangeType)
self.counter = RangeWidget.Counter(parent, ranges, self.counterChanged, rangeType)
# Need another horizontal layout to wrap the other widgets.
layout = Qt.QHBoxLayout()
layout.addWidget(self.slider)
layout.addWidget(self.counter)
self.setLayout(layout)
# Flag to ignore the slider event caused by a change to the counter.
self.ignoreSlider = False
self.range = ranges
def sliderChanged(self, value):
""" Handles changing the counter when the slider is updated """
# If the counter was changed, ignore any of these events
if not self.ignoreSlider:
# Value is already float. Just set the counter
self.counter.setValue(self.rangeType(value))
self.notifyChanged(self.rangeType(value))
self.ignoreSlider = False
def counterChanged(self, value):
""" Handles changing the slider when the counter is updated """
# Get the current slider value and check to see if the new value changes it
current = self.slider.value()
new = int(round(self.range.demap_range(value), 0))
# If it needs to change, ignore the slider event
# Otherwise, the slider will cause the counter to round to the nearest tick
if current != new:
self.ignoreSlider = True
self.slider.setValue(new)
self.notifyChanged(self.rangeType(value))
if __name__ == "__main__":
from PyQt4 import Qt
import sys
def valueChanged(frequency):
print("Value updated - " + str(frequency))
app = Qt.QApplication(sys.argv)
widget = RangeWidget(qtgui_range(0, 100, 10, 1, 100), valueChanged, "Test", "counter_slider", int)
widget.show()
widget.setWindowTitle("Test Qt Range")
app.exec_()
widget = None

176
python/rds_parser_table_qt.py

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright 2016 <+YOU OR YOUR COMPANY+>. # Copyright 2016 <+YOU OR YOUR COMPANY+>.
@ -22,26 +22,30 @@
from __future__ import print_function#print without newline print('.', end="") from __future__ import print_function#print without newline print('.', end="")
from gnuradio import gr from gnuradio import gr
import pmt,functools,csv,md5,collections,copy,sqlite3,atexit,time,re,sys import pmt,functools,csv,collections,copy,sqlite3,atexit,time,re,sys,hashlib
#old imports: folium #old imports: folium
from datetime import datetime from datetime import datetime
from datetime import timedelta from datetime import timedelta
import multirds.chart as chart import multirds.chart as chart
from multirds.tmc_classes import language#supported: de, en (both partially) from multirds.tmc_classes import language#supported: de, en (both partially)
from PyQt4 import Qt, QtCore, QtGui from PyQt5 import Qt, QtCore, QtGui, QtWidgets
import pprint,code import pprint,code
pp = pprint.PrettyPrinter() pp = pprint.PrettyPrinter()
import cProfile, pstats, StringIO #for profiling import cProfile, pstats #for profiling
from io import StringIO #py3
pr = cProfile.Profile() pr = cProfile.Profile()
#from threading import Timer#to periodically save DB #from threading import Timer#to periodically save DB
from PyQt4.QtCore import QObject, pyqtSignal from PyQt5.QtCore import QObject, pyqtSignal
from bitstring import BitArray from bitstring import BitArray
class rds_parser_table_qt_Signals(QObject): class rds_parser_table_qt_Signals(QObject):
DataUpdateEvent = QtCore.pyqtSignal(dict) DataUpdateEvent = QtCore.pyqtSignal(dict)
def __init__(self, parent=None): def __init__(self, parent=None):
@ -127,18 +131,18 @@ class rds_parser_table_qt(gr.sync_block):#START
# (time text,PI text,rtp_string text)''') # (time text,PI text,rtp_string text)''')
reader = csv.reader(open(self.workdir+'RDS_ODA-AIDs_names_only.csv'), reader = csv.reader(open(self.workdir+'RDS_ODA-AIDs_names_only.csv'),
delimiter=',', quotechar='"') delimiter=',', quotechar='"')
reader.next()#skip header next(reader)#skip header
for row in reader: for row in reader:
self.ODA_application_names[int(row[0])]=row[1] self.ODA_application_names[int(row[0])]=row[1]
#read RT+ class name list: #read RT+ class name list:
reader = csv.reader(open(self.workdir+'RTplus_classnames.csv'), reader = csv.reader(open(self.workdir+'RTplus_classnames.csv'),
delimiter=',', quotechar='"') delimiter=',', quotechar='"')
reader.next()#skip header next(reader)#skip header
self.rtp_classnames=dict((int(rows[0]),rows[1]) for rows in reader) self.rtp_classnames=dict((int(rows[0]),rows[1]) for rows in reader)
#read TMC-event list #read TMC-event list
reader = csv.reader(open(self.workdir+'event-list_with_forecast_sort.csv'), reader = csv.reader(open(self.workdir+'event-list_with_forecast_sort.csv'),
delimiter=',', quotechar='"') delimiter=',', quotechar='"')
reader.next()#skip header next(reader)#skip header
self.ecl_dict=dict((int(rows[0]),rows[1:]) for rows in reader) self.ecl_dict=dict((int(rows[0]),rows[1:]) for rows in reader)
#Code,Text CEN-English,Text (German),Text (German) kein Quantifier,Text (Quantifier = 1),Text (Quantifier >1),N,Q,T,D,U,C,R ,Comment #Code,Text CEN-English,Text (German),Text (German) kein Quantifier,Text (Quantifier = 1),Text (Quantifier >1),N,Q,T,D,U,C,R ,Comment
#N:nature (blank): information, F:forecast, S:silent #N:nature (blank): information, F:forecast, S:silent
@ -151,7 +155,7 @@ class rds_parser_table_qt(gr.sync_block):#START
#read update classes #read update classes
reader = csv.reader(open(self.workdir+'tmc_update_class_names.csv'), reader = csv.reader(open(self.workdir+'tmc_update_class_names.csv'),
delimiter=',', quotechar='"') delimiter=',', quotechar='"')
reader.next()#skip header, "code(C),english,german" next(reader)#skip header, "code(C),english,german"
if language=="de": if language=="de":
self.tmc_update_class_names=dict((int(rows[0]),rows[2]) self.tmc_update_class_names=dict((int(rows[0]),rows[2])
for rows in reader)#german names for rows in reader)#german names
@ -161,7 +165,7 @@ class rds_parser_table_qt(gr.sync_block):#START
#read supplementary information code list #read supplementary information code list
reader = csv.reader(open(self.workdir+'label6-supplementary-information-codes.csv'), reader = csv.reader(open(self.workdir+'label6-supplementary-information-codes.csv'),
delimiter=',', quotechar='"') delimiter=',', quotechar='"')
reader.next()#skip header, "code,english,german" next(reader)#skip header, "code,english,german"
if language=="de": if language=="de":
self.label6_suppl_info=dict((int(rows[0]),rows[2]) self.label6_suppl_info=dict((int(rows[0]),rows[2])
for rows in reader)#german for rows in reader)#german
@ -171,8 +175,8 @@ class rds_parser_table_qt(gr.sync_block):#START
#read PTY list #read PTY list
f=open(self.workdir+'pty-list.csv') f=open(self.workdir+'pty-list.csv')
reader = csv.reader(f, delimiter=',', quotechar='"') reader = csv.reader(f, delimiter=',', quotechar='"')
reader.next()#skip header next(reader)#skip header
self.pty_dict=dict((int(rows[0]),unicode(rows[1],errors='ignore')) self.pty_dict=dict((int(rows[0]),rows[1])
for rows in reader) for rows in reader)
f.close() f.close()
self.minute_count=0 self.minute_count=0
@ -264,8 +268,8 @@ class rds_parser_table_qt(gr.sync_block):#START
self.RDS_data[PI]["internals"]={"last_rt_tooltip":"","unfinished_TMC":{},"last_valid_rt":"","last_valid_psn":"","RT_history":[]} self.RDS_data[PI]["internals"]={"last_rt_tooltip":"","unfinished_TMC":{},"last_valid_rt":"","last_valid_psn":"","RT_history":[]}
self.RDS_data[PI]["time"]={"timestring":"88:88","datestring":"00-00-0000","datetime":None} self.RDS_data[PI]["time"]={"timestring":"88:88","datestring":"00-00-0000","datetime":None}
self.RDS_data[PI]["wrong_block_ratio"]=1#100% self.RDS_data[PI]["wrong_block_ratio"]=1#100%
def handle_msg(self, msg, port):#port from 0 to 3 def handle_msg(self, msg, port): #port from 0 to 3
if pmt.to_long(pmt.car(msg))==1L:#sync/desync messages from RDS decoder if pmt.is_integer(pmt.car(msg)) and pmt.to_long(pmt.car(msg))==1: #sync/desync messages from RDS decoder
synced=pmt.to_python(pmt.cdr(msg)) synced=pmt.to_python(pmt.cdr(msg))
#print("port:%i, data: %s"%(port,data)) #print("port:%i, data: %s"%(port,data))
self.decoders[port]['synced']=synced self.decoders[port]['synced']=synced
@ -276,21 +280,21 @@ class rds_parser_table_qt(gr.sync_block):#START
wrong_block_ratio=1#100% wrong_block_ratio=1#100%
self.RDS_data[PI]["wrong_block_ratio"]=wrong_block_ratio self.RDS_data[PI]["wrong_block_ratio"]=wrong_block_ratio
self.signals.DataUpdateEvent.emit({'PI':PI,'wrong_block_ratio':wrong_block_ratio,'dots':dots}) self.signals.DataUpdateEvent.emit({'PI':PI,'wrong_block_ratio':wrong_block_ratio,'dots':dots})
elif pmt.to_long(pmt.car(msg))==2L:#wrong_block_ratio messages from RDS decoder elif pmt.is_integer(pmt.car(msg)) and pmt.to_long(pmt.car(msg))==2: #wrong_block_ratio messages from RDS decoder
wrong_block_ratio=pmt.to_python(pmt.cdr(msg)) wrong_block_ratio=pmt.to_python(pmt.cdr(msg))
PI=self.decoders[port]['PI'] PI=self.decoders[port]['PI']
if self.RDS_data.has_key(PI): if self.RDS_data.has_key(PI):
dots="."*self.RDS_data[PI]["blockcounts"]["any"] dots="."*self.RDS_data[PI]["blockcounts"]["any"]
self.RDS_data[PI]["wrong_block_ratio"]=wrong_block_ratio self.RDS_data[PI]["wrong_block_ratio"]=wrong_block_ratio
self.signals.DataUpdateEvent.emit({'PI':PI,'wrong_block_ratio':wrong_block_ratio,'dots':dots}) self.signals.DataUpdateEvent.emit({'PI':PI,'wrong_block_ratio':wrong_block_ratio,'dots':dots})
elif pmt.to_long(pmt.car(msg))==3L: #carrier quality message elif pmt.is_integer(pmt.car(msg)) and pmt.to_long(pmt.car(msg))==3: #carrier quality message
pilot_SNR=pmt.to_long(pmt.cdr(msg)) pilot_SNR=pmt.to_long(pmt.cdr(msg))
self.decoders[port]['pilot_SNR']=pilot_SNR self.decoders[port]['pilot_SNR']=pilot_SNR
self.update_freq() self.update_freq()
PI=self.decoders[port]['PI'] PI=self.decoders[port]['PI']
if self.RDS_data.has_key(PI): if self.RDS_data.has_key(PI):
self.signals.DataUpdateEvent.emit({'PI':PI,'pilot_SNR':pilot_SNR}) self.signals.DataUpdateEvent.emit({'PI':PI,'pilot_SNR':pilot_SNR})
elif pmt.to_long(pmt.car(msg))==4L:#mode messages from RDS sync_decim elif pmt.is_integer(pmt.car(msg)) and pmt.to_long(pmt.car(msg))==4: #mode messages from RDS sync_decim
mode=pmt.to_python(pmt.cdr(msg)) mode=pmt.to_python(pmt.cdr(msg))
self.decoders[port]['decim_mode']=mode self.decoders[port]['decim_mode']=mode
self.update_freq() self.update_freq()
@ -318,11 +322,11 @@ class rds_parser_table_qt(gr.sync_block):#START
groupNR=array[2]&0b11110000 groupNR=array[2]&0b11110000
groupVar=array[2]&0b00001000 groupVar=array[2]&0b00001000
if (groupVar == 0): if (groupVar == 0):
groupType=str(groupNR >> 4)+"A" groupType=bytes(groupNR >> 4)+"A"
else: else:
groupType=str(groupNR >> 4)+"B" groupType=bytes(groupNR >> 4)+"B"
#if self.debug: #if self.debug:
#PI=str(port)+"_%02X%02X" %(array[0],array[1]) #PI=bytes(port)+"_%02X%02X" %(array[0],array[1])
#else: #else:
#PI="%02X%02X" %(array[0],array[1]) #PI="%02X%02X" %(array[0],array[1])
PI="%02X%02X" %(array[0],array[1]) PI="%02X%02X" %(array[0],array[1])
@ -361,7 +365,7 @@ class rds_parser_table_qt(gr.sync_block):#START
if self.RDS_data[PI]["blockcounts"]["any"]==5: if self.RDS_data[PI]["blockcounts"]["any"]==5:
self.RDS_data[PI]["blockcounts"]["any"]=0 self.RDS_data[PI]["blockcounts"]["any"]=0
if self.writeDB: if self.writeDB:
t=(str(PI),groupType,self.RDS_data[PI]["blockcounts"][groupType])#TODO only update DB every few seconds t=(bytes(PI),groupType,self.RDS_data[PI]["blockcounts"][groupType])#TODO only update DB every few seconds
db.execute("INSERT OR REPLACE INTO grouptypeCounts (PI,grouptype,count) VALUES (?,?,?)",t) db.execute("INSERT OR REPLACE INTO grouptypeCounts (PI,grouptype,count) VALUES (?,?,?)",t)
dots="."*self.RDS_data[PI]["blockcounts"]["any"] dots="."*self.RDS_data[PI]["blockcounts"]["any"]
self.RDS_data[PI]["TP"]=TP self.RDS_data[PI]["TP"]=TP
@ -376,7 +380,7 @@ class rds_parser_table_qt(gr.sync_block):#START
#add any received groups to DB (slow) #add any received groups to DB (slow)
#content="%02X%02X%02X%02X%02X" %(array[3]&0x1f,array[4],array[5],array[6],array[7]) #content="%02X%02X%02X%02X%02X" %(array[3]&0x1f,array[4],array[5],array[6],array[7])
#t=(str(datetime.now()),PI,self.RDS_data[PI]["PSN"],groupType,content) #t=(bytes(datetime.now()),PI,self.RDS_data[PI]["PSN"],groupType,content)
#db.execute("INSERT INTO groups VALUES (?,?,?,?,?)",t) #db.execute("INSERT INTO groups VALUES (?,?,?,?,?)",t)
if (groupType == "0A"):#AF PSN if (groupType == "0A"):#AF PSN
@ -392,7 +396,7 @@ class rds_parser_table_qt(gr.sync_block):#START
MS=(array[3]>>3)&0x1 MS=(array[3]>>3)&0x1
self.RDS_data[PI]["TA"]=TA self.RDS_data[PI]["TA"]=TA
#style='font-family:Courier New;color:%s' #style='font-family:Courier New;color:%s'
flag_string="<span style=''>TP:%i, TA:%i, MS:%i, DI:%s</span>"%(TP,TA,MS,str(self.RDS_data[PI]["DI"])) flag_string="<span style=''>TP:%i, TA:%i, MS:%i, DI:%s</span>"%(TP,TA,MS,bytes(self.RDS_data[PI]["DI"]))
pty_colored=self.RDS_data[PI]["PTY"] pty_colored=self.RDS_data[PI]["PTY"]
if TP==1: if TP==1:
if TA==1: if TA==1:
@ -482,7 +486,7 @@ class rds_parser_table_qt(gr.sync_block):#START
#textcolor="black" #textcolor="black"
textcolor=""#use default color (white if background is black) textcolor=""#use default color (white if background is black)
if not self.RDS_data[PI]["internals"]["last_valid_psn"]==self.RDS_data[PI]["PSN"]:#ignore duplicates if not self.RDS_data[PI]["internals"]["last_valid_psn"]==self.RDS_data[PI]["PSN"]:#ignore duplicates
t=(str(datetime.now()),PI,self.RDS_data[PI]["PSN"],"PSN_valid",self.RDS_data[PI]["PSN"]) t=(bytes(datetime.now()),PI,self.RDS_data[PI]["PSN"],"PSN_valid",self.RDS_data[PI]["PSN"])
if self.writeDB: if self.writeDB:
db.execute("INSERT INTO data (time,PI,PSN,dataType,data) VALUES (?,?,?,?,?)",t) db.execute("INSERT INTO data (time,PI,PSN,dataType,data) VALUES (?,?,?,?,?)",t)
t=(self.RDS_data[PI]["PSN"],PI) t=(self.RDS_data[PI]["PSN"],PI)
@ -507,12 +511,12 @@ class rds_parser_table_qt(gr.sync_block):#START
PIN_valid= PIN_day in range(1,32) and PIN_hour in range(0,24) and PIN_minute in range(0,60) PIN_valid= PIN_day in range(1,32) and PIN_hour in range(0,24) and PIN_minute in range(0,60)
if PIN_valid: if PIN_valid:
self.RDS_data[PI]["PIN"]=[PIN_day,PIN_hour,PIN_minute] self.RDS_data[PI]["PIN"]=[PIN_day,PIN_hour,PIN_minute]
data_string="radio paging code:%i,LA:%i,variant:%i,SLC:%04X,PIN (valid):%s "%(radio_paging,LA,variant,SLC,str([PIN_day,PIN_hour,PIN_minute])) data_string="radio paging code:%i,LA:%i,variant:%i,SLC:%04X,PIN (valid):%s "%(radio_paging,LA,variant,SLC,bytes([PIN_day,PIN_hour,PIN_minute]))
else: else:
data_string="radio paging code:%i,LA:%i,variant:%i,SLC:%04X,PIN:%04X "%(radio_paging,LA,variant,SLC,PIN) data_string="radio paging code:%i,LA:%i,variant:%i,SLC:%04X,PIN:%04X "%(radio_paging,LA,variant,SLC,PIN)
#%02X%02X%02X%02X%02X #%02X%02X%02X%02X%02X
t=(str(datetime.now()),PI,self.RDS_data[PI]["PSN"],"PIN",data_string) t=(bytes(datetime.now()),PI,self.RDS_data[PI]["PSN"],"PIN",data_string)
if self.writeDB: if self.writeDB:
db.execute("INSERT INTO data (time,PI,PSN,dataType,data) VALUES (?,?,?,?,?)",t) db.execute("INSERT INTO data (time,PI,PSN,dataType,data) VALUES (?,?,?,?,?)",t)
if self.debug and not variant==0:#print if not seen before if self.debug and not variant==0:#print if not seen before
@ -554,7 +558,7 @@ class rds_parser_table_qt(gr.sync_block):#START
segment=chr(array[4])+chr(array[5])+chr(array[6])+chr(array[7])#EDIT:latedecode segment=chr(array[4])+chr(array[5])+chr(array[6])+chr(array[7])#EDIT:latedecode
#self.signals.DataUpdateEvent.emit({'col':5,'row':port,'PI':PI,'groupType':groupType,'adress':adr,'segment':segment}) #self.signals.DataUpdateEvent.emit({'col':5,'row':port,'PI':PI,'groupType':groupType,'adress':adr,'segment':segment})
text_list=list(self.RDS_data[PI]["RT_"+str(ab_flag)]["RT"]) text_list=list(self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT"])
#determine text length: #determine text length:
try: try:
text_end=text_list.index('\r') text_end=text_list.index('\r')
@ -572,27 +576,27 @@ class rds_parser_table_qt(gr.sync_block):#START
text_list=['_']*64 #clear text text_list=['_']*64 #clear text
text_list[adr*4:adr*4+4]=segment text_list[adr*4:adr*4+4]=segment
#reset stored text: #reset stored text:
#self.RDS_data[PI]["RT_"+str(ab_flag)]["RT"]="_"*64 #done in text_list #self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT"]="_"*64 #done in text_list
self.RDS_data[PI]["RT_"+str(ab_flag)]["RT_valid"]=[False]*64 self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT_valid"]=[False]*64
#predict RT from last texts: #predict RT from last texts:
for rt in self.RDS_data[PI]["internals"]["RT_history"]: for rt in self.RDS_data[PI]["internals"]["RT_history"]:
if rt[adr*4:adr*4+4]==list(segment): if rt[adr*4:adr*4+4]==list(segment):
self.RDS_data[PI]["RT_"+str(ab_flag)]["RT"]="".join(rt) self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT"]="".join(rt)
predicted=True predicted=True
self.RDS_data[PI]["RT_"+str(ab_flag)]["RT_valid"][adr*4:adr*4+4]=[True] *4 self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT_valid"][adr*4:adr*4+4]=[True] *4
if not predicted: if not predicted:
self.RDS_data[PI]["RT_"+str(ab_flag)]["RT"]="".join(text_list) self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT"]="".join(text_list)
#determine if (new) text is valid #determine if (new) text is valid
self.RDS_data[PI]["RT_"+str(ab_flag)]["RT_all_valid"]=True self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT_all_valid"]=True
for i in range(0,text_end): for i in range(0,text_end):
if (not self.RDS_data[PI]["RT_"+str(ab_flag)]["RT_valid"][i]): if (not self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT_valid"][i]):
self.RDS_data[PI]["RT_"+str(ab_flag)]["RT_all_valid"] = False self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT_all_valid"] = False
if(self.RDS_data[PI]["RT_"+str(ab_flag)]["RT_all_valid"]): if(self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT_all_valid"]):
#textcolor="black" #textcolor="black"
textcolor=""#use default color (white if background is black) textcolor=""#use default color (white if background is black)
l=list(self.RDS_data[PI]["RT_"+str(ab_flag)]["RT"]) l=list(self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT"])
rt="".join(l[0:text_end])#remove underscores(default symbol) after line end marker rt="".join(l[0:text_end])#remove underscores(default symbol) after line end marker
if not self.RDS_data[PI]["internals"]["last_valid_rt"]==rt:#ignore duplicates #TODO add 2nd order duplicates ABAB if not self.RDS_data[PI]["internals"]["last_valid_rt"]==rt:#ignore duplicates #TODO add 2nd order duplicates ABAB
self.RDS_data[PI]["internals"]["RT_history"].append(l) self.RDS_data[PI]["internals"]["RT_history"].append(l)
@ -600,23 +604,23 @@ class rds_parser_table_qt(gr.sync_block):#START
self.RDS_data[PI]["internals"]["RT_history"].pop(0) self.RDS_data[PI]["internals"]["RT_history"].pop(0)
if self.writeDB: if self.writeDB:
t=( t=(
str(datetime.now()),PI,self.RDS_data[PI]["PSN"], bytes(datetime.now()),PI,self.RDS_data[PI]["PSN"],
"RT",self.decode_chars(rt) "RT",self.decode_chars(rt)
) )
db.execute("INSERT INTO data (time,PI,PSN,dataType,data) VALUES (?,?,?,?,?)",t) db.execute("INSERT INTO data (time,PI,PSN,dataType,data) VALUES (?,?,?,?,?)",t)
self.RDS_data[PI]["internals"]["last_valid_rt"]=rt self.RDS_data[PI]["internals"]["last_valid_rt"]=rt
try:#save rt+ if it exist try:#save rt+ if it exist
if self.writeDB: if self.writeDB:
t=(str(datetime.now()),PI, t=(bytes(datetime.now()),PI,
self.RDS_data[PI]["PSN"],"RT+", self.RDS_data[PI]["PSN"],"RT+",
self.decode_chars(str(self.RDS_data[PI]["RT+"])) self.decode_chars(bytes(self.RDS_data[PI]["RT+"]))
) )
db.execute("INSERT INTO data (time,PI,PSN,dataType,data) VALUES (?,?,?,?,?)",t) db.execute("INSERT INTO data (time,PI,PSN,dataType,data) VALUES (?,?,?,?,?)",t)
except KeyError: except KeyError:
pass#no rt+ -> dont save pass#no rt+ -> dont save
else: else:
textcolor="gray" textcolor="gray"
display_text=self.decode_chars(self.RDS_data[PI]["RT_"+str(ab_flag)]["RT"].split("\r")[0]) display_text=self.decode_chars(self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT"].split("\r")[0])
formatted_text=self.color_text(display_text,adr*4,adr*4+4,textcolor,segmentcolor) formatted_text=self.color_text(display_text,adr*4,adr*4+4,textcolor,segmentcolor)
rtcol=self.colorder.index('text') rtcol=self.colorder.index('text')
self.signals.DataUpdateEvent.emit({'col':rtcol,'row':port,'PI':PI,'string':formatted_text}) self.signals.DataUpdateEvent.emit({'col':rtcol,'row':port,'PI':PI,'string':formatted_text})
@ -626,9 +630,9 @@ class rds_parser_table_qt(gr.sync_block):#START
app_data=int((array[4]<<8)|(array[5]))#content defined by ODA-app app_data=int((array[4]<<8)|(array[5]))#content defined by ODA-app
app_group_raw=int(array[3]&0x1f) #group type in which this app is sent app_group_raw=int(array[3]&0x1f) #group type in which this app is sent
if (app_group_raw&0x1 == 0): if (app_group_raw&0x1 == 0):
app_group=str(app_group_raw >> 1)+"A" app_group=bytes(app_group_raw >> 1)+"A"
else: else:
app_group=str(app_group_raw >> 1)+"B" app_group=bytes(app_group_raw >> 1)+"B"
if not self.RDS_data[PI]["AID_list"].has_key(AID):#new ODA found if not self.RDS_data[PI]["AID_list"].has_key(AID):#new ODA found
try: try:
@ -711,7 +715,7 @@ class rds_parser_table_qt(gr.sync_block):#START
self.RDS_data[PI]["time"]["datestring"]=datestring self.RDS_data[PI]["time"]["datestring"]=datestring
self.RDS_data[PI]["time"]["datetime"]=datetime(date.year,date.month,date.day,hours,minutes)+timedelta(hours=local_time_offset) self.RDS_data[PI]["time"]["datetime"]=datetime(date.year,date.month,date.day,hours,minutes)+timedelta(hours=local_time_offset)
if self.writeDB: if self.writeDB:
t=(str(datetime.now()),PI,self.RDS_data[PI]["PSN"],"CT",datestring+" "+timestring+"; datecode(MJD):"+str(datecode)) t=(bytes(datetime.now()),PI,self.RDS_data[PI]["PSN"],"CT",datestring+" "+timestring+"; datecode(MJD):"+bytes(datecode))
db.execute("INSERT INTO data (time,PI,PSN,dataType,data) VALUES (?,?,?,?,?)",t) db.execute("INSERT INTO data (time,PI,PSN,dataType,data) VALUES (?,?,?,?,?)",t)
except ValueError as e: except ValueError as e:
print("ERROR: could not interpret time or date:") print("ERROR: could not interpret time or date:")
@ -734,7 +738,7 @@ class rds_parser_table_qt(gr.sync_block):#START
self.IH_data[PI][ih_data]={} self.IH_data[PI][ih_data]={}
self.IH_data[PI][ih_data]["count"]=0 self.IH_data[PI][ih_data]["count"]=0
self.IH_data[PI][ih_data]["count"]+=1 self.IH_data[PI][ih_data]["count"]+=1
self.IH_data[PI][ih_data]["last_time"]=str(datetime.now()) self.IH_data[PI][ih_data]["last_time"]=bytes(datetime.now())
#TMC-alert-c (grouptype mostly 8A): #TMC-alert-c (grouptype mostly 8A):
elif (self.RDS_data[PI]["AID_list"].has_key(52550) elif (self.RDS_data[PI]["AID_list"].has_key(52550)
and self.RDS_data[PI]["AID_list"][52550]["groupType"]==groupType):#TMC alert-C and self.RDS_data[PI]["AID_list"][52550]["groupType"]==groupType):#TMC alert-C
@ -759,7 +763,7 @@ class rds_parser_table_qt(gr.sync_block):#START
})#this gnuradio instance doesnt seem to be able to convert from numpy.int64 to pmt })#this gnuradio instance doesnt seem to be able to convert from numpy.int64 to pmt
self.message_port_pub(pmt.intern('tmc_raw'), send_pmt) self.message_port_pub(pmt.intern('tmc_raw'), send_pmt)
#~ tmc_hash=md5.new(str([PI,tmc_x,tmc_y,tmc_z])).hexdigest() #~ tmc_hash=hashlib.md5(bytes([PI,tmc_x,tmc_y,tmc_z])).hexdigest()
tmc_T=tmc_x>>4 #0:TMC-message 1:tuning info/service provider name tmc_T=tmc_x>>4 #0:TMC-message 1:tuning info/service provider name
#~ tmc_F=int((tmc_x>>3)&0x1) #identifies the message as a Single Group (F = 1) or Multi Group (F = 0) #~ tmc_F=int((tmc_x>>3)&0x1) #identifies the message as a Single Group (F = 1) or Multi Group (F = 0)
#~ Y15=int(tmc_y>>15) #~ Y15=int(tmc_y>>15)
@ -835,11 +839,11 @@ class rds_parser_table_qt(gr.sync_block):#START
tag2_start=int((tag2>>5)&(2**6-1)) tag2_start=int((tag2>>5)&(2**6-1))
tag2_len=int(tag2&(2**5-1)) tag2_len=int(tag2&(2**5-1))
if not self.RDS_data[PI]["RT+"]["last_item_toggle_bit"] == item_toggle_bit: #new item if not self.RDS_data[PI]["RT+"]["last_item_toggle_bit"] == item_toggle_bit: #new item
#self.RDS_data[PI]["RT+"]["history"][str(datetime.now())]=self.RDS_data[PI]["internals"]["last_rt_tooltip"] #self.RDS_data[PI]["RT+"]["history"][bytes(datetime.now())]=self.RDS_data[PI]["internals"]["last_rt_tooltip"]
t=(str(datetime.now()),PI,self.RDS_data[PI]["PSN"],"RT+",str(self.RDS_data[PI]["RT+"])) t=(bytes(datetime.now()),PI,self.RDS_data[PI]["PSN"],"RT+",bytes(self.RDS_data[PI]["RT+"]))
if self.writeDB: if self.writeDB:
db.execute("INSERT INTO data (time,PI,PSN,dataType,data) VALUES (?,?,?,?,?)",t) db.execute("INSERT INTO data (time,PI,PSN,dataType,data) VALUES (?,?,?,?,?)",t)
self.RDS_data[PI]["RT+_history"][str(datetime.now())]=copy.deepcopy(self.RDS_data[PI]["RT+"])#save old item self.RDS_data[PI]["RT+_history"][bytes(datetime.now())]=copy.deepcopy(self.RDS_data[PI]["RT+"])#save old item
self.RDS_data[PI]["RT+"]["last_item_toggle_bit"] = item_toggle_bit self.RDS_data[PI]["RT+"]["last_item_toggle_bit"] = item_toggle_bit
rtcol=self.colorder.index('text') rtcol=self.colorder.index('text')
if self.debug: if self.debug:
@ -847,8 +851,8 @@ class rds_parser_table_qt(gr.sync_block):#START
self.signals.DataUpdateEvent.emit({'col':rtcol,'row':port,'PI':PI,'tooltip':""}) self.signals.DataUpdateEvent.emit({'col':rtcol,'row':port,'PI':PI,'tooltip':""})
if self.RDS_data[PI].has_key("RT_0"): if self.RDS_data[PI].has_key("RT_0"):
ab_flag=self.RDS_data[PI]["RT_last_ab_flag"] ab_flag=self.RDS_data[PI]["RT_last_ab_flag"]
rt=self.RDS_data[PI]["RT_"+str(ab_flag)]["RT"] rt=self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT"]
rt_valid=self.RDS_data[PI]["RT_"+str(ab_flag)]["RT_valid"] rt_valid=self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT_valid"]
if not tag1_type=="DUMMY_CLASS" and all(rt_valid[tag1_start:tag1_start+tag1_len+1]): if not tag1_type=="DUMMY_CLASS" and all(rt_valid[tag1_start:tag1_start+tag1_len+1]):
self.RDS_data[PI]["RT+"][tag1_type]=rt[tag1_start:tag1_start+tag1_len+1] self.RDS_data[PI]["RT+"][tag1_type]=rt[tag1_start:tag1_start+tag1_len+1]
self.RDS_data[PI]["internals"]["RT+_times"][tag1_type]=time.time() self.RDS_data[PI]["internals"]["RT+_times"][tag1_type]=time.time()
@ -868,8 +872,8 @@ class rds_parser_table_qt(gr.sync_block):#START
self.signals.DataUpdateEvent.emit({'col':rtpcol,'row':port,'PI':PI,'string':tags}) self.signals.DataUpdateEvent.emit({'col':rtpcol,'row':port,'PI':PI,'string':tags})
if(tag2_type=="ITEM.TITLE" and self.RDS_data[PI].has_key("RT_0")):#TODO remove duplicate code if(tag2_type=="ITEM.TITLE" and self.RDS_data[PI].has_key("RT_0")):#TODO remove duplicate code
ab_flag=self.RDS_data[PI]["RT_last_ab_flag"] ab_flag=self.RDS_data[PI]["RT_last_ab_flag"]
rt=self.RDS_data[PI]["RT_"+str(ab_flag)]["RT"] rt=self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT"]
rt_valid=self.RDS_data[PI]["RT_"+str(ab_flag)]["RT_valid"] rt_valid=self.RDS_data[PI]["RT_"+bytes(ab_flag)]["RT_valid"]
artist="?" artist="?"
song="?" song="?"
if all(rt_valid[tag1_start:tag1_start+tag1_len+1]): if all(rt_valid[tag1_start:tag1_start+tag1_len+1]):
@ -1046,7 +1050,7 @@ class rds_parser_table_qt(gr.sync_block):#START
print("symbol not decoded: "+"?%02X?"%ord(char)+ print("symbol not decoded: "+"?%02X?"%ord(char)+
"in string:"+return_string) "in string:"+return_string)
pass pass
if not type(return_string)==unicode: if not type(return_string)==str:
code.interact(local=locals()) code.interact(local=locals())
return return_string return return_string
def color_text(self, text, start,end,textcolor,segmentcolor): def color_text(self, text, start,end,textcolor,segmentcolor):
@ -1056,14 +1060,14 @@ class rds_parser_table_qt(gr.sync_block):#START
segmentcolor,text[start:end], segmentcolor,text[start:end],
textcolor,text[end:]) textcolor,text[end:])
return formatted_text return formatted_text
class rds_parser_table_qt_Widget(QtGui.QWidget): class rds_parser_table_qt_Widget(QtWidgets.QWidget):
def __init__(self, signals,label,tableobj): def __init__(self, signals,label,tableobj):
#print("gui initializing")self.tableobj.RDS_data["D3A2"] #print("gui initializing")self.tableobj.RDS_data["D3A2"]
self.signals = signals self.signals = signals
self.tableobj=tableobj self.tableobj=tableobj
self.signals.DataUpdateEvent.connect(self.display_data) self.signals.DataUpdateEvent.connect(self.display_data)
""" Creates the QT Range widget """ """ Creates the QT Range widget """
QtGui.QWidget.__init__(self) QtWidgets.QWidget.__init__(self)
layout = Qt.QVBoxLayout() layout = Qt.QVBoxLayout()
#self.label = Qt.QLabel(label) #self.label = Qt.QLabel(label)
#layout.addWidget(self.label)#title of table disabled to save space #layout.addWidget(self.label)#title of table disabled to save space
@ -1071,42 +1075,42 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
self.setLayout(layout) self.setLayout(layout)
#self.decoder_to_PI={} #self.decoder_to_PI={}
self.PI_to_row={} self.PI_to_row={}
self.table=QtGui.QTableWidget(self) self.table=QtWidgets.QTableWidget(self)
rowcount=0 rowcount=0
self.table.setRowCount(rowcount) self.table.setRowCount(rowcount)
#self.colorder=['ID','freq','name','buttons','PTY','AF','time','text','quality'] #self.colorder=['ID','freq','name','buttons','PTY','AF','time','text','quality']
self.colorder=tableobj.colorder self.colorder=tableobj.colorder
self.table.setColumnCount(len(self.colorder)) self.table.setColumnCount(len(self.colorder))
self.table.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) #disallow editing self.table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) #disallow editing
layout.addWidget(self.table) layout.addWidget(self.table)
self.table.setHorizontalHeaderLabels(self.colorder) self.table.setHorizontalHeaderLabels(self.colorder)
#self.table.setMaximumHeight(300)#TODO use dynamic value #self.table.setMaximumHeight(300)#TODO use dynamic value
button_layout = Qt.QHBoxLayout() button_layout = Qt.QHBoxLayout()
codebutton = QtGui.QPushButton("code.interact") codebutton = QtWidgets.QPushButton("code.interact")
codebutton.clicked.connect(self.onCLick) codebutton.clicked.connect(self.onCLick)
button_layout.addWidget(codebutton) button_layout.addWidget(codebutton)
ih_button = QtGui.QPushButton("show IH data") ih_button = QtWidgets.QPushButton("show IH data")
ih_button.clicked.connect(self.showIHdata) ih_button.clicked.connect(self.showIHdata)
button_layout.addWidget(ih_button) button_layout.addWidget(ih_button)
save_button = QtGui.QPushButton("save") save_button = QtWidgets.QPushButton("save")
save_button.clicked.connect(self.saveData) save_button.clicked.connect(self.saveData)
button_layout.addWidget(save_button) button_layout.addWidget(save_button)
print_button = QtGui.QPushButton("print profile") print_button = QtWidgets.QPushButton("print profile")
print_button.clicked.connect(self.printProfile) print_button.clicked.connect(self.printProfile)
button_layout.addWidget(print_button) button_layout.addWidget(print_button)
mode_button = QtGui.QPushButton("searchMode") mode_button = QtWidgets.QPushButton("searchMode")
mode_button.clicked.connect(self.switchMode) mode_button.clicked.connect(self.switchMode)
button_layout.addWidget(mode_button) button_layout.addWidget(mode_button)
layout.addLayout(button_layout) layout.addLayout(button_layout)
label_layout = Qt.QHBoxLayout() label_layout = Qt.QHBoxLayout()
self.freq_label=QtGui.QLabel("decoder frequencies:") self.freq_label=QtWidgets.QLabel("decoder frequencies:")
self.freq_label.setWordWrap(True) self.freq_label.setWordWrap(True)
self.freq_label.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, self.freq_label.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
QtGui.QSizePolicy.Ignored))#expand in horizontal direction and only wrap if window too small QtWidgets.QSizePolicy.Ignored))#expand in horizontal direction and only wrap if window too small
self.freq_label.setTextFormat(QtCore.Qt.RichText)#instead of AutoText self.freq_label.setTextFormat(QtCore.Qt.RichText)#instead of AutoText
self.count_label=QtGui.QLabel("count:") self.count_label=QtWidgets.QLabel("count:")
self.count_label.setAlignment(QtCore.Qt.AlignRight) self.count_label.setAlignment(QtCore.Qt.AlignRight)
label_layout.addWidget(self.freq_label) label_layout.addWidget(self.freq_label)
label_layout.addWidget(self.count_label) label_layout.addWidget(self.count_label)
@ -1114,7 +1118,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
#self.setMinimumSize(Qt.QSize(500,40*self.tableobj.nPorts)) #self.setMinimumSize(Qt.QSize(500,40*self.tableobj.nPorts))
self.setMinimumSize(Qt.QSize(500,40*(4+self.tableobj.nPorts))) self.setMinimumSize(Qt.QSize(500,40*(4+self.tableobj.nPorts)))
self.lastResizeTime=0 self.lastResizeTime=0
self.clip = QtGui.QApplication.clipboard() self.clip = QtWidgets.QApplication.clipboard()
#self.cb.clear(mode=cb.Clipboard ) #self.cb.clear(mode=cb.Clipboard )
#self.cb.setText("Clipboard Text", mode=cb.Clipboard) #self.cb.setText("Clipboard Text", mode=cb.Clipboard)
def keyPressEvent(self, e): def keyPressEvent(self, e):
@ -1125,7 +1129,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
if e.key() == QtCore.Qt.Key_C: #copy if e.key() == QtCore.Qt.Key_C: #copy
try: try:
qs = self.table.cellWidget(selected.topRow(),selected.leftColumn()).text()#get QString from table qs = self.table.cellWidget(selected.topRow(),selected.leftColumn()).text()#get QString from table
s=re.sub("<.*?>","", str(qs))#remove html tags s=re.sub("<.*?>","", bytes(qs))#remove html tags
self.clip.setText(s) self.clip.setText(s)
except Exception as e: except Exception as e:
print(e) print(e)
@ -1134,30 +1138,30 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
rowPosition = self.table.rowCount() rowPosition = self.table.rowCount()
self.table.insertRow(rowPosition) self.table.insertRow(rowPosition)
#for col in range(self.table.columnCount()-1):#all labels except in last column -> buttons #for col in range(self.table.columnCount()-1):#all labels except in last column -> buttons
# self.table.setCellWidget(rowPosition,col,QtGui.QLabel()) # self.table.setCellWidget(rowPosition,col,QtWidgets.QLabel())
#initialize labels everywhere: #initialize labels everywhere:
for col in range(self.table.columnCount()): for col in range(self.table.columnCount()):
self.table.setCellWidget(rowPosition,col,QtGui.QLabel()) self.table.setCellWidget(rowPosition,col,QtWidgets.QLabel())
button_layout = Qt.QHBoxLayout() button_layout = Qt.QHBoxLayout()
details_button=QtGui.QPushButton("Detail") details_button=QtWidgets.QPushButton("Detail")
details_button.clicked.connect(functools.partial(self.getDetails, row=rowPosition)) details_button.clicked.connect(functools.partial(self.getDetails, row=rowPosition))
button_layout.addWidget(details_button) button_layout.addWidget(details_button)
#2017-03-17 disabled LR buttons #2017-03-17 disabled LR buttons
#2017-04-24 enabled LR buttons #2017-04-24 enabled LR buttons
left_button=QtGui.QPushButton("L") left_button=QtWidgets.QPushButton("L")
#left_button.clicked.connect(functools.partial(self.setAudio, row=rowPosition,audio_channel="left")) #left_button.clicked.connect(functools.partial(self.setAudio, row=rowPosition,audio_channel="left"))
left_button.clicked.connect(functools.partial(self.setAudio2, row=rowPosition,audio_channel=0)) left_button.clicked.connect(functools.partial(self.setAudio2, row=rowPosition,audio_channel=0))
button_layout.addWidget(left_button) button_layout.addWidget(left_button)
center_button=QtGui.QPushButton("C") center_button=QtWidgets.QPushButton("C")
#center_button.clicked.connect(functools.partial(self.setAudio, row=rowPosition,audio_channel="center")) #center_button.clicked.connect(functools.partial(self.setAudio, row=rowPosition,audio_channel="center"))
center_button.clicked.connect(functools.partial(self.setAudio2, row=rowPosition,audio_channel=1)) center_button.clicked.connect(functools.partial(self.setAudio2, row=rowPosition,audio_channel=1))
button_layout.addWidget(center_button) button_layout.addWidget(center_button)
right_button=QtGui.QPushButton("R") right_button=QtWidgets.QPushButton("R")
#right_button.clicked.connect(functools.partial(self.setAudio, row=rowPosition,audio_channel="right")) #right_button.clicked.connect(functools.partial(self.setAudio, row=rowPosition,audio_channel="right"))
right_button.clicked.connect(functools.partial(self.setAudio2, row=rowPosition,audio_channel=2)) right_button.clicked.connect(functools.partial(self.setAudio2, row=rowPosition,audio_channel=2))
button_layout.addWidget(right_button) button_layout.addWidget(right_button)
cellWidget = QtGui.QWidget() cellWidget = QtWidgets.QWidget()
cellWidget.setLayout(button_layout) cellWidget.setLayout(button_layout)
button_col=3 button_col=3
self.table.setCellWidget(rowPosition,button_col,cellWidget) self.table.setCellWidget(rowPosition,button_col,cellWidget)
@ -1209,7 +1213,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
if event.has_key('AF'): if event.has_key('AF'):
#setAF #setAF
PIcol=self.colorder.index('AF') PIcol=self.colorder.index('AF')
self.table.cellWidget(row,PIcol).setText(str(event['AF']['number'])) self.table.cellWidget(row,PIcol).setText(bytes(event['AF']['number']))
if event.has_key('PSN'): if event.has_key('PSN'):
#setPSN #setPSN
PSNcol=self.colorder.index('name') PSNcol=self.colorder.index('name')
@ -1227,7 +1231,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
#send_pmt = pmt.string_to_symbol("switch mode") #send_pmt = pmt.string_to_symbol("switch mode")
self.tableobj.message_port_pub(pmt.intern('ctrl'), send_pmt) self.tableobj.message_port_pub(pmt.intern('ctrl'), send_pmt)
def saveData(self): def saveData(self):
filename="RDS_data_"+str(datetime.now())+".txt" filename="RDS_data_"+bytes(datetime.now())+".txt"
f=open(self.tableobj.workdir+filename,"w") f=open(self.tableobj.workdir+filename,"w")
rds_data=copy.deepcopy(self.tableobj.RDS_data) rds_data=copy.deepcopy(self.tableobj.RDS_data)
for PI in sorted(rds_data): for PI in sorted(rds_data):
@ -1242,7 +1246,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
print("data saved in file %s"%filename) print("data saved in file %s"%filename)
def showIHdata(self): def showIHdata(self):
view=Qt.QDialog() view=Qt.QDialog()
l=QtGui.QLabel("In House Data:\n%s"%pp.pformat(self.tableobj.IH_data)) l=QtWidgets.QLabel("In House Data:\n%s"%pp.pformat(self.tableobj.IH_data))
l.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse | l.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse |
QtCore.Qt.TextSelectableByKeyboard) QtCore.Qt.TextSelectableByKeyboard)
l.setWordWrap(True) l.setWordWrap(True)
@ -1254,7 +1258,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
def setAudio(self,row,audio_channel): def setAudio(self,row,audio_channel):
PIcol=self.colorder.index('ID') PIcol=self.colorder.index('ID')
PI=str(self.table.cellWidget(row,PIcol).text()) PI=bytes(self.table.cellWidget(row,PIcol).text())
freq=int(self.tableobj.RDS_data[PI]['AF']['main']) freq=int(self.tableobj.RDS_data[PI]['AF']['main'])
#print("setaudio row:%i, chan:%s, PI:%s,freq:%i"%(row,audio_channel,PI,freq)) #print("setaudio row:%i, chan:%s, PI:%s,freq:%i"%(row,audio_channel,PI,freq))
send_pmt = pmt.pmt_to_python.pmt_from_dict({"cmd":"set_audio_freq", send_pmt = pmt.pmt_to_python.pmt_from_dict({"cmd":"set_audio_freq",
@ -1267,7 +1271,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
def setAudio2(self,row,audio_channel): def setAudio2(self,row,audio_channel):
PIcol=self.colorder.index('ID') PIcol=self.colorder.index('ID')
PI=str(self.table.cellWidget(row,PIcol).text()) PI=bytes(self.table.cellWidget(row,PIcol).text())
#find port: #find port:
for port,decoder in enumerate(self.tableobj.decoders): for port,decoder in enumerate(self.tableobj.decoders):
if decoder['PI']==PI: if decoder['PI']==PI:
@ -1280,7 +1284,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
def getDetails(self,row): def getDetails(self,row):
PIcol=self.colorder.index('ID') PIcol=self.colorder.index('ID')
PI=str(self.table.cellWidget(row,PIcol).text()) PI=bytes(self.table.cellWidget(row,PIcol).text())
view = chart.DialogViewer() view = chart.DialogViewer()
if self.tableobj.PI_dict.has_key(PI) and self.tableobj.PI_dict[PI]>3: if self.tableobj.PI_dict.has_key(PI) and self.tableobj.PI_dict[PI]>3:
#dont print piechart if no packets received (detected via EON) #dont print piechart if no packets received (detected via EON)
@ -1293,7 +1297,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
#and sorts based on integer valure of number in front #and sorts based on integer valure of number in front
for key in sorted(blockcounts,key=lambda elem: int(elem[0:-1])): for key in sorted(blockcounts,key=lambda elem: int(elem[0:-1])):
count=blockcounts[key] count=blockcounts[key]
table.addRow([key+": "+str(count),count]) table.addRow([key+": "+bytes(count),count])
mychart=chart.PieChart(table) mychart=chart.PieChart(table)
view.setGraph(mychart) view.setGraph(mychart)
#view.resize(360, 240) #view.resize(360, 240)
@ -1309,15 +1313,15 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
#combine char lists into strings (more compact) #combine char lists into strings (more compact)
except KeyError: except KeyError:
pass pass
l=QtGui.QLabel("Data:%s"%pp.pformat(rds_data)) l=QtWidgets.QLabel("Data:%s"%pp.pformat(rds_data))
l.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse | l.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse |
QtCore.Qt.TextSelectableByKeyboard) QtCore.Qt.TextSelectableByKeyboard)
l.setWordWrap(True) l.setWordWrap(True)
#l=QtGui.QLabel("Data:") #l=QtWidgets.QLabel("Data:")
#view.layout().addWidget(l) #view.layout().addWidget(l)
scrollArea = QtGui.QScrollArea(self) scrollArea = QtWidgets.QScrollArea(self)
scrollArea.setWidgetResizable(True) scrollArea.setWidgetResizable(True)
scrollArea.setWidget(l) scrollArea.setWidget(l)
view.layout().addWidget(scrollArea) view.layout().addWidget(scrollArea)

8
python/rds_table_qt.py

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright 2016 <+YOU OR YOUR COMPANY+>. # Copyright 2016 <+YOU OR YOUR COMPANY+>.
@ -22,11 +22,11 @@
import numpy import numpy
from gnuradio import gr from gnuradio import gr
import code,pmt,functools import code,pmt,functools
from PyQt4 import Qt, QtCore, QtGui from PyQt5 import Qt, QtCore, QtGui, QtWidgets
import pprint import pprint
pp = pprint.PrettyPrinter() pp = pprint.PrettyPrinter()
from PyQt4.QtCore import QObject, pyqtSignal from PyQt5.QtCore import QObject, pyqtSignal
class rds_table_qt_Signals(QObject): class rds_table_qt_Signals(QObject):
DataUpdateEvent = QtCore.pyqtSignal(dict) DataUpdateEvent = QtCore.pyqtSignal(dict)
@ -89,7 +89,7 @@ class rds_table_qt(gr.sync_block):
#def handle_msg(self, msg): #def handle_msg(self, msg):
# self.signals.DataUpdateEvent.emit({'string':pmt.to_python(msg)}) # self.signals.DataUpdateEvent.emit({'string':pmt.to_python(msg)})
# print(msg) # print(msg)
class rds_table_qt_Widget(QtGui.QWidget): class rds_table_qt_Widget(QtWidgets.QWidget):
def __init__(self, signals,label): def __init__(self, signals,label):
print("gui initializing") print("gui initializing")
self.signals = signals self.signals = signals

2
python/station_search.py

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright 2016 <+YOU OR YOUR COMPANY+>. # Copyright 2016 <+YOU OR YOUR COMPANY+>.

2
python/stream_selector.py

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright 2017 <+YOU OR YOUR COMPANY+>. # Copyright 2017 <+YOU OR YOUR COMPANY+>.

13
python/tmc_classes.py

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright 2017 <+YOU OR YOUR COMPANY+>. # Copyright 2017 <+YOU OR YOUR COMPANY+>.
@ -31,7 +31,8 @@
from bitstring import BitArray from bitstring import BitArray
import copy,csv,code import copy,csv,code
import hashlib,os,time import hashlib,os,time
import cPickle as pickle#faster for python2 #import cPickle as pickle#faster for python2
import pickle
from collections import namedtuple from collections import namedtuple
@ -826,7 +827,7 @@ class tmc_message:
try: try:
retstr=str(self.event.updateClass)+": "+self.getTime()+": "+self.location.loctype_str+": "+self.location.loctype_name.encode('utf-8')+": "+self.location_text()+": "+self.events_string()+"; "+self.info_str()+"; "+str(list(self.psns))+"x%i"%self.confirmations retstr=str(self.event.updateClass)+": "+self.getTime()+": "+self.location.loctype_str+": "+self.location.loctype_name.encode('utf-8')+": "+self.location_text()+": "+self.events_string()+"; "+self.info_str()+"; "+str(list(self.psns))+"x%i"%self.confirmations
except UnicodeDecodeError as e: except UnicodeDecodeError as e:
print e print(e)
code.interact(local=locals()) code.interact(local=locals())
#print("got log_string") #print("got log_string")
return retstr return retstr
@ -963,7 +964,7 @@ class tmc_message:
print("invalid main event") print("invalid main event")
print(self) print(self)
else:#subsequent groups in multigroup -> Y0..Y11 and Z0..Z15 are special format else:#subsequent groups in multigroup -> Y0..Y11 and Z0..Z15 are special format
raise ValueError, "subsequent groups must be added to existing tmc message" raise ValueError("subsequent groups must be added to existing tmc message")
def add_group(self,tmc_y,tmc_z): def add_group(self,tmc_y,tmc_z):
sg=int((tmc_y>>14)&0x1)#=1 if second group Y14 sg=int((tmc_y>>14)&0x1)#=1 if second group Y14
gsi=int((tmc_y>>12)&0x3)#group sequence indicator Y12..13 ,max length:5 gsi=int((tmc_y>>12)&0x3)#group sequence indicator Y12..13 ,max length:5
@ -1072,7 +1073,7 @@ class mgm_tag:#mgm=multi group message
elif raw<=255:#months elif raw<=255:#months
return "%s months"%((raw-231)/2.0) return "%s months"%((raw-231)/2.0)
else: else:
raise ValueError, "label7/8 time must be between 0 and 255" raise ValueError("label7/8 time must be between 0 and 255")
@staticmethod @staticmethod
def length_to_km(raw):#label2 raw to km def length_to_km(raw):#label2 raw to km
if raw==0: if raw==0:
@ -1084,7 +1085,7 @@ class mgm_tag:#mgm=multi group message
elif raw <=31: elif raw <=31:
return 5*raw-55 return 5*raw-55
else: else:
raise ValueError, "label2-length must be between 0 and 31" raise ValueError("label2-length must be between 0 and 31")
def __repr__(self): def __repr__(self):
try: try:

8
python/tmc_parser.py

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright 2017 <+YOU OR YOUR COMPANY+>. # Copyright 2017 <+YOU OR YOUR COMPANY+>.
@ -23,7 +23,7 @@ from __future__ import print_function#print without newline print('.', end="")
import numpy import numpy
from gnuradio import gr from gnuradio import gr
import pmt import pmt
from PyQt4 import Qt, QtCore, QtGui from PyQt5 import Qt, QtCore, QtGui, QtWidgets
import code,time,csv,sqlite3,atexit import code,time,csv,sqlite3,atexit
from bitstring import BitArray from bitstring import BitArray
from multirds.tmc_classes import tmc_dict,tmc_message,language,lcl from multirds.tmc_classes import tmc_dict,tmc_message,language,lcl
@ -290,7 +290,7 @@ def print_dbg(message,end="\n"):
dbg=False dbg=False
if dbg: if dbg:
print(message,end=end) print(message,end=end)
class tmc_parser_Widget(QtGui.QWidget): class tmc_parser_Widget(QtWidgets.QWidget):
def print_tmc_msg(self,tmc_msg): def print_tmc_msg(self,tmc_msg):
self.parser.dataLock.acquire(1) self.parser.dataLock.acquire(1)
@ -361,7 +361,7 @@ class tmc_parser_Widget(QtGui.QWidget):
def update_showInvalid(self): def update_showInvalid(self):
self.showInvalid=self.GUI_showInvalid.isChecked() self.showInvalid=self.GUI_showInvalid.isChecked()
def __init__(self, parser,maxheight): def __init__(self, parser,maxheight):
QtGui.QWidget.__init__(self) QtWidgets.QWidget.__init__(self)
layout = Qt.QVBoxLayout() layout = Qt.QVBoxLayout()
self.logMutex=QtCore.QSemaphore(1) self.logMutex=QtCore.QSemaphore(1)
self.setLayout(layout) self.setLayout(layout)

105
python/top_block.py

@ -1,105 +0,0 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
##################################################
# GNU Radio Python Flow Graph
# Title: Top Block
# Generated: Thu Jun 8 13:38:58 2017
##################################################
if __name__ == '__main__':
import ctypes
import sys
if sys.platform.startswith('linux'):
try:
x11 = ctypes.cdll.LoadLibrary('libX11.so')
x11.XInitThreads()
except:
print "Warning: failed to XInitThreads()"
from PyQt4 import Qt
from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from optparse import OptionParser
import multirds
import sys
from gnuradio import qtgui
class top_block(gr.top_block, Qt.QWidget):
def __init__(self):
gr.top_block.__init__(self, "Top Block")
Qt.QWidget.__init__(self)
self.setWindowTitle("Top Block")
qtgui.util.check_set_qss()
try:
self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
except:
pass
self.top_scroll_layout = Qt.QVBoxLayout()
self.setLayout(self.top_scroll_layout)
self.top_scroll = Qt.QScrollArea()
self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
self.top_scroll_layout.addWidget(self.top_scroll)
self.top_scroll.setWidgetResizable(True)
self.top_widget = Qt.QWidget()
self.top_scroll.setWidget(self.top_widget)
self.top_layout = Qt.QVBoxLayout(self.top_widget)
self.top_grid_layout = Qt.QGridLayout()
self.top_layout.addLayout(self.top_grid_layout)
self.settings = Qt.QSettings("GNU Radio", "top_block")
self.restoreGeometry(self.settings.value("geometry").toByteArray())
##################################################
# Variables
##################################################
self.samp_rate = samp_rate = 32000
##################################################
# Blocks
##################################################
self.multirds_rds_decoder_redsea_0 = multirds.rds_decoder_redsea(False, True)
self.blocks_null_source_0 = blocks.null_source(gr.sizeof_char*1)
##################################################
# Connections
##################################################
self.connect((self.blocks_null_source_0, 0), (self.multirds_rds_decoder_redsea_0, 0))
def closeEvent(self, event):
self.settings = Qt.QSettings("GNU Radio", "top_block")
self.settings.setValue("geometry", self.saveGeometry())
event.accept()
def get_samp_rate(self):
return self.samp_rate
def set_samp_rate(self, samp_rate):
self.samp_rate = samp_rate
def main(top_block_cls=top_block, options=None):
from distutils.version import StrictVersion
if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):
style = gr.prefs().get_string('qtgui', 'style', 'raster')
Qt.QApplication.setGraphicsSystem(style)
qapp = Qt.QApplication(sys.argv)
tb = top_block_cls()
tb.start()
tb.show()
def quitting():
tb.stop()
tb.wait()
qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting)
qapp.exec_()
if __name__ == '__main__':
main()

2
python/variable_setter.py

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright 2017 <+YOU OR YOUR COMPANY+>. # Copyright 2017 <+YOU OR YOUR COMPANY+>.

4
python/vector_cutter.py

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright 2017 <+YOU OR YOUR COMPANY+>. # Copyright 2017 <+YOU OR YOUR COMPANY+>.
@ -21,7 +21,6 @@
import numpy as np import numpy as np
from gnuradio import gr from gnuradio import gr
import code
class vector_cutter(gr.sync_block): class vector_cutter(gr.sync_block):
""" """
@ -87,7 +86,6 @@ class vector_cutter(gr.sync_block):
else: else:
out[i]=out_cut*self.mask out[i]=out_cut*self.mask
#out = in0[512:1536] #out = in0[512:1536]
#code.interact(local=locals())
#out[0] = in0[0][512:1536] #out[0] = in0[0][512:1536]
#out[1] = in0[1][512:1536] #out[1] = in0[1][512:1536]
return len(output_items[0]) return len(output_items[0])

Loading…
Cancel
Save