summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt9
-rw-r--r--cmake/Modules/FindQwt.cmake2
-rw-r--r--cmake/Modules/GrMiscUtils.cmake67
-rw-r--r--cmake/Modules/GrPython.cmake2
-rw-r--r--cmake/Modules/GrSwig.cmake14
-rw-r--r--docs/doxygen/Doxyfile.in12
-rw-r--r--docs/doxygen/Doxyfile.swig_doc.in17
-rw-r--r--docs/doxygen/doxyxml/example/Doxyfile17
-rw-r--r--gnuradio-core/CMakeLists.txt6
-rw-r--r--gnuradio-core/src/examples/CMakeLists.txt1
-rw-r--r--gnuradio-core/src/examples/msg_passing/CMakeLists.txt27
-rw-r--r--gnuradio-core/src/examples/msg_passing/hier/test_msg_hier.grc287
-rw-r--r--gnuradio-core/src/examples/msg_passing/hier/test_msg_hier_topblock.grc185
-rw-r--r--gnuradio-core/src/examples/msg_passing/strobe.grc266
-rw-r--r--gnuradio-core/src/examples/pfb/CMakeLists.txt7
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc1
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc1
-rw-r--r--gnuradio-core/src/lib/general/CMakeLists.txt2
-rw-r--r--gnuradio-core/src/lib/general/general.i5
-rw-r--r--gnuradio-core/src/lib/general/gr_block_gateway.cc184
-rw-r--r--gnuradio-core/src/lib/general/gr_block_gateway.h212
-rw-r--r--gnuradio-core/src/lib/general/gr_block_gateway.i46
-rw-r--r--gnuradio-core/src/lib/general/gr_message_strobe.cc75
-rw-r--r--gnuradio-core/src/lib/general/gr_message_strobe.h62
-rw-r--r--gnuradio-core/src/lib/general/gr_message_strobe.i30
-rw-r--r--gnuradio-core/src/lib/general/gr_nop.cc3
-rw-r--r--gnuradio-core/src/lib/general/gr_simple_correlator.cc4
-rw-r--r--gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t2
-rw-r--r--gnuradio-core/src/lib/io/CMakeLists.txt9
-rw-r--r--gnuradio-core/src/lib/io/gr_file_sink.cc27
-rw-r--r--gnuradio-core/src/lib/io/gr_file_sink_base.cc2
-rw-r--r--gnuradio-core/src/lib/io/gr_file_source.cc101
-rw-r--r--gnuradio-core/src/lib/io/gr_file_source.h64
-rw-r--r--gnuradio-core/src/lib/io/gr_file_source.i2
-rw-r--r--gnuradio-core/src/lib/io/gr_message_debug.cc117
-rw-r--r--gnuradio-core/src/lib/io/gr_message_debug.h103
-rw-r--r--gnuradio-core/src/lib/io/gr_message_debug.i30
-rw-r--r--gnuradio-core/src/lib/io/gr_pdu.cc79
-rw-r--r--gnuradio-core/src/lib/io/gr_pdu.h39
-rw-r--r--gnuradio-core/src/lib/io/gr_pdu.i30
-rw-r--r--gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc132
-rw-r--r--gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h63
-rw-r--r--gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i31
-rw-r--r--gnuradio-core/src/lib/io/gr_socket_pdu.cc157
-rw-r--r--gnuradio-core/src/lib/io/gr_socket_pdu.h201
-rw-r--r--gnuradio-core/src/lib/io/gr_socket_pdu.i33
-rw-r--r--gnuradio-core/src/lib/io/gr_stream_pdu_base.cc117
-rw-r--r--gnuradio-core/src/lib/io/gr_stream_pdu_base.h59
-rw-r--r--gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc137
-rw-r--r--gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h76
-rw-r--r--gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i31
-rw-r--r--gnuradio-core/src/lib/io/gr_tuntap_pdu.cc145
-rw-r--r--gnuradio-core/src/lib/io/gr_tuntap_pdu.h74
-rw-r--r--gnuradio-core/src/lib/io/gr_tuntap_pdu.i30
-rw-r--r--gnuradio-core/src/lib/io/io.i13
-rw-r--r--gnuradio-core/src/lib/runtime/CMakeLists.txt2
-rw-r--r--gnuradio-core/src/lib/runtime/gr_basic_block.cc177
-rw-r--r--gnuradio-core/src/lib/runtime/gr_basic_block.h391
-rw-r--r--gnuradio-core/src/lib/runtime/gr_basic_block.i14
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.cc16
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.h76
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.i8
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_detail.cc6
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_detail.h5
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_registry.cc76
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_registry.h42
-rw-r--r--gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc70
-rw-r--r--gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h5
-rw-r--r--gnuradio-core/src/lib/runtime/gr_flowgraph.cc41
-rw-r--r--gnuradio-core/src/lib/runtime/gr_flowgraph.h60
-rw-r--r--gnuradio-core/src/lib/runtime/gr_hier_block2.cc35
-rw-r--r--gnuradio-core/src/lib/runtime/gr_hier_block2.h48
-rw-r--r--gnuradio-core/src/lib/runtime/gr_hier_block2.i21
-rw-r--r--gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc118
-rw-r--r--gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h5
-rw-r--r--gnuradio-core/src/lib/runtime/gr_msg_accepter.cc4
-rw-r--r--gnuradio-core/src/lib/runtime/gr_msg_accepter.h2
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tpb_detail.cc40
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tpb_detail.h26
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc50
-rw-r--r--gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc8
-rw-r--r--gnuradio-core/src/lib/swig/CMakeLists.txt4
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt8
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/__init__.py3
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/gateway.py215
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/hier_block2.py16
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/qa_block_gateway.py235
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_pdu.py110
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/top_block.py6
-rw-r--r--gr-analog/lib/fmdet_cf_impl.cc10
-rw-r--r--gr-atsc/src/lib/CMakeLists.txt2
-rw-r--r--gr-atsc/src/lib/qa_atsci_single_viterbi.cc2
-rw-r--r--gr-audio/swig/CMakeLists.txt2
-rw-r--r--gr-blocks/gnuradio-blocks.pc.in2
-rw-r--r--gr-blocks/grc/blocks_file_source.xml1
-rw-r--r--gr-blocks/grc/blocks_patterned_interleaver.xml66
-rw-r--r--gr-blocks/include/blocks/CMakeLists.txt1
-rw-r--r--gr-blocks/include/blocks/file_source.h28
-rw-r--r--gr-blocks/include/blocks/multiply_const_cc.h1
-rw-r--r--gr-blocks/include/blocks/multiply_const_ff.h1
-rw-r--r--gr-blocks/include/blocks/patterned_interleaver.h23
-rw-r--r--gr-blocks/include/blocks/stream_mux.h2
-rw-r--r--gr-blocks/lib/CMakeLists.txt1
-rw-r--r--gr-blocks/lib/file_source_impl.cc98
-rw-r--r--gr-blocks/lib/file_source_impl.h13
-rw-r--r--gr-blocks/lib/keep_m_in_n_impl.cc4
-rw-r--r--gr-blocks/lib/keep_m_in_n_impl.h2
-rw-r--r--gr-blocks/lib/patterned_interleaver_impl.cc87
-rw-r--r--gr-blocks/lib/patterned_interleaver_impl.h61
-rwxr-xr-xgr-blocks/python/qa_patterned_interleaver.py56
-rw-r--r--gr-blocks/swig/CMakeLists.txt2
-rw-r--r--gr-blocks/swig/blocks_swig.i3
-rw-r--r--gr-comedi/src/CMakeLists.txt2
-rw-r--r--gr-digital/examples/demod/ber_simulation.grc2
-rw-r--r--gr-digital/examples/demod/digital_freq_lock.grc2
-rw-r--r--gr-digital/examples/demod/pam_sync.grc2
-rw-r--r--gr-digital/examples/demod/pam_timing.grc2
-rw-r--r--gr-digital/swig/CMakeLists.txt2
-rw-r--r--gr-fcd/lib/fcd_source_c_impl.cc2
-rw-r--r--gr-fcd/swig/CMakeLists.txt2
-rw-r--r--gr-fft/swig/CMakeLists.txt2
-rw-r--r--gr-filter/examples/CMakeLists.txt8
-rw-r--r--gr-howto-write-a-block/cmake/Modules/GrSwig.cmake2
-rw-r--r--gr-howto-write-a-block/docs/doxygen/Doxyfile.in12
-rw-r--r--gr-howto-write-a-block/docs/doxygen/Doxyfile.swig_doc.in17
-rw-r--r--gr-howto-write-a-block/docs/doxygen/doxyxml/example/Doxyfile17
-rw-r--r--gr-noaa/swig/CMakeLists.txt2
-rw-r--r--gr-pager/lib/pager_flex_parse.cc6
-rw-r--r--gr-pager/swig/CMakeLists.txt2
-rw-r--r--gr-qtgui/grc/qtgui_sink_x.xml7
-rw-r--r--gr-qtgui/swig/CMakeLists.txt2
-rw-r--r--gr-shd/swig/CMakeLists.txt2
-rw-r--r--gr-trellis/src/lib/CMakeLists.txt2
-rw-r--r--gr-uhd/swig/CMakeLists.txt2
-rw-r--r--gr-utils/src/python/CMakeLists.txt1
-rwxr-xr-xgr-utils/src/python/grcc66
-rw-r--r--gr-video-sdl/src/CMakeLists.txt2
-rw-r--r--gr-vocoder/swig/CMakeLists.txt2
-rw-r--r--gr-wavelet/swig/CMakeLists.txt2
-rw-r--r--grc/blocks/block_tree.xml9
-rw-r--r--grc/blocks/gr_file_source.xml1
-rw-r--r--grc/blocks/gr_message_debug.xml27
-rw-r--r--grc/blocks/gr_message_strobe.xml35
-rw-r--r--grc/blocks/gr_pdu_to_tagged_stream.xml40
-rw-r--r--grc/blocks/gr_socket_pdu.xml62
-rw-r--r--grc/blocks/gr_tagged_stream_to_pdu.xml40
-rw-r--r--grc/blocks/gr_tuntap_pdu.xml34
-rw-r--r--grc/blocks/pad_sink.xml9
-rw-r--r--grc/blocks/pad_source.xml9
-rw-r--r--grc/python/Connection.py3
-rw-r--r--grc/python/Constants.py1
-rw-r--r--grc/python/FlowGraph.py10
-rw-r--r--grc/python/Generator.py4
-rw-r--r--grc/python/Port.py2
-rw-r--r--grc/python/convert_hier.py20
-rw-r--r--grc/python/flow_graph.tmpl26
-rw-r--r--gruel/CMakeLists.txt1
-rw-r--r--gruel/src/include/gruel/msg_accepter.h4
-rw-r--r--gruel/src/include/gruel/msg_passing.h20
-rw-r--r--gruel/src/include/gruel/pmt.h19
-rw-r--r--gruel/src/lib/pmt/pmt.cc32
-rw-r--r--gruel/src/lib/pmt/qa_pmt_prims.cc9
-rw-r--r--gruel/src/swig/CMakeLists.txt2
-rw-r--r--gruel/src/swig/pmt_swig.i9
-rw-r--r--volk/CMakeLists.txt10
-rw-r--r--volk/apps/CMakeLists.txt2
166 files changed, 5913 insertions, 558 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9af8d7eb9b..4d0e59e70a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,6 +50,13 @@ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O2")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O2")
########################################################################
+# Environment setup
+########################################################################
+IF(NOT DEFINED BOOST_ROOT)
+ SET(BOOST_ROOT ${CMAKE_INSTALL_PREFIX})
+ENDIF()
+
+########################################################################
# Import executables from a native build (for cross compiling)
# http://www.vtk.org/Wiki/CMake_Cross_Compiling#Using_executables_in_the_build_created_during_the_build
########################################################################
@@ -225,6 +232,8 @@ install(
########################################################################
list(APPEND GR_TEST_TARGET_DEPS volk gruel gnuradio-core)
list(APPEND GR_TEST_PYTHON_DIRS
+ ${CMAKE_SOURCE_DIR}/gruel/src/python
+ ${CMAKE_BINARY_DIR}/gruel/src/swig
${CMAKE_BINARY_DIR}/gnuradio-core/src/python
${CMAKE_BINARY_DIR}/gnuradio-core/src/lib/swig
)
diff --git a/cmake/Modules/FindQwt.cmake b/cmake/Modules/FindQwt.cmake
index f2cf3440dd..db5ca6d27e 100644
--- a/cmake/Modules/FindQwt.cmake
+++ b/cmake/Modules/FindQwt.cmake
@@ -11,6 +11,7 @@ find_path (QWT_INCLUDE_DIRS
/usr/include/qwt-qt4
/usr/include/qwt
/opt/local/include/qwt
+ /opt/local/lib/qwt.framework/Headers
/sw/include/qwt
)
@@ -20,6 +21,7 @@ find_library (QWT_LIBRARIES
/usr/local/lib
/usr/lib
/opt/local/lib
+ /opt/local/lib/qwt.framework
/sw/lib
)
diff --git a/cmake/Modules/GrMiscUtils.cmake b/cmake/Modules/GrMiscUtils.cmake
index a73e3e6d7e..3e80846d62 100644
--- a/cmake/Modules/GrMiscUtils.cmake
+++ b/cmake/Modules/GrMiscUtils.cmake
@@ -208,3 +208,70 @@ function(GR_GEN_TARGET_DEPS name var)
set(${var} "DEPENDS;${name};COMMAND;${name}" PARENT_SCOPE)
endif()
endfunction(GR_GEN_TARGET_DEPS)
+
+
+########################################################################
+# 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/src/python/grcc)
+
+ # GRCC uses some stuff in grc and gnuradio-core, so we force
+ # the known paths here
+ list(APPEND PYTHONPATHS
+ ${CMAKE_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/gnuradio-core/src/python
+ ${CMAKE_SOURCE_DIR}/gnuradio-core/src/lib/swig
+ ${CMAKE_BINARY_DIR}/gnuradio-core/src/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)
diff --git a/cmake/Modules/GrPython.cmake b/cmake/Modules/GrPython.cmake
index 14f2b29cd0..791114e052 100644
--- a/cmake/Modules/GrPython.cmake
+++ b/cmake/Modules/GrPython.cmake
@@ -96,11 +96,13 @@ 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)
########################################################################
diff --git a/cmake/Modules/GrSwig.cmake b/cmake/Modules/GrSwig.cmake
index 175d0d759a..b9bf0bb0b9 100644
--- a/cmake/Modules/GrSwig.cmake
+++ b/cmake/Modules/GrSwig.cmake
@@ -105,12 +105,10 @@ endfunction(GR_SWIG_MAKE_DOCS)
macro(GR_SWIG_MAKE name)
set(ifiles ${ARGN})
- list(APPEND GR_SWIG_TARGET_DEPS ${GR_SWIG_LIBRARIES})
-
#do swig doc generation if specified
if (GR_SWIG_DOC_FILE)
set(GR_SWIG_DOCS_SOURCE_DEPS ${GR_SWIG_SOURCE_DEPS})
- set(GR_SWIG_DOCS_TAREGT_DEPS ${GR_SWIG_TARGET_DEPS})
+ set(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)
@@ -207,21 +205,25 @@ file(WRITE ${CMAKE_BINARY_DIR}/get_swig_deps.py "
import os, sys, re
-include_matcher = re.compile('[#|%]include\\s*[<|\"](.*)[>|\"]')
+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 include_matcher.findall(file_contents, re.MULTILINE)
+ return matcher.findall(file_contents, re.MULTILINE)
def get_swig_deps(file_path, level):
deps = [file_path]
if level == 0: return deps
- for inc_file in get_swig_incs(file_path):
+ 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__':
diff --git a/docs/doxygen/Doxyfile.in b/docs/doxygen/Doxyfile.in
index ad3c2d01f4..78a7a5d166 100644
--- a/docs/doxygen/Doxyfile.in
+++ b/docs/doxygen/Doxyfile.in
@@ -455,12 +455,6 @@ MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = NO
-
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
@@ -862,12 +856,6 @@ HTML_FOOTER =
HTML_STYLESHEET =
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS = YES
-
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded. For this to work a browser that supports
diff --git a/docs/doxygen/Doxyfile.swig_doc.in b/docs/doxygen/Doxyfile.swig_doc.in
index 94e14bda1b..8f6182ca83 100644
--- a/docs/doxygen/Doxyfile.swig_doc.in
+++ b/docs/doxygen/Doxyfile.swig_doc.in
@@ -470,12 +470,6 @@ MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = NO
-
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
@@ -796,12 +790,6 @@ HTML_FOOTER =
HTML_STYLESHEET =
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS = YES
-
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded. For this to work a browser that supports
@@ -950,11 +938,6 @@ ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
-# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
-# and Class Hierarchy pages using a tree view instead of an ordered list.
-
-USE_INLINE_TREES = NO
-
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
diff --git a/docs/doxygen/doxyxml/example/Doxyfile b/docs/doxygen/doxyxml/example/Doxyfile
index 9780043be0..dd2e5c77eb 100644
--- a/docs/doxygen/doxyxml/example/Doxyfile
+++ b/docs/doxygen/doxyxml/example/Doxyfile
@@ -476,12 +476,6 @@ MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = NO
-
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
@@ -808,12 +802,6 @@ HTML_STYLESHEET =
HTML_TIMESTAMP = YES
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS = YES
-
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded. For this to work a browser that supports
@@ -978,11 +966,6 @@ ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
-# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
-# and Class Hierarchy pages using a tree view instead of an ordered list.
-
-USE_INLINE_TREES = NO
-
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
diff --git a/gnuradio-core/CMakeLists.txt b/gnuradio-core/CMakeLists.txt
index 4e76b3c5a6..2f06791ca6 100644
--- a/gnuradio-core/CMakeLists.txt
+++ b/gnuradio-core/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2010-2011 Free Software Foundation, Inc.
+# Copyright 2010-2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -45,6 +45,7 @@ GR_REGISTER_COMPONENT("gnuradio-core" ENABLE_GR_CORE
include(GrMiscUtils)
GR_SET_GLOBAL(GNURADIO_CORE_INCLUDE_DIRS
+ ${Boost_INCLUDE_DIRS}
${GRUEL_INCLUDE_DIRS} #headers depend on gruel
${CMAKE_CURRENT_SOURCE_DIR}/src/lib/runtime
${CMAKE_CURRENT_BINARY_DIR}/src/lib/general
@@ -60,11 +61,12 @@ GR_SET_GLOBAL(GNURADIO_CORE_INCLUDE_DIRS
${CMAKE_CURRENT_BINARY_DIR}/src/lib/swig
${CMAKE_CURRENT_SOURCE_DIR}/src/lib/swig
${CMAKE_CURRENT_SOURCE_DIR}/src/lib/hier
+ ${Boost_INCLUDE_DIRS}
)
GR_SET_GLOBAL(GNURADIO_CORE_SWIG_INCLUDE_DIRS
${CMAKE_SOURCE_DIR}/gruel/src/swig
- ${CMAKE_BINARY_DIR}/gruel/src/swig/
+ ${CMAKE_BINARY_DIR}/gruel/src/swig
${CMAKE_CURRENT_SOURCE_DIR}/src/lib/swig
${GNURADIO_CORE_INCLUDE_DIRS}
)
diff --git a/gnuradio-core/src/examples/CMakeLists.txt b/gnuradio-core/src/examples/CMakeLists.txt
index c2b847c919..01d9eb83e0 100644
--- a/gnuradio-core/src/examples/CMakeLists.txt
+++ b/gnuradio-core/src/examples/CMakeLists.txt
@@ -18,6 +18,7 @@
# Boston, MA 02110-1301, USA.
add_subdirectory(mp-sched)
+add_subdirectory(msg_passing)
add_subdirectory(network)
add_subdirectory(pfb)
add_subdirectory(tags)
diff --git a/gnuradio-core/src/examples/msg_passing/CMakeLists.txt b/gnuradio-core/src/examples/msg_passing/CMakeLists.txt
new file mode 100644
index 0000000000..c4b207a1e4
--- /dev/null
+++ b/gnuradio-core/src/examples/msg_passing/CMakeLists.txt
@@ -0,0 +1,27 @@
+# Copyright 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.
+
+include(GrPython)
+
+install(
+ FILES
+ strobe.grc
+ DESTINATION ${GR_PKG_DATA_DIR}/examples/msg_passing
+ COMPONENT "core_python"
+)
diff --git a/gnuradio-core/src/examples/msg_passing/hier/test_msg_hier.grc b/gnuradio-core/src/examples/msg_passing/hier/test_msg_hier.grc
new file mode 100644
index 0000000000..0faed49bc7
--- /dev/null
+++ b/gnuradio-core/src/examples/msg_passing/hier/test_msg_hier.grc
@@ -0,0 +1,287 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Mon Dec 10 19:56:24 2012</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>test_msg_hier</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>hb</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>pad_source</key>
+ <param>
+ <key>id</key>
+ <value>pad_source_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>TEST_PORT</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>message</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>optional</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(234, 145)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>pad_source</key>
+ <param>
+ <key>id</key>
+ <value>pad_source_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>TEST_PORT2</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>message</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>optional</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(167, 54)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_message_strobe</key>
+ <param>
+ <key>id</key>
+ <value>gr_message_strobe_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>msg</key>
+ <value>pmt.pmt_cons(pmt.PMT_NIL, pmt.pmt_make_u8vector(16,0x77))</value>
+ </param>
+ <param>
+ <key>period</key>
+ <value>200</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(362, 81)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>pad_sink</key>
+ <param>
+ <key>id</key>
+ <value>pad_sink_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>TEST_PORT</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>message</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>optional</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(618, 87)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_message_strobe</key>
+ <param>
+ <key>id</key>
+ <value>gr_message_strobe_0_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>msg</key>
+ <value>pmt.pmt_intern("OUTPUT2")</value>
+ </param>
+ <param>
+ <key>period</key>
+ <value>100</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(400, 156)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>pad_sink</key>
+ <param>
+ <key>id</key>
+ <value>pad_sink_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>TEST_PORT3</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>message</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>optional</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(695, 172)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>pad_source_0_0</source_block_id>
+ <sink_block_id>gr_message_strobe_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>pad_source_0</source_block_id>
+ <sink_block_id>gr_message_strobe_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_message_strobe_0</source_block_id>
+ <sink_block_id>pad_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_message_strobe_0_1</source_block_id>
+ <sink_block_id>pad_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_message_strobe_0_1</source_block_id>
+ <sink_block_id>pad_sink_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gnuradio-core/src/examples/msg_passing/hier/test_msg_hier_topblock.grc b/gnuradio-core/src/examples/msg_passing/hier/test_msg_hier_topblock.grc
new file mode 100644
index 0000000000..f440b06b39
--- /dev/null
+++ b/gnuradio-core/src/examples/msg_passing/hier/test_msg_hier_topblock.grc
@@ -0,0 +1,185 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Mon Dec 10 19:56:42 2012</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>test_msg_hier_topblock</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>no_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_message_strobe</key>
+ <param>
+ <key>id</key>
+ <value>gr_message_strobe_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>msg</key>
+ <value>pmt.pmt_intern("UPDATED2")</value>
+ </param>
+ <param>
+ <key>period</key>
+ <value>3000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(51, 88)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_message_strobe</key>
+ <param>
+ <key>id</key>
+ <value>gr_message_strobe_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>msg</key>
+ <value>pmt.pmt_intern("UPDATED")</value>
+ </param>
+ <param>
+ <key>period</key>
+ <value>2000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(211, 168)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_message_debug</key>
+ <param>
+ <key>id</key>
+ <value>gr_message_debug_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(758, 71)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>TEST_MSG_HIER</key>
+ <param>
+ <key>id</key>
+ <value>TEST_MSG_HIER_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(402, 52)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>TEST_MSG_HIER_0</source_block_id>
+ <sink_block_id>gr_message_debug_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_message_strobe_0</source_block_id>
+ <sink_block_id>TEST_MSG_HIER_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_message_strobe_0_0</source_block_id>
+ <sink_block_id>TEST_MSG_HIER_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>TEST_MSG_HIER_0</source_block_id>
+ <sink_block_id>gr_message_debug_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>TEST_MSG_HIER_0</source_block_id>
+ <sink_block_id>gr_message_debug_0</sink_block_id>
+ <source_key>1</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gnuradio-core/src/examples/msg_passing/strobe.grc b/gnuradio-core/src/examples/msg_passing/strobe.grc
new file mode 100644
index 0000000000..7e7e8c345e
--- /dev/null
+++ b/gnuradio-core/src/examples/msg_passing/strobe.grc
@@ -0,0 +1,266 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Thu Dec 6 11:33:08 2012</timestamp>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>32000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 170)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_pdu_to_tagged_stream</key>
+ <param>
+ <key>id</key>
+ <value>gr_pdu_to_tagged_stream_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(443, 89)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_message_debug</key>
+ <param>
+ <key>id</key>
+ <value>gr_message_debug_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1049, 176)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_tagged_stream_to_pdu</key>
+ <param>
+ <key>id</key>
+ <value>gr_tagged_stream_to_pdu_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(870, 89)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_kludge_copy</key>
+ <param>
+ <key>id</key>
+ <value>gr_kludge_copy_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>num_ports</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(686, 89)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_message_strobe</key>
+ <param>
+ <key>id</key>
+ <value>gr_message_strobe_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>msg</key>
+ <value>pmt.pmt_intern("TEST")</value>
+ </param>
+ <param>
+ <key>period</key>
+ <value>1000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(423, 177)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_message_strobe</key>
+ <param>
+ <key>id</key>
+ <value>gr_message_strobe_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>msg</key>
+ <value>pmt.pmt_cons( pmt.PMT_NIL, pmt.pmt_make_u8vector(512,0) )</value>
+ </param>
+ <param>
+ <key>period</key>
+ <value>750</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(99, 85)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>strobe</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>no_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>gr_message_strobe_0_0</source_block_id>
+ <sink_block_id>gr_pdu_to_tagged_stream_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_message_strobe_0</source_block_id>
+ <sink_block_id>gr_message_debug_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_tagged_stream_to_pdu_0</source_block_id>
+ <sink_block_id>gr_message_debug_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_kludge_copy_0</source_block_id>
+ <sink_block_id>gr_tagged_stream_to_pdu_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_pdu_to_tagged_stream_0</source_block_id>
+ <sink_block_id>gr_kludge_copy_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gnuradio-core/src/examples/pfb/CMakeLists.txt b/gnuradio-core/src/examples/pfb/CMakeLists.txt
index 6bb25568c8..090b2401d0 100644
--- a/gnuradio-core/src/examples/pfb/CMakeLists.txt
+++ b/gnuradio-core/src/examples/pfb/CMakeLists.txt
@@ -25,7 +25,6 @@ GR_PYTHON_INSTALL(PROGRAMS
decimate.py
fmtest.py
interpolate.py
- resampler_demo.grc
resampler.py
synth_filter.py
synth_to_chan.py
@@ -34,3 +33,9 @@ GR_PYTHON_INSTALL(PROGRAMS
COMPONENT "core_python"
)
+install(
+ FILES
+ resampler_demo.grc
+ DESTINATION ${GR_PKG_DATA_DIR}/examples/pfb
+ COMPONENT "core_python"
+)
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc
index 06e98447ec..ee09fef44e 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc
+++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc
@@ -86,6 +86,7 @@ gr_pfb_arb_resampler_ccf::~gr_pfb_arb_resampler_ccf ()
{
for(unsigned int i = 0; i < d_int_rate; i++) {
delete d_filters[i];
+ delete d_diff_filters[i];
}
}
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc
index 9a9b869929..f01af2e6f4 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc
+++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc
@@ -86,6 +86,7 @@ gr_pfb_arb_resampler_fff::~gr_pfb_arb_resampler_fff ()
{
for(unsigned int i = 0; i < d_int_rate; i++) {
delete d_filters[i];
+ delete d_diff_filters[i];
}
}
diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt
index 3cf7f74e4c..4c99acfc36 100644
--- a/gnuradio-core/src/lib/general/CMakeLists.txt
+++ b/gnuradio-core/src/lib/general/CMakeLists.txt
@@ -187,6 +187,7 @@ set(gr_core_general_triple_threats
gr_agc2_ff
gr_align_on_samplenumbers_ss
gr_bin_statistics_f
+ gr_block_gateway
gr_bytes_to_syms
gr_char_to_float
gr_char_to_short
@@ -298,6 +299,7 @@ set(gr_core_general_triple_threats
gr_burst_tagger
gr_correlate_access_code_tag_bb
gr_tag_debug
+ gr_message_strobe
)
foreach(file_tt ${gr_core_general_triple_threats})
diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i
index 790549c4dd..1446088a2c 100644
--- a/gnuradio-core/src/lib/general/general.i
+++ b/gnuradio-core/src/lib/general/general.i
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+ * Copyright 2004-2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -143,6 +143,7 @@
#include <gr_add_ff.h>
#include <gr_vector_map.h>
#include <gr_tag_debug.h>
+#include <gr_message_strobe.h>
%}
%include "gri_control_loop.i"
@@ -266,3 +267,5 @@
%include "gr_add_ff.i"
%include "gr_vector_map.i"
%include "gr_tag_debug.i"
+%include "gr_block_gateway.i"
+%include "gr_message_strobe.i"
diff --git a/gnuradio-core/src/lib/general/gr_block_gateway.cc b/gnuradio-core/src/lib/general/gr_block_gateway.cc
new file mode 100644
index 0000000000..79b42803af
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_block_gateway.cc
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2011-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.
+ */
+
+#include <gr_block_gateway.h>
+#include <gr_io_signature.h>
+#include <iostream>
+#include <boost/bind.hpp>
+
+/***********************************************************************
+ * Helper routines
+ **********************************************************************/
+template <typename OutType, typename InType>
+void copy_pointers(OutType &out, const InType &in){
+ out.resize(in.size());
+ for (size_t i = 0; i < in.size(); i++){
+ out[i] = (void *)(in[i]);
+ }
+}
+
+/***********************************************************************
+ * The gr_block gateway implementation class
+ **********************************************************************/
+class gr_block_gateway_impl : public gr_block_gateway{
+public:
+ gr_block_gateway_impl(
+ gr_feval_ll *handler,
+ const std::string &name,
+ gr_io_signature_sptr in_sig,
+ gr_io_signature_sptr out_sig,
+ const gr_block_gw_work_type work_type,
+ const unsigned factor
+ ):
+ gr_block(name, in_sig, out_sig),
+ _handler(handler),
+ _work_type(work_type)
+ {
+ switch(_work_type){
+ case GR_BLOCK_GW_WORK_GENERAL:
+ _decim = 1; //not relevant, but set anyway
+ _interp = 1; //not relevant, but set anyway
+ break;
+
+ case GR_BLOCK_GW_WORK_SYNC:
+ _decim = 1;
+ _interp = 1;
+ this->set_fixed_rate(true);
+ break;
+
+ case GR_BLOCK_GW_WORK_DECIM:
+ _decim = factor;
+ _interp = 1;
+ break;
+
+ case GR_BLOCK_GW_WORK_INTERP:
+ _decim = 1;
+ _interp = factor;
+ this->set_output_multiple(_interp);
+ break;
+ }
+ }
+
+ /*******************************************************************
+ * Overloads for various scheduler-called functions
+ ******************************************************************/
+ void forecast(
+ int noutput_items,
+ gr_vector_int &ninput_items_required
+ ){
+ switch(_work_type){
+ case GR_BLOCK_GW_WORK_GENERAL:
+ _message.action = gr_block_gw_message_type::ACTION_FORECAST;
+ _message.forecast_args_noutput_items = noutput_items;
+ _message.forecast_args_ninput_items_required = ninput_items_required;
+ _handler->calleval(0);
+ ninput_items_required = _message.forecast_args_ninput_items_required;
+ return;
+
+ default:
+ unsigned ninputs = ninput_items_required.size();
+ for (unsigned i = 0; i < ninputs; i++)
+ ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items);
+ return;
+ }
+ }
+
+ int general_work(
+ int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items
+ ){
+ switch(_work_type){
+ case GR_BLOCK_GW_WORK_GENERAL:
+ _message.action = gr_block_gw_message_type::ACTION_GENERAL_WORK;
+ _message.general_work_args_noutput_items = noutput_items;
+ _message.general_work_args_ninput_items = ninput_items;
+ copy_pointers(_message.general_work_args_input_items, input_items);
+ _message.general_work_args_output_items = output_items;
+ _handler->calleval(0);
+ return _message.general_work_args_return_value;
+
+ default:
+ int r = work (noutput_items, input_items, output_items);
+ if (r > 0) consume_each(r*_decim/_interp);
+ return r;
+ }
+ }
+
+ int work(
+ int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items
+ ){
+ _message.action = gr_block_gw_message_type::ACTION_WORK;
+ _message.work_args_ninput_items = fixed_rate_noutput_to_ninput(noutput_items);
+ if (_message.work_args_ninput_items == 0) return -1;
+ _message.work_args_noutput_items = noutput_items;
+ copy_pointers(_message.work_args_input_items, input_items);
+ _message.work_args_output_items = output_items;
+ _handler->calleval(0);
+ return _message.work_args_return_value;
+ }
+
+ int fixed_rate_noutput_to_ninput(int noutput_items){
+ return (noutput_items*_decim/_interp) + history() - 1;
+ }
+
+ int fixed_rate_ninput_to_noutput(int ninput_items){
+ return std::max(0, ninput_items - (int)history() + 1)*_interp/_decim;
+ }
+
+ bool start(void){
+ _message.action = gr_block_gw_message_type::ACTION_START;
+ _handler->calleval(0);
+ return _message.start_args_return_value;
+ }
+
+ bool stop(void){
+ _message.action = gr_block_gw_message_type::ACTION_STOP;
+ _handler->calleval(0);
+ return _message.stop_args_return_value;
+ }
+
+ gr_block_gw_message_type &gr_block_message(void){
+ return _message;
+ }
+
+private:
+ gr_feval_ll *_handler;
+ gr_block_gw_message_type _message;
+ const gr_block_gw_work_type _work_type;
+ unsigned _decim, _interp;
+};
+
+boost::shared_ptr<gr_block_gateway> gr_make_block_gateway(
+ gr_feval_ll *handler,
+ const std::string &name,
+ gr_io_signature_sptr in_sig,
+ gr_io_signature_sptr out_sig,
+ const gr_block_gw_work_type work_type,
+ const unsigned factor
+){
+ return boost::shared_ptr<gr_block_gateway>(
+ new gr_block_gateway_impl(handler, name, in_sig, out_sig, work_type, factor)
+ );
+}
diff --git a/gnuradio-core/src/lib/general/gr_block_gateway.h b/gnuradio-core/src/lib/general/gr_block_gateway.h
new file mode 100644
index 0000000000..ae91d41b59
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_block_gateway.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2011-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.
+ */
+
+#ifndef INCLUDED_GRBLOCK_GATEWAY_H
+#define INCLUDED_GRBLOCK_GATEWAY_H
+
+#include <gr_core_api.h>
+#include <gr_block.h>
+#include <gr_feval.h>
+
+/*!
+ * The work type enum tells the gateway what kind of block to implement.
+ * The choices are familiar gnuradio block overloads (sync, decim, interp).
+ */
+enum gr_block_gw_work_type{
+ GR_BLOCK_GW_WORK_GENERAL,
+ GR_BLOCK_GW_WORK_SYNC,
+ GR_BLOCK_GW_WORK_DECIM,
+ GR_BLOCK_GW_WORK_INTERP,
+};
+
+/*!
+ * Shared message structure between python and gateway.
+ * Each action type represents a scheduler-called function.
+ */
+struct gr_block_gw_message_type{
+ enum action_type{
+ ACTION_GENERAL_WORK, //dispatch work
+ ACTION_WORK, //dispatch work
+ ACTION_FORECAST, //dispatch forecast
+ ACTION_START, //dispatch start
+ ACTION_STOP, //dispatch stop
+ };
+
+ action_type action;
+
+ int general_work_args_noutput_items;
+ std::vector<int> general_work_args_ninput_items;
+ std::vector<void *> general_work_args_input_items; //TODO this should be const void*, but swig cant int cast it right
+ std::vector<void *> general_work_args_output_items;
+ int general_work_args_return_value;
+
+ int work_args_ninput_items;
+ int work_args_noutput_items;
+ std::vector<void *> work_args_input_items; //TODO this should be const void*, but swig cant int cast it right
+ std::vector<void *> work_args_output_items;
+ int work_args_return_value;
+
+ int forecast_args_noutput_items;
+ std::vector<int> forecast_args_ninput_items_required;
+
+ bool start_args_return_value;
+
+ bool stop_args_return_value;
+};
+
+/*!
+ * The gateway block which performs all the magic.
+ *
+ * The gateway provides access to all the gr_block routines.
+ * The methods prefixed with gr_block__ are renamed
+ * to class methods without the prefix in python.
+ */
+class GR_CORE_API gr_block_gateway : virtual public gr_block{
+public:
+ //! Provide access to the shared message object
+ virtual gr_block_gw_message_type &gr_block_message(void) = 0;
+
+ long gr_block__unique_id(void) const{
+ return gr_block::unique_id();
+ }
+
+ std::string gr_block__name(void) const{
+ return gr_block::name();
+ }
+
+ unsigned gr_block__history(void) const{
+ return gr_block::history();
+ }
+
+ void gr_block__set_history(unsigned history){
+ return gr_block::set_history(history);
+ }
+
+ void gr_block__set_fixed_rate(bool fixed_rate){
+ return gr_block::set_fixed_rate(fixed_rate);
+ }
+
+ bool gr_block__fixed_rate(void) const{
+ return gr_block::fixed_rate();
+ }
+
+ void gr_block__set_output_multiple(int multiple){
+ return gr_block::set_output_multiple(multiple);
+ }
+
+ int gr_block__output_multiple(void) const{
+ return gr_block::output_multiple();
+ }
+
+ void gr_block__consume(int which_input, int how_many_items){
+ return gr_block::consume(which_input, how_many_items);
+ }
+
+ void gr_block__consume_each(int how_many_items){
+ return gr_block::consume_each(how_many_items);
+ }
+
+ void gr_block__produce(int which_output, int how_many_items){
+ return gr_block::produce(which_output, how_many_items);
+ }
+
+ void gr_block__set_relative_rate(double relative_rate){
+ return gr_block::set_relative_rate(relative_rate);
+ }
+
+ double gr_block__relative_rate(void) const{
+ return gr_block::relative_rate();
+ }
+
+ uint64_t gr_block__nitems_read(unsigned int which_input){
+ return gr_block::nitems_read(which_input);
+ }
+
+ uint64_t gr_block__nitems_written(unsigned int which_output){
+ return gr_block::nitems_written(which_output);
+ }
+
+ gr_block::tag_propagation_policy_t gr_block__tag_propagation_policy(void){
+ return gr_block::tag_propagation_policy();
+ }
+
+ void gr_block__set_tag_propagation_policy(gr_block::tag_propagation_policy_t p){
+ return gr_block::set_tag_propagation_policy(p);
+ }
+
+ void gr_block__add_item_tag(
+ unsigned int which_output, const gr_tag_t &tag
+ ){
+ return gr_block::add_item_tag(which_output, tag);
+ }
+
+ void gr_block__add_item_tag(
+ unsigned int which_output,
+ uint64_t abs_offset,
+ const pmt::pmt_t &key,
+ const pmt::pmt_t &value,
+ const pmt::pmt_t &srcid=pmt::PMT_F
+ ){
+ return gr_block::add_item_tag(which_output, abs_offset, key, value, srcid);
+ }
+
+ std::vector<gr_tag_t> gr_block__get_tags_in_range(
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end
+ ){
+ std::vector<gr_tag_t> tags;
+ gr_block::get_tags_in_range(tags, which_input, abs_start, abs_end);
+ return tags;
+ }
+
+ std::vector<gr_tag_t> gr_block__get_tags_in_range(
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end,
+ const pmt::pmt_t &key
+ ){
+ std::vector<gr_tag_t> tags;
+ gr_block::get_tags_in_range(tags, which_input, abs_start, abs_end, key);
+ return tags;
+ }
+};
+
+/*!
+ * Make a new gateway block.
+ * \param handler the swig director object with callback
+ * \param name the name of the block (Ex: "Shirley")
+ * \param in_sig the input signature for this block
+ * \param out_sig the output signature for this block
+ * \param work_type the type of block overload to implement
+ * \param factor the decimation or interpolation factor
+ * \return a new gateway block
+ */
+GR_CORE_API boost::shared_ptr<gr_block_gateway> gr_make_block_gateway(
+ gr_feval_ll *handler,
+ const std::string &name,
+ gr_io_signature_sptr in_sig,
+ gr_io_signature_sptr out_sig,
+ const gr_block_gw_work_type work_type,
+ const unsigned factor
+);
+
+#endif /* INCLUDED_GRBLOCK_GATEWAY_H */
diff --git a/gnuradio-core/src/lib/general/gr_block_gateway.i b/gnuradio-core/src/lib/general/gr_block_gateway.i
new file mode 100644
index 0000000000..8adafdfea3
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_block_gateway.i
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011-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.
+ */
+
+////////////////////////////////////////////////////////////////////////
+// standard includes
+////////////////////////////////////////////////////////////////////////
+%include <gnuradio.i>
+%include <gr_tags.i>
+%include <gr_feval.i>
+
+////////////////////////////////////////////////////////////////////////
+// block headers
+////////////////////////////////////////////////////////////////////////
+%{
+#include <gr_block_gateway.h>
+%}
+
+////////////////////////////////////////////////////////////////////////
+// data type support
+////////////////////////////////////////////////////////////////////////
+%template(int_vector_t) std::vector<int>;
+%template(void_star_vector_t) std::vector<void *>;
+
+////////////////////////////////////////////////////////////////////////
+// block magic
+////////////////////////////////////////////////////////////////////////
+GR_SWIG_BLOCK_MAGIC(gr,block_gateway);
+%include <gr_block_gateway.h>
diff --git a/gnuradio-core/src/lib/general/gr_message_strobe.cc b/gnuradio-core/src/lib/general/gr_message_strobe.cc
new file mode 100644
index 0000000000..6a9f807d18
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_message_strobe.cc
@@ -0,0 +1,75 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_message_strobe.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <string.h>
+#include <iostream>
+
+// public constructor that returns a shared_ptr
+
+gr_message_strobe_sptr
+gr_make_message_strobe (pmt::pmt_t msg, float period_ms)
+{
+ return gnuradio::get_initial_sptr(new gr_message_strobe(msg, period_ms));
+}
+
+gr_message_strobe::gr_message_strobe (pmt::pmt_t msg, float period_ms)
+ : gr_block("message_strobe",
+ gr_make_io_signature(0, 0, 0),
+ gr_make_io_signature(0, 0, 0)),
+ d_finished(false),
+ d_period_ms(period_ms),
+ d_msg(msg)
+{
+ message_port_register_out(pmt::mp("strobe"));
+ d_thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&gr_message_strobe::run, this)));
+
+ message_port_register_in(pmt::mp("set_msg"));
+ set_msg_handler(pmt::mp("set_msg"), boost::bind(&gr_message_strobe::set_msg, this, _1));
+}
+
+gr_message_strobe::~gr_message_strobe()
+{
+ d_finished = true;
+ d_thread->interrupt();
+ d_thread->join();
+}
+
+void gr_message_strobe::run(){
+ while(!d_finished) {
+ boost::this_thread::sleep(boost::posix_time::milliseconds(d_period_ms));
+ if(d_finished){ return; }
+
+ message_port_pub( pmt::mp("strobe"), d_msg );
+ }
+}
diff --git a/gnuradio-core/src/lib/general/gr_message_strobe.h b/gnuradio-core/src/lib/general/gr_message_strobe.h
new file mode 100644
index 0000000000..89046ffc05
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_message_strobe.h
@@ -0,0 +1,62 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifndef INCLUDED_GR_MESSAGE_STROBE_H
+#define INCLUDED_GR_MESSAGE_STROBE_H
+
+#include <gr_core_api.h>
+#include <gr_block.h>
+#include <gr_message.h>
+#include <gr_msg_queue.h>
+
+class gr_message_strobe;
+typedef boost::shared_ptr<gr_message_strobe> gr_message_strobe_sptr;
+
+GR_CORE_API gr_message_strobe_sptr gr_make_message_strobe (pmt::pmt_t msg, float period_ms);
+
+/*!
+ * \brief Send message at defined interval
+ * \ingroup msg_blk
+ */
+class GR_CORE_API gr_message_strobe : public gr_block
+{
+ private:
+ friend GR_CORE_API gr_message_strobe_sptr
+ gr_make_message_strobe(pmt::pmt_t msg, float period_ms);
+
+ boost::shared_ptr<boost::thread> d_thread;
+ bool d_finished;
+ float d_period_ms;
+ pmt::pmt_t d_msg;
+
+ void run();
+
+ protected:
+ gr_message_strobe (pmt::pmt_t msg, float period_ms);
+
+ public:
+ ~gr_message_strobe ();
+
+ void set_msg(pmt::pmt_t msg){ d_msg = msg; }
+};
+
+#endif /* INCLUDED_GR_MESSAGE_STROBE_H */
diff --git a/gnuradio-core/src/lib/general/gr_message_strobe.i b/gnuradio-core/src/lib/general/gr_message_strobe.i
new file mode 100644
index 0000000000..490aa8e8a1
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_message_strobe.i
@@ -0,0 +1,30 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,message_strobe);
+
+%{
+#include <gr_message_strobe.h>
+%}
+
+%include "gr_message_strobe.h"
+
diff --git a/gnuradio-core/src/lib/general/gr_nop.cc b/gnuradio-core/src/lib/general/gr_nop.cc
index ca5983c397..edfe1d76d9 100644
--- a/gnuradio-core/src/lib/general/gr_nop.cc
+++ b/gnuradio-core/src/lib/general/gr_nop.cc
@@ -40,7 +40,8 @@ gr_nop::gr_nop (size_t sizeof_stream_item)
d_nmsgs_recvd(0)
{
// Arrange to have count_received_msgs called when messages are received.
- set_msg_handler(boost::bind(&gr_nop::count_received_msgs, this, _1));
+ message_port_register_in(pmt::mp("port"));
+ set_msg_handler(pmt::mp("port"), boost::bind(&gr_nop::count_received_msgs, this, _1));
}
// Trivial message handler that just counts them.
diff --git a/gnuradio-core/src/lib/general/gr_simple_correlator.cc b/gnuradio-core/src/lib/general/gr_simple_correlator.cc
index 9c2ebef15a..b9209e74f0 100644
--- a/gnuradio-core/src/lib/general/gr_simple_correlator.cc
+++ b/gnuradio-core/src/lib/general/gr_simple_correlator.cc
@@ -158,11 +158,13 @@ gr_simple_correlator::general_work (int noutput_items,
int decision;
int hamming_dist;
+#ifdef DEBUG_SIMPLE_CORRELATOR
struct debug_data {
float raw_data;
float sampled;
float enter_locked;
} debug_data;
+#endif
while (n < nin){
@@ -212,7 +214,9 @@ gr_simple_correlator::general_work (int noutput_items,
else if (d_state == ST_UNDER_THRESHOLD && hamming_dist > THRESHOLD){
// no longer seeing good PN code, compute center of goodness
enter_locked ();
+#ifdef DEBUG_SIMPLE_CORRELATOR
debug_data.enter_locked = 1.0;
+#endif
}
break;
diff --git a/gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t
index 37963cdfee..20968afe22 100644
--- a/gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t
+++ b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t
@@ -44,7 +44,7 @@
// some sanity checks
assert(offset < periodicity);
assert(offset >= 0);
- assert(periodicity > data.size());
+ assert((size_t)periodicity > data.size());
}
int
diff --git a/gnuradio-core/src/lib/io/CMakeLists.txt b/gnuradio-core/src/lib/io/CMakeLists.txt
index ddd43a4a32..c5b85d304f 100644
--- a/gnuradio-core/src/lib/io/CMakeLists.txt
+++ b/gnuradio-core/src/lib/io/CMakeLists.txt
@@ -38,6 +38,8 @@ list(APPEND gnuradio_core_sources
${CMAKE_CURRENT_SOURCE_DIR}/microtune_xxxx.cc
${CMAKE_CURRENT_SOURCE_DIR}/ppio_ppdev.cc
${CMAKE_CURRENT_SOURCE_DIR}/gri_wavfile.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_pdu.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_stream_pdu_base.cc
)
########################################################################
@@ -59,6 +61,8 @@ install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/microtune_xxxx.h
${CMAKE_CURRENT_SOURCE_DIR}/ppio_ppdev.h
${CMAKE_CURRENT_SOURCE_DIR}/gri_wavfile.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_pdu.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_stream_pdu_base.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio
COMPONENT "core_devel"
)
@@ -86,9 +90,11 @@ set(gr_core_io_triple_threats
gr_file_source
gr_file_descriptor_sink
gr_file_descriptor_source
+ gr_message_debug
gr_message_sink
gr_message_source
gr_message_burst_source
+ gr_pdu_to_tagged_stream
microtune_xxxx_eval_board
microtune_4702_eval_board
microtune_4937_eval_board
@@ -99,6 +105,9 @@ set(gr_core_io_triple_threats
gr_wavfile_source
gr_wavfile_sink
gr_tagged_file_sink
+ gr_tagged_stream_to_pdu
+ gr_tuntap_pdu
+ gr_socket_pdu
)
foreach(file_tt ${gr_core_io_triple_threats})
diff --git a/gnuradio-core/src/lib/io/gr_file_sink.cc b/gnuradio-core/src/lib/io/gr_file_sink.cc
index 5d147fcfea..10c8360cb6 100644
--- a/gnuradio-core/src/lib/io/gr_file_sink.cc
+++ b/gnuradio-core/src/lib/io/gr_file_sink.cc
@@ -42,8 +42,6 @@ gr_file_sink::gr_file_sink(size_t itemsize, const char *filename)
gr_file_sink_base(filename, true),
d_itemsize(itemsize)
{
- if (!open(filename))
- throw std::runtime_error ("can't open file");
}
gr_file_sink::~gr_file_sink ()
@@ -55,23 +53,32 @@ gr_file_sink::work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- char *inbuf = (char *) input_items[0];
+ char *inbuf = (char*)input_items[0];
int nwritten = 0;
do_update(); // update d_fp is reqd
- if (!d_fp)
+ if(!d_fp)
return noutput_items; // drop output on the floor
- while (nwritten < noutput_items){
- int count = fwrite (inbuf, d_itemsize, noutput_items - nwritten, d_fp);
- if (count == 0) // FIXME add error handling
- break;
+ while(nwritten < noutput_items) {
+ int count = fwrite(inbuf, d_itemsize, noutput_items - nwritten, d_fp);
+ if(count == 0) {
+ if(ferror(d_fp)) {
+ std::stringstream s;
+ s << "file_sink write failed with error " << fileno(d_fp) << std::endl;
+ throw std::runtime_error(s.str());
+ }
+ else { // is EOF
+ break;
+ }
+ }
nwritten += count;
inbuf += count * d_itemsize;
}
- if (d_unbuffered)
- fflush (d_fp);
+
+ if(d_unbuffered)
+ fflush (d_fp);
return nwritten;
}
diff --git a/gnuradio-core/src/lib/io/gr_file_sink_base.cc b/gnuradio-core/src/lib/io/gr_file_sink_base.cc
index cb67bbb6cf..4eecf928ee 100644
--- a/gnuradio-core/src/lib/io/gr_file_sink_base.cc
+++ b/gnuradio-core/src/lib/io/gr_file_sink_base.cc
@@ -126,5 +126,5 @@ gr_file_sink_base::do_update()
void
gr_file_sink_base::set_unbuffered(bool unbuffered)
{
- d_unbuffered = unbuffered;
+ d_unbuffered = unbuffered;
}
diff --git a/gnuradio-core/src/lib/io/gr_file_source.cc b/gnuradio-core/src/lib/io/gr_file_source.cc
index 3f06a82449..09f3986cd2 100644
--- a/gnuradio-core/src/lib/io/gr_file_source.cc
+++ b/gnuradio-core/src/lib/io/gr_file_source.cc
@@ -49,24 +49,14 @@
#define OUR_O_LARGEFILE 0
#endif
-gr_file_source::gr_file_source (size_t itemsize, const char *filename, bool repeat)
- : gr_sync_block ("file_source",
- gr_make_io_signature (0, 0, 0),
- gr_make_io_signature (1, 1, itemsize)),
- d_itemsize (itemsize), d_fp (0), d_repeat (repeat)
+gr_file_source::gr_file_source(size_t itemsize, const char *filename, bool repeat)
+ : gr_sync_block("file_source",
+ gr_make_io_signature (0, 0, 0),
+ gr_make_io_signature (1, 1, itemsize)),
+ d_itemsize(itemsize), d_fp(0), d_new_fp (0), d_repeat(repeat),
+ d_updated(false)
{
- // we use "open" to use to the O_LARGEFILE flag
-
- int fd;
- if ((fd = open (filename, O_RDONLY | OUR_O_LARGEFILE | OUR_O_BINARY)) < 0){
- perror (filename);
- throw std::runtime_error ("can't open file");
- }
-
- if ((d_fp = fdopen (fd, "rb")) == NULL){
- perror (filename);
- throw std::runtime_error ("can't open file");
- }
+ open(filename, repeat);
}
// public constructor that returns a shared_ptr
@@ -79,7 +69,11 @@ gr_make_file_source (size_t itemsize, const char *filename, bool repeat)
gr_file_source::~gr_file_source ()
{
- fclose ((FILE *) d_fp);
+ close();
+ if(d_fp) {
+ fclose(d_fp);
+ d_fp = 0;
+ }
}
int
@@ -91,6 +85,11 @@ gr_file_source::work (int noutput_items,
int i;
int size = noutput_items;
+ do_update(); // update d_fp is reqd
+ if(d_fp == NULL)
+ throw std::runtime_error("work with file not open");
+
+ boost::mutex::scoped_lock lock(fp_mutex); // hold for the rest of this function
while (size) {
i = fread(o, d_itemsize, size, (FILE *) d_fp);
@@ -111,8 +110,9 @@ gr_file_source::work (int noutput_items,
break;
if (fseek ((FILE *) d_fp, 0, SEEK_SET) == -1) {
- fprintf(stderr, "[%s] fseek failed\n", __FILE__);
- exit(-1);
+ std::stringstream s;
+ s << "[" << __FILE__ << "]" << " fseek failed" << std::endl;
+ throw std::runtime_error(s.str());
}
}
@@ -128,5 +128,64 @@ gr_file_source::work (int noutput_items,
bool
gr_file_source::seek (long seek_point, int whence)
{
- return fseek ((FILE *) d_fp, seek_point * d_itemsize, whence) == 0;
+ // obtain exclusive access for duration of this function
+ boost::mutex::scoped_lock lock(fp_mutex);
+ return fseek((FILE *) d_fp, seek_point * d_itemsize, whence) == 0;
+}
+
+void
+gr_file_source::open(const char *filename, bool repeat)
+{
+ // obtain exclusive access for duration of this function
+ boost::mutex::scoped_lock lock(fp_mutex);
+
+ int fd;
+
+ // we use "open" to use to the O_LARGEFILE flag
+ if((fd = ::open(filename, O_RDONLY | OUR_O_LARGEFILE | OUR_O_BINARY)) < 0) {
+ perror(filename);
+ throw std::runtime_error("can't open file");
+ }
+
+ if(d_new_fp) {
+ fclose(d_new_fp);
+ d_new_fp = 0;
+ }
+
+ if((d_new_fp = fdopen (fd, "rb")) == NULL) {
+ perror(filename);
+ ::close(fd); // don't leak file descriptor if fdopen fails
+ throw std::runtime_error("can't open file");
+ }
+
+ d_updated = true;
+ d_repeat = repeat;
+}
+
+void
+gr_file_source::close()
+{
+ // obtain exclusive access for duration of this function
+ boost::mutex::scoped_lock lock(fp_mutex);
+
+ if(d_new_fp != NULL) {
+ fclose(d_new_fp);
+ d_new_fp = NULL;
+ }
+ d_updated = true;
+}
+
+void
+gr_file_source::do_update()
+{
+ if(d_updated) {
+ boost::mutex::scoped_lock lock(fp_mutex); // hold while in scope
+
+ if(d_fp)
+ fclose(d_fp);
+
+ d_fp = d_new_fp; // install new file pointer
+ d_new_fp = 0;
+ d_updated = false;
+ }
}
diff --git a/gnuradio-core/src/lib/io/gr_file_source.h b/gnuradio-core/src/lib/io/gr_file_source.h
index 1cc44a3b1f..0478fba04b 100644
--- a/gnuradio-core/src/lib/io/gr_file_source.h
+++ b/gnuradio-core/src/lib/io/gr_file_source.h
@@ -25,6 +25,7 @@
#include <gr_core_api.h>
#include <gr_sync_block.h>
+#include <boost/thread/mutex.hpp>
class gr_file_source;
typedef boost::shared_ptr<gr_file_source> gr_file_source_sptr;
@@ -39,31 +40,68 @@ gr_make_file_source (size_t itemsize, const char *filename, bool repeat = false)
class GR_CORE_API gr_file_source : public gr_sync_block
{
- friend GR_CORE_API gr_file_source_sptr gr_make_file_source (size_t itemsize,
- const char *filename,
- bool repeat);
private:
- size_t d_itemsize;
- void *d_fp;
- bool d_repeat;
+ size_t d_itemsize;
+ FILE *d_fp;
+ FILE *d_new_fp;
+ bool d_repeat;
+ bool d_updated;
protected:
- gr_file_source (size_t itemsize, const char *filename, bool repeat);
+ gr_file_source(size_t itemsize, const char *filename, bool repeat);
+
+ void do_update();
+
+ boost::mutex fp_mutex;
public:
- ~gr_file_source ();
+ /*!
+ * \brief Create a file source.
+ *
+ * Opens \p filename as a source of items into a flowgraph. The data
+ * is expected to be in binary format, item after item. The \p
+ * itemsize of the block determines the conversion from bits to
+ * items.
+ *
+ * If \p repeat is turned on, the file will repeat the file after
+ * it's reached the end.
+ *
+ * \param itemsize the size of each item in the file, in bytes
+ * \param filename name of the file to source from
+ * \param repeat repeat file from start
+ */
+ friend GR_CORE_API gr_file_source_sptr
+ gr_make_file_source(size_t itemsize,
+ const char *filename,
+ bool repeat);
+
+ ~gr_file_source();
- int work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
/*!
- * \brief seek file to \p seek_point relative to \p whence
+ * \brief Seek file to \p seek_point relative to \p whence
*
* \param seek_point sample offset in file
* \param whence one of SEEK_SET, SEEK_CUR, SEEK_END (man fseek)
*/
- bool seek (long seek_point, int whence);
+ bool seek(long seek_point, int whence);
+
+ /*!
+ * \brief Opens a new file.
+ *
+ * \param filename name of the file to source from
+ * \param repeat repeat file from start
+ */
+ void open(const char *filename, bool repeat);
+
+ /*!
+ * \brief Close the file handle.
+ */
+ void close();
+
};
#endif /* INCLUDED_GR_FILE_SOURCE_H */
diff --git a/gnuradio-core/src/lib/io/gr_file_source.i b/gnuradio-core/src/lib/io/gr_file_source.i
index 9bf44691d0..e71cef0d14 100644
--- a/gnuradio-core/src/lib/io/gr_file_source.i
+++ b/gnuradio-core/src/lib/io/gr_file_source.i
@@ -40,4 +40,6 @@ class gr_file_source : public gr_sync_block
~gr_file_source ();
bool seek (long seek_point, int whence);
+ void open (const char *filename, bool repeat);
+ void close();
};
diff --git a/gnuradio-core/src/lib/io/gr_message_debug.cc b/gnuradio-core/src/lib/io/gr_message_debug.cc
new file mode 100644
index 0000000000..27f4c65fdc
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_message_debug.cc
@@ -0,0 +1,117 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2010,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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_message_debug.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <string.h>
+#include <iostream>
+
+// public constructor that returns a shared_ptr
+
+gr_message_debug_sptr
+gr_make_message_debug ()
+{
+ return gnuradio::get_initial_sptr(new gr_message_debug());
+}
+
+void
+gr_message_debug::print(pmt::pmt_t msg)
+{
+ std::cout << "******* MESSAGE DEBUG PRINT ********\n";
+ pmt::pmt_print(msg);
+ std::cout << "************************************\n";
+}
+
+void
+gr_message_debug::store(pmt::pmt_t msg)
+{
+ gruel::scoped_lock guard(d_mutex);
+ d_messages.push_back(msg);
+}
+
+void
+gr_message_debug::print_verbose(pmt::pmt_t msg)
+{
+ pmt::pmt_t meta = pmt::pmt_car(msg);
+ pmt::pmt_t vector = pmt::pmt_cdr(msg);
+ std::cout << "* MESSAGE DEBUG PRINT PDU VERBOSE *\n";
+ pmt::pmt_print(meta);
+ size_t len = pmt::pmt_length(vector);
+ std::cout << "pdu_length = " << len << std::endl;
+ std::cout << "contents = " << std::endl;
+ size_t offset(0);
+ const uint8_t* d = (const uint8_t*) pmt_uniform_vector_elements(vector, offset);
+ for(size_t i=0; i<len; i+=16){
+ printf("%04x: ", i);
+ for(size_t j=i; j<std::min(i+16,len); j++){
+ printf("%02x ",d[j] );
+ }
+
+ std::cout << std::endl;
+ }
+
+ std::cout << "***********************************\n";
+}
+
+int
+gr_message_debug::num_messages()
+{
+ return (int)d_messages.size();
+}
+
+pmt::pmt_t
+gr_message_debug::get_message(int i)
+{
+ gruel::scoped_lock guard(d_mutex);
+
+ if((size_t)i >= d_messages.size()) {
+ throw std::runtime_error("gr_message_debug: index for message out of bounds.\n");
+ }
+
+ return d_messages[i];
+}
+
+gr_message_debug::gr_message_debug()
+ : gr_block("message_debug",
+ gr_make_io_signature(0, 0, 0),
+ gr_make_io_signature(0, 0, 0))
+{
+ message_port_register_in(pmt::mp("print"));
+ set_msg_handler(pmt::mp("print"), boost::bind(&gr_message_debug::print, this, _1));
+
+ message_port_register_in(pmt::mp("store"));
+ set_msg_handler(pmt::mp("store"), boost::bind(&gr_message_debug::store, this, _1));
+}
+
+gr_message_debug::~gr_message_debug()
+{
+}
diff --git a/gnuradio-core/src/lib/io/gr_message_debug.h b/gnuradio-core/src/lib/io/gr_message_debug.h
new file mode 100644
index 0000000000..6e6e5103cb
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_message_debug.h
@@ -0,0 +1,103 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,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.
+ */
+
+#ifndef INCLUDED_GR_MESSAGE_DEBUG_H
+#define INCLUDED_GR_MESSAGE_DEBUG_H
+
+#include <gr_core_api.h>
+#include <gr_block.h>
+#include <gr_message.h>
+#include <gr_msg_queue.h>
+#include <gruel/thread.h>
+
+class gr_message_debug;
+typedef boost::shared_ptr<gr_message_debug> gr_message_debug_sptr;
+
+GR_CORE_API gr_message_debug_sptr gr_make_message_debug();
+
+/*!
+ * \brief Print received messages to stdout
+ * \ingroup sink_blk
+ */
+class GR_CORE_API gr_message_debug : public gr_block
+{
+ private:
+ friend GR_CORE_API gr_message_debug_sptr
+ gr_make_message_debug();
+
+ /*!
+ * \brief Messages received in this port are printed to stdout.
+ *
+ * This port receives messages from the scheduler's message handling
+ * mechanism and prints it to stdout. This message handler function
+ * is only meant to be used by the scheduler to handle messages
+ * posted to port 'print'.
+ *
+ * \param msg A pmt message passed from the scheduler's message handling.
+ */
+ void print(pmt::pmt_t msg);
+ void print_verbose(pmt::pmt_t msg);
+
+ /*!
+ * \brief Messages received in this port are stored in a vector.
+ *
+ * This port receives messages from the scheduler's message handling
+ * mechanism and stores it in a vector. Messages can be retrieved
+ * later using the 'get_message' function. This message handler
+ * function is only meant to be used by the scheduler to handle
+ * messages posted to port 'store'.
+ *
+ * \param msg A pmt message passed from the scheduler's message handling.
+ */
+ void store(pmt::pmt_t msg);
+
+ gruel::mutex d_mutex;
+ std::vector<pmt::pmt_t> d_messages;
+
+ protected:
+ gr_message_debug ();
+
+ public:
+ ~gr_message_debug ();
+
+ /*!
+ * \brief Reports the number of messages received by this block.
+ */
+ int num_messages();
+
+ /*!
+ * \brief Get a message (as a PMT) from the message vector at index \p i.
+ *
+ * Messages passed to the 'store' port will be stored in a
+ * vector. This function retrieves those messages by index. They are
+ * index in order of when they were received (all messages are just
+ * pushed onto the back of a vector). This is mostly useful in
+ * debugging message passing graphs and in QA code.
+ *
+ * \param i The index in the vector for the message to retrieve.
+ *
+ * \return a message at index \p i as a pmt_t.
+ */
+ pmt::pmt_t get_message(int i);
+};
+
+#endif /* INCLUDED_GR_MESSAGE_DEBUG_H */
diff --git a/gnuradio-core/src/lib/io/gr_message_debug.i b/gnuradio-core/src/lib/io/gr_message_debug.i
new file mode 100644
index 0000000000..65d3bfc4aa
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_message_debug.i
@@ -0,0 +1,30 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,message_debug);
+
+%{
+#include <gr_message_debug.h>
+%}
+
+%include "gr_message_debug.h"
+
diff --git a/gnuradio-core/src/lib/io/gr_pdu.cc b/gnuradio-core/src/lib/io/gr_pdu.cc
new file mode 100644
index 0000000000..b2757c307e
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_pdu.cc
@@ -0,0 +1,79 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_pdu.h>
+
+size_t
+gr_pdu_itemsize(gr_pdu_vector_type type){
+ switch(type){
+ case BYTE:
+ return 1;
+ case FLOAT:
+ return sizeof(float);
+ case COMPLEX:
+ return sizeof(gr_complex);
+ default:
+ throw std::runtime_error("bad type!");
+ }
+}
+
+bool
+gr_pdu_type_matches(gr_pdu_vector_type type, pmt::pmt_t v){
+ switch(type){
+ case BYTE:
+ return pmt::pmt_is_u8vector(v);
+ case FLOAT:
+ return pmt::pmt_is_f32vector(v);
+ case COMPLEX:
+ return pmt::pmt_is_c32vector(v);
+ default:
+ throw std::runtime_error("bad type!");
+ }
+}
+
+pmt::pmt_t
+gr_pdu_make_vector(gr_pdu_vector_type type, const uint8_t* buf, size_t items){
+ switch(type){
+ case BYTE:
+ return pmt::pmt_init_u8vector(items, buf);
+ case FLOAT:
+ return pmt::pmt_init_f32vector(items, (const float*)buf);
+ case COMPLEX:
+ return pmt::pmt_init_c32vector(items, (const gr_complex*)buf);
+ default:
+ throw std::runtime_error("bad type!");
+ }
+}
+
+gr_pdu_vector_type type_from_pmt(pmt::pmt_t vector){
+ if(pmt_is_u8vector(vector))
+ return BYTE;
+ if(pmt_is_f32vector(vector))
+ return FLOAT;
+ if(pmt_is_c32vector(vector))
+ return COMPLEX;
+ throw std::runtime_error("bad type!");
+}
diff --git a/gnuradio-core/src/lib/io/gr_pdu.h b/gnuradio-core/src/lib/io/gr_pdu.h
new file mode 100644
index 0000000000..5ed9cdded8
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_pdu.h
@@ -0,0 +1,39 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifndef GR_PDU_H
+#define GR_PDU_H
+
+#include <gr_complex.h>
+#include <gruel/pmt.h>
+
+#define pdu_port_id pmt::mp("pdus")
+#define pdu_length_tag pmt::mp("pdu_length")
+
+enum gr_pdu_vector_type { BYTE, FLOAT, COMPLEX };
+
+size_t gr_pdu_itemsize(gr_pdu_vector_type type);
+bool gr_pdu_type_matches(gr_pdu_vector_type type, pmt::pmt_t v);
+pmt::pmt_t gr_pdu_make_vector(gr_pdu_vector_type type, const uint8_t* buf, size_t items);
+gr_pdu_vector_type type_from_pmt(pmt::pmt_t vector);
+
+#endif
diff --git a/gnuradio-core/src/lib/io/gr_pdu.i b/gnuradio-core/src/lib/io/gr_pdu.i
new file mode 100644
index 0000000000..7cb3c62c78
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_pdu.i
@@ -0,0 +1,30 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005 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.
+ */
+
+%{
+#include <gr_pdu.h>
+%}
+
+enum gr_pdu_vector_type { BYTE, FLOAT, COMPLEX };
+
+
+
diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc
new file mode 100644
index 0000000000..5c319dc39d
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc
@@ -0,0 +1,132 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_pdu_to_tagged_stream.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <string.h>
+
+
+// public constructor that returns a shared_ptr
+
+gr_pdu_to_tagged_stream_sptr
+gr_make_pdu_to_tagged_stream(gr_pdu_vector_type t)
+{
+ return gnuradio::get_initial_sptr(new gr_pdu_to_tagged_stream(t));
+}
+
+gr_pdu_to_tagged_stream::gr_pdu_to_tagged_stream (gr_pdu_vector_type t)
+ : gr_sync_block("pdu_to_tagged_stream",
+ gr_make_io_signature(0, 0, 0),
+ gr_make_io_signature(1, 1, gr_pdu_itemsize(t))),
+ d_vectortype(t), d_itemsize(gr_pdu_itemsize(t))
+{
+ message_port_register_in(pdu_port_id);
+}
+
+gr_pdu_to_tagged_stream::~gr_pdu_to_tagged_stream()
+{
+}
+
+int
+gr_pdu_to_tagged_stream::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ char *out = (char *) output_items[0];
+ int nout = 0;
+
+ // if we have remaining output, send it
+ if(d_remain.size() > 0){
+ nout = std::min((size_t)d_remain.size()/d_itemsize, (size_t)noutput_items);
+ memcpy(out, &d_remain[0], nout*d_itemsize);
+ d_remain.erase( d_remain.begin(), d_remain.begin()+nout);
+ noutput_items -= nout;
+ out += nout*d_itemsize;
+ }
+
+ // if we have space for at least one item output as much as we can
+ if(noutput_items > 0){
+
+ // grab a message if one exists
+ //pmt::pmt_t msg( delete_head_nowait( pdu_port_id ) );
+ pmt::pmt_t msg( delete_head_blocking( pdu_port_id ) );
+ if(msg.get() == NULL ){
+ return nout;
+ }
+
+ // make sure type is valid
+ if(!pmt::pmt_is_pair(msg)){
+ throw std::runtime_error("received a malformed pdu message!");
+ }
+
+// printf("got a msg\n");
+// pmt::pmt_print(msg);
+
+ // grab the components of the pdu message
+ pmt::pmt_t meta(pmt::pmt_car(msg)); // make sure this is NIL || Dict ?
+ pmt::pmt_t vect(pmt::pmt_cdr(msg)); // make sure this is a vector?
+
+ // compute offset for output tag
+ uint64_t offset = nitems_written(0) + nout;
+
+ // add a tag for pdu length
+ add_item_tag(0, offset, pdu_length_tag, pmt::pmt_from_long( pmt::pmt_length(vect) ), pmt::mp(alias()));
+
+ // if we recieved metadata add it as tags
+ if( !pmt_eq(meta, pmt::PMT_NIL) ){
+ pmt::pmt_t pair(pmt::pmt_dict_keys( meta ));
+ while( !pmt_eq(pair, pmt::PMT_NIL) ){
+ pmt::pmt_t k(pmt::pmt_cdr(pair));
+ pmt::pmt_t v(pmt::pmt_dict_ref(meta, k, pmt::PMT_NIL));
+ add_item_tag(0, offset, k, v, pmt::mp(alias()));
+ }
+ }
+
+ // copy vector output
+ size_t ncopy = std::min((size_t)noutput_items, (size_t)pmt::pmt_length(vect));
+ size_t nsave = pmt::pmt_length(vect) - ncopy;
+
+ // copy output
+ size_t io(0);
+ nout += ncopy;
+ memcpy(out, pmt_uniform_vector_elements(vect,io), ncopy*d_itemsize);
+
+ // save leftover items if needed for next work call
+ if(nsave > 0){
+ d_remain.resize(nsave*d_itemsize, 0);
+ memcpy(&d_remain[0], pmt_uniform_vector_elements(vect,ncopy), nsave*d_itemsize);
+ }
+
+ }
+
+ return nout;
+}
diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h
new file mode 100644
index 0000000000..3105a3d386
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h
@@ -0,0 +1,63 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifndef INCLUDED_GR_PDU_TO_TAGGED_STREAM_H
+#define INCLUDED_GR_PDU_TO_TAGGED_STREAM_H
+
+#include <gr_core_api.h>
+#include <gr_sync_block.h>
+#include <gr_message.h>
+#include <gr_msg_queue.h>
+#include <gr_pdu.h>
+
+class gr_pdu_to_tagged_stream;
+typedef boost::shared_ptr<gr_pdu_to_tagged_stream> gr_pdu_to_tagged_stream_sptr;
+
+GR_CORE_API gr_pdu_to_tagged_stream_sptr gr_make_pdu_to_tagged_stream (gr_pdu_vector_type t);
+
+/*!
+ * \brief Turn received messages into a stream
+ * \ingroup source_blk
+ */
+class GR_CORE_API gr_pdu_to_tagged_stream : public gr_sync_block
+{
+ private:
+ gr_pdu_vector_type d_vectortype;
+ size_t d_itemsize;
+ std::vector<uint8_t> d_remain;
+
+ friend GR_CORE_API gr_pdu_to_tagged_stream_sptr
+ gr_make_pdu_to_tagged_stream(gr_pdu_vector_type t);
+
+ protected:
+ gr_pdu_to_tagged_stream (gr_pdu_vector_type t);
+
+ public:
+ ~gr_pdu_to_tagged_stream ();
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+};
+
+#endif /* INCLUDED_GR_PDU_TO_TAGGED_SOURCE_H */
diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i
new file mode 100644
index 0000000000..ec760b309a
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i
@@ -0,0 +1,31 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,pdu_to_tagged_stream);
+
+%{
+#include <gr_pdu_to_tagged_stream.h>
+%}
+
+%include <gr_pdu_to_tagged_stream.h>
+
+
diff --git a/gnuradio-core/src/lib/io/gr_socket_pdu.cc b/gnuradio-core/src/lib/io/gr_socket_pdu.cc
new file mode 100644
index 0000000000..bb374b3006
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_socket_pdu.cc
@@ -0,0 +1,157 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_socket_pdu.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <string.h>
+#include <iostream>
+#include <gr_pdu.h>
+#include <boost/format.hpp>
+
+// public constructor that returns a shared_ptr
+gr_socket_pdu_sptr
+gr_make_socket_pdu (std::string type, std::string addr, std::string port, int MTU)
+{
+ return gnuradio::get_initial_sptr(new gr_socket_pdu(type,addr,port,MTU));
+}
+
+gr_socket_pdu::gr_socket_pdu (std::string type, std::string addr, std::string port, int MTU)
+ : gr_stream_pdu_base(MTU)
+{
+
+ if( (type == "TCP_SERVER") || (type == "TCP_CLIENT")){
+ boost::asio::ip::tcp::resolver resolver(_io_service);
+ boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), addr, port);
+ _tcp_endpoint = *resolver.resolve(query);
+ }
+ if( (type == "UDP_SERVER") || (type == "UDP_CLIENT")){
+ boost::asio::ip::udp::resolver resolver(_io_service);
+ boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port);
+ if( (type == "UDP_SERVER") ){
+ _udp_endpoint = *resolver.resolve(query);
+ } else {
+ _udp_endpoint_other = *resolver.resolve(query);
+ }
+ }
+
+ // register ports
+ message_port_register_out(pmt::mp("pdus"));
+ message_port_register_in(pmt::mp("pdus"));
+
+ // set up socketry
+ if (type == "TCP_SERVER"){
+ _acceptor_tcp.reset(new boost::asio::ip::tcp::acceptor(_io_service, _tcp_endpoint));
+ _acceptor_tcp->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ start_tcp_accept();
+ // bind tcp server send handler
+ set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::tcp_server_send, this, _1));
+ } else if(type =="TCP_CLIENT"){
+ boost::system::error_code error = boost::asio::error::host_not_found;
+ _tcp_socket.reset(new boost::asio::ip::tcp::socket(_io_service));
+ _tcp_socket->connect(_tcp_endpoint, error);
+ if(error){
+ throw boost::system::system_error(error);
+ }
+ set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::tcp_client_send, this, _1));
+ _tcp_socket->async_read_some(
+ boost::asio::buffer(rxbuf),
+ boost::bind(&gr_socket_pdu::handle_tcp_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
+
+ } else if(type =="UDP_SERVER"){
+ _udp_socket.reset(new boost::asio::ip::udp::socket(_io_service, _udp_endpoint));
+ _udp_socket->async_receive_from( boost::asio::buffer(rxbuf), _udp_endpoint_other,
+ boost::bind(&gr_socket_pdu::handle_udp_read, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::udp_send, this, _1));
+ } else if(type =="UDP_CLIENT"){
+ _udp_socket.reset(new boost::asio::ip::udp::socket(_io_service, _udp_endpoint));
+ _udp_socket->async_receive_from( boost::asio::buffer(rxbuf), _udp_endpoint_other,
+ boost::bind(&gr_socket_pdu::handle_udp_read, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::udp_send, this, _1));
+ } else {
+ throw std::runtime_error("unknown socket type!");
+ }
+
+ // start thread for io_service
+ d_thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&gr_socket_pdu::run_io_service, this)));
+ d_started = true;
+}
+
+void tcp_connection::handle_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred)
+ {
+ if(!error)
+ {
+ pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&buf[0]);
+ pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector);
+
+ d_block->message_port_pub( pmt::mp("pdus"), pdu );
+
+ socket_.async_read_some(
+ boost::asio::buffer(buf),
+ boost::bind(&tcp_connection::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
+
+ } else {
+ std::cout << "error occurred\n";
+ }
+
+ }
+
+
+void gr_socket_pdu::tcp_server_send(pmt::pmt_t msg){
+ pmt::pmt_t vector = pmt::pmt_cdr(msg);
+ for(size_t i=0; i<d_tcp_connections.size(); i++){
+ d_tcp_connections[i]->send(vector);
+ }
+}
+
+void gr_socket_pdu::tcp_client_send(pmt::pmt_t msg){
+ pmt::pmt_t vector = pmt::pmt_cdr(msg);
+ size_t len = pmt::pmt_length(vector);
+ size_t offset(0);
+ boost::array<char, 10000> txbuf;
+ memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len);
+ _tcp_socket->send(boost::asio::buffer(txbuf,len));
+}
+
+void gr_socket_pdu::udp_send(pmt::pmt_t msg){
+ pmt::pmt_t vector = pmt::pmt_cdr(msg);
+ size_t len = pmt::pmt_length(vector);
+ size_t offset(0);
+ boost::array<char, 10000> txbuf;
+ memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len);
+ if(_udp_endpoint_other.address().to_string() != "0.0.0.0")
+ _udp_socket->send_to(boost::asio::buffer(txbuf,len), _udp_endpoint_other);
+}
diff --git a/gnuradio-core/src/lib/io/gr_socket_pdu.h b/gnuradio-core/src/lib/io/gr_socket_pdu.h
new file mode 100644
index 0000000000..f554febdc1
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_socket_pdu.h
@@ -0,0 +1,201 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifndef INCLUDED_GR_SOCKET_PDU_H
+#define INCLUDED_GR_SOCKET_PDU_H
+
+#include <gr_core_api.h>
+#include <gr_sync_block.h>
+#include <gr_message.h>
+#include <gr_msg_queue.h>
+#include <gr_stream_pdu_base.h>
+#include <boost/asio.hpp>
+
+class gr_socket_pdu;
+typedef boost::shared_ptr<gr_socket_pdu> gr_socket_pdu_sptr;
+
+GR_CORE_API gr_socket_pdu_sptr gr_make_socket_pdu (std::string type, std::string addr, std::string port, int MTU=10000);
+
+class tcp_connection
+ : public boost::enable_shared_from_this<tcp_connection>
+{
+public:
+ typedef boost::shared_ptr<tcp_connection> pointer;
+ gr_socket_pdu *d_block;
+ boost::array<char, 10000> buf;
+
+ static pointer create(boost::asio::io_service& io_service)
+ {
+ return pointer(new tcp_connection(io_service));
+ }
+
+ boost::asio::ip::tcp::socket& socket()
+ {
+ return socket_;
+ }
+
+ void start(gr_socket_pdu* parent)
+ {
+ d_block = parent;
+// message_ = "connected to gr_socket_pdu\n";
+// boost::asio::async_write(socket_, boost::asio::buffer(message_),
+// boost::bind(&tcp_connection::handle_write, shared_from_this(),
+// boost::asio::placeholders::error,
+// boost::asio::placeholders::bytes_transferred));
+
+ socket_.async_read_some(
+ boost::asio::buffer(buf),
+ boost::bind(&tcp_connection::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
+ }
+ void send(pmt::pmt_t vector){
+ size_t len = pmt::pmt_length(vector);
+ size_t offset(0);
+ boost::array<char, 10000> txbuf;
+ memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len);
+ boost::asio::async_write(socket_, boost::asio::buffer(txbuf, len),
+ boost::bind(&tcp_connection::handle_write, shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+
+ ~tcp_connection(){
+// std::cout << "tcp_connection destroyed\n";
+ }
+
+private:
+ tcp_connection(boost::asio::io_service& io_service)
+ : socket_(io_service)
+ {
+ }
+
+ void handle_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred);
+
+ void handle_write(const boost::system::error_code& /*error*/,
+ size_t /*bytes_transferred*/)
+ {
+ }
+
+ boost::asio::ip::tcp::socket socket_;
+ std::string message_;
+};
+
+
+/*!
+ * \brief Gather received items into messages and insert into msgq
+ * \ingroup sink_blk
+ */
+class GR_CORE_API gr_socket_pdu : public gr_stream_pdu_base
+{
+ private:
+ friend GR_CORE_API gr_socket_pdu_sptr
+ gr_make_socket_pdu(std::string type, std::string addr, std::string port, int MTU);
+
+ boost::asio::io_service _io_service;
+
+ boost::array<char, 10000> rxbuf;
+
+ // tcp specific
+ boost::asio::ip::tcp::endpoint _tcp_endpoint;
+
+ // specific to tcp server
+ boost::shared_ptr<boost::asio::ip::tcp::acceptor> _acceptor_tcp;
+ std::vector<tcp_connection::pointer> d_tcp_connections;
+ void tcp_server_send(pmt::pmt_t msg);
+ void tcp_client_send(pmt::pmt_t msg);
+ void udp_send(pmt::pmt_t msg);
+
+ // specific to tcp client
+ boost::shared_ptr<boost::asio::ip::tcp::socket> _tcp_socket;
+
+ // specific to udp client/server
+ boost::asio::ip::udp::endpoint _udp_endpoint;
+ boost::asio::ip::udp::endpoint _udp_endpoint_other;
+ boost::shared_ptr<boost::asio::ip::udp::socket> _udp_socket;
+
+ void handle_receive(const boost::system::error_code& error, std::size_t ){
+ }
+
+ void start_tcp_accept(){
+ tcp_connection::pointer new_connection =
+ tcp_connection::create(_acceptor_tcp->get_io_service());
+
+ _acceptor_tcp->async_accept(new_connection->socket(),
+ boost::bind(&gr_socket_pdu::handle_tcp_accept, this, new_connection,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_tcp_accept(tcp_connection::pointer new_connection, const boost::system::error_code& error){
+ if (!error)
+ {
+ new_connection->start(this);
+ d_tcp_connections.push_back(new_connection);
+ start_tcp_accept();
+ } else {
+ std::cout << error << std::endl;
+ }
+ }
+
+ void run_io_service(){
+ _io_service.run();
+ }
+
+ void handle_udp_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred){
+ if(!error){
+ pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&rxbuf[0]);
+ pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector);
+
+ message_port_pub( pmt::mp("pdus"), pdu );
+
+ _udp_socket->async_receive_from( boost::asio::buffer(rxbuf), _udp_endpoint_other,
+ boost::bind(&gr_socket_pdu::handle_udp_read, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ } else {
+ throw boost::system::system_error(error);
+// std::cout << "error occurred\n";
+ }
+ }
+ void handle_tcp_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred){
+ if(!error)
+ {
+ pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&rxbuf[0]);
+ pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector);
+
+ message_port_pub( pmt::mp("pdus"), pdu );
+
+ _tcp_socket->async_read_some(
+ boost::asio::buffer(rxbuf),
+ boost::bind(&gr_socket_pdu::handle_tcp_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
+
+ } else {
+ //std::cout << "error occurred\n";
+ throw boost::system::system_error(error);
+ }
+ }
+
+ protected:
+ gr_socket_pdu (std::string type, std::string addr, std::string port, int MTU=10000);
+ public:
+ ~gr_socket_pdu () {}
+};
+
+#endif /* INCLUDED_GR_TUNTAP_PDU_H */
diff --git a/gnuradio-core/src/lib/io/gr_socket_pdu.i b/gnuradio-core/src/lib/io/gr_socket_pdu.i
new file mode 100644
index 0000000000..3e20b63e20
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_socket_pdu.i
@@ -0,0 +1,33 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,socket_pdu);
+
+%ignore tcp_connection;
+
+%{
+#include <gr_socket_pdu.h>
+%}
+
+%include "gr_stream_pdu_base.h"
+%include "gr_socket_pdu.h"
+
diff --git a/gnuradio-core/src/lib/io/gr_stream_pdu_base.cc b/gnuradio-core/src/lib/io/gr_stream_pdu_base.cc
new file mode 100644
index 0000000000..cff7296cba
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_stream_pdu_base.cc
@@ -0,0 +1,117 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_stream_pdu_base.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <string.h>
+#include <iostream>
+#include <gr_pdu.h>
+#include <boost/format.hpp>
+
+static const long timeout_us = 100*1000; //100ms
+
+gr_stream_pdu_base::gr_stream_pdu_base (int MTU)
+ : gr_sync_block("stream_pdu_base",
+ gr_make_io_signature(0, 0, 0),
+ gr_make_io_signature(0, 0, 0)),
+ d_finished(false), d_started(false), d_fd(-1)
+{
+ // reserve space for rx buffer
+ d_rxbuf.resize(MTU,0);
+}
+
+gr_stream_pdu_base::~gr_stream_pdu_base()
+{
+ stop_rxthread();
+}
+
+void gr_stream_pdu_base::stop_rxthread(){
+ d_finished = true;
+ if(d_started){
+ d_thread->interrupt();
+ d_thread->join();
+ }
+ }
+
+void gr_stream_pdu_base::start_rxthread(pmt::pmt_t _rxport){
+ rxport = _rxport;
+ d_thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&gr_stream_pdu_base::run, this)));
+ d_started = true;
+ }
+
+void gr_stream_pdu_base::run(){
+ while(!d_finished) {
+ if(not wait_ready()){ continue; }
+ const int result = read( d_fd, &d_rxbuf[0], d_rxbuf.size() );
+ if(result <= 0){ throw std::runtime_error("gr_stream_pdu_base, bad socket read!"); }
+ pmt::pmt_t vector = pmt::pmt_init_u8vector(result, &d_rxbuf[0]);
+ pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector);
+ message_port_pub(rxport, pdu);
+ }
+}
+
+void gr_stream_pdu_base::send(pmt::pmt_t msg){
+ pmt::pmt_t vector = pmt::pmt_cdr(msg);
+ size_t offset(0);
+ size_t itemsize(gr_pdu_itemsize(type_from_pmt(vector)));
+ int len( pmt::pmt_length(vector)*itemsize );
+
+ const int rv = write(d_fd, pmt::pmt_uniform_vector_elements(vector, offset), len);
+ if(rv != len){
+ std::cerr << boost::format("WARNING: gr_stream_pdu_base::send(pdu) write failed! (d_fd=%d, len=%d, rv=%d)")
+ % d_fd % len % rv << std::endl;
+ }
+}
+
+int
+gr_stream_pdu_base::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ throw std::runtime_error("should not be called.\n");
+ return 0;
+}
+
+bool gr_stream_pdu_base::wait_ready(){
+ //setup timeval for timeout
+ timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = timeout_us;
+
+ //setup rset for timeout
+ fd_set rset;
+ FD_ZERO(&rset);
+ FD_SET(d_fd, &rset);
+
+ //call select with timeout on receive socket
+ return ::select(d_fd+1, &rset, NULL, NULL, &tv) > 0;
+}
diff --git a/gnuradio-core/src/lib/io/gr_stream_pdu_base.h b/gnuradio-core/src/lib/io/gr_stream_pdu_base.h
new file mode 100644
index 0000000000..35bacf523f
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_stream_pdu_base.h
@@ -0,0 +1,59 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifndef INCLUDED_GR_STREAM_PDU_BASE_H
+#define INCLUDED_GR_STREAM_PDU_BASE_H
+
+#include <gr_core_api.h>
+#include <gr_sync_block.h>
+#include <gr_message.h>
+#include <gr_msg_queue.h>
+
+/*!
+ * \brief Gather received items into messages and insert into msgq
+ * \ingroup sink_blk
+ */
+class GR_CORE_API gr_stream_pdu_base : public gr_sync_block
+{
+ public:
+ boost::shared_ptr<boost::thread> d_thread;
+ bool d_finished;
+ bool d_started;
+ std::vector<uint8_t> d_rxbuf;
+ void run();
+ int d_fd;
+ gr_stream_pdu_base (int MTU=10000);
+ ~gr_stream_pdu_base ();
+ void send(pmt::pmt_t msg);
+ bool wait_ready();
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ void start_rxthread(pmt::pmt_t _rxport);
+ void stop_rxthread();
+ private:
+ pmt::pmt_t rxport;
+};
+
+typedef boost::shared_ptr<gr_stream_pdu_base> gr_stream_pdu_base_sptr;
+
+#endif /* INCLUDED_GR_TUNTAP_PDU_H */
diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc
new file mode 100644
index 0000000000..8211b7672d
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc
@@ -0,0 +1,137 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_tagged_stream_to_pdu.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <string.h>
+
+// public constructor that returns a shared_ptr
+
+gr_tagged_stream_to_pdu_sptr
+gr_make_tagged_stream_to_pdu(gr_pdu_vector_type t)
+{
+ return gnuradio::get_initial_sptr(new gr_tagged_stream_to_pdu(t));
+}
+
+gr_tagged_stream_to_pdu::gr_tagged_stream_to_pdu (gr_pdu_vector_type t)
+ : gr_sync_block("tagged_stream_to_pdu",
+ gr_make_io_signature(1, 1, gr_pdu_itemsize(t)),
+ gr_make_io_signature(0, 0, 0)),
+ d_vectortype(t), d_itemsize(gr_pdu_itemsize(t)), d_inpdu(false),
+ d_pdu_meta(pmt::PMT_NIL), d_pdu_vector(pmt::PMT_NIL)
+{
+ message_port_register_out(pdu_port_id);
+}
+
+gr_tagged_stream_to_pdu::~gr_tagged_stream_to_pdu()
+{
+ printf("destructor running\n");
+}
+
+int
+gr_tagged_stream_to_pdu::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const uint8_t *in = (const uint8_t*) input_items[0];
+ uint64_t abs_N = nitems_read(0);
+
+ // if we are not in a pdu already, start a new one
+ if(!d_inpdu){
+ get_tags_in_range(d_tags, 0, abs_N, abs_N+1);
+ bool found_length_tag(false);
+ for(d_tags_itr = d_tags.begin(); (d_tags_itr != d_tags.end()) && (!found_length_tag); d_tags_itr++){
+ if( pmt::pmt_equal( (*d_tags_itr).key, pdu_length_tag ) ){
+ if( (*d_tags_itr).offset != abs_N ){
+ throw std::runtime_error("expected next pdu length tag on a different item...");
+ }
+ found_length_tag = true;
+ d_pdu_length = pmt::pmt_to_long( (*d_tags_itr).value );
+ d_pdu_remain = d_pdu_length;
+ d_pdu_meta = pmt::pmt_make_dict();
+ break;
+ } // if have length tag
+ } // iter over tags
+ if(!found_length_tag){
+ throw std::runtime_error("tagged stream does not contain a pdu_length tag!");
+ }
+ }
+
+ size_t ncopy = std::min((size_t)noutput_items, d_pdu_remain);
+
+ // copy any tags in this range into our meta object
+ get_tags_in_range(d_tags, 0, abs_N, abs_N+ncopy);
+ for(d_tags_itr = d_tags.begin(); d_tags_itr != d_tags.end(); d_tags_itr++){
+ if( ! pmt_equal( (*d_tags_itr).key, pdu_length_tag ) ){
+ d_pdu_meta = pmt_dict_add(d_pdu_meta, (*d_tags_itr).key, (*d_tags_itr).value);
+ }
+ }
+
+ // copy samples for this vector into either a pmt or our save buffer
+ if(ncopy == d_pdu_remain){ // we will send this pdu
+ if(d_save.size() == 0){
+ d_pdu_vector = gr_pdu_make_vector(d_vectortype, in, ncopy);
+ send_message();
+ } else {
+ size_t oldsize = d_save.size();
+ d_save.resize((oldsize + ncopy)*d_itemsize, 0);
+ memcpy( &d_save[oldsize*d_itemsize], in, ncopy*d_itemsize );
+ d_pdu_vector = gr_pdu_make_vector(d_vectortype, &d_save[0], d_pdu_length);
+ send_message();
+ d_save.clear();
+ }
+ } else {
+ d_inpdu = true;
+ size_t oldsize = d_save.size();
+ d_save.resize( (oldsize+ncopy)*d_itemsize );
+ memcpy( &d_save[oldsize*d_itemsize], in, ncopy*d_itemsize );
+ d_pdu_remain -= ncopy;
+ }
+
+ return ncopy;
+}
+
+void gr_tagged_stream_to_pdu::send_message(){
+
+ if(pmt::pmt_length(d_pdu_vector) != d_pdu_length){
+ throw std::runtime_error("msg length not correct");
+ }
+
+ pmt::pmt_t msg = pmt::pmt_cons( d_pdu_meta, d_pdu_vector );
+ message_port_pub( pdu_port_id, msg );
+
+ d_pdu_meta = pmt::PMT_NIL;
+ d_pdu_vector = pmt::PMT_NIL;
+ d_pdu_length = 0;
+ d_pdu_remain = 0;
+ d_inpdu = false;
+}
diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h
new file mode 100644
index 0000000000..c3fff35815
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h
@@ -0,0 +1,76 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifndef INCLUDED_GR_TAGGED_STREAM_TO_PDU_H
+#define INCLUDED_GR_TAGGED_STREAM_TO_PDU_H
+
+#include <gr_core_api.h>
+#include <gr_sync_block.h>
+#include <gr_message.h>
+#include <gr_msg_queue.h>
+#include <gr_pdu.h>
+
+class gr_tagged_stream_to_pdu;
+typedef boost::shared_ptr<gr_tagged_stream_to_pdu> gr_tagged_stream_to_pdu_sptr;
+
+GR_CORE_API gr_tagged_stream_to_pdu_sptr gr_make_tagged_stream_to_pdu (gr_pdu_vector_type t);
+
+/*!
+ * \brief Turn received messages into a stream
+ * \ingroup source_blk
+ */
+class GR_CORE_API gr_tagged_stream_to_pdu : public gr_sync_block
+{
+ private:
+ gr_pdu_vector_type d_vectortype;
+ size_t d_itemsize;
+
+ std::vector<uint8_t> d_save;
+
+ std::vector<gr_tag_t> d_tags;
+ std::vector<gr_tag_t>::iterator d_tags_itr;
+
+ bool d_inpdu;
+
+ size_t d_pdu_length;
+ size_t d_pdu_remain;
+ pmt::pmt_t d_pdu_meta;
+ pmt::pmt_t d_pdu_vector;
+
+ friend GR_CORE_API gr_tagged_stream_to_pdu_sptr
+ gr_make_tagged_stream_to_pdu(gr_pdu_vector_type t);
+
+ protected:
+ gr_tagged_stream_to_pdu (gr_pdu_vector_type t);
+
+ public:
+ ~gr_tagged_stream_to_pdu ();
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ void send_message();
+
+};
+
+#endif /* INCLUDED_GR_PDU_TO_TAGGED_SOURCE_H */
diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i
new file mode 100644
index 0000000000..f12987b74c
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i
@@ -0,0 +1,31 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,tagged_stream_to_pdu);
+
+%{
+#include <gr_tagged_stream_to_pdu.h>
+%}
+
+%include <gr_tagged_stream_to_pdu.h>
+
+
diff --git a/gnuradio-core/src/lib/io/gr_tuntap_pdu.cc b/gnuradio-core/src/lib/io/gr_tuntap_pdu.cc
new file mode 100644
index 0000000000..8dd4b18a10
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_tuntap_pdu.cc
@@ -0,0 +1,145 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_tuntap_pdu.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <string.h>
+#include <iostream>
+#include <gr_pdu.h>
+#include <boost/format.hpp>
+
+#if (defined(linux) || defined(__linux) || defined(__linux__))
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <arpa/inet.h>
+#include <linux/if.h>
+
+
+// public constructor that returns a shared_ptr
+
+gr_tuntap_pdu_sptr
+gr_make_tuntap_pdu (std::string dev, int MTU)
+{
+ return gnuradio::get_initial_sptr(new gr_tuntap_pdu(dev, MTU));
+}
+
+gr_tuntap_pdu::gr_tuntap_pdu (std::string dev, int MTU)
+ : gr_stream_pdu_base(MTU)
+{
+
+ // make the tuntap
+ char dev_cstr[1024];
+ memset(dev_cstr, 0x00, 1024);
+ strncpy(dev_cstr, dev.c_str(), std::min(sizeof(dev_cstr), dev.size()));
+ d_fd = tun_alloc(dev_cstr);
+ if(d_fd <= 0){
+ throw std::runtime_error("TunTap make: tun_alloc failed (are you running as root?)");
+ }
+
+ std::cout << boost::format(
+ "Allocated virtual ethernet interface: %s\n"
+ "You must now use ifconfig to set its IP address. E.g.,\n"
+ " $ sudo ifconfig %s 192.168.200.1\n"
+ "Be sure to use a different address in the same subnet for each machine.\n"
+ ) % dev % dev << std::endl;
+
+ // set up output message port
+ message_port_register_out(pmt::mp("pdus"));
+ start_rxthread(pmt::mp("pdus"));
+
+ // set up input message port
+ message_port_register_in(pmt::mp("pdus"));
+ set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_tuntap_pdu::send, this, _1));
+}
+
+
+int gr_tuntap_pdu::tun_alloc(char *dev, int flags) {
+ struct ifreq ifr;
+ int fd, err;
+ const char *clonedev = "/dev/net/tun";
+
+ /* Arguments taken by the function:
+ *
+ * char *dev: the name of an interface (or '\0'). MUST have enough
+ * space to hold the interface name if '\0' is passed
+ * int flags: interface flags (eg, IFF_TUN etc.)
+ */
+
+ /* open the clone device */
+ if( (fd = open(clonedev, O_RDWR)) < 0 ) {
+ return fd;
+ }
+
+ /* preparation of the struct ifr, of type "struct ifreq" */
+ memset(&ifr, 0, sizeof(ifr));
+
+ ifr.ifr_flags = flags; /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */
+
+ if (*dev) {
+ /* if a device name was specified, put it in the structure; otherwise,
+ * the kernel will try to allocate the "next" device of the
+ * specified type */
+ strncpy(ifr.ifr_name, dev, IFNAMSIZ);
+ }
+
+ /* try to create the device */
+ if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
+ close(fd);
+ return err;
+ }
+
+ /* if the operation was successful, write back the name of the
+ * interface to the variable "dev", so the caller can know
+ * it. Note that the caller MUST reserve space in *dev (see calling
+ * code below) */
+ strcpy(dev, ifr.ifr_name);
+
+ /* this is the special file descriptor that the caller will use to talk
+ * with the virtual interface */
+ return fd;
+}
+
+#else //if not linux
+
+gr_block_sptr
+gr_make_tuntap_pdu(std::string dev, int MTU)
+{
+ gr_block_sptr rv;
+ throw std::runtime_error("tuntap only implemented on linux");
+ return rv;
+}
+
+#endif
diff --git a/gnuradio-core/src/lib/io/gr_tuntap_pdu.h b/gnuradio-core/src/lib/io/gr_tuntap_pdu.h
new file mode 100644
index 0000000000..18c83f42b2
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_tuntap_pdu.h
@@ -0,0 +1,74 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifndef INCLUDED_GR_TUNTAP_PDU_H
+#define INCLUDED_GR_TUNTAP_PDU_H
+
+#include <gr_core_api.h>
+#include <gr_sync_block.h>
+#include <gr_message.h>
+#include <gr_msg_queue.h>
+#include <gr_stream_pdu_base.h>
+
+#if (defined(linux) || defined(__linux) || defined(__linux__))
+
+#include <linux/if_tun.h>
+
+class gr_tuntap_pdu;
+typedef boost::shared_ptr<gr_tuntap_pdu> gr_tuntap_pdu_sptr;
+
+GR_CORE_API gr_tuntap_pdu_sptr gr_make_tuntap_pdu (std::string dev, int MTU=10000);
+
+/*!
+ * \brief Gather received items into messages and insert into msgq
+ * \ingroup sink_blk
+ */
+class GR_CORE_API gr_tuntap_pdu : public gr_stream_pdu_base
+{
+ private:
+ friend GR_CORE_API gr_tuntap_pdu_sptr
+ gr_make_tuntap_pdu(std::string dev, int MTU);
+ int tun_alloc(char* dev, int flags = IFF_TAP | IFF_NO_PI);
+ std::string d_dev;
+ protected:
+ gr_tuntap_pdu (std::string dev, int MTU=10000);
+
+ public:
+ ~gr_tuntap_pdu () {}
+
+};
+
+#else // if not linux
+
+class gr_tuntap_pdu
+{
+private:
+ gr_tuntap_pdu() {};
+public:
+ ~gr_tuntap_pdu() {};
+};
+
+GR_CORE_API gr_block_sptr gr_make_tuntap_pdu (std::string dev, int MTU=0);
+
+#endif
+
+#endif /* INCLUDED_GR_TUNTAP_PDU_H */
diff --git a/gnuradio-core/src/lib/io/gr_tuntap_pdu.i b/gnuradio-core/src/lib/io/gr_tuntap_pdu.i
new file mode 100644
index 0000000000..589bbc3853
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_tuntap_pdu.i
@@ -0,0 +1,30 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,tuntap_pdu);
+
+%{
+#include <gr_tuntap_pdu.h>
+%}
+
+%include "gr_tuntap_pdu.h"
+
diff --git a/gnuradio-core/src/lib/io/io.i b/gnuradio-core/src/lib/io/io.i
index 07f2e9195e..055f288474 100644
--- a/gnuradio-core/src/lib/io/io.i
+++ b/gnuradio-core/src/lib/io/io.i
@@ -46,6 +46,12 @@
#include <gr_wavfile_sink.h>
#include <gr_wavfile_source.h>
#include <gr_tagged_file_sink.h>
+#include <gr_pdu_to_tagged_stream.h>
+#include <gr_tagged_stream_to_pdu.h>
+#include <gr_message_debug.h>
+#include <gr_pdu.h>
+#include <gr_tuntap_pdu.h>
+#include <gr_socket_pdu.h>
%}
%include "gr_file_sink_base.i"
@@ -69,4 +75,11 @@
%include "gr_wavfile_sink.i"
%include "gr_wavfile_source.i"
%include "gr_tagged_file_sink.i"
+%include "gr_pdu_to_tagged_stream.i"
+%include "gr_tagged_stream_to_pdu.i"
+%include "gr_message_debug.i"
+%include "gr_pdu.i"
+%include "gr_tuntap_pdu.i"
+%include "gr_socket_pdu.i"
+
diff --git a/gnuradio-core/src/lib/runtime/CMakeLists.txt b/gnuradio-core/src/lib/runtime/CMakeLists.txt
index 5f3672dde9..70938a0f17 100644
--- a/gnuradio-core/src/lib/runtime/CMakeLists.txt
+++ b/gnuradio-core/src/lib/runtime/CMakeLists.txt
@@ -54,6 +54,7 @@ list(APPEND gnuradio_core_sources
${CMAKE_CURRENT_SOURCE_DIR}/gr_block.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_block_detail.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_block_executor.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_block_registry.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2_detail.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_buffer.cc
@@ -116,6 +117,7 @@ install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/gr_block.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_block_detail.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_block_executor.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_block_registry.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2_detail.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_buffer.h
diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.cc b/gnuradio-core/src/lib/runtime/gr_basic_block.cc
index 3d809aa8b7..6ff57a1d6c 100644
--- a/gnuradio-core/src/lib/runtime/gr_basic_block.cc
+++ b/gnuradio-core/src/lib/runtime/gr_basic_block.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -25,7 +25,10 @@
#endif
#include <gr_basic_block.h>
+#include <gr_block_registry.h>
#include <stdexcept>
+#include <sstream>
+#include <iostream>
using namespace pmt;
@@ -35,7 +38,7 @@ static long s_ncurrently_allocated = 0;
long
gr_basic_block_ncurrently_allocated()
{
- return s_ncurrently_allocated;
+ return s_ncurrently_allocated;
}
gr_basic_block::gr_basic_block(const std::string &name,
@@ -45,20 +48,180 @@ gr_basic_block::gr_basic_block(const std::string &name,
d_input_signature(input_signature),
d_output_signature(output_signature),
d_unique_id(s_next_id++),
+ d_symbolic_id(global_block_registry.block_register(this)),
+ d_symbol_name(global_block_registry.register_symbolic_name(this)),
d_color(WHITE),
- d_max_output_buffer(std::max(output_signature->max_streams(),1), -1),
- d_min_output_buffer(std::max(output_signature->max_streams(),1), -1)
+ message_subscribers(pmt::pmt_make_dict())
{
- s_ncurrently_allocated++;
+ s_ncurrently_allocated++;
}
gr_basic_block::~gr_basic_block()
{
- s_ncurrently_allocated--;
+ s_ncurrently_allocated--;
+ global_block_registry.block_unregister(this);
}
gr_basic_block_sptr
gr_basic_block::to_basic_block()
{
- return shared_from_this();
+ return shared_from_this();
+}
+
+void
+gr_basic_block::set_block_alias(std::string name)
+{
+ global_block_registry.register_symbolic_name(this, name);
+}
+
+// ** Message passing interface **
+
+// - register a new input message port
+void
+gr_basic_block::message_port_register_in(pmt::pmt_t port_id)
+{
+ if(!pmt::pmt_is_symbol(port_id)) {
+ throw std::runtime_error("message_port_register_in: bad port id");
+ }
+ msg_queue[port_id] = msg_queue_t();
+ msg_queue_ready[port_id] = boost::shared_ptr<boost::condition_variable>(new boost::condition_variable());
+}
+
+pmt::pmt_t
+gr_basic_block::message_ports_in()
+{
+ pmt::pmt_t port_names = pmt::pmt_make_vector(msg_queue.size(), pmt::PMT_NIL);
+ msg_queue_map_itr itr = msg_queue.begin();
+ for(size_t i = 0; i < msg_queue.size(); i++) {
+ pmt::pmt_vector_set(port_names, i, (*itr).first);
+ itr++;
+ }
+ return port_names;
+}
+
+// - register a new output message port
+void
+gr_basic_block::message_port_register_out(pmt::pmt_t port_id)
+{
+ if(!pmt::pmt_is_symbol(port_id)) {
+ throw std::runtime_error("message_port_register_out: bad port id");
+ }
+ if(pmt::pmt_dict_has_key(message_subscribers, port_id)) {
+ throw std::runtime_error("message_port_register_out: port already in use");
+ }
+ message_subscribers = pmt::pmt_dict_add(message_subscribers, port_id, pmt::PMT_NIL);
+}
+
+pmt::pmt_t
+gr_basic_block::message_ports_out()
+{
+ size_t len = pmt::pmt_length(message_subscribers);
+ pmt::pmt_t port_names = pmt::pmt_make_vector(len, pmt::PMT_NIL);
+ pmt::pmt_t keys = pmt::pmt_dict_keys(message_subscribers);
+ for(size_t i = 0; i < len; i++) {
+ pmt::pmt_vector_set(port_names, i, pmt::pmt_nth(i, keys));
+ }
+ return port_names;
+}
+
+// - publish a message on a message port
+void gr_basic_block::message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg)
+{
+ if(!pmt::pmt_dict_has_key(message_subscribers, port_id)) {
+ throw std::runtime_error("port does not exist");
+ }
+
+ pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers, port_id, pmt::PMT_NIL);
+ // iterate through subscribers on port
+ while(pmt::pmt_is_pair(currlist)) {
+ pmt::pmt_t target = pmt::pmt_car(currlist);
+
+ pmt::pmt_t block = pmt::pmt_car(target);
+ pmt::pmt_t port = pmt::pmt_cdr(target);
+
+ currlist = pmt::pmt_cdr(currlist);
+ gr_basic_block_sptr blk = global_block_registry.block_lookup(block);
+ //blk->post(msg);
+ blk->post(port, msg);
+ }
+}
+
+// - subscribe to a message port
+void
+gr_basic_block::message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target){
+ if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){
+ std::stringstream ss;
+ ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) << "\" on block: " << pmt::pmt_write_string(target) << std::endl;
+ throw std::runtime_error(ss.str());
+ }
+ pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL);
+
+ // ignore re-adds of the same target
+ if(!pmt::pmt_list_has(currlist, target))
+ message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_add(currlist,target));
+}
+
+void
+gr_basic_block::message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target){
+ if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){
+ std::stringstream ss;
+ ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) << "\" on block: " << pmt::pmt_write_string(target) << std::endl;
+ throw std::runtime_error(ss.str());
+ }
+
+ // ignore unsubs of unknown targets
+ pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL);
+ message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_rm(currlist,target));
+}
+
+void
+gr_basic_block::_post(pmt_t which_port, pmt_t msg)
+{
+ insert_tail(which_port, msg);
+}
+
+void
+gr_basic_block::insert_tail(pmt::pmt_t which_port, pmt::pmt_t msg)
+{
+ gruel::scoped_lock guard(mutex);
+
+ if( (msg_queue.find(which_port) == msg_queue.end()) || (msg_queue_ready.find(which_port) == msg_queue_ready.end())){
+ std::cout << "target port = " << pmt::pmt_symbol_to_string(which_port) << std::endl;
+ throw std::runtime_error("attempted to insert_tail on invalid queue!");
+ }
+
+ msg_queue[which_port].push_back(msg);
+ msg_queue_ready[which_port]->notify_one();
+
+ // wake up thread if BLKD_IN or BLKD_OUT
+ global_block_registry.notify_blk(alias());
+}
+
+pmt_t
+gr_basic_block::delete_head_nowait(pmt::pmt_t which_port)
+{
+ gruel::scoped_lock guard(mutex);
+
+ if (empty_p(which_port)){
+ return pmt::pmt_t();
+ }
+
+ pmt_t m(msg_queue[which_port].front());
+ msg_queue[which_port].pop_front();
+
+ return m;
+}
+
+pmt_t
+gr_basic_block::delete_head_blocking(pmt::pmt_t which_port)
+{
+ gruel::scoped_lock guard(mutex);
+
+ while (empty_p(which_port)){
+ msg_queue_ready[which_port]->wait(guard);
+ }
+
+ pmt_t m(msg_queue[which_port].front());
+ msg_queue[which_port].pop_front();
+ return m;
}
diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.h b/gnuradio-core/src/lib/runtime/gr_basic_block.h
index b8e8148b23..f3b7b835b4 100644
--- a/gnuradio-core/src/lib/runtime/gr_basic_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_basic_block.h
@@ -29,8 +29,13 @@
#include <boost/enable_shared_from_this.hpp>
#include <boost/function.hpp>
#include <gr_msg_accepter.h>
-#include <gr_io_signature.h>
#include <string>
+#include <deque>
+#include <map>
+#include <gr_io_signature.h>
+#include <gruel/thread.h>
+#include <boost/foreach.hpp>
+#include <boost/thread/condition_variable.hpp>
#include <iostream>
/*!
@@ -46,183 +51,215 @@
class GR_CORE_API gr_basic_block : public gr_msg_accepter, public boost::enable_shared_from_this<gr_basic_block>
{
- typedef boost::function<void(pmt::pmt_t)> msg_handler_t;
-
-private:
- /*
- * This function is called by the runtime system to dispatch messages.
- *
- * The thread-safety guarantees mentioned in set_msg_handler are implemented
- * by the callers of this method.
- */
- void dispatch_msg(pmt::pmt_t msg)
- {
- if (d_msg_handler) // Is there a handler?
- d_msg_handler(msg); // Yes, invoke it.
- };
-
- msg_handler_t d_msg_handler;
-
- /*
- * Used to expand the vectors that hold the min/max buffer sizes.
- *
- * Specifically, when -1 is used, the vectors are just initialized
- * with 1 value; this is used by the flat_flowgraph to expand when
- * required to add a new value for new ports on these blocks.
- */
- void expand_minmax_buffer(int port) {
- if((size_t)port >= d_max_output_buffer.size())
- set_max_output_buffer(port, -1);
- if((size_t)port >= d_min_output_buffer.size())
- set_min_output_buffer(port, -1);
- }
-
-protected:
- friend class gr_flowgraph;
- friend class gr_flat_flowgraph; // TODO: will be redundant
- friend class gr_tpb_thread_body;
-
- enum vcolor { WHITE, GREY, BLACK };
-
- std::string d_name;
- gr_io_signature_sptr d_input_signature;
- gr_io_signature_sptr d_output_signature;
- long d_unique_id;
- vcolor d_color;
- std::vector<long> d_max_output_buffer;
- std::vector<long> d_min_output_buffer;
-
- gr_basic_block(void){} //allows pure virtual interface sub-classes
-
- //! Protected constructor prevents instantiation by non-derived classes
- gr_basic_block(const std::string &name,
- gr_io_signature_sptr input_signature,
- gr_io_signature_sptr output_signature);
-
- //! may only be called during constructor
- void set_input_signature(gr_io_signature_sptr iosig) {
- d_input_signature = iosig;
- }
-
- //! may only be called during constructor
- void set_output_signature(gr_io_signature_sptr iosig) {
- d_output_signature = iosig;
- }
+ typedef boost::function<void(pmt::pmt_t)> msg_handler_t;
+
+ private:
+ /*
+ * This function is called by the runtime system to dispatch messages.
+ *
+ * The thread-safety guarantees mentioned in set_msg_handler are implemented
+ * by the callers of this method.
+ */
+ void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg)
+ {
+ // AA Update this
+ if (d_msg_handlers.find(which_port) != d_msg_handlers.end()) // Is there a handler?
+ d_msg_handlers[which_port](msg); // Yes, invoke it.
+ };
+
+ //msg_handler_t d_msg_handler;
+ typedef std::map<pmt::pmt_t , msg_handler_t, pmt::pmt_comperator> d_msg_handlers_t;
+ d_msg_handlers_t d_msg_handlers;
+
+ typedef std::deque<pmt::pmt_t> msg_queue_t;
+ typedef std::map<pmt::pmt_t, msg_queue_t, pmt::pmt_comperator> msg_queue_map_t;
+ typedef std::map<pmt::pmt_t, msg_queue_t, pmt::pmt_comperator>::iterator msg_queue_map_itr;
+ std::map<pmt::pmt_t, boost::shared_ptr<boost::condition_variable>, pmt::pmt_comperator> msg_queue_ready;
+
+ gruel::mutex mutex; //< protects all vars
+
+ protected:
+ friend class gr_flowgraph;
+ friend class gr_flat_flowgraph; // TODO: will be redundant
+ friend class gr_tpb_thread_body;
+
+ enum vcolor { WHITE, GREY, BLACK };
+
+ std::string d_name;
+ gr_io_signature_sptr d_input_signature;
+ gr_io_signature_sptr d_output_signature;
+ long d_unique_id;
+ long d_symbolic_id;
+ std::string d_symbol_name;
+ std::string d_symbol_alias;
+ vcolor d_color;
+ msg_queue_map_t msg_queue;
+
+ gr_basic_block(void){} //allows pure virtual interface sub-classes
+
+ //! Protected constructor prevents instantiation by non-derived classes
+ gr_basic_block(const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature);
+
+ //! may only be called during constructor
+ void set_input_signature(gr_io_signature_sptr iosig) {
+ d_input_signature = iosig;
+ }
+
+ //! may only be called during constructor
+ void set_output_signature(gr_io_signature_sptr iosig) {
+ d_output_signature = iosig;
+ }
+
+ /*!
+ * \brief Allow the flowgraph to set for sorting and partitioning
+ */
+ void set_color(vcolor color) { d_color = color; }
+ vcolor color() const { return d_color; }
+
+ // Message passing interface
+ pmt::pmt_t message_subscribers;
+
+ public:
+ virtual ~gr_basic_block();
+ long unique_id() const { return d_unique_id; }
+ long symbolic_id() const { return d_symbolic_id; }
+ std::string name() const { return d_name; }
+ std::string symbol_name() const { return d_symbol_name; }
+ gr_io_signature_sptr input_signature() const { return d_input_signature; }
+ gr_io_signature_sptr output_signature() const { return d_output_signature; }
+ gr_basic_block_sptr to_basic_block(); // Needed for Python type coercion
+ bool alias_set() { return !d_symbol_alias.empty(); }
+ std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); }
+ pmt::pmt_t alias_pmt(){ return pmt::pmt_intern(alias()); }
+ void set_block_alias(std::string name);
+
+ // ** Message passing interface **
+ void message_port_register_in(pmt::pmt_t port_id);
+ void message_port_register_out(pmt::pmt_t port_id);
+ void message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg);
+ void message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target);
+ void message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target);
+
+ virtual bool message_port_is_hier(pmt::pmt_t port_id) { std::cout << "is_hier\n"; return false; }
+ virtual bool message_port_is_hier_in(pmt::pmt_t port_id) { std::cout << "is_hier_in\n"; return false; }
+ virtual bool message_port_is_hier_out(pmt::pmt_t port_id) { std::cout << "is_hier_out\n"; return false; }
+
+ /*!
+ * \brief Get input message port names.
+ *
+ * Returns the available input message ports for a block. The
+ * return object is a PMT vector that is filled with PMT symbols.
+ */
+ pmt::pmt_t message_ports_in();
+
+ /*!
+ * \brief Get output message port names.
+ *
+ * Returns the available output message ports for a block. The
+ * return object is a PMT vector that is filled with PMT symbols.
+ */
+ pmt::pmt_t message_ports_out();
+
+ /*!
+ * Accept msg, place in queue, arrange for thread to be awakened if it's not already.
+ */
+ void _post(pmt::pmt_t which_port, pmt::pmt_t msg);
+
+ //! is the queue empty?
+ //bool empty_p(const pmt::pmt_t &which_port) const { return msg_queue[which_port].empty(); }
+ bool empty_p(pmt::pmt_t which_port) {
+ if(msg_queue.find(which_port) == msg_queue.end())
+ throw std::runtime_error("port does not exist!");
+ return msg_queue[which_port].empty();
+ }
+ bool empty_p() {
+ bool rv = true;
+ BOOST_FOREACH(msg_queue_map_t::value_type &i, msg_queue){ rv &= msg_queue[i.first].empty(); }
+ return rv;
+ }
+
+ //| Acquires and release the mutex
+ void insert_tail( pmt::pmt_t which_port, pmt::pmt_t msg);
+ /*!
+ * \returns returns pmt at head of queue or pmt_t() if empty.
+ */
+ pmt::pmt_t delete_head_nowait( pmt::pmt_t which_port);
+
+ /*!
+ * \returns returns pmt at head of queue or pmt_t() if empty.
+ */
+ pmt::pmt_t delete_head_blocking( pmt::pmt_t which_port);
+
+ msg_queue_t::iterator get_iterator(pmt::pmt_t which_port){
+ return msg_queue[which_port].begin();
+ }
- /*!
- * \brief Allow the flowgraph to set for sorting and partitioning
- */
- void set_color(vcolor color) { d_color = color; }
- vcolor color() const { return d_color; }
-
-public:
- virtual ~gr_basic_block();
- long unique_id() const { return d_unique_id; }
- std::string name() const { return d_name; }
- gr_io_signature_sptr input_signature() const { return d_input_signature; }
- gr_io_signature_sptr output_signature() const { return d_output_signature; }
- gr_basic_block_sptr to_basic_block(); // Needed for Python type coercion
-
- /*!
- * \brief Returns max buffer size on output port \p i.
- */
- long max_output_buffer(size_t i) {
- if(i >= d_max_output_buffer.size())
- throw std::invalid_argument("gr_basic_block::max_output_buffer: port out of range.");
- return d_max_output_buffer[i];
- }
-
- /*!
- * \brief Sets max buffer size on all output ports.
- */
- void set_max_output_buffer(long max_output_buffer) {
- for(int i=0; i<output_signature()->max_streams(); i++) {
- set_max_output_buffer(i, max_output_buffer);
- }
- }
-
- /*!
- * \brief Sets max buffer size on output port \p port.
- */
- void set_max_output_buffer(int port, long max_output_buffer) {
- if((size_t)port >= d_max_output_buffer.size())
- d_max_output_buffer.push_back(max_output_buffer);
- else
- d_max_output_buffer[port] = max_output_buffer;
- }
-
- /*!
- * \brief Returns min buffer size on output port \p i.
- */
- long min_output_buffer(size_t i) {
- if(i >= d_min_output_buffer.size())
- throw std::invalid_argument("gr_basic_block::min_output_buffer: port out of range.");
- return d_min_output_buffer[i];
- }
-
- /*!
- * \brief Sets min buffer size on all output ports.
- */
- void set_min_output_buffer(long min_output_buffer) {
- for(int i=0; i<output_signature()->max_streams(); i++) {
- set_min_output_buffer(i, min_output_buffer);
- }
+ void erase_msg(pmt::pmt_t which_port, msg_queue_t::iterator it){
+ msg_queue[which_port].erase(it);
+ }
+
+ virtual bool has_msg_port(pmt::pmt_t which_port){
+ if(msg_queue.find(which_port) != msg_queue.end()){
+ return true;
}
-
- /*!
- * \brief Sets min buffer size on output port \p port.
- */
- void set_min_output_buffer(int port, long min_output_buffer) {
- if((size_t)port >= d_min_output_buffer.size())
- d_min_output_buffer.push_back(min_output_buffer);
- else
- d_min_output_buffer[port] = min_output_buffer;
- }
-
- /*!
- * \brief Confirm that ninputs and noutputs is an acceptable combination.
- *
- * \param ninputs number of input streams connected
- * \param noutputs number of output streams connected
- *
- * \returns true if this is a valid configuration for this block.
- *
- * This function is called by the runtime system whenever the
- * topology changes. Most classes do not need to override this.
- * This check is in addition to the constraints specified by the input
- * and output gr_io_signatures.
- */
- virtual bool check_topology(int ninputs, int noutputs) { return true; }
-
- /*!
- * \brief Set the callback that is fired when messages are available.
- *
- * \p msg_handler can be any kind of function pointer or function object
- * that has the signature:
- * <pre>
- * void msg_handler(pmt::pmt msg);
- * </pre>
- *
- * (You may want to use boost::bind to massage your callable into the
- * correct form. See gr_nop.{h,cc} for an example that sets up a class
- * method as the callback.)
- *
- * Blocks that desire to handle messages must call this method in their
- * constructors to register the handler that will be invoked when messages
- * are available.
- *
- * If the block inherits from gr_block, the runtime system will ensure that
- * msg_handler is called in a thread-safe manner, such that work and
- * msg_handler will never be called concurrently. This allows msg_handler
- * to update state variables without having to worry about thread-safety
- * issues with work, general_work or another invocation of msg_handler.
- *
- * If the block inherits from gr_hier_block2, the runtime system will
- * ensure that no reentrant calls are made to msg_handler.
- */
- template <typename T> void set_msg_handler(T msg_handler){
- d_msg_handler = msg_handler_t(msg_handler);
+ if(pmt::pmt_dict_has_key(message_subscribers, which_port)){
+ return true;
}
+ return false;
+ }
+
+
+ /*!
+ * \brief Confirm that ninputs and noutputs is an acceptable combination.
+ *
+ * \param ninputs number of input streams connected
+ * \param noutputs number of output streams connected
+ *
+ * \returns true if this is a valid configuration for this block.
+ *
+ * This function is called by the runtime system whenever the
+ * topology changes. Most classes do not need to override this.
+ * This check is in addition to the constraints specified by the input
+ * and output gr_io_signatures.
+ */
+ virtual bool check_topology(int ninputs, int noutputs) { return true; }
+
+ /*!
+ * \brief Set the callback that is fired when messages are available.
+ *
+ * \p msg_handler can be any kind of function pointer or function object
+ * that has the signature:
+ * <pre>
+ * void msg_handler(pmt::pmt msg);
+ * </pre>
+ *
+ * (You may want to use boost::bind to massage your callable into the
+ * correct form. See gr_nop.{h,cc} for an example that sets up a class
+ * method as the callback.)
+ *
+ * Blocks that desire to handle messages must call this method in their
+ * constructors to register the handler that will be invoked when messages
+ * are available.
+ *
+ * If the block inherits from gr_block, the runtime system will ensure that
+ * msg_handler is called in a thread-safe manner, such that work and
+ * msg_handler will never be called concurrently. This allows msg_handler
+ * to update state variables without having to worry about thread-safety
+ * issues with work, general_work or another invocation of msg_handler.
+ *
+ * If the block inherits from gr_hier_block2, the runtime system will
+ * ensure that no reentrant calls are made to msg_handler.
+ */
+ //template <typename T> void set_msg_handler(T msg_handler){
+ // d_msg_handler = msg_handler_t(msg_handler);
+ //}
+ template <typename T> void set_msg_handler(pmt::pmt_t which_port, T msg_handler){
+ if(msg_queue.find(which_port) == msg_queue.end()){
+ throw std::runtime_error("attempt to set_msg_handler() on bad input message port!"); }
+ d_msg_handlers[which_port] = msg_handler_t(msg_handler);
+ }
};
inline bool operator<(gr_basic_block_sptr lhs, gr_basic_block_sptr rhs)
@@ -237,8 +274,8 @@ GR_CORE_API long gr_basic_block_ncurrently_allocated();
inline std::ostream &operator << (std::ostream &os, gr_basic_block_sptr basic_block)
{
- os << basic_block->name() << "(" << basic_block->unique_id() << ")";
- return os;
+ os << basic_block->name() << "(" << basic_block->unique_id() << ")";
+ return os;
}
#endif /* INCLUDED_GR_BASIC_BLOCK_H */
diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.i b/gnuradio-core/src/lib/runtime/gr_basic_block.i
index 7713f2fe15..62f16462d6 100644
--- a/gnuradio-core/src/lib/runtime/gr_basic_block.i
+++ b/gnuradio-core/src/lib/runtime/gr_basic_block.i
@@ -23,6 +23,8 @@
class gr_basic_block;
typedef boost::shared_ptr<gr_basic_block> gr_basic_block_sptr;
%template(gr_basic_block_sptr) boost::shared_ptr<gr_basic_block>;
+%include "pmt_swig.i"
+using namespace pmt;
// support vectors of these...
namespace std {
@@ -37,17 +39,17 @@ protected:
public:
virtual ~gr_basic_block();
std::string name() const;
+ std::string symbol_name() const;
gr_io_signature_sptr input_signature() const;
gr_io_signature_sptr output_signature() const;
long unique_id() const;
gr_basic_block_sptr to_basic_block();
bool check_topology (int ninputs, int noutputs);
- long max_output_buffer(int i);
- void set_max_output_buffer(long max_output_buffer);
- void set_max_output_buffer(int port, long max_output_buffer);
- long min_output_buffer(int i);
- void set_min_output_buffer(long min_output_buffer);
- void set_min_output_buffer(int port, long min_output_buffer);
+ std::string alias();
+ void set_block_alias(std::string name);
+ void _post(pmt_t which_port, pmt_t msg);
+ pmt_t message_ports_in();
+ pmt_t message_ports_out();
};
%rename(block_ncurrently_allocated) gr_basic_block_ncurrently_allocated;
diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc
index 7e01c0ba89..43aebf0bfd 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block.cc
@@ -28,6 +28,7 @@
#include <gr_block_detail.h>
#include <stdexcept>
#include <iostream>
+#include <gr_block_registry.h>
gr_block::gr_block (const std::string &name,
gr_io_signature_sptr input_signature,
@@ -42,12 +43,16 @@ gr_block::gr_block (const std::string &name,
d_fixed_rate(false),
d_max_noutput_items_set(false),
d_max_noutput_items(0),
- d_tag_propagation_policy(TPP_ALL_TO_ALL)
+ d_tag_propagation_policy(TPP_ALL_TO_ALL),
+ d_max_output_buffer(std::max(output_signature->max_streams(),1), -1),
+ d_min_output_buffer(std::max(output_signature->max_streams(),1), -1)
{
+ global_block_registry.register_primitive(alias(), this);
}
gr_block::~gr_block ()
{
+ global_block_registry.unregister_primitive(alias());
}
// stub implementation: 1:1
@@ -246,3 +251,12 @@ operator << (std::ostream& os, const gr_block *m)
return os;
}
+int
+gr_block::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ throw std::runtime_error("gr_block::general_work() not implemented");
+ return 0;
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h
index c89138bb34..57e3fda90a 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_block.h
@@ -124,7 +124,7 @@ class GR_CORE_API gr_block : public gr_basic_block {
virtual int general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items) = 0;
+ gr_vector_void_star &output_items);
/*!
* \brief Called to enable drivers, etc for i/o devices.
@@ -288,6 +288,76 @@ class GR_CORE_API gr_block : public gr_basic_block {
*/
bool is_set_max_noutput_items();
+ /*
+ * Used to expand the vectors that hold the min/max buffer sizes.
+ *
+ * Specifically, when -1 is used, the vectors are just initialized
+ * with 1 value; this is used by the flat_flowgraph to expand when
+ * required to add a new value for new ports on these blocks.
+ */
+ void expand_minmax_buffer(int port) {
+ if((size_t)port >= d_max_output_buffer.size())
+ set_max_output_buffer(port, -1);
+ if((size_t)port >= d_min_output_buffer.size())
+ set_min_output_buffer(port, -1);
+ }
+
+ /*!
+ * \brief Returns max buffer size on output port \p i.
+ */
+ long max_output_buffer(size_t i) {
+ if(i >= d_max_output_buffer.size())
+ throw std::invalid_argument("gr_basic_block::max_output_buffer: port out of range.");
+ return d_max_output_buffer[i];
+ }
+
+ /*!
+ * \brief Sets max buffer size on all output ports.
+ */
+ void set_max_output_buffer(long max_output_buffer) {
+ for(int i = 0; i < output_signature()->max_streams(); i++) {
+ set_max_output_buffer(i, max_output_buffer);
+ }
+ }
+
+ /*!
+ * \brief Sets max buffer size on output port \p port.
+ */
+ void set_max_output_buffer(int port, long max_output_buffer) {
+ if((size_t)port >= d_max_output_buffer.size())
+ d_max_output_buffer.push_back(max_output_buffer);
+ else
+ d_max_output_buffer[port] = max_output_buffer;
+ }
+
+ /*!
+ * \brief Returns min buffer size on output port \p i.
+ */
+ long min_output_buffer(size_t i) {
+ if(i >= d_min_output_buffer.size())
+ throw std::invalid_argument("gr_basic_block::min_output_buffer: port out of range.");
+ return d_min_output_buffer[i];
+ }
+
+ /*!
+ * \brief Sets min buffer size on all output ports.
+ */
+ void set_min_output_buffer(long min_output_buffer) {
+ for(int i=0; i<output_signature()->max_streams(); i++) {
+ set_min_output_buffer(i, min_output_buffer);
+ }
+ }
+
+ /*!
+ * \brief Sets min buffer size on output port \p port.
+ */
+ void set_min_output_buffer(int port, long min_output_buffer) {
+ if((size_t)port >= d_min_output_buffer.size())
+ d_min_output_buffer.push_back(min_output_buffer);
+ else
+ d_min_output_buffer[port] = min_output_buffer;
+ }
+
// ----------------------------------------------------------------------------
private:
@@ -384,6 +454,10 @@ class GR_CORE_API gr_block : public gr_basic_block {
uint64_t abs_end,
const pmt::pmt_t &key);
+ std::vector<long> d_max_output_buffer;
+ std::vector<long> d_min_output_buffer;
+
+
// These are really only for internal use, but leaving them public avoids
// having to work up an ever-varying list of friend GR_CORE_APIs
diff --git a/gnuradio-core/src/lib/runtime/gr_block.i b/gnuradio-core/src/lib/runtime/gr_block.i
index e9341e8cbf..db6c1d04a7 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.i
+++ b/gnuradio-core/src/lib/runtime/gr_block.i
@@ -58,6 +58,14 @@ class gr_block : public gr_basic_block {
void unset_max_noutput_items();
bool is_set_max_noutput_items();
+ // Methods to manage block's min/max buffer sizes.
+ long max_output_buffer(int i);
+ void set_max_output_buffer(long max_output_buffer);
+ void set_max_output_buffer(int port, long max_output_buffer);
+ long min_output_buffer(int i);
+ void set_min_output_buffer(long min_output_buffer);
+ void set_min_output_buffer(int port, long min_output_buffer);
+
// internal use
gr_block_detail_sptr detail () const { return d_detail; }
void set_detail (gr_block_detail_sptr detail) { d_detail = detail; }
diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.cc b/gnuradio-core/src/lib/runtime/gr_block_detail.cc
index 2792cd4713..337c9518ef 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_detail.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block_detail.cc
@@ -127,12 +127,6 @@ gr_block_detail::produce_each (int how_many_items)
}
-void
-gr_block_detail::_post(pmt_t msg)
-{
- d_tpb.insert_tail(msg);
-}
-
uint64_t
gr_block_detail::nitems_read(unsigned int which_input)
{
diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.h b/gnuradio-core/src/lib/runtime/gr_block_detail.h
index c96f00db8b..16d9f4d42e 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_detail.h
+++ b/gnuradio-core/src/lib/runtime/gr_block_detail.h
@@ -85,11 +85,6 @@ class GR_CORE_API gr_block_detail {
*/
void produce_each (int how_many_items);
- /*!
- * Accept msg, place in queue, arrange for thread to be awakened if it's not already.
- */
- void _post(pmt::pmt_t msg);
-
// Return the number of items read on input stream which_input
uint64_t nitems_read(unsigned int which_input);
diff --git a/gnuradio-core/src/lib/runtime/gr_block_registry.cc b/gnuradio-core/src/lib/runtime/gr_block_registry.cc
new file mode 100644
index 0000000000..ff23d97eb2
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/gr_block_registry.cc
@@ -0,0 +1,76 @@
+#include <gr_basic_block.h>
+#include <gr_block_registry.h>
+#include <gr_tpb_detail.h>
+#include <gr_block_detail.h>
+#include <gr_block.h>
+#include <stdio.h>
+
+gr_block_registry global_block_registry;
+
+gr_block_registry::gr_block_registry(){
+ d_ref_map = pmt::pmt_make_dict();
+}
+
+long gr_block_registry::block_register(gr_basic_block* block){
+ if(d_map.find(block->name()) == d_map.end()){
+ d_map[block->name()] = blocksubmap_t();
+ d_map[block->name()][0] = block;
+ return 0;
+ } else {
+ for(size_t i=0; i<=d_map[block->name()].size(); i++){
+ if(d_map[block->name()].find(i) == d_map[block->name()].end()){
+ d_map[block->name()][i] = block;
+ return i;
+ }
+ }
+ }
+ throw std::runtime_error("should not reach this");
+}
+
+void gr_block_registry::block_unregister(gr_basic_block* block){
+ d_map[block->name()].erase( d_map[block->name()].find(block->symbolic_id()));
+ d_ref_map = pmt::pmt_dict_delete(d_ref_map, pmt::pmt_intern(block->symbol_name()));
+ if(block->alias_set()){
+ d_ref_map = pmt::pmt_dict_delete(d_ref_map, pmt::pmt_intern(block->alias()));
+ }
+}
+
+std::string gr_block_registry::register_symbolic_name(gr_basic_block* block){
+ std::stringstream ss;
+ ss << block->name() << block->symbolic_id();
+ //std::cout << "register_symbolic_name: " << ss.str() << std::endl;
+ register_symbolic_name(block, ss.str());
+ return ss.str();
+}
+
+void gr_block_registry::register_symbolic_name(gr_basic_block* block, std::string name){
+ if(pmt_dict_has_key(d_ref_map, pmt::pmt_intern(name))){
+ throw std::runtime_error("symbol already exists, can not re-use!");
+ }
+ d_ref_map = pmt_dict_add(d_ref_map, pmt::pmt_intern(name), pmt::pmt_make_any(block));
+}
+
+gr_basic_block_sptr gr_block_registry::block_lookup(pmt::pmt_t symbol){
+ pmt::pmt_t ref = pmt_dict_ref(d_ref_map, symbol, pmt::PMT_NIL);
+ if(pmt::pmt_eq(ref, pmt::PMT_NIL)){
+ throw std::runtime_error("block lookup failed! block not found!");
+ }
+ gr_basic_block* blk = boost::any_cast<gr_basic_block*>( pmt::pmt_any_ref(ref) );
+ return blk->shared_from_this();
+}
+
+
+void gr_block_registry::register_primitive(std::string blk, gr_block* ref){
+ primitive_map[blk] = ref;
+}
+
+void gr_block_registry::unregister_primitive(std::string blk){
+ primitive_map.erase(primitive_map.find(blk));
+}
+
+void gr_block_registry::notify_blk(std::string blk){
+ if(primitive_map.find(blk) == primitive_map.end()){ return; }
+ if(primitive_map[blk]->detail().get())
+ primitive_map[blk]->detail()->d_tpb.notify_msg();
+}
+
diff --git a/gnuradio-core/src/lib/runtime/gr_block_registry.h b/gnuradio-core/src/lib/runtime/gr_block_registry.h
new file mode 100644
index 0000000000..6a2d939e51
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/gr_block_registry.h
@@ -0,0 +1,42 @@
+#ifndef GR_BLOCK_REGISTRY_H
+#define GR_BLOCK_REGISTRY_H
+
+#include <map>
+
+#ifndef GR_BASIC_BLOCK_H
+class gr_basic_block;
+class gr_block;
+#endif
+
+class gr_block_registry {
+ public:
+ gr_block_registry();
+
+ long block_register(gr_basic_block* block);
+ void block_unregister(gr_basic_block* block);
+
+ std::string register_symbolic_name(gr_basic_block* block);
+ void register_symbolic_name(gr_basic_block* block, std::string name);
+
+ gr_basic_block_sptr block_lookup(pmt::pmt_t symbol);
+
+ void register_primitive(std::string blk, gr_block* ref);
+ void unregister_primitive(std::string blk);
+ void notify_blk(std::string blk);
+
+ private:
+
+ //typedef std::map< long, gr_basic_block_sptr > blocksubmap_t;
+ typedef std::map< long, gr_basic_block* > blocksubmap_t;
+ typedef std::map< std::string, blocksubmap_t > blockmap_t;
+
+ blockmap_t d_map;
+ pmt::pmt_t d_ref_map;
+ std::map< std::string, gr_block*> primitive_map;
+
+};
+
+extern gr_block_registry global_block_registry;
+
+#endif
+
diff --git a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
index b70135b854..9294a5dca2 100644
--- a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
+++ b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
@@ -31,8 +31,9 @@
#include <volk/volk.h>
#include <iostream>
#include <map>
+#include <boost/format.hpp>
-#define GR_FLAT_FLOWGRAPH_DEBUG 0
+#define GR_FLAT_FLOWGRAPH_DEBUG 0
// 32Kbyte buffer size between blocks
#define GR_FIXED_BUFFER_SIZE (32*(1L<<10))
@@ -71,6 +72,15 @@ gr_flat_flowgraph::setup_connections()
block->set_is_unaligned(false);
}
+ // Connect message ports connetions
+ for(gr_msg_edge_viter_t i = d_msg_edges.begin(); i != d_msg_edges.end(); i++){
+ if(GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << boost::format("flat_fg connecting msg primitives: (%s, %s)->(%s, %s)\n") %
+ i->src().block() % i->src().port() %
+ i->dst().block() % i->dst().port();
+ i->src().block()->message_port_sub( i->src().port(), pmt::pmt_cons(i->dst().block()->alias_pmt(), i->dst().port()) );
+ }
+
}
gr_block_detail_sptr
@@ -80,18 +90,23 @@ gr_flat_flowgraph::allocate_block_detail(gr_basic_block_sptr block)
int noutputs = calc_used_ports(block, false).size();
gr_block_detail_sptr detail = gr_make_block_detail(ninputs, noutputs);
+ gr_block_sptr grblock = cast_to_block_sptr(block);
+ if(!grblock)
+ throw std::runtime_error("allocate_block_detail found non-gr_block");
+
if (GR_FLAT_FLOWGRAPH_DEBUG)
std::cout << "Creating block detail for " << block << std::endl;
for (int i = 0; i < noutputs; i++) {
- block->expand_minmax_buffer(i);
+ grblock->expand_minmax_buffer(i);
+
gr_buffer_sptr buffer = allocate_buffer(block, i);
if (GR_FLAT_FLOWGRAPH_DEBUG)
std::cout << "Allocated buffer for output " << block << ":" << i << std::endl;
detail->set_output(i, buffer);
// Update the block's max_output_buffer based on what was actually allocated.
- block->set_max_output_buffer(i, buffer->bufsize());
+ grblock->set_max_output_buffer(i, buffer->bufsize());
}
return detail;
@@ -119,15 +134,15 @@ gr_flat_flowgraph::allocate_buffer(gr_basic_block_sptr block, int port)
gr_basic_block_vector_t blocks = calc_downstream_blocks(block, port);
// limit buffer size if indicated
- if(block->max_output_buffer(port) > 0) {
+ if(grblock->max_output_buffer(port) > 0) {
// std::cout << "constraining output items to " << block->max_output_buffer(port) << "\n";
- nitems = std::min((long)nitems, (long)block->max_output_buffer(port));
+ nitems = std::min((long)nitems, (long)grblock->max_output_buffer(port));
nitems -= nitems%grblock->output_multiple();
if( nitems < 1 )
throw std::runtime_error("problems allocating a buffer with the given max output buffer constraint!");
}
- else if(block->min_output_buffer(port) > 0) {
- nitems = std::max((long)nitems, (long)block->min_output_buffer(port));
+ else if(grblock->min_output_buffer(port) > 0) {
+ nitems = std::max((long)nitems, (long)grblock->min_output_buffer(port));
nitems -= nitems%grblock->output_multiple();
if( nitems < 1 )
throw std::runtime_error("problems allocating a buffer with the given min output buffer constraint!");
@@ -345,3 +360,44 @@ gr_flat_flowgraph::make_block_vector(gr_basic_block_vector_t &blocks)
return result;
}
+
+
+void gr_flat_flowgraph::clear_endpoint(const gr_msg_endpoint &e, bool is_src){
+ for(size_t i=0; i<d_msg_edges.size(); i++){
+ if(is_src){
+ if(d_msg_edges[i].src() == e){
+ d_msg_edges.erase(d_msg_edges.begin() + i);
+ i--;
+ }
+ } else {
+ if(d_msg_edges[i].dst() == e){
+ d_msg_edges.erase(d_msg_edges.begin() + i);
+ i--;
+ }
+ }
+ }
+}
+
+void gr_flat_flowgraph::replace_endpoint(const gr_msg_endpoint &e, const gr_msg_endpoint &r, bool is_src){
+ size_t n_replr(0);
+ if(GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << boost::format("gr_flat_flowgraph::replace_endpoint( %s, %s, %d )\n") % e.block()% r.block()% is_src;
+ for(size_t i=0; i<d_msg_edges.size(); i++){
+ if(is_src){
+ if(d_msg_edges[i].src() == e){
+ if(GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << boost::format("gr_flat_flowgraph::replace_endpoint() flattening to ( %s, %s )\n") % r.block()% d_msg_edges[i].dst().block();
+ d_msg_edges.push_back( gr_msg_edge(r, d_msg_edges[i].dst() ) );
+ n_replr++;
+ }
+ } else {
+ if(d_msg_edges[i].dst() == e){
+ if(GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << boost::format("gr_flat_flowgraph::replace_endpoint() flattening to ( %s, %s )\n") % r.block()% d_msg_edges[i].dst().block();
+ d_msg_edges.push_back( gr_msg_edge(d_msg_edges[i].src(), r ) );
+ n_replr++;
+ }
+ }
+ }
+}
+
diff --git a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h
index 0926bcc8f3..5c8268d7df 100644
--- a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h
+++ b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h
@@ -46,7 +46,7 @@ public:
// Wire gr_blocks together in new flat_flowgraph
void setup_connections();
-
+
// Merge applicable connections from existing flat flowgraph
void merge_connections(gr_flat_flowgraph_sptr sfg);
@@ -57,6 +57,9 @@ public:
*/
static gr_block_vector_t make_block_vector(gr_basic_block_vector_t &blocks);
+ void replace_endpoint(const gr_msg_endpoint &e, const gr_msg_endpoint &r, bool is_src);
+ void clear_endpoint(const gr_msg_endpoint &e, bool is_src);
+
private:
gr_flat_flowgraph();
diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc
index 78e1bc99af..63a2084802 100644
--- a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc
+++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc
@@ -149,6 +149,16 @@ gr_flowgraph::check_valid_port(gr_io_signature_sptr sig, int port)
}
}
+void
+gr_flowgraph::check_valid_port(const gr_msg_endpoint &e)
+{
+ if (GR_FLOWGRAPH_DEBUG)
+ std::cout << "check_valid_port( " << e.block() << ", " << e.port() << ")\n";
+
+ if(!e.block()->has_msg_port(e.port()))
+ throw std::invalid_argument("invalid msg port in connect() or disconnect()");
+}
+
void
gr_flowgraph::check_dst_not_used(const gr_endpoint &dst)
{
@@ -180,6 +190,13 @@ gr_flowgraph::calc_used_blocks()
{
gr_basic_block_vector_t tmp;
+ // make sure free standing message blocks are included
+ for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) {
+// for now only blocks receiving messages get a thread context - uncomment to allow senders to also obtain one
+// tmp.push_back(p->src().block());
+ tmp.push_back(p->dst().block());
+ }
+
// Collect all blocks in the edge list
for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
tmp.push_back(p->src().block());
@@ -472,3 +489,27 @@ gr_flowgraph::topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_ve
output.push_back(block);
}
+void gr_flowgraph::connect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst){
+ check_valid_port(src);
+ check_valid_port(dst);
+ for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) {
+ if(p->src() == src && p->dst() == dst){
+ throw std::runtime_error("connect called on already connected edge!");
+ }
+ }
+ d_msg_edges.push_back(gr_msg_edge(src,dst));
+}
+
+void gr_flowgraph::disconnect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst){
+ check_valid_port(src);
+ check_valid_port(dst);
+ for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) {
+ if(p->src() == src && p->dst() == dst){
+ d_msg_edges.erase(p);
+ return;
+ }
+ }
+ throw std::runtime_error("disconnect called on non-connected edge!");
+}
+
+
diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.h b/gnuradio-core/src/lib/runtime/gr_flowgraph.h
index a2c1580eb8..bef70f626f 100644
--- a/gnuradio-core/src/lib/runtime/gr_flowgraph.h
+++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.h
@@ -52,6 +52,31 @@ inline bool gr_endpoint::operator==(const gr_endpoint &other) const
d_port == other.d_port);
}
+class GR_CORE_API gr_msg_endpoint
+{
+private:
+ gr_basic_block_sptr d_basic_block;
+ pmt::pmt_t d_port;
+ bool d_is_hier;
+public:
+ gr_msg_endpoint() : d_basic_block(), d_port(pmt::PMT_NIL) { }
+ gr_msg_endpoint(gr_basic_block_sptr block, pmt::pmt_t port, bool is_hier=false){ d_basic_block = block; d_port = port; d_is_hier = is_hier;}
+ gr_basic_block_sptr block() const { return d_basic_block; }
+ pmt::pmt_t port() const { return d_port; }
+ bool is_hier() const { return d_is_hier; }
+ void set_hier(bool h) { d_is_hier = h; }
+
+ bool operator==(const gr_msg_endpoint &other) const;
+
+};
+
+inline bool gr_msg_endpoint::operator==(const gr_msg_endpoint &other) const
+{
+ return (d_basic_block == other.d_basic_block &&
+ pmt::pmt_equal(d_port, other.d_port));
+}
+
+
// Hold vectors of gr_endpoint objects
typedef std::vector<gr_endpoint> gr_endpoint_vector_t;
typedef std::vector<gr_endpoint>::iterator gr_endpoint_viter_t;
@@ -75,11 +100,35 @@ private:
gr_endpoint d_dst;
};
+
// Hold vectors of gr_edge objects
typedef std::vector<gr_edge> gr_edge_vector_t;
typedef std::vector<gr_edge>::iterator gr_edge_viter_t;
+/*!
+ *\brief Class representing a msg connection between to graph msg endpoints
+ *
+ */
+class GR_CORE_API gr_msg_edge
+{
+public:
+ gr_msg_edge() : d_src(), d_dst() { };
+ gr_msg_edge(const gr_msg_endpoint &src, const gr_msg_endpoint &dst) : d_src(src), d_dst(dst) { }
+ ~gr_msg_edge() {}
+
+ const gr_msg_endpoint &src() const { return d_src; }
+ const gr_msg_endpoint &dst() const { return d_dst; }
+
+private:
+ gr_msg_endpoint d_src;
+ gr_msg_endpoint d_dst;
+};
+
+// Hold vectors of gr_edge objects
+typedef std::vector<gr_msg_edge> gr_msg_edge_vector_t;
+typedef std::vector<gr_msg_edge>::iterator gr_msg_edge_viter_t;
+
// Create a shared pointer to a heap allocated flowgraph
// (types defined in gr_runtime_types.h)
GR_CORE_API gr_flowgraph_sptr gr_make_flowgraph();
@@ -110,6 +159,12 @@ public:
void disconnect(gr_basic_block_sptr src_block, int src_port,
gr_basic_block_sptr dst_block, int dst_port);
+ // Connect two msg endpoints
+ void connect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst);
+
+ // Disconnect two msg endpoints
+ void disconnect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst);
+
// Validate connectivity, raise exception if invalid
void validate();
@@ -118,6 +173,9 @@ public:
// Return vector of edges
const gr_edge_vector_t &edges() const { return d_edges; }
+
+ // Return vector of msg edges
+ const gr_msg_edge_vector_t &msg_edges() const { return d_msg_edges; }
// Return vector of connected blocks
gr_basic_block_vector_t calc_used_blocks();
@@ -132,6 +190,7 @@ public:
protected:
gr_basic_block_vector_t d_blocks;
gr_edge_vector_t d_edges;
+ gr_msg_edge_vector_t d_msg_edges;
gr_flowgraph();
std::vector<int> calc_used_ports(gr_basic_block_sptr block, bool check_inputs);
@@ -143,6 +202,7 @@ protected:
private:
void check_valid_port(gr_io_signature_sptr sig, int port);
+ void check_valid_port(const gr_msg_endpoint &e);
void check_dst_not_used(const gr_endpoint &dst);
void check_type_match(const gr_endpoint &src, const gr_endpoint &dst);
gr_edge_vector_t calc_connections(gr_basic_block_sptr block, bool check_inputs); // false=use outputs
diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
index 756852df80..8c2794c63c 100644
--- a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
+++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
@@ -44,7 +44,9 @@ gr_hier_block2::gr_hier_block2(const std::string &name,
gr_io_signature_sptr input_signature,
gr_io_signature_sptr output_signature)
: gr_basic_block(name, input_signature, output_signature),
- d_detail(new gr_hier_block2_detail(this))
+ d_detail(new gr_hier_block2_detail(this)),
+ hier_message_ports_in(pmt::PMT_NIL),
+ hier_message_ports_out(pmt::PMT_NIL)
{
// This bit of magic ensures that self() works in the constructors of derived classes.
gnuradio::detail::sptr_magic::create_and_stash_initial_sptr(this);
@@ -81,6 +83,36 @@ gr_hier_block2::connect(gr_basic_block_sptr src, int src_port,
}
void
+gr_hier_block2::msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport)
+{
+ if(!pmt::pmt_is_symbol(srcport)){throw std::runtime_error("bad port id"); }
+ d_detail->msg_connect(src, srcport, dst, dstport);
+}
+
+void
+gr_hier_block2::msg_connect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport)
+{
+ d_detail->msg_connect(src, pmt::mp(srcport), dst, pmt::mp(dstport));
+}
+
+void
+gr_hier_block2::msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport)
+{
+ if(!pmt::pmt_is_symbol(srcport)){throw std::runtime_error("bad port id"); }
+ d_detail->msg_disconnect(src, srcport, dst, dstport);
+}
+
+void
+gr_hier_block2::msg_disconnect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport)
+{
+ d_detail->msg_disconnect(src, pmt::mp(srcport), dst, pmt::mp(dstport));
+}
+
+void
gr_hier_block2::disconnect(gr_basic_block_sptr block)
{
d_detail->disconnect(block);
@@ -111,6 +143,7 @@ gr_hier_block2::unlock()
d_detail->unlock();
}
+
gr_flat_flowgraph_sptr
gr_hier_block2::flatten() const
{
diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.h b/gnuradio-core/src/lib/runtime/gr_hier_block2.h
index 1231787241..f80dd73e4b 100644
--- a/gnuradio-core/src/lib/runtime/gr_hier_block2.h
+++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.h
@@ -98,6 +98,21 @@ public:
gr_basic_block_sptr dst, int dst_port);
/*!
+ * \brief Add gr-blocks or hierarchical blocks to internal graph and wire together
+ *
+ * This adds (if not done earlier by another connect) a pair of gr-blocks or
+ * hierarchical blocks to the internal message port subscription
+ */
+ void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport);
+ void msg_connect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport);
+ void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport);
+ void msg_disconnect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport);
+
+ /*!
* \brief Remove a gr-block or hierarchical block from the internal flowgraph.
*
* This removes a gr-block or hierarchical block from the internal flowgraph,
@@ -151,6 +166,39 @@ public:
gr_flat_flowgraph_sptr flatten() const;
gr_hier_block2_sptr to_hier_block2(); // Needed for Python type coercion
+
+ bool has_msg_port(pmt::pmt_t which_port){
+ return message_port_is_hier(which_port) || gr_basic_block::has_msg_port(which_port);
+ }
+
+ bool message_port_is_hier(pmt::pmt_t port_id){
+ return message_port_is_hier_in(port_id) || message_port_is_hier_out(port_id);
+ }
+ bool message_port_is_hier_in(pmt::pmt_t port_id){
+ return pmt::pmt_list_has(hier_message_ports_in, port_id);
+ }
+ bool message_port_is_hier_out(pmt::pmt_t port_id){
+ return pmt::pmt_list_has(hier_message_ports_out, port_id);
+ }
+
+ pmt::pmt_t hier_message_ports_in;
+ pmt::pmt_t hier_message_ports_out;
+
+ void message_port_register_hier_in(pmt::pmt_t port_id){
+ if(pmt::pmt_list_has(hier_message_ports_in, port_id))
+ throw std::invalid_argument("hier msg in port by this name already registered");
+ if(msg_queue.find(port_id) != msg_queue.end())
+ throw std::invalid_argument("block already has a primitive input port by this name");
+ hier_message_ports_in = pmt::pmt_list_add(hier_message_ports_in, port_id);
+ }
+ void message_port_register_hier_out(pmt::pmt_t port_id){
+ if(pmt::pmt_list_has(hier_message_ports_out, port_id))
+ throw std::invalid_argument("hier msg out port by this name already registered");
+ if(pmt::pmt_dict_has_key(message_subscribers, port_id))
+ throw std::invalid_argument("block already has a primitive output port by this name");
+ hier_message_ports_out = pmt::pmt_list_add(hier_message_ports_out, port_id);
+ }
+
};
inline gr_hier_block2_sptr cast_to_hier_block2_sptr(gr_basic_block_sptr block) {
diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.i b/gnuradio-core/src/lib/runtime/gr_hier_block2.i
index eefb965b4e..a857394ca7 100644
--- a/gnuradio-core/src/lib/runtime/gr_hier_block2.i
+++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.i
@@ -38,6 +38,10 @@ gr_hier_block2_sptr gr_make_hier_block2(const std::string name,
// better interface in scripting land.
%rename(primitive_connect) gr_hier_block2::connect;
%rename(primitive_disconnect) gr_hier_block2::disconnect;
+%rename(primitive_msg_connect) gr_hier_block2::msg_connect;
+%rename(primitive_msg_disconnect) gr_hier_block2::msg_disconnect;
+%rename(primitive_message_port_register_hier_in) gr_hier_block2::message_port_register_hier_in;
+%rename(primitive_message_port_register_hier_out) gr_hier_block2::message_port_register_hier_out;
class gr_hier_block2 : public gr_basic_block
{
@@ -54,6 +58,19 @@ public:
void connect(gr_basic_block_sptr src, int src_port,
gr_basic_block_sptr dst, int dst_port)
throw (std::invalid_argument);
+ void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport)
+ throw (std::runtime_error);
+ void msg_connect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport)
+ throw (std::runtime_error);
+ void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport)
+ throw (std::runtime_error);
+ void msg_disconnect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport)
+ throw (std::runtime_error);
+
void disconnect(gr_basic_block_sptr block)
throw (std::invalid_argument);
void disconnect(gr_basic_block_sptr src, int src_port,
@@ -63,5 +80,9 @@ public:
void lock();
void unlock();
+ void message_port_register_hier_in(pmt::pmt_t port_id);
+ void message_port_register_hier_out(pmt::pmt_t port_id);
+
+
gr_hier_block2_sptr to_hier_block2(); // Needed for Python type coercion
};
diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
index 76c5ce06fe..add6da0248 100644
--- a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
+++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
@@ -27,6 +27,7 @@
#include <gr_io_signature.h>
#include <stdexcept>
#include <sstream>
+#include <boost/format.hpp>
#define GR_HIER_BLOCK2_DETAIL_DEBUG 0
@@ -53,6 +54,7 @@ gr_hier_block2_detail::gr_hier_block2_detail(gr_hier_block2 *owner) :
d_outputs = gr_endpoint_vector_t(max_outputs);
}
+
gr_hier_block2_detail::~gr_hier_block2_detail()
{
d_owner = 0; // Don't use delete, we didn't allocate
@@ -144,6 +146,65 @@ gr_hier_block2_detail::connect(gr_basic_block_sptr src, int src_port,
}
void
+gr_hier_block2_detail::msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport)
+{
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "connecting message port..." << std::endl;
+
+ // register the subscription
+// this is done later...
+// src->message_port_sub(srcport, pmt::pmt_cons(dst->alias_pmt(), dstport));
+
+ // add block uniquely to list to internal blocks
+ if (std::find(d_blocks.begin(), d_blocks.end(), dst) == d_blocks.end()){
+ d_blocks.push_back(src);
+ d_blocks.push_back(dst);
+ }
+
+ bool hier_out = (d_owner == src.get()) && src->message_port_is_hier_out(srcport);;
+ bool hier_in = (d_owner == dst.get()) && dst->message_port_is_hier_in(dstport);
+
+ gr_hier_block2_sptr src_block(cast_to_hier_block2_sptr(src));
+ gr_hier_block2_sptr dst_block(cast_to_hier_block2_sptr(dst));
+
+ if (src_block && src.get() != d_owner) {
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "connect: src is hierarchical, setting parent to " << this << std::endl;
+ src_block->d_detail->d_parent_detail = this;
+ }
+
+ if (dst_block && dst.get() != d_owner) {
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "connect: dst is hierarchical, setting parent to " << this << std::endl;
+ dst_block->d_detail->d_parent_detail = this;
+ }
+
+ // add edge for this message connection
+ if(GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << boost::format("connect( (%s, %s, %d), (%s, %s, %d) )\n") %
+ src % srcport % hier_out %
+ dst % dstport % hier_in;
+ d_fg->connect( gr_msg_endpoint(src, srcport, hier_out), gr_msg_endpoint(dst, dstport, hier_in));
+}
+
+void
+gr_hier_block2_detail::msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport)
+{
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "disconnecting message port..." << std::endl;
+
+ // unregister the subscription - if already subscribed
+ src->message_port_unsub(srcport, pmt::pmt_cons(dst->alias_pmt(), dstport));
+
+ // remove edge for this message connection
+ bool hier_out = (d_owner == src.get()) && src->message_port_is_hier_out(srcport);;
+ bool hier_in = (d_owner == dst.get()) && dst->message_port_is_hier_in(dstport);
+ d_fg->disconnect( gr_msg_endpoint(src, srcport, hier_out), gr_msg_endpoint(dst, dstport, hier_in));
+}
+
+void
gr_hier_block2_detail::disconnect(gr_basic_block_sptr block)
{
// Check on singleton list
@@ -405,11 +466,16 @@ void
gr_hier_block2_detail::flatten_aux(gr_flat_flowgraph_sptr sfg) const
{
if (GR_HIER_BLOCK2_DETAIL_DEBUG)
- std::cout << "Flattening " << d_owner->name() << std::endl;
+ std::cout << " ** Flattening " << d_owner->name() << std::endl;
// Add my edges to the flow graph, resolving references to actual endpoints
gr_edge_vector_t edges = d_fg->edges();
+ gr_msg_edge_vector_t msg_edges = d_fg->msg_edges();
gr_edge_viter_t p;
+ gr_msg_edge_viter_t q,u;
+
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "Flattening stream connections: " << std::endl;
for (p = edges.begin(); p != edges.end(); p++) {
if (GR_HIER_BLOCK2_DETAIL_DEBUG)
@@ -428,6 +494,53 @@ gr_hier_block2_detail::flatten_aux(gr_flat_flowgraph_sptr sfg) const
}
}
+ // loop through flattening hierarchical connections
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "Flattening msg connections: " << std::endl;
+
+
+ std::vector<std::pair<gr_msg_endpoint, bool> > resolved_endpoints;
+ for(q = msg_edges.begin(); q != msg_edges.end(); q++) {
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << boost::format(" flattening edge ( %s, %s, %d) -> ( %s, %s, %d)\n") % q->src().block() % q->src().port() % q->src().is_hier() % q->dst().block() % q->dst().port() % q->dst().is_hier();
+
+ bool normal_connection = true;
+
+ // resolve existing connections to hier ports
+ if(q->dst().is_hier()){
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << boost::format(" resolve hier output (%s, %s)") % q->dst().block() % q->dst().port() << std::endl;
+ sfg->replace_endpoint( q->dst(), q->src(), true );
+ resolved_endpoints.push_back(std::pair<gr_msg_endpoint, bool>(q->dst(),true));
+ normal_connection = false;
+ }
+
+ if(q->src().is_hier()){
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << boost::format(" resolve hier input (%s, %s)") % q->src().block() % q->src().port() << std::endl;
+ sfg->replace_endpoint( q->src(), q->dst(), false );
+ resolved_endpoints.push_back(std::pair<gr_msg_endpoint, bool>(q->src(),false));
+ normal_connection = false;
+ }
+
+ // propogate non hier connections through
+ if(normal_connection){
+ sfg->connect( q->src(), q->dst() );
+ }
+ }
+ for(std::vector<std::pair<gr_msg_endpoint, bool> >::iterator it = resolved_endpoints.begin(); it != resolved_endpoints.end(); it++){
+ sfg->clear_endpoint( (*it).first, (*it).second );
+ }
+
+/* // connect primitive edges in the new fg
+ for(q = msg_edges.begin(); q != msg_edges.end(); q++) {
+ if( (!q->src().is_hier()) && (!q->dst().is_hier()) ){
+ sfg->connect( q->src(), q->dst() );
+ } else {
+ std::cout << "not connecting hier connection!" << std::endl;
+ }
+ }*/
+
// Construct unique list of blocks used either in edges, inputs,
// outputs, or by themselves. I still hate STL.
gr_basic_block_vector_t blocks; // unique list of used blocks
@@ -468,7 +581,7 @@ gr_hier_block2_detail::flatten_aux(gr_flat_flowgraph_sptr sfg) const
// Recurse hierarchical children
for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
gr_hier_block2_sptr hier_block2(cast_to_hier_block2_sptr(*p));
- if (hier_block2) {
+ if (hier_block2 && (hier_block2.get() != d_owner)) {
if (GR_HIER_BLOCK2_DETAIL_DEBUG)
std::cout << "flatten_aux: recursing into hierarchical block " << hier_block2 << std::endl;
hier_block2->d_detail->flatten_aux(sfg);
@@ -499,3 +612,4 @@ gr_hier_block2_detail::unlock()
else
d_owner->unlock();
}
+
diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
index f4f950e9de..b38dae3016 100644
--- a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
+++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
@@ -39,6 +39,10 @@ public:
void connect(gr_basic_block_sptr block);
void connect(gr_basic_block_sptr src, int src_port,
gr_basic_block_sptr dst, int dst_port);
+ void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport);
+ void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport);
void disconnect(gr_basic_block_sptr block);
void disconnect(gr_basic_block_sptr, int src_port,
gr_basic_block_sptr, int dst_port);
@@ -57,6 +61,7 @@ private:
gr_endpoint_vector_t d_outputs; // Single internal endpoint per external output
gr_basic_block_vector_t d_blocks;
+
void connect_input(int my_port, int port, gr_basic_block_sptr block);
void connect_output(int my_port, int port, gr_basic_block_sptr block);
void disconnect_input(int my_port, int port, gr_basic_block_sptr block);
diff --git a/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc b/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc
index 5018ee9e69..93d5fb20e8 100644
--- a/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc
+++ b/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc
@@ -41,12 +41,12 @@ gr_msg_accepter::~gr_msg_accepter()
}
void
-gr_msg_accepter::post(pmt_t msg)
+gr_msg_accepter::post(pmt_t which_port, pmt_t msg)
{
// Notify derived class, handled case by case
gr_block *p = dynamic_cast<gr_block *>(this);
if (p) {
- p->detail()->_post(msg);
+ p->_post(which_port,msg);
return;
}
gr_hier_block2 *p2 = dynamic_cast<gr_hier_block2 *>(this);
diff --git a/gnuradio-core/src/lib/runtime/gr_msg_accepter.h b/gnuradio-core/src/lib/runtime/gr_msg_accepter.h
index 3e5c976388..a497ba6e7d 100644
--- a/gnuradio-core/src/lib/runtime/gr_msg_accepter.h
+++ b/gnuradio-core/src/lib/runtime/gr_msg_accepter.h
@@ -36,7 +36,7 @@ public:
gr_msg_accepter();
~gr_msg_accepter();
- void post(pmt::pmt_t msg);
+ void post(pmt::pmt_t which_port, pmt::pmt_t msg);
};
diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc b/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc
index 46b33d91fd..46eb6bbe0d 100644
--- a/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc
+++ b/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc
@@ -68,43 +68,3 @@ gr_tpb_detail::notify_neighbors(gr_block_detail *d)
notify_upstream(d);
}
-void
-gr_tpb_detail::insert_tail(pmt::pmt_t msg)
-{
- gruel::scoped_lock guard(mutex);
-
- msg_queue.push_back(msg);
-
- // wake up thread if BLKD_IN or BLKD_OUT
- input_cond.notify_one();
- output_cond.notify_one();
-}
-
-pmt_t
-gr_tpb_detail::delete_head_nowait()
-{
- gruel::scoped_lock guard(mutex);
-
- if (empty_p())
- return pmt_t();
-
- pmt_t m(msg_queue.front());
- msg_queue.pop_front();
-
- return m;
-}
-
-/*
- * Caller must already be holding the mutex
- */
-pmt_t
-gr_tpb_detail::delete_head_nowait_already_holding_mutex()
-{
- if (empty_p())
- return pmt_t();
-
- pmt_t m(msg_queue.front());
- msg_queue.pop_front();
-
- return m;
-}
diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_detail.h b/gnuradio-core/src/lib/runtime/gr_tpb_detail.h
index b6e342dee3..69feb60073 100644
--- a/gnuradio-core/src/lib/runtime/gr_tpb_detail.h
+++ b/gnuradio-core/src/lib/runtime/gr_tpb_detail.h
@@ -39,9 +39,6 @@ struct GR_CORE_API gr_tpb_detail {
bool output_changed;
gruel::condition_variable output_cond;
-private:
- std::deque<pmt::pmt_t> msg_queue;
-
public:
gr_tpb_detail()
: input_changed(false), output_changed(false) { }
@@ -55,6 +52,12 @@ public:
//! Called by us to notify both upstream and downstream
void notify_neighbors(gr_block_detail *d);
+ //! Called by pmt msg posters
+ void notify_msg(){
+ input_cond.notify_one();
+ output_cond.notify_one();
+ }
+
//! Called by us
void clear_changed()
{
@@ -63,23 +66,6 @@ public:
output_changed = false;
}
- //! is the queue empty?
- bool empty_p() const { return msg_queue.empty(); }
-
- //| Acquires and release the mutex
- void insert_tail(pmt::pmt_t msg);
-
- /*!
- * \returns returns pmt at head of queue or pmt_t() if empty.
- */
- pmt::pmt_t delete_head_nowait();
-
- /*!
- * \returns returns pmt at head of queue or pmt_t() if empty.
- * Caller must already be holding the mutex
- */
- pmt::pmt_t delete_head_nowait_already_holding_mutex();
-
private:
//! Used by notify_downstream
diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
index a5aabb379f..9f17a48a80 100644
--- a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
+++ b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
@@ -25,13 +25,14 @@
#include <iostream>
#include <boost/thread.hpp>
#include <gruel/pmt.h>
+#include <boost/foreach.hpp>
using namespace pmt;
gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_items)
: d_exec(block, max_noutput_items)
{
- // std::cerr << "gr_tpb_thread_body: " << block << std::endl;
+ //std::cerr << "gr_tpb_thread_body: " << block << std::endl;
gr_block_detail *d = block->detail().get();
gr_block_executor::state s;
@@ -42,11 +43,22 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_item
boost::this_thread::interruption_point();
// handle any queued up messages
- while ((msg = d->d_tpb.delete_head_nowait()))
- block->dispatch_msg(msg);
+ //BOOST_FOREACH( pmt::pmt_t port, block->msg_queue.keys() )
+
+ BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue )
+ {
+ while ((msg = block->delete_head_nowait(i.first))){
+ block->dispatch_msg(i.first,msg);
+ }
+ }
d->d_tpb.clear_changed();
- s = d_exec.run_one_iteration();
+ // run one iteration if we are a connected stream block
+ if(d->noutputs() >0 || d->ninputs()>0){
+ s = d_exec.run_one_iteration();
+ } else {
+ s = gr_block_executor::BLKD_IN;
+ }
switch(s){
case gr_block_executor::READY: // Tell neighbors we made progress.
@@ -67,15 +79,18 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_item
while (!d->d_tpb.input_changed){
// wait for input or message
- while(!d->d_tpb.input_changed && d->d_tpb.empty_p())
+ while(!d->d_tpb.input_changed && block->empty_p())
d->d_tpb.input_cond.wait(guard);
// handle all pending messages
- while ((msg = d->d_tpb.delete_head_nowait_already_holding_mutex())){
- guard.unlock(); // release lock while processing msg
- block->dispatch_msg(msg);
- guard.lock();
- }
+ BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue )
+ {
+ while ((msg = block->delete_head_nowait(i.first))){
+ guard.unlock(); // release lock while processing msg
+ block->dispatch_msg(i.first, msg);
+ guard.lock();
+ }
+ }
}
}
break;
@@ -87,15 +102,18 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_item
while (!d->d_tpb.output_changed){
// wait for output room or message
- while(!d->d_tpb.output_changed && d->d_tpb.empty_p())
+ while(!d->d_tpb.output_changed && block->empty_p())
d->d_tpb.output_cond.wait(guard);
// handle all pending messages
- while ((msg = d->d_tpb.delete_head_nowait_already_holding_mutex())){
- guard.unlock(); // release lock while processing msg
- block->dispatch_msg(msg);
- guard.lock();
- }
+ BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue )
+ {
+ while ((msg = block->delete_head_nowait(i.first))){
+ guard.unlock(); // release lock while processing msg
+ block->dispatch_msg(i.first,msg);
+ guard.lock();
+ }
+ }
}
}
break;
diff --git a/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc
index 25ae0b1e19..c84a219bd1 100644
--- a/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc
+++ b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc
@@ -65,15 +65,11 @@ void qa_set_msg_handler::t0()
tb->start();
// Send them...
+ pmt_t port(pmt_intern("port"));
for (int i = 0; i < NMSGS; i++){
- send(nop, mp(mp("example-msg"), mp(i)));
+ send(nop, port, mp(mp("example-msg"), mp(i)));
}
- // And send a message to null_source to confirm that the default
- // message handling action (which should be a nop) doesn't dump
- // core.
- send(src, mp(mp("example-msg"), mp(0)));
-
// Give the messages a chance to be processed
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
diff --git a/gnuradio-core/src/lib/swig/CMakeLists.txt b/gnuradio-core/src/lib/swig/CMakeLists.txt
index 5b740d916d..734547131c 100644
--- a/gnuradio-core/src/lib/swig/CMakeLists.txt
+++ b/gnuradio-core/src/lib/swig/CMakeLists.txt
@@ -25,11 +25,9 @@ include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
set(GR_SWIG_INCLUDE_DIRS
- ${Boost_INCLUDE_DIRS}
- ${GSL_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_BINARY_DIR}
${GRUEL_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
- ${CMAKE_CURRENT_BINARY_DIR}
)
set(GR_SWIG_LIBRARIES gnuradio-core)
diff --git a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt
index 6a05550212..62f3d7e46d 100644
--- a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt
+++ b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt
@@ -23,6 +23,7 @@ include(GrPython)
GR_PYTHON_INSTALL(FILES
__init__.py
exceptions.py
+ gateway.py
gr_threading.py
gr_threading_23.py
gr_threading_24.py
@@ -42,6 +43,13 @@ include(GrTest)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
+ set(GR_TEST_PYTHON_DIRS
+ ${CMAKE_SOURCE_DIR}/gruel/src/python
+ ${CMAKE_BINARY_DIR}/gruel/src/swig
+ ${CMAKE_BINARY_DIR}/gnuradio-core/src/python
+ ${CMAKE_BINARY_DIR}/gnuradio-core/src/lib/swig
+ )
+ set(GR_TEST_TARGET_DEPS volk gruel gnuradio-core)
GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gnuradio-core/src/python/gnuradio/gr/__init__.py b/gnuradio-core/src/python/gnuradio/gr/__init__.py
index e5a8fdbf9e..5d01ea11b1 100644
--- a/gnuradio-core/src/python/gnuradio/gr/__init__.py
+++ b/gnuradio-core/src/python/gnuradio/gr/__init__.py
@@ -1,5 +1,5 @@
#
-# Copyright 2003,2004,2006,2008,2009,2010 Free Software Foundation, Inc.
+# Copyright 2003-2012 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -28,6 +28,7 @@ from gnuradio_core import *
from exceptions import *
from hier_block2 import *
from top_block import *
+from gateway import basic_block, sync_block, decim_block, interp_block
# create a couple of aliases
serial_to_parallel = stream_to_vector
diff --git a/gnuradio-core/src/python/gnuradio/gr/gateway.py b/gnuradio-core/src/python/gnuradio/gr/gateway.py
new file mode 100644
index 0000000000..244b8b5925
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/gr/gateway.py
@@ -0,0 +1,215 @@
+#
+# Copyright 2011-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.
+#
+
+import gnuradio_core as gr_core
+from gnuradio_core import io_signature, io_signaturev
+from gnuradio_core import gr_block_gw_message_type
+from gnuradio_core import block_gateway
+import numpy
+
+########################################################################
+# Magic to turn pointers into numpy arrays
+# http://docs.scipy.org/doc/numpy/reference/arrays.interface.html
+########################################################################
+def pointer_to_ndarray(addr, dtype, nitems):
+ class array_like:
+ __array_interface__ = {
+ 'data' : (int(addr), False),
+ 'typestr' : dtype.base.str,
+ 'descr' : dtype.base.descr,
+ 'shape' : (nitems,) + dtype.shape,
+ 'strides' : None,
+ 'version' : 3
+ }
+ return numpy.asarray(array_like()).view(dtype.base)
+
+########################################################################
+# Handler that does callbacks from C++
+########################################################################
+class gateway_handler(gr_core.feval_ll):
+
+ #dont put a constructor, it wont work
+
+ def init(self, callback):
+ self._callback = callback
+
+ def eval(self, arg):
+ try: self._callback()
+ except Exception as ex:
+ print("handler caught exception: %s"%ex)
+ import traceback; traceback.print_exc()
+ raise ex
+ return 0
+
+########################################################################
+# The guts that make this into a gr block
+########################################################################
+class gateway_block(object):
+
+ def __init__(self, name, in_sig, out_sig, work_type, factor):
+
+ #ensure that the sigs are iterable dtypes
+ def sig_to_dtype_sig(sig):
+ if sig is None: sig = ()
+ return map(numpy.dtype, sig)
+ self.__in_sig = sig_to_dtype_sig(in_sig)
+ self.__out_sig = sig_to_dtype_sig(out_sig)
+
+ #cache the ranges to iterate when dispatching work
+ self.__in_indexes = range(len(self.__in_sig))
+ self.__out_indexes = range(len(self.__out_sig))
+
+ #convert the signatures into gr.io_signatures
+ def sig_to_gr_io_sigv(sig):
+ if not len(sig): return io_signature(0, 0, 0)
+ return io_signaturev(len(sig), len(sig), [s.itemsize for s in sig])
+ gr_in_sig = sig_to_gr_io_sigv(self.__in_sig)
+ gr_out_sig = sig_to_gr_io_sigv(self.__out_sig)
+
+ #create internal gateway block
+ self.__handler = gateway_handler()
+ self.__handler.init(self.__gr_block_handle)
+ self.__gateway = block_gateway(
+ self.__handler, name, gr_in_sig, gr_out_sig, work_type, factor)
+ self.__message = self.__gateway.gr_block_message()
+
+ #register gr_block functions
+ prefix = 'gr_block__'
+ for attr in [x for x in dir(self.__gateway) if x.startswith(prefix)]:
+ setattr(self, attr.replace(prefix, ''), getattr(self.__gateway, attr))
+ self.pop_msg_queue = lambda: gr_core.gr_block_gw_pop_msg_queue_safe(self.__gateway)
+
+ def to_basic_block(self):
+ """
+ Makes this block connectable by hier/top block python
+ """
+ return self.__gateway.to_basic_block()
+
+ def __gr_block_handle(self):
+ """
+ Dispatch tasks according to the action type specified in the message.
+ """
+ if self.__message.action == gr_block_gw_message_type.ACTION_GENERAL_WORK:
+ self.__message.general_work_args_return_value = self.general_work(
+
+ input_items=[pointer_to_ndarray(
+ self.__message.general_work_args_input_items[i],
+ self.__in_sig[i],
+ self.__message.general_work_args_ninput_items[i]
+ ) for i in self.__in_indexes],
+
+ output_items=[pointer_to_ndarray(
+ self.__message.general_work_args_output_items[i],
+ self.__out_sig[i],
+ self.__message.general_work_args_noutput_items
+ ) for i in self.__out_indexes],
+ )
+
+ elif self.__message.action == gr_block_gw_message_type.ACTION_WORK:
+ self.__message.work_args_return_value = self.work(
+
+ input_items=[pointer_to_ndarray(
+ self.__message.work_args_input_items[i],
+ self.__in_sig[i],
+ self.__message.work_args_ninput_items
+ ) for i in self.__in_indexes],
+
+ output_items=[pointer_to_ndarray(
+ self.__message.work_args_output_items[i],
+ self.__out_sig[i],
+ self.__message.work_args_noutput_items
+ ) for i in self.__out_indexes],
+ )
+
+ elif self.__message.action == gr_block_gw_message_type.ACTION_FORECAST:
+ self.forecast(
+ noutput_items=self.__message.forecast_args_noutput_items,
+ ninput_items_required=self.__message.forecast_args_ninput_items_required,
+ )
+
+ elif self.__message.action == gr_block_gw_message_type.ACTION_START:
+ self.__message.start_args_return_value = self.start()
+
+ elif self.__message.action == gr_block_gw_message_type.ACTION_STOP:
+ self.__message.stop_args_return_value = self.stop()
+
+ def forecast(self, noutput_items, ninput_items_required):
+ """
+ forecast is only called from a general block
+ this is the default implementation
+ """
+ for ninput_item in ninput_items_required:
+ ninput_item = noutput_items + self.history() - 1;
+ return
+
+ def general_work(self, *args, **kwargs):
+ """general work to be overloaded in a derived class"""
+ raise NotImplementedError("general work not implemented")
+
+ def work(self, *args, **kwargs):
+ """work to be overloaded in a derived class"""
+ raise NotImplementedError("work not implemented")
+
+ def start(self): return True
+ def stop(self): return True
+
+########################################################################
+# Wrappers for the user to inherit from
+########################################################################
+class basic_block(gateway_block):
+ def __init__(self, name, in_sig, out_sig):
+ gateway_block.__init__(self,
+ name=name,
+ in_sig=in_sig,
+ out_sig=out_sig,
+ work_type=gr_core.GR_BLOCK_GW_WORK_GENERAL,
+ factor=1, #not relevant factor
+ )
+
+class sync_block(gateway_block):
+ def __init__(self, name, in_sig, out_sig):
+ gateway_block.__init__(self,
+ name=name,
+ in_sig=in_sig,
+ out_sig=out_sig,
+ work_type=gr_core.GR_BLOCK_GW_WORK_SYNC,
+ factor=1,
+ )
+
+class decim_block(gateway_block):
+ def __init__(self, name, in_sig, out_sig, decim):
+ gateway_block.__init__(self,
+ name=name,
+ in_sig=in_sig,
+ out_sig=out_sig,
+ work_type=gr_core.GR_BLOCK_GW_WORK_DECIM,
+ factor=decim,
+ )
+
+class interp_block(gateway_block):
+ def __init__(self, name, in_sig, out_sig, interp):
+ gateway_block.__init__(self,
+ name=name,
+ in_sig=in_sig,
+ out_sig=out_sig,
+ work_type=gr_core.GR_BLOCK_GW_WORK_INTERP,
+ factor=interp,
+ )
diff --git a/gnuradio-core/src/python/gnuradio/gr/hier_block2.py b/gnuradio-core/src/python/gnuradio/gr/hier_block2.py
index 0c45f1691d..b957822381 100644
--- a/gnuradio-core/src/python/gnuradio/gr/hier_block2.py
+++ b/gnuradio-core/src/python/gnuradio/gr/hier_block2.py
@@ -20,6 +20,10 @@
#
from gnuradio_core import hier_block2_swig
+try:
+ import pmt
+except ImportError:
+ from gruel import pmt
#
# This hack forces a 'has-a' relationship to look like an 'is-a' one.
@@ -111,3 +115,15 @@ class hier_block2(object):
self._hb.primitive_disconnect(src_block.to_basic_block(), src_port,
dst_block.to_basic_block(), dst_port)
+ def msg_connect(self, src, srcport, dst, dstport):
+ self.primitive_msg_connect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport);
+
+ def msg_disconnect(self, src, srcport, dst, dstport):
+ self.primitive_msg_disconnect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport);
+
+ def message_port_register_hier_in(self, portname):
+ self.primitive_message_port_register_hier_in(pmt.pmt_intern(portname));
+
+ def message_port_register_hier_out(self, portname):
+ self.primitive_message_port_register_hier_out(pmt.pmt_intern(portname));
+
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_block_gateway.py b/gnuradio-core/src/python/gnuradio/gr/qa_block_gateway.py
new file mode 100644
index 0000000000..911879f6ff
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_block_gateway.py
@@ -0,0 +1,235 @@
+#
+# Copyright 2011-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.
+#
+
+from gnuradio import gr, gr_unittest
+import pmt
+import numpy
+
+class add_2_f32_1_f32(gr.sync_block):
+ def __init__(self):
+ gr.sync_block.__init__(
+ self,
+ name = "add 2 f32",
+ in_sig = [numpy.float32, numpy.float32],
+ out_sig = [numpy.float32],
+ )
+
+ def work(self, input_items, output_items):
+ output_items[0][:] = input_items[0] + input_items[1]
+ return len(output_items[0])
+
+class add_2_fc32_1_fc32(gr.sync_block):
+ def __init__(self):
+ gr.sync_block.__init__(
+ self,
+ name = "add 2 fc32",
+ in_sig = [numpy.complex64, numpy.complex64],
+ out_sig = [numpy.complex64],
+ )
+
+ def work(self, input_items, output_items):
+ output_items[0][:] = input_items[0] + input_items[1]
+ return len(output_items[0])
+
+class convolve(gr.sync_block):
+ """
+ A demonstration using block history to properly perform a convolution.
+ """
+ def __init__(self):
+ gr.sync_block.__init__(
+ self,
+ name = "convolve",
+ in_sig = [numpy.float32],
+ out_sig = [numpy.float32]
+ )
+ self._taps = [1, 0, 0, 0]
+ self.set_history(len(self._taps))
+
+ def work(self, input_items, output_items):
+ output_items[0][:] = numpy.convolve(input_items[0], self._taps, mode='valid')
+ return len(output_items[0])
+
+class decim2x(gr.decim_block):
+ def __init__(self):
+ gr.decim_block.__init__(
+ self,
+ name = "decim2x",
+ in_sig = [numpy.float32],
+ out_sig = [numpy.float32],
+ decim = 2
+ )
+
+ def work(self, input_items, output_items):
+ output_items[0][:] = input_items[0][::2]
+ return len(output_items[0])
+
+class interp2x(gr.interp_block):
+ def __init__(self):
+ gr.interp_block.__init__(
+ self,
+ name = "interp2x",
+ in_sig = [numpy.float32],
+ out_sig = [numpy.float32],
+ interp = 2
+ )
+
+ def work(self, input_items, output_items):
+ output_items[0][1::2] = input_items[0]
+ output_items[0][::2] = input_items[0]
+ return len(output_items[0])
+
+class tag_source(gr.sync_block):
+ def __init__(self):
+ gr.sync_block.__init__(
+ self,
+ name = "tag source",
+ in_sig = None,
+ out_sig = [numpy.float32],
+ )
+
+ def work(self, input_items, output_items):
+ num_output_items = len(output_items[0])
+
+ #put code here to fill the output items...
+
+ #make a new tag on the middle element every time work is called
+ count = self.nitems_written(0) + num_output_items/2
+ key = pmt.pmt_string_to_symbol("example_key")
+ value = pmt.pmt_string_to_symbol("example_value")
+ self.add_item_tag(0, count, key, value)
+
+ return num_output_items
+
+class tag_sink(gr.sync_block):
+ def __init__(self):
+ gr.sync_block.__init__(
+ self,
+ name = "tag sink",
+ in_sig = [numpy.float32],
+ out_sig = None,
+ )
+ self.key = None
+
+ def work(self, input_items, output_items):
+ num_input_items = len(input_items[0])
+
+ #put code here to process the input items...
+
+ #print all the tags received in this work call
+ nread = self.nitems_read(0)
+ tags = self.get_tags_in_range(0, nread, nread+num_input_items)
+ for tag in tags:
+ #print tag.offset
+ #print pmt.pmt_symbol_to_string(tag.key)
+ #print pmt.pmt_symbol_to_string(tag.value)
+ self.key = pmt.pmt_symbol_to_string(tag.key)
+
+ return num_input_items
+
+class fc32_to_f32_2(gr.sync_block):
+ def __init__(self):
+ gr.sync_block.__init__(
+ self,
+ name = "fc32_to_f32_2",
+ in_sig = [numpy.complex64],
+ out_sig = [(numpy.float32, 2)],
+ )
+
+ def work(self, input_items, output_items):
+ output_items[0][::,0] = numpy.real(input_items[0])
+ output_items[0][::,1] = numpy.imag(input_items[0])
+ return len(output_items[0])
+
+class test_block_gateway(gr_unittest.TestCase):
+
+ def test_add_f32(self):
+ tb = gr.top_block()
+ src0 = gr.vector_source_f([1, 3, 5, 7, 9], False)
+ src1 = gr.vector_source_f([0, 2, 4, 6, 8], False)
+ adder = add_2_f32_1_f32()
+ sink = gr.vector_sink_f()
+ tb.connect((src0, 0), (adder, 0))
+ tb.connect((src1, 0), (adder, 1))
+ tb.connect(adder, sink)
+ tb.run()
+ self.assertEqual(sink.data(), (1, 5, 9, 13, 17))
+
+ def test_add_fc32(self):
+ tb = gr.top_block()
+ src0 = gr.vector_source_c([1, 3j, 5, 7j, 9], False)
+ src1 = gr.vector_source_c([0, 2j, 4, 6j, 8], False)
+ adder = add_2_fc32_1_fc32()
+ sink = gr.vector_sink_c()
+ tb.connect((src0, 0), (adder, 0))
+ tb.connect((src1, 0), (adder, 1))
+ tb.connect(adder, sink)
+ tb.run()
+ self.assertEqual(sink.data(), (1, 5j, 9, 13j, 17))
+
+ def test_convolve(self):
+ tb = gr.top_block()
+ src = gr.vector_source_f([1, 2, 3, 4, 5, 6, 7, 8], False)
+ cv = convolve()
+ sink = gr.vector_sink_f()
+ tb.connect(src, cv, sink)
+ tb.run()
+ self.assertEqual(sink.data(), (1, 2, 3, 4, 5, 6, 7, 8))
+
+ def test_decim2x(self):
+ tb = gr.top_block()
+ src = gr.vector_source_f([1, 2, 3, 4, 5, 6, 7, 8], False)
+ d2x = decim2x()
+ sink = gr.vector_sink_f()
+ tb.connect(src, d2x, sink)
+ tb.run()
+ self.assertEqual(sink.data(), (1, 3, 5, 7))
+
+ def test_interp2x(self):
+ tb = gr.top_block()
+ src = gr.vector_source_f([1, 3, 5, 7, 9], False)
+ i2x = interp2x()
+ sink = gr.vector_sink_f()
+ tb.connect(src, i2x, sink)
+ tb.run()
+ self.assertEqual(sink.data(), (1, 1, 3, 3, 5, 5, 7, 7, 9, 9))
+
+ def test_tags(self):
+ src = tag_source()
+ sink = tag_sink()
+ head = gr.head(gr.sizeof_float, 50000) #should be enough items to get a tag through
+ tb = gr.top_block()
+ tb.connect(src, head, sink)
+ tb.run()
+ self.assertEqual(sink.key, "example_key")
+
+ def test_fc32_to_f32_2(self):
+ tb = gr.top_block()
+ src = gr.vector_source_c([1+2j, 3+4j, 5+6j, 7+8j, 9+10j], False)
+ convert = fc32_to_f32_2()
+ v2s = gr.vector_to_stream(gr.sizeof_float, 2)
+ sink = gr.vector_sink_f()
+ tb.connect(src, convert, v2s, sink)
+ tb.run()
+ self.assertEqual(sink.data(), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
+
+if __name__ == '__main__':
+ gr_unittest.run(test_block_gateway, "test_block_gateway.xml")
+
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py
new file mode 100755
index 0000000000..ebc365b611
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+from gnuradio import gr, gr_unittest
+import pmt
+import time
+
+class test_pdu(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_000(self):
+ # Just run some data through and make sure it doesn't puke.
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+
+ src = gr.pdu_to_tagged_stream(gr.BYTE)
+ snk3 = gr.tagged_stream_to_pdu(gr.BYTE)
+ snk2 = gr.vector_sink_b()
+ snk = gr.tag_debug(1, "test")
+
+ dbg = gr.message_debug()
+
+ # Test that the right number of ports exist.
+ pi = dbg.message_ports_in()
+ po = dbg.message_ports_out()
+ self.assertEqual(pmt.pmt_length(pi), 2)
+ self.assertEqual(pmt.pmt_length(po), 0)
+
+ pi = snk3.message_ports_in()
+ po = snk3.message_ports_out()
+ self.assertEqual(pmt.pmt_length(pi), 0)
+ self.assertEqual(pmt.pmt_length(po), 1)
+
+ #print "Message Debug input ports: "
+ #pmt.pmt_print(pi)
+ #print "Message Debug output ports: "
+ #pmt.pmt_print(po)
+
+ #print "Stream to PDU input ports: "
+ #pmt.pmt_print(pi)
+ #print "Stream to PDU output ports: "
+ #pmt.pmt_print(po)
+ time.sleep(0.1)
+
+ self.tb.connect(src, snk)
+ self.tb.connect(src, snk2)
+ self.tb.connect(src, snk3)
+
+ self.tb.msg_connect(snk3, "pdus", dbg, "store")
+ self.tb.start()
+
+ # make our reference and message pmts
+ port = pmt.pmt_intern("pdus")
+ msg = pmt.pmt_cons( pmt.PMT_NIL, pmt.pmt_make_u8vector(16, 0xFF) )
+
+ #print "printing port & msg"
+ #pmt.pmt_print(port)
+ #pmt.pmt_print(msg)
+
+ # post the message
+ src.to_basic_block()._post( port, msg )
+
+ while(dbg.num_messages() < 1):
+ time.sleep(0.5)
+ self.tb.stop()
+ self.tb.wait()
+
+ # Get the vector of data from the vector sink
+ result_data = snk2.data()
+
+ # Get the vector of data from the message sink
+ # Convert the message PMT as a pair into its vector
+ result_msg = dbg.get_message(0)
+ msg_vec = pmt.pmt_cdr(result_msg)
+ pmt.pmt_print(msg_vec)
+
+ # Convert the PMT vector into a Python list
+ msg_data = []
+ for i in xrange(16):
+ msg_data.append(pmt.pmt_u8vector_ref(msg_vec, i))
+
+ actual_data = 16*[0xFF,]
+ self.assertEqual(actual_data, list(result_data))
+ self.assertEqual(actual_data, msg_data)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_pdu, "test_pdu.xml")
diff --git a/gnuradio-core/src/python/gnuradio/gr/top_block.py b/gnuradio-core/src/python/gnuradio/gr/top_block.py
index 43af8073b6..dc1f443aa9 100644
--- a/gnuradio-core/src/python/gnuradio/gr/top_block.py
+++ b/gnuradio-core/src/python/gnuradio/gr/top_block.py
@@ -123,6 +123,12 @@ class top_block(object):
for i in range (1, len (points)):
self._connect(points[i-1], points[i])
+ def msg_connect(self, src, srcport, dst, dstport):
+ self.primitive_msg_connect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport);
+
+ def msg_disconnect(self, src, srcport, dst, dstport):
+ self.primitive_msg_disconnect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport);
+
def _connect(self, src, dst):
(src_block, src_port) = self._coerce_endpoint(src)
(dst_block, dst_port) = self._coerce_endpoint(dst)
diff --git a/gr-analog/lib/fmdet_cf_impl.cc b/gr-analog/lib/fmdet_cf_impl.cc
index d3a58966b6..c92ea28896 100644
--- a/gr-analog/lib/fmdet_cf_impl.cc
+++ b/gr-analog/lib/fmdet_cf_impl.cc
@@ -49,11 +49,11 @@ namespace gr {
d_S1(0.1), d_S2(0.1),
d_S3(0.1), d_S4(0.1)
{
- const float h[] = { 0.003118678733, -0.012139843428, 0.027270898036,
- -0.051318579352, 0.090406910552, -0.162926865366,
- 0.361885392563, 0.000000000000, -0.361885392563,
- 0.162926865366, -0.090406910552, 0.051318579352,
- -0.027270898036, 0.012139843428, -0.003118678733};
+ //const float h[] = { 0.003118678733, -0.012139843428, 0.027270898036,
+ // -0.051318579352, 0.090406910552, -0.162926865366,
+ // 0.361885392563, 0.000000000000, -0.361885392563,
+ // 0.162926865366, -0.090406910552, 0.051318579352,
+ // -0.027270898036, 0.012139843428, -0.003118678733};
//std::vector<float> taps(15);
diff --git a/gr-atsc/src/lib/CMakeLists.txt b/gr-atsc/src/lib/CMakeLists.txt
index 8c67d90285..58e3af88b0 100644
--- a/gr-atsc/src/lib/CMakeLists.txt
+++ b/gr-atsc/src/lib/CMakeLists.txt
@@ -204,8 +204,6 @@ if(ENABLE_PYTHON)
include(GrPython)
include(GrSwig)
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_INCLUDE_DIRS
${GR_ATSC_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
diff --git a/gr-atsc/src/lib/qa_atsci_single_viterbi.cc b/gr-atsc/src/lib/qa_atsci_single_viterbi.cc
index ca0cf74647..699dce9526 100644
--- a/gr-atsc/src/lib/qa_atsci_single_viterbi.cc
+++ b/gr-atsc/src/lib/qa_atsci_single_viterbi.cc
@@ -236,7 +236,7 @@ qa_atsci_single_viterbi::t1 ()
// FIXME, should we be able to tell how many errs too?
if (differs) {
- const int ERRTOL = 12; /* Or relate to delay? */
+ //const int ERRTOL = 12; /* Or relate to delay? */
int shouldfix = 1;
//int lasti = -ERRTOL;
diff --git a/gr-audio/swig/CMakeLists.txt b/gr-audio/swig/CMakeLists.txt
index fab3666609..4997ca3f7d 100644
--- a/gr-audio/swig/CMakeLists.txt
+++ b/gr-audio/swig/CMakeLists.txt
@@ -23,8 +23,6 @@
include(GrPython)
include(GrSwig)
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_INCLUDE_DIRS
${GR_AUDIO_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
diff --git a/gr-blocks/gnuradio-blocks.pc.in b/gr-blocks/gnuradio-blocks.pc.in
index abcfe017b9..c24564157e 100644
--- a/gr-blocks/gnuradio-blocks.pc.in
+++ b/gr-blocks/gnuradio-blocks.pc.in
@@ -5,7 +5,7 @@ includedir=@includedir@
Name: gnuradio-blocks
Description: GNU Radio basic block library
-Requires: gnuradio-core gnuradio-audio
+Requires: gnuradio-core
Version: @LIBVER@
Libs: -L${libdir} -lgnuradio-blocks
Cflags: -I${includedir}
diff --git a/gr-blocks/grc/blocks_file_source.xml b/gr-blocks/grc/blocks_file_source.xml
index 753465bb39..7ac573f2da 100644
--- a/gr-blocks/grc/blocks_file_source.xml
+++ b/gr-blocks/grc/blocks_file_source.xml
@@ -9,6 +9,7 @@
<key>blocks_file_source</key>
<import>from gnuradio import blocks</import>
<make>blocks.file_source($type.size*$vlen, $file, $repeat)</make>
+ <callback>open($file, $repeat)</callback>
<param>
<name>File</name>
<key>file</key>
diff --git a/gr-blocks/grc/blocks_patterned_interleaver.xml b/gr-blocks/grc/blocks_patterned_interleaver.xml
new file mode 100644
index 0000000000..8dd0fac41d
--- /dev/null
+++ b/gr-blocks/grc/blocks_patterned_interleaver.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Vector to Stream
+###################################################
+ -->
+<block>
+ <name>Patterned Interleaver</name>
+ <key>blocks_patterned_interleaver</key>
+ <import>from gnuradio import blocks</import>
+ <make>blocks.patterned_interleaver($type.size*$vlen, $pattern)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Pattern</name>
+ <key>pattern</key>
+ <value>[0,0,1,2]</value>
+ <type>int_vector</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt;= 1</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>1+max($pattern)</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/gr-blocks/include/blocks/CMakeLists.txt b/gr-blocks/include/blocks/CMakeLists.txt
index ac674528f1..787fddba37 100644
--- a/gr-blocks/include/blocks/CMakeLists.txt
+++ b/gr-blocks/include/blocks/CMakeLists.txt
@@ -118,6 +118,7 @@ install(FILES
multiply_const_cc.h
multiply_const_ff.h
nlog10_ff.h
+ patterned_interleaver.h
repeat.h
short_to_char.h
short_to_float.h
diff --git a/gr-blocks/include/blocks/file_source.h b/gr-blocks/include/blocks/file_source.h
index 6207cdf700..1a12aa905d 100644
--- a/gr-blocks/include/blocks/file_source.h
+++ b/gr-blocks/include/blocks/file_source.h
@@ -40,6 +40,21 @@ namespace gr {
// gr::blocks::file_source::sptr
typedef boost::shared_ptr<file_source> sptr;
+ /*!
+ * \brief Create a file source.
+ *
+ * Opens \p filename as a source of items into a flowgraph. The
+ * data is expected to be in binary format, item after item. The
+ * \p itemsize of the block determines the conversion from bits
+ * to items.
+ *
+ * If \p repeat is turned on, the file will repeat the file after
+ * it's reached the end.
+ *
+ * \param itemsize the size of each item in the file, in bytes
+ * \param filename name of the file to source from
+ * \param repeat repeat file from start
+ */
static sptr make(size_t itemsize, const char *filename, bool repeat = false);
/*!
@@ -49,6 +64,19 @@ namespace gr {
* \param whence one of SEEK_SET, SEEK_CUR, SEEK_END (man fseek)
*/
virtual bool seek(long seek_point, int whence) = 0;
+
+ /*!
+ * \brief Opens a new file.
+ *
+ * \param filename name of the file to source from
+ * \param repeat repeat file from start
+ */
+ virtual void open(const char *filename, bool repeat) = 0;
+
+ /*!
+ * \brief Close the file handle.
+ */
+ virtual void close() = 0;
};
} /* namespace blocks */
diff --git a/gr-blocks/include/blocks/multiply_const_cc.h b/gr-blocks/include/blocks/multiply_const_cc.h
index 032a765a42..9572eaec70 100644
--- a/gr-blocks/include/blocks/multiply_const_cc.h
+++ b/gr-blocks/include/blocks/multiply_const_cc.h
@@ -46,6 +46,7 @@ namespace gr {
/*!
* \brief Create an instance of multiply_const_cc
* \param k complex multiplicative constant
+ * \param vlen Vector length of incoming stream
*/
static sptr make(gr_complex k, size_t vlen=1);
diff --git a/gr-blocks/include/blocks/multiply_const_ff.h b/gr-blocks/include/blocks/multiply_const_ff.h
index e755f59bf3..d2d5e805cb 100644
--- a/gr-blocks/include/blocks/multiply_const_ff.h
+++ b/gr-blocks/include/blocks/multiply_const_ff.h
@@ -46,6 +46,7 @@ namespace gr {
/*!
* \brief Create an instance of multiply_const_ff
* \param k real multiplicative constant
+ * \param vlen Vector length of incoming stream
*/
static sptr make(float k, size_t vlen=1);
diff --git a/gr-blocks/include/blocks/patterned_interleaver.h b/gr-blocks/include/blocks/patterned_interleaver.h
new file mode 100644
index 0000000000..cfcdac6e73
--- /dev/null
+++ b/gr-blocks/include/blocks/patterned_interleaver.h
@@ -0,0 +1,23 @@
+#ifndef INCLUDED_BLOCKS_PATTERNED_INTERLEAVER_H
+#define INCLUDED_BLOCKS_PATTERNED_INTERLEAVER_H
+
+#include <blocks/api.h>
+#include <gr_block.h>
+
+namespace gr {
+ namespace blocks {
+
+ class BLOCKS_API patterned_interleaver : virtual public gr_block
+ {
+ public:
+
+ typedef boost::shared_ptr<patterned_interleaver> sptr;
+
+ static sptr make(size_t itemsize, std::vector<int> pattern);
+ };
+
+ }
+}
+
+#endif
+
diff --git a/gr-blocks/include/blocks/stream_mux.h b/gr-blocks/include/blocks/stream_mux.h
index 905ea3c9f0..58d564f9fe 100644
--- a/gr-blocks/include/blocks/stream_mux.h
+++ b/gr-blocks/include/blocks/stream_mux.h
@@ -53,7 +53,7 @@ namespace gr {
* \ingroup converter_blk
*
* \param itemsize the item size of the stream
- * \param length a vector (list/tuple) specifying the number of
+ * \param lengths a vector (list/tuple) specifying the number of
* items from each stream the mux together.
* Warning: this requires that at least as many items
* per stream are available or the system will wait
diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt
index 0b6c892985..3a8ffac753 100644
--- a/gr-blocks/lib/CMakeLists.txt
+++ b/gr-blocks/lib/CMakeLists.txt
@@ -160,6 +160,7 @@ list(APPEND gr_blocks_sources
multiply_const_cc_impl.cc
multiply_const_ff_impl.cc
nlog10_ff_impl.cc
+ patterned_interleaver_impl.cc
repeat_impl.cc
short_to_char_impl.cc
short_to_float_impl.cc
diff --git a/gr-blocks/lib/file_source_impl.cc b/gr-blocks/lib/file_source_impl.cc
index 0d20827b79..ed1f50c435 100644
--- a/gr-blocks/lib/file_source_impl.cc
+++ b/gr-blocks/lib/file_source_impl.cc
@@ -54,39 +54,87 @@ namespace gr {
file_source::sptr file_source::make(size_t itemsize, const char *filename, bool repeat)
{
- return gnuradio::get_initial_sptr(new file_source_impl(itemsize, filename, repeat));
+ return gnuradio::get_initial_sptr
+ (new file_source_impl(itemsize, filename, repeat));
}
file_source_impl::file_source_impl(size_t itemsize, const char *filename, bool repeat)
: gr_sync_block("file_source",
gr_make_io_signature(0, 0, 0),
gr_make_io_signature(1, 1, itemsize)),
- d_itemsize(itemsize), d_fp (0), d_repeat(repeat)
+ d_itemsize(itemsize), d_fp(0), d_new_fp(0), d_repeat(repeat),
+ d_updated(false)
{
- // we use "open" to use to the O_LARGEFILE flag
+ open(filename, repeat);
+ }
+
+ file_source_impl::~file_source_impl()
+ {
+ fclose ((FILE*)d_fp);
+ }
+
+ bool
+ file_source_impl::seek(long seek_point, int whence)
+ {
+ return fseek((FILE*)d_fp, seek_point *d_itemsize, whence) == 0;
+ }
+
+
+ void
+ file_source_impl::open(const char *filename, bool repeat)
+ {
+ // obtain exclusive access for duration of this function
+ boost::mutex::scoped_lock lock(fp_mutex);
int fd;
- if ((fd = open (filename, O_RDONLY | OUR_O_LARGEFILE | OUR_O_BINARY)) < 0){
- perror (filename);
- throw std::runtime_error ("can't open file");
+ // we use "open" to use to the O_LARGEFILE flag
+ if((fd = ::open(filename, O_RDONLY | OUR_O_LARGEFILE | OUR_O_BINARY)) < 0) {
+ perror(filename);
+ throw std::runtime_error("can't open file");
+ }
+
+ if(d_new_fp) {
+ fclose(d_new_fp);
+ d_new_fp = 0;
}
- if ((d_fp = fdopen (fd, "rb")) == NULL) {
+ if((d_new_fp = fdopen (fd, "rb")) == NULL) {
perror(filename);
+ ::close(fd); // don't leak file descriptor if fdopen fails
throw std::runtime_error("can't open file");
}
+
+ d_updated = true;
+ d_repeat = repeat;
}
- file_source_impl::~file_source_impl()
+ void
+ file_source_impl::close()
{
- fclose ((FILE *) d_fp);
+ // obtain exclusive access for duration of this function
+ boost::mutex::scoped_lock lock(fp_mutex);
+
+ if(d_new_fp != NULL) {
+ fclose(d_new_fp);
+ d_new_fp = NULL;
+ }
+ d_updated = true;
}
-
- bool
- file_source_impl::seek(long seek_point, int whence)
+
+ void
+ file_source_impl::do_update()
{
- return fseek ((FILE *) d_fp, seek_point *d_itemsize, whence) == 0;
+ if(d_updated) {
+ boost::mutex::scoped_lock lock(fp_mutex); // hold while in scope
+
+ if(d_fp)
+ fclose(d_fp);
+
+ d_fp = d_new_fp; // install new file pointer
+ d_new_fp = 0;
+ d_updated = false;
+ }
}
int
@@ -94,37 +142,41 @@ namespace gr {
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- char *o = (char *) output_items[0];
+ char *o = (char*)output_items[0];
int i;
int size = noutput_items;
- while (size) {
- i = fread(o, d_itemsize, size, (FILE *) d_fp);
+ do_update(); // update d_fp is reqd
+ if(d_fp == NULL)
+ throw std::runtime_error("work with file not open");
+
+ boost::mutex::scoped_lock lock(fp_mutex); // hold for the rest of this function
+ while(size) {
+ i = fread(o, d_itemsize, size, (FILE*)d_fp);
size -= i;
o += i * d_itemsize;
- if (size == 0) // done
+ if(size == 0) // done
break;
- if (i > 0) // short read, try again
+ if(i > 0) // short read, try again
continue;
// We got a zero from fread. This is either EOF or error. In
// any event, if we're in repeat mode, seek back to the beginning
// of the file and try again, else break
-
- if (!d_repeat)
+ if(!d_repeat)
break;
- if (fseek ((FILE *) d_fp, 0, SEEK_SET) == -1) {
+ if(fseek ((FILE *) d_fp, 0, SEEK_SET) == -1) {
fprintf(stderr, "[%s] fseek failed\n", __FILE__);
exit(-1);
}
}
- if (size > 0) { // EOF or error
- if (size == noutput_items) // we didn't read anything; say we're done
+ if(size > 0) { // EOF or error
+ if(size == noutput_items) // we didn't read anything; say we're done
return -1;
return noutput_items - size; // else return partial result
}
diff --git a/gr-blocks/lib/file_source_impl.h b/gr-blocks/lib/file_source_impl.h
index c35d563d13..600fe80ab6 100644
--- a/gr-blocks/lib/file_source_impl.h
+++ b/gr-blocks/lib/file_source_impl.h
@@ -31,15 +31,22 @@ namespace gr {
class BLOCKS_API file_source_impl : public file_source
{
private:
- size_t d_itemsize;
- void *d_fp;
- bool d_repeat;
+ size_t d_itemsize;
+ FILE *d_fp;
+ FILE *d_new_fp;
+ bool d_repeat;
+ bool d_updated;
+ boost::mutex fp_mutex;
+ void do_update();
+
public:
file_source_impl(size_t itemsize, const char *filename, bool repeat);
~file_source_impl();
bool seek(long seek_point, int whence);
+ void open(const char *filename, bool repeat);
+ void close();
int work(int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gr-blocks/lib/keep_m_in_n_impl.cc b/gr-blocks/lib/keep_m_in_n_impl.cc
index b3efdd9624..312b09c253 100644
--- a/gr-blocks/lib/keep_m_in_n_impl.cc
+++ b/gr-blocks/lib/keep_m_in_n_impl.cc
@@ -39,10 +39,10 @@ namespace gr {
: gr_block("keep_m_in_n",
gr_make_io_signature (1, 1, itemsize),
gr_make_io_signature (1, 1, itemsize)),
- d_itemsize(itemsize),
d_m(m),
d_n(n),
- d_offset(offset)
+ d_offset(offset),
+ d_itemsize(itemsize)
{
// sanity checking
assert(d_m > 0);
diff --git a/gr-blocks/lib/keep_m_in_n_impl.h b/gr-blocks/lib/keep_m_in_n_impl.h
index 5e264dba0a..0b8819489a 100644
--- a/gr-blocks/lib/keep_m_in_n_impl.h
+++ b/gr-blocks/lib/keep_m_in_n_impl.h
@@ -30,8 +30,8 @@ namespace gr {
class BLOCKS_API keep_m_in_n_impl : public keep_m_in_n
{
- int d_n;
int d_m;
+ int d_n;
int d_count;
int d_offset;
int d_itemsize;
diff --git a/gr-blocks/lib/patterned_interleaver_impl.cc b/gr-blocks/lib/patterned_interleaver_impl.cc
new file mode 100644
index 0000000000..437c733a10
--- /dev/null
+++ b/gr-blocks/lib/patterned_interleaver_impl.cc
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "patterned_interleaver_impl.h"
+#include <gr_io_signature.h>
+
+namespace gr {
+ namespace blocks {
+
+ patterned_interleaver::sptr patterned_interleaver::make(size_t itemsize, std::vector<int> pattern)
+ {
+ return gnuradio::get_initial_sptr(new patterned_interleaver_impl(itemsize, pattern));
+ }
+
+ patterned_interleaver_impl::patterned_interleaver_impl(size_t itemsize, std::vector<int> pattern)
+ : gr_block ("patterned_interleaver",
+ gr_make_io_signature (pattern_max(pattern)+1, pattern_max(pattern)+1, itemsize),
+ gr_make_io_signature (1, 1, itemsize)),
+ d_pattern(pattern), d_counts( pattern_max(pattern)+1, 0), d_itemsize(itemsize)
+ {
+ BOOST_FOREACH( int i, d_pattern)
+ { d_counts[i]++; }
+ set_output_multiple(d_pattern.size());
+ }
+
+ int
+ patterned_interleaver_impl::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ size_t nblks = noutput_items/d_pattern.size();
+
+ std::vector<const char*> ii;
+ for(size_t i=0; i<input_items.size(); i++){
+ ii.push_back((const char*)input_items[i]);
+ }
+
+ char *oo = (char *) output_items[0];
+
+ for(size_t i=0; i<nblks; i++){
+ for(size_t j=0; j<d_pattern.size(); j++){
+ memcpy(oo, ii[d_pattern[j]], d_itemsize);
+ oo += d_itemsize;
+ ii[d_pattern[j]] += d_itemsize;
+ }
+ }
+
+ for(size_t i=0; i<d_counts.size(); i++){
+ consume(i, d_counts[i]*nblks );
+ }
+ return nblks*d_pattern.size();
+ }
+
+ void patterned_interleaver_impl::forecast (int noutput_items,
+ gr_vector_int &ninput_items_required){
+ int nblks = noutput_items / d_pattern.size();
+ for(size_t i=0; i<ninput_items_required.size(); i++){
+ ninput_items_required[i] = d_counts[i] * nblks;
+ }
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
diff --git a/gr-blocks/lib/patterned_interleaver_impl.h b/gr-blocks/lib/patterned_interleaver_impl.h
new file mode 100644
index 0000000000..4266c96360
--- /dev/null
+++ b/gr-blocks/lib/patterned_interleaver_impl.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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.
+ */
+
+#ifndef INCLUDED_PATTERNED_INTERLEAVER_IMPL_H
+#define INCLUDED_PATTERNED_INTERLEAVER_IMPL_H
+
+#include <blocks/patterned_interleaver.h>
+#include <boost/foreach.hpp>
+
+namespace gr {
+ namespace blocks {
+
+ class BLOCKS_API patterned_interleaver_impl : public patterned_interleaver
+ {
+ public:
+ patterned_interleaver_impl(size_t itemsize, std::vector<int> pattern);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ int pattern_max(std::vector<int> pattern){
+ int mval(0);
+ BOOST_FOREACH( int i, pattern)
+ { mval = std::max(mval, i); }
+ return mval;
+ }
+
+ void forecast (int noutput_items,
+ gr_vector_int &ninput_items_required);
+
+ std::vector<int> d_pattern;
+ std::vector<int> d_counts;
+ size_t d_itemsize;
+
+ };
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif
diff --git a/gr-blocks/python/qa_patterned_interleaver.py b/gr-blocks/python/qa_patterned_interleaver.py
new file mode 100755
index 0000000000..3cf29c9178
--- /dev/null
+++ b/gr-blocks/python/qa_patterned_interleaver.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+#
+# Copyright 2008,2010 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 gnuradio import gr, gr_unittest
+try:
+ import blocks_swig as blocks
+except:
+ from gnuradio import blocks
+import math
+
+class test_patterned_interleaver (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_000(self):
+ dst_data = [0,0,1,2,0,2,1,0];
+ src0 = gr.vector_source_f(200*[0])
+ src1 = gr.vector_source_f(200*[1])
+ src2 = gr.vector_source_f(200*[2])
+ itg = blocks.patterned_interleaver(gr.sizeof_float, dst_data)
+ dst = gr.vector_sink_f()
+ head = gr.head(gr.sizeof_float, 8);
+
+ self.tb.connect( src0, (itg,0) );
+ self.tb.connect( src1, (itg,1) );
+ self.tb.connect( src2, (itg,2) );
+ self.tb.connect( itg, head, dst );
+
+ self.tb.run()
+ self.assertEqual(list(dst_data), list(dst.data()))
+
+if __name__ == '__main__':
+ gr_unittest.run(test_patterned_interleaver, "test_patterned_interleaver.xml")
diff --git a/gr-blocks/swig/CMakeLists.txt b/gr-blocks/swig/CMakeLists.txt
index cd27485470..fb29789f08 100644
--- a/gr-blocks/swig/CMakeLists.txt
+++ b/gr-blocks/swig/CMakeLists.txt
@@ -23,8 +23,6 @@
include(GrPython)
include(GrSwig)
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_INCLUDE_DIRS
${GR_BLOCKS_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
diff --git a/gr-blocks/swig/blocks_swig.i b/gr-blocks/swig/blocks_swig.i
index 45b2594984..7ec6bb423f 100644
--- a/gr-blocks/swig/blocks_swig.i
+++ b/gr-blocks/swig/blocks_swig.i
@@ -93,6 +93,7 @@
#include "blocks/not_bb.h"
#include "blocks/not_ss.h"
#include "blocks/not_ii.h"
+#include "blocks/patterned_interleaver.h"
#include "blocks/or_bb.h"
#include "blocks/or_ss.h"
#include "blocks/or_ii.h"
@@ -181,6 +182,7 @@
%include "blocks/not_bb.h"
%include "blocks/not_ss.h"
%include "blocks/not_ii.h"
+%include "blocks/patterned_interleaver.h"
%include "blocks/or_bb.h"
%include "blocks/or_ss.h"
%include "blocks/or_ii.h"
@@ -268,6 +270,7 @@ GR_SWIG_BLOCK_MAGIC2(blocks, nlog10_ff);
GR_SWIG_BLOCK_MAGIC2(blocks, not_bb);
GR_SWIG_BLOCK_MAGIC2(blocks, not_ss);
GR_SWIG_BLOCK_MAGIC2(blocks, not_ii);
+GR_SWIG_BLOCK_MAGIC2(blocks, patterned_interleaver);
GR_SWIG_BLOCK_MAGIC2(blocks, or_bb);
GR_SWIG_BLOCK_MAGIC2(blocks, or_ss);
GR_SWIG_BLOCK_MAGIC2(blocks, or_ii);
diff --git a/gr-comedi/src/CMakeLists.txt b/gr-comedi/src/CMakeLists.txt
index 91bbf92128..957eacaf28 100644
--- a/gr-comedi/src/CMakeLists.txt
+++ b/gr-comedi/src/CMakeLists.txt
@@ -67,8 +67,6 @@ if(ENABLE_PYTHON)
include(GrPython)
include(GrSwig)
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_INCLUDE_DIRS
${GR_COMEDI_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
diff --git a/gr-digital/examples/demod/ber_simulation.grc b/gr-digital/examples/demod/ber_simulation.grc
index b7c6a624b6..daf8bfde0d 100644
--- a/gr-digital/examples/demod/ber_simulation.grc
+++ b/gr-digital/examples/demod/ber_simulation.grc
@@ -5,7 +5,7 @@
<key>options</key>
<param>
<key>id</key>
- <value>ber_sim</value>
+ <value>ber_simulation</value>
</param>
<param>
<key>_enabled</key>
diff --git a/gr-digital/examples/demod/digital_freq_lock.grc b/gr-digital/examples/demod/digital_freq_lock.grc
index df105dd7f5..09d3085dd0 100644
--- a/gr-digital/examples/demod/digital_freq_lock.grc
+++ b/gr-digital/examples/demod/digital_freq_lock.grc
@@ -5,7 +5,7 @@
<key>options</key>
<param>
<key>id</key>
- <value>top_block</value>
+ <value>digital_freq_lock</value>
</param>
<param>
<key>_enabled</key>
diff --git a/gr-digital/examples/demod/pam_sync.grc b/gr-digital/examples/demod/pam_sync.grc
index f870a0b067..dbd4befa6f 100644
--- a/gr-digital/examples/demod/pam_sync.grc
+++ b/gr-digital/examples/demod/pam_sync.grc
@@ -5,7 +5,7 @@
<key>options</key>
<param>
<key>id</key>
- <value>top_block</value>
+ <value>pam_sync</value>
</param>
<param>
<key>_enabled</key>
diff --git a/gr-digital/examples/demod/pam_timing.grc b/gr-digital/examples/demod/pam_timing.grc
index 14a7d403e3..c253d9a9fc 100644
--- a/gr-digital/examples/demod/pam_timing.grc
+++ b/gr-digital/examples/demod/pam_timing.grc
@@ -5,7 +5,7 @@
<key>options</key>
<param>
<key>id</key>
- <value>top_block</value>
+ <value>pam_timing</value>
</param>
<param>
<key>_enabled</key>
diff --git a/gr-digital/swig/CMakeLists.txt b/gr-digital/swig/CMakeLists.txt
index 42bc8baa62..efbd1c2c92 100644
--- a/gr-digital/swig/CMakeLists.txt
+++ b/gr-digital/swig/CMakeLists.txt
@@ -114,7 +114,7 @@ set(GR_SWIG_INCLUDE_DIRS
# Setup swig docs to depend on includes and pull in from build directory
set(GR_SWIG_LIBRARIES gnuradio-digital)
-set(GR_SWIG_TARGET_DEPS digital_generated_includes core_swig)
+set(GR_SWIG_TARGET_DEPS digital_generated_includes)
set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/digital_swig_doc.i)
set(GR_SWIG_DOC_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/../include
diff --git a/gr-fcd/lib/fcd_source_c_impl.cc b/gr-fcd/lib/fcd_source_c_impl.cc
index 34a2218273..81ccee092d 100644
--- a/gr-fcd/lib/fcd_source_c_impl.cc
+++ b/gr-fcd/lib/fcd_source_c_impl.cc
@@ -176,7 +176,7 @@ void fcd_source_c_impl::set_lna_gain(float gain)
// Set mixer gain
void fcd_source_c_impl::set_mixer_gain(float gain)
{
- FCD_MODE_ENUM fme;
+ __GR_ATTR_UNUSED FCD_MODE_ENUM fme;
unsigned char g;
if ( gain > 4.0 ) {
diff --git a/gr-fcd/swig/CMakeLists.txt b/gr-fcd/swig/CMakeLists.txt
index 73676ae6ac..f715c47856 100644
--- a/gr-fcd/swig/CMakeLists.txt
+++ b/gr-fcd/swig/CMakeLists.txt
@@ -25,8 +25,6 @@ include(GrSwig)
#set(GR_SWIG_FLAGS -DGR_HAVE_FCD) #needed to parse fcd_swig.i
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_INCLUDE_DIRS
${GR_FCD_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
diff --git a/gr-fft/swig/CMakeLists.txt b/gr-fft/swig/CMakeLists.txt
index 3276669857..7ea41f220e 100644
--- a/gr-fft/swig/CMakeLists.txt
+++ b/gr-fft/swig/CMakeLists.txt
@@ -23,8 +23,6 @@
include(GrPython)
include(GrSwig)
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_INCLUDE_DIRS
${GR_FFT_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
diff --git a/gr-filter/examples/CMakeLists.txt b/gr-filter/examples/CMakeLists.txt
index d94e5c16e1..84a93d55fb 100644
--- a/gr-filter/examples/CMakeLists.txt
+++ b/gr-filter/examples/CMakeLists.txt
@@ -31,9 +31,15 @@ GR_PYTHON_INSTALL(PROGRAMS
interpolate.py
reconstruction.py
resampler.py
- resampler_demo.grc
synth_filter.py
synth_to_chan.py
DESTINATION ${GR_PKG_FILTER_EXAMPLES_DIR}
COMPONENT "filter_python"
)
+
+install(
+ FILES
+ resampler_demo.grc
+ DESTINATION ${GR_PKG_FILTER_EXAMPLES_DIR}
+ COMPONENT "filter_python"
+)
diff --git a/gr-howto-write-a-block/cmake/Modules/GrSwig.cmake b/gr-howto-write-a-block/cmake/Modules/GrSwig.cmake
index 6ba5ee3a5c..51a753ec54 100644
--- a/gr-howto-write-a-block/cmake/Modules/GrSwig.cmake
+++ b/gr-howto-write-a-block/cmake/Modules/GrSwig.cmake
@@ -108,7 +108,7 @@ macro(GR_SWIG_MAKE name)
#do swig doc generation if specified
if (GR_SWIG_DOC_FILE)
set(GR_SWIG_DOCS_SOURCE_DEPS ${GR_SWIG_SOURCE_DEPS})
- set(GR_SWIG_DOCS_TAREGT_DEPS ${GR_SWIG_TARGET_DEPS})
+ set(GR_SWIG_DOCS_TARGET_DEPS ${GR_SWIG_TARGET_DEPS})
GR_SWIG_MAKE_DOCS(${GR_SWIG_DOC_FILE} ${GR_SWIG_DOC_DIRS})
list(APPEND GR_SWIG_SOURCE_DEPS ${GR_SWIG_DOC_FILE})
endif()
diff --git a/gr-howto-write-a-block/docs/doxygen/Doxyfile.in b/gr-howto-write-a-block/docs/doxygen/Doxyfile.in
index cb6a913bbe..6ee69ee35b 100644
--- a/gr-howto-write-a-block/docs/doxygen/Doxyfile.in
+++ b/gr-howto-write-a-block/docs/doxygen/Doxyfile.in
@@ -455,12 +455,6 @@ MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = NO
-
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
@@ -807,12 +801,6 @@ HTML_FOOTER =
HTML_STYLESHEET =
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS = YES
-
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded. For this to work a browser that supports
diff --git a/gr-howto-write-a-block/docs/doxygen/Doxyfile.swig_doc.in b/gr-howto-write-a-block/docs/doxygen/Doxyfile.swig_doc.in
index 50b8aa81d6..121c3e8585 100644
--- a/gr-howto-write-a-block/docs/doxygen/Doxyfile.swig_doc.in
+++ b/gr-howto-write-a-block/docs/doxygen/Doxyfile.swig_doc.in
@@ -470,12 +470,6 @@ MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = NO
-
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
@@ -796,12 +790,6 @@ HTML_FOOTER =
HTML_STYLESHEET =
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS = YES
-
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded. For this to work a browser that supports
@@ -950,11 +938,6 @@ ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
-# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
-# and Class Hierarchy pages using a tree view instead of an ordered list.
-
-USE_INLINE_TREES = NO
-
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
diff --git a/gr-howto-write-a-block/docs/doxygen/doxyxml/example/Doxyfile b/gr-howto-write-a-block/docs/doxygen/doxyxml/example/Doxyfile
index 9780043be0..dd2e5c77eb 100644
--- a/gr-howto-write-a-block/docs/doxygen/doxyxml/example/Doxyfile
+++ b/gr-howto-write-a-block/docs/doxygen/doxyxml/example/Doxyfile
@@ -476,12 +476,6 @@ MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = NO
-
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.
@@ -808,12 +802,6 @@ HTML_STYLESHEET =
HTML_TIMESTAMP = YES
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS = YES
-
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded. For this to work a browser that supports
@@ -978,11 +966,6 @@ ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
-# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
-# and Class Hierarchy pages using a tree view instead of an ordered list.
-
-USE_INLINE_TREES = NO
-
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
# is shown.
diff --git a/gr-noaa/swig/CMakeLists.txt b/gr-noaa/swig/CMakeLists.txt
index a336bf8a43..a8335062cb 100644
--- a/gr-noaa/swig/CMakeLists.txt
+++ b/gr-noaa/swig/CMakeLists.txt
@@ -23,8 +23,6 @@
include(GrPython)
include(GrSwig)
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_INCLUDE_DIRS
${GR_NOAA_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
diff --git a/gr-pager/lib/pager_flex_parse.cc b/gr-pager/lib/pager_flex_parse.cc
index 9418c44613..d7c308ddb6 100644
--- a/gr-pager/lib/pager_flex_parse.cc
+++ b/gr-pager/lib/pager_flex_parse.cc
@@ -156,16 +156,16 @@ void pager_flex_parse::parse_data()
void pager_flex_parse::parse_alphanumeric(int mw1, int mw2, int j)
{
int frag;
- bool cont;
+ //bool cont;
if (!d_laddr) {
frag = (d_datawords[mw1] >> 11) & 0x03;
- cont = (d_datawords[mw1] >> 10) & 0x01;
+ //cont = (d_datawords[mw1] >> 10) & 0x01;
mw1++;
}
else {
frag = (d_datawords[j+1] >> 11) & 0x03;
- cont = (d_datawords[j+1] >> 10) & 0x01;
+ //cont = (d_datawords[j+1] >> 10) & 0x01;
mw2--;
}
diff --git a/gr-pager/swig/CMakeLists.txt b/gr-pager/swig/CMakeLists.txt
index 0fa8e6ee5b..9a8d9d0d8b 100644
--- a/gr-pager/swig/CMakeLists.txt
+++ b/gr-pager/swig/CMakeLists.txt
@@ -23,8 +23,6 @@
include(GrPython)
include(GrSwig)
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_INCLUDE_DIRS
${GR_PAGER_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
diff --git a/gr-qtgui/grc/qtgui_sink_x.xml b/gr-qtgui/grc/qtgui_sink_x.xml
index 83d6ec2879..6488ac04cd 100644
--- a/gr-qtgui/grc/qtgui_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_sink_x.xml
@@ -24,6 +24,7 @@ qtgui.$(type.fcn)(
$plottime, \#plottime
$plotconst, \#plotconst
)
+self.$(id).set_update_time(1.0 / $rate)
self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget)
$(gui_hint()($win))</make>
<callback>set_frequency_range($fc, $bw)</callback>
@@ -133,6 +134,12 @@ $(gui_hint()($win))</make>
<type>gui_hint</type>
<hide>part</hide>
</param>
+ <param>
+ <name>Update Rate</name>
+ <key>rate</key>
+ <value>10</value>
+ <type>real</type>
+ </param>
<sink>
<name>in</name>
<type>$type</type>
diff --git a/gr-qtgui/swig/CMakeLists.txt b/gr-qtgui/swig/CMakeLists.txt
index e84035b9f7..9f092f6c6e 100644
--- a/gr-qtgui/swig/CMakeLists.txt
+++ b/gr-qtgui/swig/CMakeLists.txt
@@ -23,8 +23,6 @@
include(GrPython)
include(GrSwig)
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_INCLUDE_DIRS
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
${GR_QTGUI_INCLUDE_DIRS}
diff --git a/gr-shd/swig/CMakeLists.txt b/gr-shd/swig/CMakeLists.txt
index 878b80c0f4..b61adfcad5 100644
--- a/gr-shd/swig/CMakeLists.txt
+++ b/gr-shd/swig/CMakeLists.txt
@@ -25,8 +25,6 @@ include(GrSwig)
set(GR_SWIG_FLAGS -DGR_HAVE_SHD) #needed to parse shd_swig.i
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_INCLUDE_DIRS
${GR_SHD_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
diff --git a/gr-trellis/src/lib/CMakeLists.txt b/gr-trellis/src/lib/CMakeLists.txt
index 8f29f9605b..a42aa19cf1 100644
--- a/gr-trellis/src/lib/CMakeLists.txt
+++ b/gr-trellis/src/lib/CMakeLists.txt
@@ -198,8 +198,6 @@ if(ENABLE_PYTHON)
include(GrPython)
include(GrSwig)
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_SOURCE_DEPS
${generated_trellis_includes}
${generated_trellis_swigs}
diff --git a/gr-uhd/swig/CMakeLists.txt b/gr-uhd/swig/CMakeLists.txt
index 6d99af350b..3b26b2bfac 100644
--- a/gr-uhd/swig/CMakeLists.txt
+++ b/gr-uhd/swig/CMakeLists.txt
@@ -25,8 +25,6 @@ include(GrSwig)
set(GR_SWIG_FLAGS -DGR_HAVE_UHD) #needed to parse uhd_swig.i
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_INCLUDE_DIRS
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
${GR_UHD_INCLUDE_DIRS}
diff --git a/gr-utils/src/python/CMakeLists.txt b/gr-utils/src/python/CMakeLists.txt
index 13fa06bbc2..d2af6b9520 100644
--- a/gr-utils/src/python/CMakeLists.txt
+++ b/gr-utils/src/python/CMakeLists.txt
@@ -51,6 +51,7 @@ GR_PYTHON_INSTALL(
gr_plot_qt
gr_filter_design
gr_read_file_metadata
+ grcc
DESTINATION ${GR_RUNTIME_DIR}
COMPONENT "utils"
)
diff --git a/gr-utils/src/python/grcc b/gr-utils/src/python/grcc
new file mode 100755
index 0000000000..7e5665dc05
--- /dev/null
+++ b/gr-utils/src/python/grcc
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+try:
+ from grc.python.Platform import Platform
+except ImportError:
+ from gnuradio.grc.python.Platform import Platform
+
+from optparse import OptionParser
+import os, sys
+
+class grcc:
+ def __init__(self, grcfile, out_dir):
+ self.out_dir = out_dir
+ self.platform = Platform()
+ data = self.platform.parse_flow_graph(grcfile)
+
+ self.fg = self.platform.get_new_flow_graph()
+ self.fg.import_data(data)
+ self.fg.validate()
+
+ self.gen = self.platform.get_generator()(self.fg, out_dir)
+ self.gen.write()
+
+ def exec_program(self):
+ progname = self.fg.get_option('id')
+ os.system("{0}/{1}.py".format(self.out_dir, progname))
+
+if __name__ == "__main__":
+ usage="%prog: [options] filename"
+ description = "Compiles a GRC file (.grc) into a GNU Radio Python program. The program is stored in ~/.grc_gnuradio by default, but this location can be changed with the -d option."
+
+ parser = OptionParser(conflict_handler="resolve", usage=usage, description=description)
+ parser.add_option("-d", "--directory", type="string", default='{0}/.grc_gnuradio/'.format(os.environ["HOME"]),
+ help="Specify the directory to output the compile program [default=%default]")
+ parser.add_option("-e", "--execute", action="store_true", default=False,
+ help="Run the program after compiling [default=%default]")
+ (options, args) = parser.parse_args ()
+
+ if(len(args) != 1):
+ sys.stderr.write("Please specify a GRC file name to compile.\n")
+ sys.exit(1)
+
+ g = grcc(args[0], options.directory+"/")
+
+ if(options.execute):
+ g.exec_program()
diff --git a/gr-video-sdl/src/CMakeLists.txt b/gr-video-sdl/src/CMakeLists.txt
index 14fdb3802f..27fb4115f6 100644
--- a/gr-video-sdl/src/CMakeLists.txt
+++ b/gr-video-sdl/src/CMakeLists.txt
@@ -66,8 +66,6 @@ if(ENABLE_PYTHON)
include(GrPython)
include(GrSwig)
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_INCLUDE_DIRS
${GR_COMEDI_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
diff --git a/gr-vocoder/swig/CMakeLists.txt b/gr-vocoder/swig/CMakeLists.txt
index da89370feb..aaf09700f2 100644
--- a/gr-vocoder/swig/CMakeLists.txt
+++ b/gr-vocoder/swig/CMakeLists.txt
@@ -23,8 +23,6 @@
include(GrPython)
include(GrSwig)
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_INCLUDE_DIRS
${GR_VOCODER_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
diff --git a/gr-wavelet/swig/CMakeLists.txt b/gr-wavelet/swig/CMakeLists.txt
index 4c78575f8e..2c5f433ebb 100644
--- a/gr-wavelet/swig/CMakeLists.txt
+++ b/gr-wavelet/swig/CMakeLists.txt
@@ -23,8 +23,6 @@
include(GrPython)
include(GrSwig)
-set(GR_SWIG_TARGET_DEPS core_swig)
-
set(GR_SWIG_INCLUDE_DIRS
${GR_WAVELET_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml
index 2210701116..37a6321f5d 100644
--- a/grc/blocks/block_tree.xml
+++ b/grc/blocks/block_tree.xml
@@ -38,6 +38,15 @@
<block>virtual_sink</block>
<block>gr_tag_debug</block>
</cat>
+ <cat>
+ <name>Message Tools</name>
+ <block>gr_message_debug</block>
+ <block>gr_message_strobe</block>
+ <block>gr_pdu_to_tagged_stream</block>
+ <block>gr_tagged_stream_to_pdu</block>
+ <block>gr_tuntap_pdu</block>
+ <block>gr_socket_pdu</block>
+ </cat>
<cat>
<name>Operators</name>
<block>gr_add_xx</block>
diff --git a/grc/blocks/gr_file_source.xml b/grc/blocks/gr_file_source.xml
index fcc7a70401..5f0e16b279 100644
--- a/grc/blocks/gr_file_source.xml
+++ b/grc/blocks/gr_file_source.xml
@@ -9,6 +9,7 @@
<key>gr_file_source</key>
<import>from gnuradio import gr</import>
<make>gr.file_source($type.size*$vlen, $file, $repeat)</make>
+ <callback>open($file, $repeat)</callback>
<param>
<name>File</name>
<key>file</key>
diff --git a/grc/blocks/gr_message_debug.xml b/grc/blocks/gr_message_debug.xml
new file mode 100644
index 0000000000..4d73fbd9cc
--- /dev/null
+++ b/grc/blocks/gr_message_debug.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Message Debug
+###################################################
+ -->
+<block>
+ <name>Message Debug</name>
+ <key>gr_message_debug</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.message_debug()</make>
+ <sink>
+ <name>print</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+ <sink>
+ <name>store</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+ <sink>
+ <name>print_pdu_verbose</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+</block>
diff --git a/grc/blocks/gr_message_strobe.xml b/grc/blocks/gr_message_strobe.xml
new file mode 100644
index 0000000000..60a7724dfc
--- /dev/null
+++ b/grc/blocks/gr_message_strobe.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Message Strobe
+###################################################
+ -->
+<block>
+ <name>Message Strobe</name>
+ <key>gr_message_strobe</key>
+ <import>from gnuradio import gr</import>
+ <import>from gruel import pmt</import>
+ <make>gr.message_strobe($msg, $period)</make>
+ <param>
+ <name>Message PMT</name>
+ <key>msg</key>
+ <value>pmt.pmt_intern("TEST")</value>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Period (ms)</name>
+ <key>period</key>
+ <value>1000</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>set_msg</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+ <source>
+ <name>strobe</name>
+ <type>message</type>
+ <optional>1</optional>
+ </source>
+</block>
diff --git a/grc/blocks/gr_pdu_to_tagged_stream.xml b/grc/blocks/gr_pdu_to_tagged_stream.xml
new file mode 100644
index 0000000000..fc1c4d16a3
--- /dev/null
+++ b/grc/blocks/gr_pdu_to_tagged_stream.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## PDU Message to Tagged Stream
+###################################################
+ -->
+<block>
+ <name>PDU to Tagged Stream</name>
+ <key>gr_pdu_to_tagged_stream</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.pdu_to_tagged_stream($type.tv)</make>
+ <param>
+ <name>Item Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>tv:gr.BYTE</opt>
+ </option>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>tv:gr.COMPLEX</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>tv:gr.FLOAT</opt>
+ </option>
+ </param>
+ <sink>
+ <name>pdus</name>
+ <type>message</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_socket_pdu.xml b/grc/blocks/gr_socket_pdu.xml
new file mode 100644
index 0000000000..a175c36991
--- /dev/null
+++ b/grc/blocks/gr_socket_pdu.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Socket PDU Message source/sink
+###################################################
+ -->
+<block>
+ <name>Socket PDU</name>
+ <key>gr_socket_pdu</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.socket_pdu($type, $host, $port, $mtu)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <value>TCP_SERVER</value>
+ <type>enum</type>
+ <option>
+ <name>TCP Server</name>
+ <key>"TCP_SERVER"</key>
+ </option>
+ <option>
+ <name>TCP Client</name>
+ <key>"TCP_CLIENT"</key>
+ </option>
+ <option>
+ <name>UDP Server</name>
+ <key>"UDP_SERVER"</key>
+ </option>
+ <option>
+ <name>UDP Client</name>
+ <key>"UDP_CLIENT"</key>
+ </option>
+ </param>
+ <param>
+ <name>Host</name>
+ <key>host</key>
+ <value></value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Port</name>
+ <key>port</key>
+ <value>52001</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>MTU</name>
+ <key>mtu</key>
+ <value>10000</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>pdus</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+ <source>
+ <name>pdus</name>
+ <type>message</type>
+ <optional>1</optional>
+ </source>
+</block>
diff --git a/grc/blocks/gr_tagged_stream_to_pdu.xml b/grc/blocks/gr_tagged_stream_to_pdu.xml
new file mode 100644
index 0000000000..e70a016080
--- /dev/null
+++ b/grc/blocks/gr_tagged_stream_to_pdu.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Tagged Stream to PDU Message
+###################################################
+ -->
+<block>
+ <name>Tagged Stream to PDU</name>
+ <key>gr_tagged_stream_to_pdu</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.tagged_stream_to_pdu($type.tv)</make>
+ <param>
+ <name>Item Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>tv:gr.BYTE</opt>
+ </option>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>tv:gr.COMPLEX</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>tv:gr.FLOAT</opt>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>pdus</name>
+ <type>message</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_tuntap_pdu.xml b/grc/blocks/gr_tuntap_pdu.xml
new file mode 100644
index 0000000000..f169345afa
--- /dev/null
+++ b/grc/blocks/gr_tuntap_pdu.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Tuntap PDU Message source/sink
+###################################################
+ -->
+<block>
+ <name>TunTap PDU</name>
+ <key>gr_tuntap_pdu</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.tuntap_pdu($ifn, $mtu)</make>
+ <param>
+ <name>Interface Name</name>
+ <key>ifn</key>
+ <value>tun0</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>MTU</name>
+ <key>mtu</key>
+ <value>10000</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>pdus</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+ <source>
+ <name>pdus</name>
+ <type>message</type>
+ <optional>1</optional>
+ </source>
+</block>
diff --git a/grc/blocks/pad_sink.xml b/grc/blocks/pad_sink.xml
index f89eaa53c5..f0e10a3391 100644
--- a/grc/blocks/pad_sink.xml
+++ b/grc/blocks/pad_sink.xml
@@ -7,7 +7,9 @@
<block>
<name>Pad Sink</name>
<key>pad_sink</key>
- <make></make>
+ <make>#if str($type) == "message"
+None;self.message_port_register_hier_in($label)
+#end if</make>
<param>
<name>Label</name>
<key>label</key>
@@ -44,6 +46,11 @@
<opt>size:gr.sizeof_char</opt>
</option>
<option>
+ <name>Message</name>
+ <key>message</key>
+ <opt>size:0</opt>
+ </option>
+ <option>
<name>Wildcard</name>
<key></key>
<opt>size:0</opt>
diff --git a/grc/blocks/pad_source.xml b/grc/blocks/pad_source.xml
index cbf38eb390..a56a65dcc3 100644
--- a/grc/blocks/pad_source.xml
+++ b/grc/blocks/pad_source.xml
@@ -7,7 +7,9 @@
<block>
<name>Pad Source</name>
<key>pad_source</key>
- <make></make>
+ <make>#if str($type) == "message"
+None;self.message_port_register_hier_out($label)
+#end if</make>
<param>
<name>Label</name>
<key>label</key>
@@ -44,6 +46,11 @@
<opt>size:gr.sizeof_char</opt>
</option>
<option>
+ <name>Message</name>
+ <key>message</key>
+ <opt>size:0</opt>
+ </option>
+ <option>
<name>Wildcard</name>
<key></key>
<opt>size:0</opt>
diff --git a/grc/python/Connection.py b/grc/python/Connection.py
index 218baf0743..341dd2d821 100644
--- a/grc/python/Connection.py
+++ b/grc/python/Connection.py
@@ -31,6 +31,9 @@ class Connection(_Connection, _GUIConnection):
def is_msg(self):
return self.get_source().get_type() == self.get_sink().get_type() == 'msg'
+ def is_message(self):
+ return self.get_source().get_type() == self.get_sink().get_type() == 'message'
+
def validate(self):
"""
Validate the connections.
diff --git a/grc/python/Constants.py b/grc/python/Constants.py
index 1a65caf1c0..b8dc9a96a1 100644
--- a/grc/python/Constants.py
+++ b/grc/python/Constants.py
@@ -58,6 +58,7 @@ CORE_TYPES = ( #name, key, sizeof, color
('Integer 16', 's16', 2, '#FFFF66'),
('Integer 8', 's8', 1, '#FF66FF'),
('Message Queue', 'msg', 0, '#777777'),
+ ('Async Message', 'message', 0, '#C0C0C0'),
('Wildcard', '', 0, '#FFFFFF'),
)
diff --git a/grc/python/FlowGraph.py b/grc/python/FlowGraph.py
index efe362760c..376c2e337f 100644
--- a/grc/python/FlowGraph.py
+++ b/grc/python/FlowGraph.py
@@ -58,6 +58,8 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph):
'in': self.get_pad_sources(),
'out': self.get_pad_sinks(),
}[direction]
+ # we only want stream ports
+ sorted_pads = filter(lambda b: b.get_param('type').get_evaluated() != 'message', sorted_pads);
#load io signature
return [{
'label': str(pad.get_param('label').get_evaluated()),
@@ -83,6 +85,14 @@ class FlowGraph(_FlowGraph, _GUIFlowGraph):
pads = filter(lambda b: b.get_key() == 'pad_sink', self.get_enabled_blocks())
return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id()))
+ def get_msg_pad_sources(self):
+ ps = self.get_pad_sources();
+ return filter(lambda b: b.get_param('type').get_evaluated() == 'message', ps);
+
+ def get_msg_pad_sinks(self):
+ ps = self.get_pad_sinks();
+ return filter(lambda b: b.get_param('type').get_evaluated() == 'message', ps);
+
def get_imports(self):
"""
Get a set of all import statments in this flow graph namespace.
diff --git a/grc/python/Generator.py b/grc/python/Generator.py
index 2a6fe51d5d..616ea00fcb 100644
--- a/grc/python/Generator.py
+++ b/grc/python/Generator.py
@@ -116,8 +116,9 @@ Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''')
#list of regular blocks (all blocks minus the special ones)
blocks = filter(lambda b: b not in (imports + parameters), blocks)
#list of connections where each endpoint is enabled
- connections = filter(lambda c: not c.is_msg(), self._flow_graph.get_enabled_connections())
+ connections = filter(lambda c: not (c.is_msg() or c.is_message()), self._flow_graph.get_enabled_connections())
messages = filter(lambda c: c.is_msg(), self._flow_graph.get_enabled_connections())
+ messages2 = filter(lambda c: c.is_message(), self._flow_graph.get_enabled_connections())
#list of variable names
var_ids = [var.get_id() for var in parameters + variables]
#prepend self.
@@ -142,6 +143,7 @@ Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''')
'blocks': blocks,
'connections': connections,
'messages': messages,
+ 'messages2': messages2,
'generate_options': self._generate_options,
'var_id2cbs': var_id2cbs,
}
diff --git a/grc/python/Port.py b/grc/python/Port.py
index 9f8b50d052..738a33ba72 100644
--- a/grc/python/Port.py
+++ b/grc/python/Port.py
@@ -116,7 +116,7 @@ class Port(_Port, _GUIPort):
_Port.validate(self)
if not self.get_enabled_connections() and not self.get_optional():
self.add_error_message('Port is not connected.')
- if not self.is_source() and len(self.get_enabled_connections()) > 1:
+ if not self.is_source() and (not self.get_type() == "message") and len(self.get_enabled_connections()) > 1:
self.add_error_message('Port has too many connections.')
#message port logic
if self.get_type() == 'msg':
diff --git a/grc/python/convert_hier.py b/grc/python/convert_hier.py
index b609af24ae..508ec63b2b 100644
--- a/grc/python/convert_hier.py
+++ b/grc/python/convert_hier.py
@@ -25,6 +25,8 @@ def convert_hier(flow_graph, python_file):
#extract info from the flow graph
input_sigs = flow_graph.get_io_signaturev('in')
output_sigs = flow_graph.get_io_signaturev('out')
+ input_msgp = flow_graph.get_msg_pad_sources();
+ output_msgp = flow_graph.get_msg_pad_sinks();
parameters = flow_graph.get_parameters()
block_key = flow_graph.get_option('id')
block_name = flow_graph.get_option('title') or flow_graph.get_option('id').replace('_', ' ').title()
@@ -55,7 +57,7 @@ def convert_hier(flow_graph, python_file):
param_n['type'] = 'raw'
params_n.append(param_n)
block_n['param'] = params_n
- #sink data
+ #sink data stream ports
block_n['sink'] = list()
for input_sig in input_sigs:
sink_n = odict()
@@ -64,7 +66,14 @@ def convert_hier(flow_graph, python_file):
sink_n['vlen'] = input_sig['vlen']
if input_sig['optional']: sink_n['optional'] = '1'
block_n['sink'].append(sink_n)
- #source data
+ #sink data msg ports
+ for input_sig in input_msgp:
+ sink_n = odict()
+ sink_n['name'] = input_sig.get_param("label").get_value();
+ sink_n['type'] = "message"
+ sink_n['optional'] = input_sig.get_param("optional").get_value();
+ block_n['sink'].append(sink_n)
+ #source data stream ports
block_n['source'] = list()
for output_sig in output_sigs:
source_n = odict()
@@ -73,6 +82,13 @@ def convert_hier(flow_graph, python_file):
source_n['vlen'] = output_sig['vlen']
if output_sig['optional']: source_n['optional'] = '1'
block_n['source'].append(source_n)
+ #source data msg ports
+ for output_sig in output_msgp:
+ source_n = odict()
+ source_n['name'] = output_sig.get_param("label").get_value();
+ source_n['type'] = "message"
+ source_n['optional'] = output_sig.get_param("optional").get_value();
+ block_n['source'].append(source_n)
#doc data
block_n['doc'] = "%s\n%s\n%s"%(block_author, block_desc, python_file)
block_n['grc_source'] = "%s"%(flow_graph.grc_file_path)
diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl
index 17feb01f65..163e7f76aa 100644
--- a/grc/python/flow_graph.tmpl
+++ b/grc/python/flow_graph.tmpl
@@ -191,6 +191,32 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))])
#end for
########################################################
+##Create Asynch Message Connections
+########################################################
+#if $messages2
+ $DIVIDER
+ # Asynch Message Connections
+ $DIVIDER
+#end if
+#for $msg in $messages2
+ #set $sr = $msg.get_source()
+ #set $source = "self.%s"%($sr.get_parent().get_id())
+ #set $source_port = $sr.get_name();
+ #if $sr.get_parent().get_key() == "pad_source"
+ #set $source = "self"
+ #set $source_port = $sr.get_parent().get_param("label").get_value();
+ #end if
+ #set $sk = $msg.get_sink()
+ #set $sink = "self.%s"%($sk.get_parent().get_id())
+ #set $sink_port = $sk.get_name();
+ #if $sk.get_parent().get_key() == "pad_sink"
+ #set $sink = "self"
+ #set $sink_port = $sk.get_parent().get_param("label").get_value();
+ #end if
+ self.msg_connect($source, "$source_port", $sink, "$sink_port")
+#end for
+
+########################################################
##Create Callbacks
## Write a set method for this variable that calls the callbacks
########################################################
diff --git a/gruel/CMakeLists.txt b/gruel/CMakeLists.txt
index 3e8c5166e5..627135abe9 100644
--- a/gruel/CMakeLists.txt
+++ b/gruel/CMakeLists.txt
@@ -37,7 +37,6 @@ include(GrMiscUtils)
GR_SET_GLOBAL(GRUEL_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/src/include
${CMAKE_CURRENT_BINARY_DIR}/src/include
- ${Boost_INCLUDE_DIRS}
)
########################################################################
diff --git a/gruel/src/include/gruel/msg_accepter.h b/gruel/src/include/gruel/msg_accepter.h
index 2dc1a68592..45acb3c784 100644
--- a/gruel/src/include/gruel/msg_accepter.h
+++ b/gruel/src/include/gruel/msg_accepter.h
@@ -37,13 +37,13 @@ namespace gruel {
virtual ~msg_accepter();
/*!
- * \brief send \p msg to \p msg_accepter
+ * \brief send \p msg to \p msg_accepter on port \p which_port
*
* Sending a message is an asynchronous operation. The \p post
* call will not wait for the message either to arrive at the
* destination or to be received.
*/
- virtual void post(pmt::pmt_t msg) = 0;
+ virtual void post(pmt::pmt_t which_port, pmt::pmt_t msg) = 0;
};
typedef boost::shared_ptr<msg_accepter> msg_accepter_sptr;
diff --git a/gruel/src/include/gruel/msg_passing.h b/gruel/src/include/gruel/msg_passing.h
index 0cc0cd1111..25f30118f7 100644
--- a/gruel/src/include/gruel/msg_passing.h
+++ b/gruel/src/include/gruel/msg_passing.h
@@ -36,6 +36,7 @@ namespace gruel {
* \brief send message to msg_accepter
*
* \param accepter is the target of the send.
+ * \param which_port A pmt symbol describing the port by name.
* \param msg is the message to send. It's usually a pmt tuple.
*
* Sending a message is an asynchronous operation. The \p send
@@ -45,9 +46,9 @@ namespace gruel {
* \returns msg
*/
static inline pmt::pmt_t
- send(msg_accepter_sptr accepter, const pmt::pmt_t &msg)
+ send(msg_accepter_sptr accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg)
{
- accepter->post(msg);
+ accepter->post(which_port, msg);
return msg;
}
@@ -55,6 +56,7 @@ namespace gruel {
* \brief send message to msg_accepter
*
* \param accepter is the target of the send.
+ * \param which_port A pmt symbol describing the port by name.
* \param msg is the message to send. It's usually a pmt tuple.
*
* Sending a message is an asynchronous operation. The \p send
@@ -64,9 +66,9 @@ namespace gruel {
* \returns msg
*/
static inline pmt::pmt_t
- send(msg_accepter *accepter, const pmt::pmt_t &msg)
+ send(msg_accepter *accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg)
{
- accepter->post(msg);
+ accepter->post(which_port, msg);
return msg;
}
@@ -74,6 +76,7 @@ namespace gruel {
* \brief send message to msg_accepter
*
* \param accepter is the target of the send.
+ * \param which_port A pmt symbol describing the port by name.
* \param msg is the message to send. It's usually a pmt tuple.
*
* Sending a message is an asynchronous operation. The \p send
@@ -83,9 +86,9 @@ namespace gruel {
* \returns msg
*/
static inline pmt::pmt_t
- send(msg_accepter &accepter, const pmt::pmt_t &msg)
+ send(msg_accepter &accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg)
{
- accepter.post(msg);
+ accepter.post(which_port, msg);
return msg;
}
@@ -93,6 +96,7 @@ namespace gruel {
* \brief send message to msg_accepter
*
* \param accepter is the target of the send. precond: pmt_is_msg_accepter(accepter)
+ * \param which_port A pmt symbol describing the port by name.
* \param msg is the message to send. It's usually a pmt tuple.
*
* Sending a message is an asynchronous operation. The \p send
@@ -102,9 +106,9 @@ namespace gruel {
* \returns msg
*/
static inline pmt::pmt_t
- send(pmt::pmt_t accepter, const pmt::pmt_t &msg)
+ send(pmt::pmt_t accepter, const pmt::pmt_t &which_port, const pmt::pmt_t &msg)
{
- return send(pmt_msg_accepter_ref(accepter), msg);
+ return send(pmt_msg_accepter_ref(accepter), which_port, msg);
}
} /* namespace gruel */
diff --git a/gruel/src/include/gruel/pmt.h b/gruel/src/include/gruel/pmt.h
index 1e8b38627f..d09686783c 100644
--- a/gruel/src/include/gruel/pmt.h
+++ b/gruel/src/include/gruel/pmt.h
@@ -729,6 +729,16 @@ GRUEL_API pmt_t pmt_list6(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, con
*/
GRUEL_API pmt_t pmt_list_add(pmt_t list, const pmt_t& item);
+/*!
+ * \brief Return \p list with \p item removed from it.
+ */
+GRUEL_API pmt_t pmt_list_rm(pmt_t list, const pmt_t& item);
+
+/*!
+ * \brief Return bool of \p list contains \p item
+ */
+GRUEL_API bool pmt_list_has(pmt_t list, const pmt_t& item);
+
/*
* ------------------------------------------------------------------------
@@ -805,6 +815,15 @@ GRUEL_API std::string pmt_serialize_str(pmt_t obj);
*/
GRUEL_API pmt_t pmt_deserialize_str(std::string str);
+/*!
+ * \brief Provide a comparator function object to allow pmt use in stl types
+ */
+class pmt_comperator {
+ public:
+ bool operator()(pmt::pmt_t const& p1, pmt::pmt_t const& p2) const
+ { return pmt::pmt_eqv(p1,p2)?false:p1.get()>p2.get(); }
+ };
+
} /* namespace pmt */
#include <gruel/pmt_sugar.h>
diff --git a/gruel/src/lib/pmt/pmt.cc b/gruel/src/lib/pmt/pmt.cc
index 1d9125d4e0..e5baca98a8 100644
--- a/gruel/src/lib/pmt/pmt.cc
+++ b/gruel/src/lib/pmt/pmt.cc
@@ -1325,6 +1325,38 @@ pmt_list_add(pmt_t list, const pmt_t& item)
}
pmt_t
+pmt_list_rm(pmt_t list, const pmt_t& item)
+{
+ if(pmt_is_pair(list)){
+ pmt_t left = pmt_car(list);
+ pmt_t right = pmt_cdr(list);
+ if(!pmt_equal(left, item)){
+ return pmt_cons(left, pmt_list_rm(right, item));
+ } else {
+ return pmt_list_rm(right, item);
+ }
+ } else {
+ return list;
+ }
+}
+
+bool
+pmt_list_has(pmt_t list, const pmt_t& item)
+{
+ if(pmt_is_pair(list)){
+ pmt_t left = pmt_car(list);
+ pmt_t right = pmt_cdr(list);
+ if(pmt_equal(left,item))
+ return true;
+ return pmt_list_has(right, item);
+ } else {
+ if(pmt_is_null(list))
+ return false;
+ throw std::runtime_error("list contains invalid format!");
+ }
+}
+
+pmt_t
pmt_caar(pmt_t pair)
{
return (pmt_car(pmt_car(pair)));
diff --git a/gruel/src/lib/pmt/qa_pmt_prims.cc b/gruel/src/lib/pmt/qa_pmt_prims.cc
index 6212b8ea4f..1bf5fcfb16 100644
--- a/gruel/src/lib/pmt/qa_pmt_prims.cc
+++ b/gruel/src/lib/pmt/qa_pmt_prims.cc
@@ -472,7 +472,7 @@ class qa_pmt_msg_accepter_nop : public gruel::msg_accepter {
public:
qa_pmt_msg_accepter_nop(){};
~qa_pmt_msg_accepter_nop();
- void post(pmt_t){};
+ void post(pmt_t,pmt_t){};
};
qa_pmt_msg_accepter_nop::~qa_pmt_msg_accepter_nop(){}
@@ -495,9 +495,10 @@ qa_pmt_prims::test_msg_accepter()
CPPUNIT_ASSERT_THROW(pmt_msg_accepter_ref(p0), pmt_wrong_type);
// just confirm interfaces on send are OK
- gruel::send(ma0.get(), sym);
- gruel::send(ma0, sym);
- gruel::send(p1, sym);
+ pmt_t port(pmt_intern("port"));
+ gruel::send(ma0.get(), port, sym);
+ gruel::send(ma0, port, sym);
+ gruel::send(p1, port, sym);
}
diff --git a/gruel/src/swig/CMakeLists.txt b/gruel/src/swig/CMakeLists.txt
index 332d5866fc..a5e3f93994 100644
--- a/gruel/src/swig/CMakeLists.txt
+++ b/gruel/src/swig/CMakeLists.txt
@@ -24,7 +24,7 @@ include(GrPython)
include(GrSwig)
set(GR_SWIG_TARGET_DEPS pmt_generated)
-set(GR_SWIG_INCLUDE_DIRS ${GRUEL_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR})
+set(GR_SWIG_INCLUDE_DIRS ${GRUEL_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} ${Boost_INCLUDE_DIRS})
set(GR_SWIG_LIBRARIES gruel)
set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/pmt_swig_doc.i)
diff --git a/gruel/src/swig/pmt_swig.i b/gruel/src/swig/pmt_swig.i
index 45cfceadcb..b1628c9983 100644
--- a/gruel/src/swig/pmt_swig.i
+++ b/gruel/src/swig/pmt_swig.i
@@ -696,6 +696,15 @@ pmt_t pmt_list6(const pmt_t& x1, const pmt_t& x2, const pmt_t& x3, const pmt_t&
*/
pmt_t pmt_list_add(pmt_t list, const pmt_t& item);
+/*!
+ * \brief Return \p list with \p item removed
+ */
+pmt_t pmt_list_rm(pmt_t list, const pmt_t& item);
+
+/*!
+ * \brief Return bool of \p list contains \p item
+ */
+bool pmt_list_has(pmt_t list, const pmt_t& item);
/*
* ------------------------------------------------------------------------
diff --git a/volk/CMakeLists.txt b/volk/CMakeLists.txt
index 68385f9740..9519505eb9 100644
--- a/volk/CMakeLists.txt
+++ b/volk/CMakeLists.txt
@@ -38,12 +38,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) #location for custom "M
# Environment setup
########################################################################
IF(NOT DEFINED BOOST_ROOT)
- SET(BOOST_ROOT "")
+ SET(BOOST_ROOT ${CMAKE_INSTALL_PREFIX})
ENDIF()
-SET(BOOST_ROOT ${BOOST_ROOT} CACHE STRING "Modify search path for Boost components")
-
-#after caching user-defined value, make sure to add the install prefix
-SET(BOOST_ROOT ${BOOST_ROOT}:${CMAKE_INSTALL_PREFIX})
IF(NOT DEFINED CROSSCOMPILE_MULTILIB)
SET(CROSSCOMPILE_MULTILIB "")
@@ -77,6 +73,10 @@ set(Boost_ADDITIONAL_VERSIONS
)
find_package(Boost COMPONENTS unit_test_framework)
+if(NOT Boost_FOUND)
+ message(FATAL_ERROR "VOLK Requires boost to build")
+endif()
+
find_package(ORC)
########################################################################
diff --git a/volk/apps/CMakeLists.txt b/volk/apps/CMakeLists.txt
index 175105a5a3..a89a9409d8 100644
--- a/volk/apps/CMakeLists.txt
+++ b/volk/apps/CMakeLists.txt
@@ -18,7 +18,7 @@
########################################################################
# Setup profiler
########################################################################
-find_package(Boost)
+find_package(Boost COMPONENTS unit_test_framework)
if(Boost_FOUND AND UNIX) #uses mkdir and $HOME