summaryrefslogtreecommitdiff
path: root/gnuradio-runtime/lib
diff options
context:
space:
mode:
authorJohnathan Corgan <johnathan@corganlabs.com>2013-03-26 20:18:53 -0700
committerJohnathan Corgan <johnathan@corganlabs.com>2013-03-26 20:18:53 -0700
commit26dceecc80390f10cedb94bd9e4fd655827d7f17 (patch)
treef88cb2995133048b4a2191bae688fa09b33a19ae /gnuradio-runtime/lib
parent9bbbda510c265b211b5b571db79ba259c67ee049 (diff)
runtime: migrate remaining gnuradio-core contents into gnuradio-runtime
Diffstat (limited to 'gnuradio-runtime/lib')
-rw-r--r--gnuradio-runtime/lib/CMakeLists.txt256
-rw-r--r--gnuradio-runtime/lib/ICE_LICENSE54
-rw-r--r--gnuradio-runtime/lib/complex_vec_test.cc82
-rw-r--r--gnuradio-runtime/lib/complex_vec_test.h28
-rw-r--r--gnuradio-runtime/lib/frontend.ice102
-rwxr-xr-xgnuradio-runtime/lib/gen_sine_table.py77
-rw-r--r--gnuradio-runtime/lib/gnuradio.ice154
-rw-r--r--gnuradio-runtime/lib/gr_basic_block.cc226
-rw-r--r--gnuradio-runtime/lib/gr_block.cc687
-rw-r--r--gnuradio-runtime/lib/gr_block_detail.cc473
-rw-r--r--gnuradio-runtime/lib/gr_block_executor.cc487
-rw-r--r--gnuradio-runtime/lib/gr_block_executor.h78
-rw-r--r--gnuradio-runtime/lib/gr_block_gateway.cc184
-rw-r--r--gnuradio-runtime/lib/gr_block_registry.cc76
-rw-r--r--gnuradio-runtime/lib/gr_buffer.cc347
-rw-r--r--gnuradio-runtime/lib/gr_circular_file.cc203
-rw-r--r--gnuradio-runtime/lib/gr_circular_file.h60
-rw-r--r--gnuradio-runtime/lib/gr_constants.cc.in57
-rw-r--r--gnuradio-runtime/lib/gr_dispatcher.cc193
-rw-r--r--gnuradio-runtime/lib/gr_error_handler.cc244
-rw-r--r--gnuradio-runtime/lib/gr_fast_atan2f.cc199
-rw-r--r--gnuradio-runtime/lib/gr_feval.cc132
-rw-r--r--gnuradio-runtime/lib/gr_flat_flowgraph.cc427
-rw-r--r--gnuradio-runtime/lib/gr_flat_flowgraph.h89
-rw-r--r--gnuradio-runtime/lib/gr_flowgraph.cc515
-rw-r--r--gnuradio-runtime/lib/gr_fxpt.cc35
-rw-r--r--gnuradio-runtime/lib/gr_hier_block2.cc153
-rw-r--r--gnuradio-runtime/lib/gr_hier_block2_detail.cc641
-rw-r--r--gnuradio-runtime/lib/gr_hier_block2_detail.h74
-rw-r--r--gnuradio-runtime/lib/gr_io_signature.cc112
-rw-r--r--gnuradio-runtime/lib/gr_local_sighandler.cc187
-rw-r--r--gnuradio-runtime/lib/gr_local_sighandler.h65
-rw-r--r--gnuradio-runtime/lib/gr_logger.cc291
-rw-r--r--gnuradio-runtime/lib/gr_message.cc78
-rw-r--r--gnuradio-runtime/lib/gr_misc.cc65
-rw-r--r--gnuradio-runtime/lib/gr_misc.h39
-rw-r--r--gnuradio-runtime/lib/gr_msg_accepter.cc59
-rw-r--r--gnuradio-runtime/lib/gr_msg_handler.cc30
-rw-r--r--gnuradio-runtime/lib/gr_msg_queue.cc125
-rw-r--r--gnuradio-runtime/lib/gr_pagesize.cc56
-rw-r--r--gnuradio-runtime/lib/gr_pagesize.h34
-rw-r--r--gnuradio-runtime/lib/gr_preferences.cc108
-rw-r--r--gnuradio-runtime/lib/gr_prefs.cc391
-rw-r--r--gnuradio-runtime/lib/gr_random.cc183
-rw-r--r--gnuradio-runtime/lib/gr_random.h65
-rw-r--r--gnuradio-runtime/lib/gr_realtime.cc32
-rw-r--r--gnuradio-runtime/lib/gr_reverse.cc60
-rw-r--r--gnuradio-runtime/lib/gr_reverse.h34
-rw-r--r--gnuradio-runtime/lib/gr_scheduler.cc33
-rw-r--r--gnuradio-runtime/lib/gr_scheduler.h65
-rw-r--r--gnuradio-runtime/lib/gr_scheduler_sts.cc87
-rw-r--r--gnuradio-runtime/lib/gr_scheduler_sts.h63
-rw-r--r--gnuradio-runtime/lib/gr_scheduler_tpb.cc103
-rw-r--r--gnuradio-runtime/lib/gr_scheduler_tpb.h61
-rw-r--r--gnuradio-runtime/lib/gr_select_handler.cc36
-rw-r--r--gnuradio-runtime/lib/gr_sincos.c83
-rw-r--r--gnuradio-runtime/lib/gr_single_threaded_scheduler.cc364
-rw-r--r--gnuradio-runtime/lib/gr_sptr_magic.cc72
-rw-r--r--gnuradio-runtime/lib/gr_sync_block.cc68
-rw-r--r--gnuradio-runtime/lib/gr_sync_decimator.cc69
-rw-r--r--gnuradio-runtime/lib/gr_sync_interpolator.cc70
-rw-r--r--gnuradio-runtime/lib/gr_sys_paths.cc55
-rw-r--r--gnuradio-runtime/lib/gr_tagged_stream_block.cc144
-rw-r--r--gnuradio-runtime/lib/gr_test.cc177
-rw-r--r--gnuradio-runtime/lib/gr_test.h195
-rw-r--r--gnuradio-runtime/lib/gr_test_types.h46
-rw-r--r--gnuradio-runtime/lib/gr_top_block.cc160
-rw-r--r--gnuradio-runtime/lib/gr_top_block_impl.cc211
-rw-r--r--gnuradio-runtime/lib/gr_top_block_impl.h88
-rw-r--r--gnuradio-runtime/lib/gr_tpb_detail.cc70
-rw-r--r--gnuradio-runtime/lib/gr_tpb_thread_body.cc151
-rw-r--r--gnuradio-runtime/lib/gr_tpb_thread_body.h46
-rw-r--r--gnuradio-runtime/lib/gr_vco.h94
-rw-r--r--gnuradio-runtime/lib/gr_vmcircbuf.cc295
-rw-r--r--gnuradio-runtime/lib/gr_vmcircbuf.h122
-rw-r--r--gnuradio-runtime/lib/gr_vmcircbuf_createfilemapping.cc204
-rw-r--r--gnuradio-runtime/lib/gr_vmcircbuf_createfilemapping.h76
-rw-r--r--gnuradio-runtime/lib/gr_vmcircbuf_mmap_shm_open.cc205
-rw-r--r--gnuradio-runtime/lib/gr_vmcircbuf_mmap_shm_open.h67
-rw-r--r--gnuradio-runtime/lib/gr_vmcircbuf_mmap_tmpfile.cc197
-rw-r--r--gnuradio-runtime/lib/gr_vmcircbuf_mmap_tmpfile.h67
-rw-r--r--gnuradio-runtime/lib/gr_vmcircbuf_sysv_shm.cc194
-rw-r--r--gnuradio-runtime/lib/gr_vmcircbuf_sysv_shm.h67
-rw-r--r--gnuradio-runtime/lib/gri_debugger_hook.cc29
-rw-r--r--gnuradio-runtime/lib/gri_debugger_hook.h30
-rw-r--r--gnuradio-runtime/lib/ice_application_base.cc43
-rw-r--r--gnuradio-runtime/lib/malloc16.c46
-rw-r--r--gnuradio-runtime/lib/malloc16.h37
-rw-r--r--gnuradio-runtime/lib/posix_memalign.cc114
-rw-r--r--gnuradio-runtime/lib/posix_memalign.h42
-rw-r--r--gnuradio-runtime/lib/qa_gr_buffer.cc307
-rw-r--r--gnuradio-runtime/lib/qa_gr_buffer.h53
-rw-r--r--gnuradio-runtime/lib/qa_gr_circular_file.cc72
-rw-r--r--gnuradio-runtime/lib/qa_gr_circular_file.h40
-rw-r--r--gnuradio-runtime/lib/qa_gr_fxpt.cc103
-rw-r--r--gnuradio-runtime/lib/qa_gr_fxpt.h48
-rw-r--r--gnuradio-runtime/lib/qa_gr_fxpt_nco.cc119
-rw-r--r--gnuradio-runtime/lib/qa_gr_fxpt_nco.h48
-rw-r--r--gnuradio-runtime/lib/qa_gr_fxpt_vco.cc110
-rw-r--r--gnuradio-runtime/lib/qa_gr_fxpt_vco.h48
-rw-r--r--gnuradio-runtime/lib/qa_gr_io_signature.cc64
-rw-r--r--gnuradio-runtime/lib/qa_gr_io_signature.h46
-rw-r--r--gnuradio-runtime/lib/qa_gr_logger.cc52
-rw-r--r--gnuradio-runtime/lib/qa_gr_logger.h42
-rw-r--r--gnuradio-runtime/lib/qa_gr_math.cc105
-rw-r--r--gnuradio-runtime/lib/qa_gr_math.h42
-rw-r--r--gnuradio-runtime/lib/qa_gr_vmcircbuf.cc40
-rw-r--r--gnuradio-runtime/lib/qa_gr_vmcircbuf.h39
-rw-r--r--gnuradio-runtime/lib/qa_runtime.cc61
-rw-r--r--gnuradio-runtime/lib/qa_runtime.h38
-rw-r--r--gnuradio-runtime/lib/qa_sincos.cc69
-rw-r--r--gnuradio-runtime/lib/qa_sincos.h41
-rw-r--r--gnuradio-runtime/lib/random.h38
-rw-r--r--gnuradio-runtime/lib/rpcmanager.cc72
-rw-r--r--gnuradio-runtime/lib/rpcpmtconverters_ice.cc123
-rw-r--r--gnuradio-runtime/lib/rpcserver_aggregator.cc93
-rw-r--r--gnuradio-runtime/lib/rpcserver_booter_aggregator.cc62
-rw-r--r--gnuradio-runtime/lib/rpcserver_booter_ice.cc54
-rw-r--r--gnuradio-runtime/lib/rpcserver_ice.cc165
-rw-r--r--gnuradio-runtime/lib/rpcserver_selector.cc40
-rw-r--r--gnuradio-runtime/lib/sine_table.h1025
-rw-r--r--gnuradio-runtime/lib/test_runtime.cc42
122 files changed, 16094 insertions, 0 deletions
diff --git a/gnuradio-runtime/lib/CMakeLists.txt b/gnuradio-runtime/lib/CMakeLists.txt
new file mode 100644
index 0000000000..b8ece6e772
--- /dev/null
+++ b/gnuradio-runtime/lib/CMakeLists.txt
@@ -0,0 +1,256 @@
+# Copyright 2013 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(GrMiscUtils)
+GR_CHECK_HDR_N_DEF(sys/resource.h HAVE_SYS_RESOURCE_H)
+
+########################################################################
+# Handle the generated constants
+########################################################################
+execute_process(COMMAND ${PYTHON_EXECUTABLE} -c
+ "import time;print time.strftime('%a, %d %b %Y %H:%M:%S', time.gmtime())"
+ OUTPUT_VARIABLE BUILD_DATE OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+message(STATUS "Loading build date ${BUILD_DATE} into gr_constants...")
+message(STATUS "Loading version ${VERSION} into gr_constants...")
+
+#double escape for windows backslash path separators
+string(REPLACE "\\" "\\\\" prefix ${prefix})
+string(REPLACE "\\" "\\\\" SYSCONFDIR ${SYSCONFDIR})
+string(REPLACE "\\" "\\\\" GR_PREFSDIR ${GR_PREFSDIR})
+
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_constants.cc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/gr_constants.cc
+@ONLY)
+
+list(APPEND gnuradio_runtime_sources ${CMAKE_CURRENT_BINARY_DIR}/gr_constants.cc)
+
+########################################################################
+# Include subdirs rather to populate to the sources lists.
+########################################################################
+#GR_INCLUDE_SUBDIRECTORY(foo)
+
+########################################################################
+# Setup the include and linker paths
+########################################################################
+include_directories(${GNURADIO_RUNTIME_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}/../include/
+ ${Boost_INCLUDE_DIRS}
+ ${GRUEL_INCLUDE_DIRS}
+ ${VOLK_INCLUDE_DIRS}
+)
+
+########################################################################
+# Setup library
+########################################################################
+list(APPEND gnuradio_runtime_sources
+ complex_vec_test.cc
+ gr_basic_block.cc
+ gr_block.cc
+ gr_block_detail.cc
+ gr_block_executor.cc
+ gr_block_gateway.cc
+ gr_block_registry.cc
+ gr_buffer.cc
+ gr_circular_file.cc
+ gr_dispatcher.cc
+ gr_error_handler.cc
+ gr_fast_atan2f.cc
+ gr_feval.cc
+ gr_flat_flowgraph.cc
+ gr_flowgraph.cc
+ gr_fxpt.cc
+ gr_hier_block2.cc
+ gr_hier_block2_detail.cc
+ gri_debugger_hook.cc
+ gr_io_signature.cc
+ gr_local_sighandler.cc
+ gr_logger.cc
+ gr_message.cc
+ gr_misc.cc
+ gr_msg_accepter.cc
+ gr_msg_handler.cc
+ gr_msg_queue.cc
+ gr_pagesize.cc
+ gr_preferences.cc
+ gr_prefs.cc
+ gr_random.cc
+ gr_realtime.cc
+ gr_reverse.cc
+ gr_scheduler.cc
+ gr_scheduler_sts.cc
+ gr_scheduler_tpb.cc
+ gr_select_handler.cc
+ gr_sincos.c
+ gr_single_threaded_scheduler.cc
+ gr_sptr_magic.cc
+ gr_sync_block.cc
+ gr_sync_decimator.cc
+ gr_sync_interpolator.cc
+ gr_sys_paths.cc
+ gr_tagged_stream_block.cc
+ gr_test.cc
+ gr_top_block.cc
+ gr_top_block_impl.cc
+ gr_tpb_detail.cc
+ gr_tpb_thread_body.cc
+ gr_vmcircbuf.cc
+ gr_vmcircbuf_createfilemapping.cc
+ gr_vmcircbuf_mmap_shm_open.cc
+ gr_vmcircbuf_mmap_tmpfile.cc
+ gr_vmcircbuf_sysv_shm.cc
+ malloc16.c
+)
+
+# PowerPC workaround for posix_memalign
+# Might not be needed, but we'll keep it for now.
+if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
+ list(APPEND gnuradio_core_sources
+ ${CMAKE_CURRENT_SOURCE_DIR}/posix_memalign.cc
+ )
+endif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
+
+list(APPEND gnuradio_runtime_libs
+ gruel
+ volk
+ ${Boost_LIBRARIES}
+)
+
+#need to link with librt on ubuntu 11.10 for shm_*
+if(LINUX)
+ list(APPEND gnuradio_runtime_libs rt)
+endif()
+
+if(ENABLE_GR_CTRLPORT)
+
+# Add definition so we can compile in ControlPort to the blocks.
+ADD_DEFINITIONS(-DGR_CTRLPORT)
+
+########################################################################
+# Run ICE To compile Slice files
+########################################################################
+EXECUTE_PROCESS(
+ COMMAND "${ICE_SLICE2CPP}" "-I${CMAKE_CURRENT_SOURCE_DIR}"
+ "--output-dir=${CMAKE_CURRENT_BINARY_DIR}"
+ "${CMAKE_CURRENT_SOURCE_DIR}/gnuradio.ice"
+ )
+
+list(APPEND gnuradio_runtime_sources
+ ice_application_base.cc
+ rpcmanager.cc
+ rpcpmtconverters_ice.cc
+ rpcserver_aggregator.cc
+ rpcserver_booter_aggregator.cc
+ rpcserver_booter_ice.cc
+ rpcserver_ice.cc
+ rpcserver_selector.cc
+ rpcpmtconverters_ice.cc
+)
+
+# Append generated file in build directory
+list(APPEND gnuradio_runtime_sources
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio.cpp
+)
+
+########################################################################
+# Add controlport stuff to gnuradio-runtime
+########################################################################
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+list(APPEND gnuradio_runtime_libs
+ ${ICE_LIBRARIES}
+)
+
+endif(ENABLE_GR_CTRLPORT)
+
+########################################################################
+# Control availability of vmcircbuf methods.
+# For now, only allows disabling of shm methods, which cause uncatchable
+# segmentation faults on Cygwin with gcc 4.x (x <= 5)
+# Usage:
+# GR_VMCIRCBUF()
+#
+# Will set TRY_SHM_VMCIRCBUF to 1 by default except on Windows machines.
+# Can manually set with -DTRY_SHM_VMCIRCBUF=0|1
+########################################################################
+
+if(WIN32)
+ OPTION(TRY_SHM_VMCIRCBUF "Try SHM VMCIRCBUF" OFF)
+else(WIN32)
+ OPTION(TRY_SHM_VMCIRCBUF "Try SHM VMCIRCBUF" ON)
+endif(WIN32)
+
+message(STATUS "TRY_SHM_VMCIRCBUF set to ${TRY_SHM_VMCIRCBUF}.")
+
+if(TRY_SHM_VMCIRCBUF)
+ add_definitions( -DTRY_SHM_VMCIRCBUF )
+endif(TRY_SHM_VMCIRCBUF)
+
+add_library(gnuradio-runtime SHARED ${gnuradio_runtime_sources})
+target_link_libraries(gnuradio-runtime ${gnuradio_runtime_libs})
+GR_LIBRARY_FOO(gnuradio-runtime RUNTIME_COMPONENT "runtime" DEVEL_COMPONENT "runtime_devel")
+set_target_properties(gnuradio-runtime PROPERTIES LINK_INTERFACE_LIBRARIES "gruel")
+
+add_dependencies(gnuradio-runtime
+ runtime_generated_includes
+)
+
+########################################################################
+# Setup tests
+########################################################################
+if(ENABLE_TESTING)
+include(GrTest)
+
+########################################################################
+# Append gnuradio-runtime test sources
+########################################################################
+list(APPEND test_gnuradio_runtime_sources
+ qa_gr_buffer.cc
+ qa_gr_circular_file.cc
+ qa_gr_fxpt.cc
+ qa_gr_fxpt_nco.cc
+ qa_gr_fxpt_vco.cc
+ qa_gr_io_signature.cc
+ qa_gr_logger.cc
+ qa_gr_math.cc
+ qa_gr_vmcircbuf.cc
+ qa_runtime.cc
+ qa_sincos.cc
+)
+
+include_directories(${CPPUNIT_INCLUDE_DIRS})
+link_directories(${CPPUNIT_LIBRARY_DIRS})
+
+add_library(test-gnuradio-runtime SHARED ${test_gnuradio_runtime_sources})
+target_link_libraries(test-gnuradio-runtime gnuradio-runtime ${CPPUNIT_LIBRARIES} ${Boost_LIBRARIES})
+
+########################################################################
+# Build the test executable
+# Set the test environment so the build libs will be found under MSVC.
+########################################################################
+list(APPEND GR_TEST_TARGET_DEPS test-gnuradio-runtime)
+add_executable(gr_runtime_test test_runtime.cc)
+target_link_libraries(gr_runtime_test test-gnuradio-runtime)
+GR_ADD_TEST(gr-runtime-test gr_runtime_test)
+
+endif(ENABLE_TESTING)
+
diff --git a/gnuradio-runtime/lib/ICE_LICENSE b/gnuradio-runtime/lib/ICE_LICENSE
new file mode 100644
index 0000000000..43ea7572d9
--- /dev/null
+++ b/gnuradio-runtime/lib/ICE_LICENSE
@@ -0,0 +1,54 @@
+Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+
+This copy of Ice is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 as
+published by the Free Software Foundation.
+
+Ice 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 version
+2 along with this program; if not, see http://www.gnu.org/licenses.
+
+Linking Ice statically or dynamically with other software (such as a
+library, module or application) is making a combined work based on Ice.
+Thus, the terms and conditions of the GNU General Public License version
+2 cover this combined work.
+
+If such software can only be used together with Ice, then not only the
+combined work but the software itself is a work derived from Ice and as
+such shall be licensed under the terms of the GNU General Public License
+version 2. This includes the situation where Ice is only being used
+through an abstraction layer.
+
+As a special exception to the above, ZeroC grants to the contributors for
+the following projects the permission to license their Ice-based software
+under the terms of the GNU Lesser General Public License (LGPL) version
+2.1 or of the BSD license:
+
+ - Orca Robotics (http://orca-robotics.sourceforge.net)
+
+ - Mumble (http://mumble.sourceforge.net)
+
+This exception does not extend to the parts of Ice used by these
+projects, or to any other derived work: as a whole, any work based on Ice
+shall be licensed under the terms and conditions of the GNU General
+Public License version 2.
+
+You may also combine Ice with any software not derived from Ice, provided
+the license of such software is compatible with the GNU General Public
+License version 2. In addition, as a special exception, ZeroC grants you
+permission to combine Ice with:
+
+ - the OpenSSL library, or with a modified version of the OpenSSL library
+ that uses the same license as OpenSSL
+
+ - any library not derived from Ice and licensed under the terms of
+ the Apache License, version 2.0
+ (http://www.apache.org/licenses/LICENSE-2.0.html)
+
+If you modify this copy of Ice, you may extend any of the exceptions
+provided above to your version of Ice, but you are not obligated to
+do so.
diff --git a/gnuradio-runtime/lib/complex_vec_test.cc b/gnuradio-runtime/lib/complex_vec_test.cc
new file mode 100644
index 0000000000..99acc2f355
--- /dev/null
+++ b/gnuradio-runtime/lib/complex_vec_test.cc
@@ -0,0 +1,82 @@
+#include <complex_vec_test.h>
+#include <stddef.h>
+
+std::vector<std::complex<float> >
+complex_vec_test0()
+{
+ std::vector<std::complex<float> > r(5);
+
+ for (size_t i = 0; i < r.size(); i++)
+ r[i] = std::complex<float>(i, i);
+
+ return r;
+}
+
+std::vector<std::complex<float> >
+complex_vec_test1(const std::vector<std::complex<float> > &input)
+{
+ std::vector<std::complex<float> > r(input.size());
+
+ for (size_t i = 0; i < input.size(); i++)
+ r[i] = std::complex<float>(input[i].real()+0.5, input[i].imag()-0.5);
+
+ return r;
+}
+
+std::complex<float>
+complex_scalar_test0()
+{
+ return std::complex<float>(5, 5);
+}
+
+std::complex<float>
+complex_scalar_test1(std::complex<float> input)
+{
+ return std::complex<float>(input.real()+0.5, input.imag()-0.5);
+}
+
+
+std::vector<float>
+float_vec_test0()
+{
+ std::vector<float> r(5);
+
+ for (size_t i = 0; i < r.size(); i++)
+ r[i] = (float) i;
+
+ return r;
+}
+
+std::vector<float>
+float_vec_test1(const std::vector<float> &input)
+{
+ std::vector<float> r(input.size());
+
+ for (size_t i = 0; i < input.size(); i++)
+ r[i] = input[i] + 0.5;
+
+ return r;
+}
+
+std::vector<int>
+int_vec_test0()
+{
+ std::vector<int> r(5);
+
+ for (size_t i = 0; i < r.size(); i++)
+ r[i] = (int) i;
+
+ return r;
+}
+
+std::vector<int>
+int_vec_test1(const std::vector<int> &input)
+{
+ std::vector<int> r(input.size());
+
+ for (size_t i = 0; i < input.size(); i++)
+ r[i] = input[i] + 1;
+
+ return r;
+}
+
diff --git a/gnuradio-runtime/lib/complex_vec_test.h b/gnuradio-runtime/lib/complex_vec_test.h
new file mode 100644
index 0000000000..bcfa732f41
--- /dev/null
+++ b/gnuradio-runtime/lib/complex_vec_test.h
@@ -0,0 +1,28 @@
+#include <gr_runtime_api.h>
+#include <vector>
+#include <complex>
+
+GR_RUNTIME_API std::vector<std::complex<float> >
+complex_vec_test0();
+
+GR_RUNTIME_API std::vector<std::complex<float> >
+complex_vec_test1(const std::vector<std::complex<float> > &input);
+
+GR_RUNTIME_API std::complex<float>
+complex_scalar_test0();
+
+GR_RUNTIME_API std::complex<float>
+complex_scalar_test1(std::complex<float> input);
+
+GR_RUNTIME_API std::vector<int>
+int_vec_test0();
+
+GR_RUNTIME_API std::vector<int>
+int_vec_test1(const std::vector<int> &input);
+
+GR_RUNTIME_API std::vector<float>
+float_vec_test0();
+
+GR_RUNTIME_API std::vector<float>
+float_vec_test1(const std::vector<float> &input);
+
diff --git a/gnuradio-runtime/lib/frontend.ice b/gnuradio-runtime/lib/frontend.ice
new file mode 100644
index 0000000000..befb5b7a97
--- /dev/null
+++ b/gnuradio-runtime/lib/frontend.ice
@@ -0,0 +1,102 @@
+/*
+ * 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 <gnuradio.ice>
+
+[["python:package:gnuradio.ctrlport"]]
+module GNURadio {
+ module Frontend {
+
+ exception NotSupported {};
+ exception InvalidSetting { string msg; };
+ exception ReceiverFailure { string msg; };
+ exception NotExist {};
+ dictionary<string, string> TunerArgs;
+
+ struct TunerStatus {
+ int a2dbits;
+ float gain;
+ bool isInverted;
+ };
+
+ interface Tuner {
+ TunerStatus configureTuner(TunerArgs args); //ADDED
+ idempotent TunerStatus status();
+ idempotent float setGain(float gain) throws NotSupported, InvalidSetting;
+ idempotent bool setInversion(bool inverted) throws NotSupported, InvalidSetting;
+ };
+
+ struct ChannelStatus {
+ string uid;
+ bool active;
+ float freq;
+ float bandwidth;
+ int payloadBits;
+ bool isComplex;
+ string signalName;
+ };
+
+ interface Channel extends Component {
+ idempotent ChannelStatus status();
+ idempotent FeedInfo feed();
+ idempotent bool active();
+ void start();
+ void stop();
+ idempotent float setCenterFreq(float freq) throws NotSupported, InvalidSetting;
+ idempotent float setBandwidth(float bw) throws NotSupported, InvalidSetting;
+ idempotent int setPayloadBits(int bits) throws NotSupported, InvalidSetting;
+ idempotent bool setComplex(bool complex) throws NotSupported, InvalidSetting;
+ void removeChannel() throws NotSupported;
+ };
+
+ sequence<Tuner*> TunerSeq;
+ sequence<Channel*> ChannelSeq;
+
+ struct ChannelizerStatus {
+ string uid;
+ string signalName;
+ };
+
+ interface Channelizer extends Component {
+ idempotent ChannelizerStatus status();
+ idempotent Tuner* getTuner();
+ idempotent ChannelSeq getChannels();
+ idempotent ChannelSeq getActiveChannels();
+ idempotent ChannelSeq getInactiveChannels();
+ Channel* createChannel(float freq, float bw, int payloadBits, string address, int port) throws NotSupported;
+ };
+
+ sequence<Channelizer*> ChannelizerSeq;
+
+ interface Receiver extends AbstractReceiver {
+ idempotent ChannelizerSeq getInputs();
+// idempotent ChannelizerSeq getActiveInputs();
+// idempotent ChannelizerSeq getInactiveInputs();
+ idempotent Channel* getChannelByID(string id) throws NotExist;
+ idempotent Channelizer* getChannelizerByID(string id) throws NotExist;
+ };
+
+
+ };
+
+
+
+};
diff --git a/gnuradio-runtime/lib/gen_sine_table.py b/gnuradio-runtime/lib/gen_sine_table.py
new file mode 100755
index 0000000000..d7d11eff11
--- /dev/null
+++ b/gnuradio-runtime/lib/gen_sine_table.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+#
+# Copyright 2004 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import math
+import sys
+
+def wrap (x):
+ if x >= 2**31:
+ return x - 2**32
+ return x
+
+def gen_approx_table (f, nentries, min_x, max_x):
+ """return a list of nentries containing tuples of the form:
+ (m, c, abs_error). min_x and max_x specify the domain
+ of the table.
+ """
+ r = []
+ incx = float (max_x - min_x) / nentries
+ for i in range (nentries):
+ a = (i * incx) + min_x
+ b = ((i + 1) * incx) + min_x
+ m = (f(b)-f(a))/(b-a)
+ c = (3*a+b)*(f(a)-f(b))/(4*(b-a)) + (f((a+b)/2) + f(a))/2
+ abs_error = c+m*a-f(a)
+ r.append ((m, c, abs_error))
+ return r
+
+def scaled_sine (x):
+ return math.sin (x * math.pi / 2**31)
+
+def gen_sine_table ():
+ nbits = 10
+ nentries = 2**nbits
+
+ # min_x = -2**31
+ # max_x = 2**31-1
+ min_x = 0
+ max_x = 2**32-1
+ t = gen_approx_table (scaled_sine, nentries, min_x, max_x)
+
+ max_error = 0
+ for e in t:
+ max_error = max (max_error, abs (e[2]))
+
+ # sys.stdout.write ('static const int WORDBITS = 32;\n')
+ # sys.stdout.write ('static const int NBITS = %d;\n' % (nbits,))
+
+ sys.stdout.write (' // max_error = %22.15e\n' % (max_error,))
+
+ # sys.stdout.write ('static const double sine_table[%d][2] = {\n'% (nentries,))
+
+ for e in t:
+ sys.stdout.write (' { %22.15e, %22.15e },\n' % (2 * e[0], e[1]))
+
+ # sys.stdout.write ('};\n')
+
+if __name__ == '__main__':
+ gen_sine_table ()
diff --git a/gnuradio-runtime/lib/gnuradio.ice b/gnuradio-runtime/lib/gnuradio.ice
new file mode 100644
index 0000000000..e17d91901b
--- /dev/null
+++ b/gnuradio-runtime/lib/gnuradio.ice
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+
+[["python:package:gnuradio.ctrlport"]]
+
+#ifndef GNURADIO_DEBUG
+#define GNURADIO_DEBUG
+
+module GNURadio {
+class Knob {};
+class KnobB extends Knob { bool value; };
+class KnobC extends Knob { byte value; };
+class KnobI extends Knob { int value; };
+class KnobF extends Knob { float value; };
+class KnobD extends Knob { double value; };
+class KnobL extends Knob { long value; };
+class KnobS extends Knob { string value; };
+
+sequence<bool> VectorB; sequence<byte> VectorC;
+sequence<int> VectorI; sequence<float> VectorF;
+sequence<double> VectorD; sequence<string> VectorS;
+sequence<long> VectorL;
+
+class KnobVecB extends Knob { VectorB value; };
+class KnobVecC extends Knob { VectorC value; };
+class KnobVecI extends Knob { VectorI value; };
+class KnobVecF extends Knob { VectorF value; };
+class KnobVecD extends Knob { VectorD value; };
+class KnobVecL extends Knob { VectorL value; };
+class KnobVecS extends Knob { VectorS value; };
+
+enum KnobType { KNOBBOOL, KNOBCHAR, KNOBINT, KNOBFLOAT,
+ KNOBDOUBLE, KNOBSTRING, KNOBLONG, KNOBVECBOOL,
+ KNOBVECCHAR, KNOBVECINT, KNOBVECFLOAT, KNOBVECDOUBLE,
+ KNOBVECSTRING, KNOBVECLONG };
+
+const int DISPNULL = 0x0000;
+const int DISPTIME = 0x0001;
+const int DISPXY = 0x0002;
+const int DISPPSD = 0x0004;
+const int DISPSPEC = 0x0008;
+const int DISPRAST = 0x0010;
+const int DISPOPTCPLX = 0x0100;
+const int DISPOPTLOG = 0x0200;
+const int DISPOPTSTEM = 0x0400;
+const int DISPOPTSTRIP = 0x0800;
+const int DISPOPTSCATTER = 0x1000;
+
+struct KnobProp {
+ KnobType type;
+ string units;
+ string description;
+ int display;
+ Knob min;
+ Knob max;
+ Knob defaultvalue;
+};
+
+sequence<string> KnobIDList;
+dictionary<string, Knob> KnobMap;
+dictionary<string, KnobProp> KnobPropMap;
+dictionary<string, string> WaveformArgMap;
+
+interface StreamReceiver {
+ void push(VectorC data);
+};
+
+interface ControlPort {
+ void set(KnobMap knobs);
+ idempotent KnobMap get(KnobIDList knobs);
+ idempotent KnobPropMap properties(KnobIDList knobs);
+ void shutdown();
+
+// string subscribe(StreamReceiver* proxy, string streamName, int requestedPeriod, int RequestedSize);
+// idempotent void unsubscribe(string streamID);
+};
+
+struct FeedInfo {
+ string protocol;
+ string address;
+ string iface;
+ string port;
+};
+
+//TODO: convert this part to a Feed Info
+struct ReceiverInfo {
+ string uid;
+ string signalType;
+ string signalName;
+ string allocatableObjectID;
+ string signalProtocol;
+ string signalAddress;
+ string signalInterface;
+ string signalPort;
+};
+
+interface Component {
+ void setName(string newName);
+};
+
+module Frontend {
+ interface AbstractReceiver extends Component {
+ idempotent ReceiverInfo getReceiverInfo();
+ };
+};
+
+module Booter {
+ dictionary<string, string> WaveformArgs;
+
+ exception WaveformRunningError {
+ string waveformClass;
+ float centerFrequencyHz;
+ };
+ exception SignalSourceError {string msg; };
+
+ interface WaveformBooter extends Frontend::AbstractReceiver {
+ string launchWaveform(string waveformClass, WaveformArgs args)
+ throws WaveformRunningError, SignalSourceError;
+
+// string launchWaveformWithSession(string waveformClass, WaveformArgs args, IceGrid::Session* session)
+// throws WaveformRunningError;
+ WaveformArgMap getDriverEnum();
+ WaveformArgMap getSourceInfo();
+ idempotent bool waveformRunning();
+ idempotent string getWaveformClass();
+ void shutdown();
+ };
+};
+
+//interface Pingable {
+// bool ping();
+//};
+
+};
+
+#endif
diff --git a/gnuradio-runtime/lib/gr_basic_block.cc b/gnuradio-runtime/lib/gr_basic_block.cc
new file mode 100644
index 0000000000..35ea797167
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_basic_block.cc
@@ -0,0 +1,226 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,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_basic_block.h>
+#include <gr_block_registry.h>
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+static long s_next_id = 0;
+static long s_ncurrently_allocated = 0;
+
+long
+gr_basic_block_ncurrently_allocated()
+{
+ return s_ncurrently_allocated;
+}
+
+gr_basic_block::gr_basic_block(const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature)
+ : d_name(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_rpc_set(false),
+ message_subscribers(pmt::make_dict())
+{
+ s_ncurrently_allocated++;
+}
+
+gr_basic_block::~gr_basic_block()
+{
+ s_ncurrently_allocated--;
+ global_block_registry.block_unregister(this);
+}
+
+gr_basic_block_sptr
+gr_basic_block::to_basic_block()
+{
+ 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::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::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::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::is_symbol(port_id)) {
+ throw std::runtime_error("message_port_register_out: bad port id");
+ }
+ if(pmt::dict_has_key(message_subscribers, port_id)) {
+ throw std::runtime_error("message_port_register_out: port already in use");
+ }
+ message_subscribers = pmt::dict_add(message_subscribers, port_id, pmt::PMT_NIL);
+}
+
+pmt::pmt_t
+gr_basic_block::message_ports_out()
+{
+ size_t len = pmt::length(message_subscribers);
+ pmt::pmt_t port_names = pmt::make_vector(len, pmt::PMT_NIL);
+ pmt::pmt_t keys = pmt::dict_keys(message_subscribers);
+ for(size_t i = 0; i < len; i++) {
+ pmt::vector_set(port_names, i, 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::dict_has_key(message_subscribers, port_id)) {
+ throw std::runtime_error("port does not exist");
+ }
+
+ pmt::pmt_t currlist = pmt::dict_ref(message_subscribers, port_id, pmt::PMT_NIL);
+ // iterate through subscribers on port
+ while(pmt::is_pair(currlist)) {
+ pmt::pmt_t target = pmt::car(currlist);
+
+ pmt::pmt_t block = pmt::car(target);
+ pmt::pmt_t port = pmt::cdr(target);
+
+ currlist = 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::dict_has_key(message_subscribers, port_id)){
+ std::stringstream ss;
+ ss << "Port does not exist: \"" << pmt::write_string(port_id) << "\" on block: " << pmt::write_string(target) << std::endl;
+ throw std::runtime_error(ss.str());
+ }
+ pmt::pmt_t currlist = pmt::dict_ref(message_subscribers,port_id,pmt::PMT_NIL);
+
+ // ignore re-adds of the same target
+ if(!pmt::list_has(currlist, target))
+ message_subscribers = pmt::dict_add(message_subscribers,port_id,pmt::list_add(currlist,target));
+}
+
+void
+gr_basic_block::message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target){
+ if(!pmt::dict_has_key(message_subscribers, port_id)){
+ std::stringstream ss;
+ ss << "Port does not exist: \"" << pmt::write_string(port_id) << "\" on block: " << pmt::write_string(target) << std::endl;
+ throw std::runtime_error(ss.str());
+ }
+
+ // ignore unsubs of unknown targets
+ pmt::pmt_t currlist = pmt::dict_ref(message_subscribers,port_id,pmt::PMT_NIL);
+ message_subscribers = pmt::dict_add(message_subscribers,port_id,pmt::list_rm(currlist,target));
+}
+
+void
+gr_basic_block::_post(pmt::pmt_t which_port, pmt::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::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::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::pmt_t m(msg_queue[which_port].front());
+ msg_queue[which_port].pop_front();
+
+ return m;
+}
+
+pmt::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::pmt_t m(msg_queue[which_port].front());
+ msg_queue[which_port].pop_front();
+ return m;
+}
diff --git a/gnuradio-runtime/lib/gr_block.cc b/gnuradio-runtime/lib/gr_block.cc
new file mode 100644
index 0000000000..8c8b85dc7e
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_block.cc
@@ -0,0 +1,687 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2009,2010,2013 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_block.h>
+#include <gr_block_detail.h>
+#include <stdexcept>
+#include <iostream>
+#include <gr_block_registry.h>
+#include <gr_prefs.h>
+
+gr_block::gr_block (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_output_multiple (1),
+ d_output_multiple_set(false),
+ d_unaligned(0),
+ d_is_unaligned(false),
+ d_relative_rate (1.0),
+ d_history(1),
+ d_fixed_rate(false),
+ d_max_noutput_items_set(false),
+ d_max_noutput_items(0),
+ d_min_noutput_items(0),
+ d_tag_propagation_policy(TPP_ALL_TO_ALL),
+ d_pc_rpc_set(false),
+ 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);
+
+#ifdef ENABLE_GR_LOG
+#ifdef HAVE_LOG4CPP
+ gr_prefs *p = gr_prefs::singleton();
+ std::string config_file = p->get_string("LOG", "log_config", "");
+ std::string log_level = p->get_string("LOG", "log_level", "off");
+ std::string log_file = p->get_string("LOG", "log_file", "");
+ std::string debug_level = p->get_string("LOG", "debug_level", "off");
+ std::string debug_file = p->get_string("LOG", "debug_file", "");
+
+ GR_CONFIG_LOGGER(config_file);
+
+ GR_LOG_GETLOGGER(LOG, "gr_log." + alias());
+ GR_LOG_SET_LEVEL(LOG, log_level);
+ if(log_file.size() > 0) {
+ if(log_file == "stdout") {
+ GR_LOG_ADD_CONSOLE_APPENDER(LOG, "cout","gr::log :%p: %c{1} - %m%n");
+ }
+ else if(log_file == "stderr") {
+ GR_LOG_ADD_CONSOLE_APPENDER(LOG, "cerr","gr::log :%p: %c{1} - %m%n");
+ }
+ else {
+ GR_LOG_ADD_FILE_APPENDER(LOG, log_file , true,"%r :%p: %c{1} - %m%n");
+ }
+ }
+ d_logger = LOG;
+
+ GR_LOG_GETLOGGER(DLOG, "gr_log_debug." + alias());
+ GR_LOG_SET_LEVEL(DLOG, debug_level);
+ if(debug_file.size() > 0) {
+ if(debug_file == "stdout") {
+ GR_LOG_ADD_CONSOLE_APPENDER(DLOG, "cout","gr::debug :%p: %c{1} - %m%n");
+ }
+ else if(debug_file == "stderr") {
+ GR_LOG_ADD_CONSOLE_APPENDER(DLOG, "cerr", "gr::debug :%p: %c{1} - %m%n");
+ }
+ else {
+ GR_LOG_ADD_FILE_APPENDER(DLOG, debug_file, true, "%r :%p: %c{1} - %m%n");
+ }
+ }
+ d_debug_logger = DLOG;
+#endif /* HAVE_LOG4CPP */
+#else /* ENABLE_GR_LOG */
+ d_logger = NULL;
+ d_debug_logger = NULL;
+#endif /* ENABLE_GR_LOG */
+}
+
+gr_block::~gr_block ()
+{
+ global_block_registry.unregister_primitive(alias());
+}
+
+// stub implementation: 1:1
+
+void
+gr_block::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+{
+ unsigned ninputs = ninput_items_required.size ();
+ for (unsigned i = 0; i < ninputs; i++)
+ ninput_items_required[i] = noutput_items + history() - 1;
+}
+
+// default implementation
+
+bool
+gr_block::start()
+{
+ return true;
+}
+
+bool
+gr_block::stop()
+{
+ return true;
+}
+
+void
+gr_block::set_output_multiple (int multiple)
+{
+ if (multiple < 1)
+ throw std::invalid_argument ("gr_block::set_output_multiple");
+
+ d_output_multiple_set = true;
+ d_output_multiple = multiple;
+}
+
+void
+gr_block::set_alignment (int multiple)
+{
+ if (multiple < 1)
+ throw std::invalid_argument ("gr_block::set_alignment_multiple");
+
+ d_output_multiple = multiple;
+}
+
+void
+gr_block::set_unaligned (int na)
+{
+ // unaligned value must be less than 0 and it doesn't make sense
+ // that it's larger than the alignment value.
+ if ((na < 0) || (na > d_output_multiple))
+ throw std::invalid_argument ("gr_block::set_unaligned");
+
+ d_unaligned = na;
+}
+
+void
+gr_block::set_is_unaligned (bool u)
+{
+ d_is_unaligned = u;
+}
+
+void
+gr_block::set_relative_rate (double relative_rate)
+{
+ if (relative_rate < 0.0)
+ throw std::invalid_argument ("gr_block::set_relative_rate");
+
+ d_relative_rate = relative_rate;
+}
+
+
+void
+gr_block::consume (int which_input, int how_many_items)
+{
+ d_detail->consume (which_input, how_many_items);
+}
+
+void
+gr_block::consume_each (int how_many_items)
+{
+ d_detail->consume_each (how_many_items);
+}
+
+void
+gr_block::produce (int which_output, int how_many_items)
+{
+ d_detail->produce (which_output, how_many_items);
+}
+
+int
+gr_block::fixed_rate_ninput_to_noutput(int ninput)
+{
+ throw std::runtime_error("Unimplemented");
+}
+
+int
+gr_block::fixed_rate_noutput_to_ninput(int noutput)
+{
+ throw std::runtime_error("Unimplemented");
+}
+
+uint64_t
+gr_block::nitems_read(unsigned int which_input)
+{
+ if(d_detail) {
+ return d_detail->nitems_read(which_input);
+ }
+ else {
+ //throw std::runtime_error("No block_detail associated with block yet");
+ return 0;
+ }
+}
+
+uint64_t
+gr_block::nitems_written(unsigned int which_output)
+{
+ if(d_detail) {
+ return d_detail->nitems_written(which_output);
+ }
+ else {
+ //throw std::runtime_error("No block_detail associated with block yet");
+ return 0;
+ }
+}
+
+void
+gr_block::add_item_tag(unsigned int which_output,
+ const gr_tag_t &tag)
+{
+ d_detail->add_item_tag(which_output, tag);
+}
+
+void
+gr_block::remove_item_tag(unsigned int which_input,
+ const gr_tag_t &tag)
+{
+ d_detail->remove_item_tag(which_input, tag);
+}
+
+void
+gr_block::get_tags_in_range(std::vector<gr_tag_t> &v,
+ unsigned int which_output,
+ uint64_t start, uint64_t end)
+{
+ d_detail->get_tags_in_range(v, which_output, start, end);
+}
+
+void
+gr_block::get_tags_in_range(std::vector<gr_tag_t> &v,
+ unsigned int which_output,
+ uint64_t start, uint64_t end,
+ const pmt::pmt_t &key)
+{
+ d_detail->get_tags_in_range(v, which_output, start, end, key);
+}
+
+gr_block::tag_propagation_policy_t
+gr_block::tag_propagation_policy()
+{
+ return d_tag_propagation_policy;
+}
+
+void
+gr_block::set_tag_propagation_policy(tag_propagation_policy_t p)
+{
+ d_tag_propagation_policy = p;
+}
+
+
+int
+gr_block::max_noutput_items()
+{
+ return d_max_noutput_items;
+}
+
+void
+gr_block::set_max_noutput_items(int m)
+{
+ if(m <= 0)
+ throw std::runtime_error("gr_block::set_max_noutput_items: value for max_noutput_items must be greater than 0.\n");
+
+ d_max_noutput_items = m;
+ d_max_noutput_items_set = true;
+}
+
+void
+gr_block::unset_max_noutput_items()
+{
+ d_max_noutput_items_set = false;
+}
+
+bool
+gr_block::is_set_max_noutput_items()
+{
+ return d_max_noutput_items_set;
+}
+
+void
+gr_block::set_processor_affinity(const std::vector<unsigned int> &mask)
+{
+ d_affinity = mask;
+ if(d_detail) {
+ d_detail->set_processor_affinity(d_affinity);
+ }
+}
+
+void
+gr_block::unset_processor_affinity()
+{
+ d_affinity.clear();
+ if(d_detail) {
+ d_detail->unset_processor_affinity();
+ }
+}
+
+float
+gr_block::pc_noutput_items()
+{
+ if(d_detail) {
+ return d_detail->pc_noutput_items();
+ }
+ else {
+ return 0;
+ }
+}
+
+float
+gr_block::pc_noutput_items_avg()
+{
+ if(d_detail) {
+ return d_detail->pc_noutput_items_avg();
+ }
+ else {
+ return 0;
+ }
+}
+
+float
+gr_block::pc_noutput_items_var()
+{
+ if(d_detail) {
+ return d_detail->pc_noutput_items_var();
+ }
+ else {
+ return 0;
+ }
+}
+
+float
+gr_block::pc_nproduced()
+{
+ if(d_detail) {
+ return d_detail->pc_nproduced();
+ }
+ else {
+ return 0;
+ }
+}
+
+float
+gr_block::pc_nproduced_avg()
+{
+ if(d_detail) {
+ return d_detail->pc_nproduced_avg();
+ }
+ else {
+ return 0;
+ }
+}
+
+float
+gr_block::pc_nproduced_var()
+{
+ if(d_detail) {
+ return d_detail->pc_nproduced_var();
+ }
+ else {
+ return 0;
+ }
+}
+
+float
+gr_block::pc_input_buffers_full(int which)
+{
+ if(d_detail) {
+ return d_detail->pc_input_buffers_full(static_cast<size_t>(which));
+ }
+ else {
+ return 0;
+ }
+}
+
+float
+gr_block::pc_input_buffers_full_avg(int which)
+{
+ if(d_detail) {
+ return d_detail->pc_input_buffers_full_avg(static_cast<size_t>(which));
+ }
+ else {
+ return 0;
+ }
+}
+
+float
+gr_block::pc_input_buffers_full_var(int which)
+{
+ if(d_detail) {
+ return d_detail->pc_input_buffers_full_var(static_cast<size_t>(which));
+ }
+ else {
+ return 0;
+ }
+}
+
+std::vector<float>
+gr_block::pc_input_buffers_full()
+{
+ if(d_detail) {
+ return d_detail->pc_input_buffers_full();
+ }
+ else {
+ return std::vector<float>(1,0);
+ }
+}
+
+std::vector<float>
+gr_block::pc_input_buffers_full_avg()
+{
+ if(d_detail) {
+ return d_detail->pc_input_buffers_full_avg();
+ }
+ else {
+ return std::vector<float>(1,0);
+ }
+}
+
+std::vector<float>
+gr_block::pc_input_buffers_full_var()
+{
+ if(d_detail) {
+ return d_detail->pc_input_buffers_full_var();
+ }
+ else {
+ return std::vector<float>(1,0);
+ }
+}
+
+float
+gr_block::pc_output_buffers_full(int which)
+{
+ if(d_detail) {
+ return d_detail->pc_output_buffers_full(static_cast<size_t>(which));
+ }
+ else {
+ return 0;
+ }
+}
+
+float
+gr_block::pc_output_buffers_full_avg(int which)
+{
+ if(d_detail) {
+ return d_detail->pc_output_buffers_full_avg(static_cast<size_t>(which));
+ }
+ else {
+ return 0;
+ }
+}
+
+float
+gr_block::pc_output_buffers_full_var(int which)
+{
+ if(d_detail) {
+ return d_detail->pc_output_buffers_full_var(static_cast<size_t>(which));
+ }
+ else {
+ return 0;
+ }
+}
+
+std::vector<float>
+gr_block::pc_output_buffers_full()
+{
+ if(d_detail) {
+ return d_detail->pc_output_buffers_full();
+ }
+ else {
+ return std::vector<float>(1,0);
+ }
+}
+
+std::vector<float>
+gr_block::pc_output_buffers_full_avg()
+{
+ if(d_detail) {
+ return d_detail->pc_output_buffers_full_avg();
+ }
+ else {
+ return std::vector<float>(1,0);
+ }
+}
+
+std::vector<float>
+gr_block::pc_output_buffers_full_var()
+{
+ if(d_detail) {
+ return d_detail->pc_output_buffers_full_var();
+ }
+ else {
+ return std::vector<float>(1,0);
+ }
+}
+
+float
+gr_block::pc_work_time()
+{
+ if(d_detail) {
+ return d_detail->pc_work_time();
+ }
+ else {
+ return 0;
+ }
+}
+
+float
+gr_block::pc_work_time_avg()
+{
+ if(d_detail) {
+ return d_detail->pc_work_time_avg();
+ }
+ else {
+ return 0;
+ }
+}
+
+float
+gr_block::pc_work_time_var()
+{
+ if(d_detail) {
+ return d_detail->pc_work_time_var();
+ }
+ else {
+ return 0;
+ }
+}
+
+void
+gr_block::reset_perf_counters()
+{
+ if(d_detail) {
+ d_detail->reset_perf_counters();
+ }
+}
+
+void
+gr_block::setup_pc_rpc()
+{
+ d_pc_rpc_set = true;
+#ifdef GR_CTRLPORT
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>(
+ alias(), "noutput_items", &gr_block::pc_noutput_items,
+ pmt::mp(0), pmt::mp(32768), pmt::mp(0),
+ "", "noutput items", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>(
+ alias(), "avg noutput_items", &gr_block::pc_noutput_items_avg,
+ pmt::mp(0), pmt::mp(32768), pmt::mp(0),
+ "", "Average noutput items", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>(
+ alias(), "var noutput_items", &gr_block::pc_noutput_items_var,
+ pmt::mp(0), pmt::mp(32768), pmt::mp(0),
+ "", "Var. noutput items", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>(
+ alias(), "nproduced", &gr_block::pc_nproduced,
+ pmt::mp(0), pmt::mp(32768), pmt::mp(0),
+ "", "items produced", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>(
+ alias(), "avg nproduced", &gr_block::pc_nproduced_avg,
+ pmt::mp(0), pmt::mp(32768), pmt::mp(0),
+ "", "Average items produced", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>(
+ alias(), "var nproduced", &gr_block::pc_nproduced_var,
+ pmt::mp(0), pmt::mp(32768), pmt::mp(0),
+ "", "Var. items produced", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>(
+ alias(), "work time", &gr_block::pc_work_time,
+ pmt::mp(0), pmt::mp(1e9), pmt::mp(0),
+ "", "clock cycles in call to work", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>(
+ alias(), "avg work time", &gr_block::pc_work_time_avg,
+ pmt::mp(0), pmt::mp(1e9), pmt::mp(0),
+ "", "Average clock cycles in call to work", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>(
+ alias(), "var work time", &gr_block::pc_work_time_var,
+ pmt::mp(0), pmt::mp(1e9), pmt::mp(0),
+ "", "Var. clock cycles in call to work", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, std::vector<float> >(
+ alias(), "input \% full", &gr_block::pc_input_buffers_full,
+ pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0),
+ "", "how full input buffers are", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, std::vector<float> >(
+ alias(), "avg input \% full", &gr_block::pc_input_buffers_full_avg,
+ pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0),
+ "", "Average of how full input buffers are", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, std::vector<float> >(
+ alias(), "var input \% full", &gr_block::pc_input_buffers_full_var,
+ pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0),
+ "", "Var. of how full input buffers are", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, std::vector<float> >(
+ alias(), "output \% full", &gr_block::pc_output_buffers_full,
+ pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0),
+ "", "how full output buffers are", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, std::vector<float> >(
+ alias(), "avg output \% full", &gr_block::pc_output_buffers_full_avg,
+ pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0),
+ "", "Average of how full output buffers are", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_block, std::vector<float> >(
+ alias(), "var output \% full", &gr_block::pc_output_buffers_full_var,
+ pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0),
+ "", "Var. of how full output buffers are", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+#endif /* GR_CTRLPORT */
+}
+
+std::ostream&
+operator << (std::ostream& os, const gr_block *m)
+{
+ os << "<gr_block " << m->name() << " (" << m->unique_id() << ")>";
+ 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-runtime/lib/gr_block_detail.cc b/gnuradio-runtime/lib/gr_block_detail.cc
new file mode 100644
index 0000000000..c85c0e9fba
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_block_detail.cc
@@ -0,0 +1,473 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2009,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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_block_detail.h>
+#include <gr_buffer.h>
+#include <iostream>
+
+static long s_ncurrently_allocated = 0;
+
+long
+gr_block_detail_ncurrently_allocated ()
+{
+ return s_ncurrently_allocated;
+}
+
+gr_block_detail::gr_block_detail (unsigned int ninputs, unsigned int noutputs)
+ : d_produce_or(0),
+ d_ninputs (ninputs), d_noutputs (noutputs),
+ d_input (ninputs), d_output (noutputs),
+ d_done (false),
+ d_ins_noutput_items(0),
+ d_avg_noutput_items(0),
+ d_var_noutput_items(0),
+ d_ins_nproduced(0),
+ d_avg_nproduced(0),
+ d_var_nproduced(0),
+ d_ins_input_buffers_full(ninputs, 0),
+ d_avg_input_buffers_full(ninputs, 0),
+ d_var_input_buffers_full(ninputs, 0),
+ d_ins_output_buffers_full(noutputs, 0),
+ d_avg_output_buffers_full(noutputs, 0),
+ d_var_output_buffers_full(noutputs, 0),
+ d_ins_work_time(0),
+ d_avg_work_time(0),
+ d_var_work_time(0),
+ d_pc_counter(0)
+{
+ s_ncurrently_allocated++;
+}
+
+gr_block_detail::~gr_block_detail ()
+{
+ // should take care of itself
+ s_ncurrently_allocated--;
+}
+
+void
+gr_block_detail::set_input (unsigned int which, gr_buffer_reader_sptr reader)
+{
+ if (which >= d_ninputs)
+ throw std::invalid_argument ("gr_block_detail::set_input");
+
+ d_input[which] = reader;
+}
+
+void
+gr_block_detail::set_output (unsigned int which, gr_buffer_sptr buffer)
+{
+ if (which >= d_noutputs)
+ throw std::invalid_argument ("gr_block_detail::set_output");
+
+ d_output[which] = buffer;
+}
+
+gr_block_detail_sptr
+gr_make_block_detail (unsigned int ninputs, unsigned int noutputs)
+{
+ return gr_block_detail_sptr (new gr_block_detail (ninputs, noutputs));
+}
+
+void
+gr_block_detail::set_done (bool done)
+{
+ d_done = done;
+ for (unsigned int i = 0; i < d_noutputs; i++)
+ d_output[i]->set_done (done);
+
+ for (unsigned int i = 0; i < d_ninputs; i++)
+ d_input[i]->set_done (done);
+}
+
+void
+gr_block_detail::consume (int which_input, int how_many_items)
+{
+ if (how_many_items > 0) {
+ input (which_input)->update_read_pointer (how_many_items);
+ }
+}
+
+
+void
+gr_block_detail::consume_each (int how_many_items)
+{
+ if (how_many_items > 0) {
+ for (int i = 0; i < ninputs (); i++) {
+ d_input[i]->update_read_pointer (how_many_items);
+ }
+ }
+}
+
+void
+gr_block_detail::produce (int which_output, int how_many_items)
+{
+ if (how_many_items > 0){
+ d_output[which_output]->update_write_pointer (how_many_items);
+ d_produce_or |= how_many_items;
+ }
+}
+
+void
+gr_block_detail::produce_each (int how_many_items)
+{
+ if (how_many_items > 0) {
+ for (int i = 0; i < noutputs (); i++) {
+ d_output[i]->update_write_pointer (how_many_items);
+ }
+ d_produce_or |= how_many_items;
+ }
+}
+
+
+uint64_t
+gr_block_detail::nitems_read(unsigned int which_input)
+{
+ if(which_input >= d_ninputs)
+ throw std::invalid_argument ("gr_block_detail::n_input_items");
+ return d_input[which_input]->nitems_read();
+}
+
+uint64_t
+gr_block_detail::nitems_written(unsigned int which_output)
+{
+ if(which_output >= d_noutputs)
+ throw std::invalid_argument ("gr_block_detail::n_output_items");
+ return d_output[which_output]->nitems_written();
+}
+
+void
+gr_block_detail::add_item_tag(unsigned int which_output, const gr_tag_t &tag)
+{
+ if(!pmt::is_symbol(tag.key)) {
+ throw pmt::wrong_type("gr_block_detail::add_item_tag key", tag.key);
+ }
+ else {
+ // Add tag to gr_buffer's deque tags
+ d_output[which_output]->add_item_tag(tag);
+ }
+}
+
+void
+gr_block_detail::remove_item_tag(unsigned int which_input, const gr_tag_t &tag)
+{
+ if(!pmt::is_symbol(tag.key)) {
+ throw pmt::wrong_type("gr_block_detail::add_item_tag key", tag.key);
+ }
+ else {
+ // Add tag to gr_buffer's deque tags
+ d_input[which_input]->buffer()->remove_item_tag(tag);
+ }
+}
+
+void
+gr_block_detail::get_tags_in_range(std::vector<gr_tag_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end)
+{
+ // get from gr_buffer_reader's deque of tags
+ d_input[which_input]->get_tags_in_range(v, abs_start, abs_end);
+}
+
+void
+gr_block_detail::get_tags_in_range(std::vector<gr_tag_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end,
+ const pmt::pmt_t &key)
+{
+ std::vector<gr_tag_t> found_items;
+
+ v.resize(0);
+
+ // get from gr_buffer_reader's deque of tags
+ d_input[which_input]->get_tags_in_range(found_items, abs_start, abs_end);
+
+ // Filter further by key name
+ pmt::pmt_t itemkey;
+ std::vector<gr_tag_t>::iterator itr;
+ for(itr = found_items.begin(); itr != found_items.end(); itr++) {
+ itemkey = (*itr).key;
+ if(pmt::eqv(key, itemkey)) {
+ v.push_back(*itr);
+ }
+ }
+}
+
+void
+gr_block_detail::set_processor_affinity(const std::vector<unsigned int> &mask)
+{
+ if(threaded) {
+ try {
+ gruel::thread_bind_to_processor(thread, mask);
+ }
+ catch (std::runtime_error e) {
+ std::cerr << "set_processor_affinity: invalid mask." << std::endl;;
+ }
+ }
+}
+
+void
+gr_block_detail::unset_processor_affinity()
+{
+ if(threaded) {
+ gruel::thread_unbind(thread);
+ }
+}
+
+void
+gr_block_detail::start_perf_counters()
+{
+ d_start_of_work = gruel::high_res_timer_now();
+}
+
+void
+gr_block_detail::stop_perf_counters(int noutput_items, int nproduced)
+{
+ d_end_of_work = gruel::high_res_timer_now();
+ gruel::high_res_timer_type diff = d_end_of_work - d_start_of_work;
+
+ if(d_pc_counter == 0) {
+ d_ins_work_time = diff;
+ d_avg_work_time = diff;
+ d_var_work_time = 0;
+ d_ins_nproduced = nproduced;
+ d_avg_nproduced = nproduced;
+ d_var_nproduced = 0;
+ d_ins_noutput_items = noutput_items;
+ d_avg_noutput_items = noutput_items;
+ d_var_noutput_items = 0;
+ for(size_t i=0; i < d_input.size(); i++) {
+ float pfull = static_cast<float>(d_input[i]->items_available()) /
+ static_cast<float>(d_input[i]->max_possible_items_available());
+ d_ins_input_buffers_full[i] = pfull;
+ d_avg_input_buffers_full[i] = pfull;
+ d_var_input_buffers_full[i] = 0;
+ }
+ for(size_t i=0; i < d_output.size(); i++) {
+ float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) /
+ static_cast<float>(d_output[i]->bufsize());
+ d_ins_output_buffers_full[i] = pfull;
+ d_avg_output_buffers_full[i] = pfull;
+ d_var_output_buffers_full[i] = 0;
+ }
+ }
+ else {
+ float d = diff - d_avg_work_time;
+ d_ins_work_time = diff;
+ d_avg_work_time = d_avg_work_time + d/d_pc_counter;
+ d_var_work_time = d_var_work_time + d*d;
+
+ d = nproduced - d_avg_nproduced;
+ d_ins_nproduced = nproduced;
+ d_avg_nproduced = d_avg_nproduced + d/d_pc_counter;
+ d_var_nproduced = d_var_nproduced + d*d;
+
+ d = noutput_items - d_avg_noutput_items;
+ d_ins_noutput_items = noutput_items;
+ d_avg_noutput_items = d_avg_noutput_items + d/d_pc_counter;
+ d_var_noutput_items = d_var_noutput_items + d*d;
+
+ for(size_t i=0; i < d_input.size(); i++) {
+ float pfull = static_cast<float>(d_input[i]->items_available()) /
+ static_cast<float>(d_input[i]->max_possible_items_available());
+
+ d = pfull - d_avg_input_buffers_full[i];
+ d_ins_input_buffers_full[i] = pfull;
+ d_avg_input_buffers_full[i] = d_avg_input_buffers_full[i] + d/d_pc_counter;
+ d_var_input_buffers_full[i] = d_var_input_buffers_full[i] + d*d;
+ }
+
+ for(size_t i=0; i < d_output.size(); i++) {
+ float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) /
+ static_cast<float>(d_output[i]->bufsize());
+
+ d = pfull - d_avg_output_buffers_full[i];
+ d_ins_output_buffers_full[i] = pfull;
+ d_avg_output_buffers_full[i] = d_avg_output_buffers_full[i] + d/d_pc_counter;
+ d_var_output_buffers_full[i] = d_var_output_buffers_full[i] + d*d;
+ }
+ }
+
+ d_pc_counter++;
+}
+
+void
+gr_block_detail::reset_perf_counters()
+{
+ d_pc_counter = 0;
+}
+
+float
+gr_block_detail::pc_noutput_items()
+{
+ return d_ins_noutput_items;
+}
+
+float
+gr_block_detail::pc_nproduced()
+{
+ return d_ins_nproduced;
+}
+
+float
+gr_block_detail::pc_input_buffers_full(size_t which)
+{
+ if(which < d_ins_input_buffers_full.size())
+ return d_ins_input_buffers_full[which];
+ else
+ return 0;
+}
+
+std::vector<float>
+gr_block_detail::pc_input_buffers_full()
+{
+ return d_ins_input_buffers_full;
+}
+
+float
+gr_block_detail::pc_output_buffers_full(size_t which)
+{
+ if(which < d_ins_output_buffers_full.size())
+ return d_ins_output_buffers_full[which];
+ else
+ return 0;
+}
+
+std::vector<float>
+gr_block_detail::pc_output_buffers_full()
+{
+ return d_ins_output_buffers_full;
+}
+
+float
+gr_block_detail::pc_work_time()
+{
+ return d_ins_work_time;
+}
+
+float
+gr_block_detail::pc_noutput_items_avg()
+{
+ return d_avg_noutput_items;
+}
+
+float
+gr_block_detail::pc_nproduced_avg()
+{
+ return d_avg_nproduced;
+}
+
+float
+gr_block_detail::pc_input_buffers_full_avg(size_t which)
+{
+ if(which < d_avg_input_buffers_full.size())
+ return d_avg_input_buffers_full[which];
+ else
+ return 0;
+}
+
+std::vector<float>
+gr_block_detail::pc_input_buffers_full_avg()
+{
+ return d_avg_input_buffers_full;
+}
+
+float
+gr_block_detail::pc_output_buffers_full_avg(size_t which)
+{
+ if(which < d_avg_output_buffers_full.size())
+ return d_avg_output_buffers_full[which];
+ else
+ return 0;
+}
+
+std::vector<float>
+gr_block_detail::pc_output_buffers_full_avg()
+{
+ return d_avg_output_buffers_full;
+}
+
+float
+gr_block_detail::pc_work_time_avg()
+{
+ return d_avg_work_time;
+}
+
+
+float
+gr_block_detail::pc_noutput_items_var()
+{
+ return d_var_noutput_items/(d_pc_counter-1);
+}
+
+float
+gr_block_detail::pc_nproduced_var()
+{
+ return d_var_nproduced/(d_pc_counter-1);
+}
+
+float
+gr_block_detail::pc_input_buffers_full_var(size_t which)
+{
+ if(which < d_avg_input_buffers_full.size())
+ return d_var_input_buffers_full[which]/(d_pc_counter-1);
+ else
+ return 0;
+}
+
+std::vector<float>
+gr_block_detail::pc_input_buffers_full_var()
+{
+ std::vector<float> var(d_avg_input_buffers_full.size(), 0);
+ for(size_t i = 0; i < d_avg_input_buffers_full.size(); i++)
+ var[i] = d_avg_input_buffers_full[i]/(d_pc_counter-1);
+ return var;
+}
+
+float
+gr_block_detail::pc_output_buffers_full_var(size_t which)
+{
+ if(which < d_avg_output_buffers_full.size())
+ return d_var_output_buffers_full[which]/(d_pc_counter-1);
+ else
+ return 0;
+}
+
+std::vector<float>
+gr_block_detail::pc_output_buffers_full_var()
+{
+ std::vector<float> var(d_avg_output_buffers_full.size(), 0);
+ for(size_t i = 0; i < d_avg_output_buffers_full.size(); i++)
+ var[i] = d_avg_output_buffers_full[i]/(d_pc_counter-1);
+ return var;
+}
+
+float
+gr_block_detail::pc_work_time_var()
+{
+ return d_var_work_time/(d_pc_counter-1);
+}
diff --git a/gnuradio-runtime/lib/gr_block_executor.cc b/gnuradio-runtime/lib/gr_block_executor.cc
new file mode 100644
index 0000000000..e070f3c508
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_block_executor.cc
@@ -0,0 +1,487 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2008,2009,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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_block_executor.h>
+#include <gr_block.h>
+#include <gr_block_detail.h>
+#include <gr_buffer.h>
+#include <gr_prefs.h>
+#include <boost/thread.hpp>
+#include <boost/format.hpp>
+#include <iostream>
+#include <limits>
+#include <assert.h>
+#include <stdio.h>
+
+// must be defined to either 0 or 1
+#define ENABLE_LOGGING 0
+
+#if (ENABLE_LOGGING)
+#define LOG(x) do { x; } while(0)
+#else
+#define LOG(x) do {;} while(0)
+#endif
+
+static int which_scheduler = 0;
+
+inline static unsigned int
+round_up (unsigned int n, unsigned int multiple)
+{
+ return ((n + multiple - 1) / multiple) * multiple;
+}
+
+inline static unsigned int
+round_down (unsigned int n, unsigned int multiple)
+{
+ return (n / multiple) * multiple;
+}
+
+//
+// Return minimum available write space in all our downstream buffers
+// or -1 if we're output blocked and the output we're blocked
+// on is done.
+//
+static int
+min_available_space (gr_block_detail *d, int output_multiple, int min_noutput_items)
+{
+ int min_space = std::numeric_limits<int>::max();
+ if (min_noutput_items == 0)
+ min_noutput_items = 1;
+ for (int i = 0; i < d->noutputs (); i++){
+ gruel::scoped_lock guard(*d->output(i)->mutex());
+ int avail_n = round_down(d->output(i)->space_available(), output_multiple);
+ int best_n = round_down(d->output(i)->bufsize()/2, output_multiple);
+ if (best_n < min_noutput_items)
+ throw std::runtime_error("Buffer too small for min_noutput_items");
+ int n = std::min(avail_n, best_n);
+ if (n < min_noutput_items){ // We're blocked on output.
+ if (d->output(i)->done()){ // Downstream is done, therefore we're done.
+ return -1;
+ }
+ return 0;
+ }
+ min_space = std::min (min_space, n);
+ }
+ return min_space;
+}
+
+static bool
+propagate_tags(gr_block::tag_propagation_policy_t policy, gr_block_detail *d,
+ const std::vector<uint64_t> &start_nitems_read, double rrate,
+ std::vector<gr_tag_t> &rtags)
+{
+ // Move tags downstream
+ // if a sink, we don't need to move downstream
+ if(d->sink_p()) {
+ return true;
+ }
+
+ switch(policy) {
+ case gr_block::TPP_DONT:
+ return true;
+ break;
+ case gr_block::TPP_ALL_TO_ALL:
+ // every tag on every input propogates to everyone downstream
+ for(int i = 0; i < d->ninputs(); i++) {
+ d->get_tags_in_range(rtags, i, start_nitems_read[i],
+ d->nitems_read(i));
+
+ std::vector<gr_tag_t>::iterator t;
+ if(rrate == 1.0) {
+ for(t = rtags.begin(); t != rtags.end(); t++) {
+ for(int o = 0; o < d->noutputs(); o++)
+ d->output(o)->add_item_tag(*t);
+ }
+ }
+ else {
+ for(t = rtags.begin(); t != rtags.end(); t++) {
+ gr_tag_t new_tag = *t;
+ new_tag.offset *= rrate;
+ for(int o = 0; o < d->noutputs(); o++)
+ d->output(o)->add_item_tag(new_tag);
+ }
+ }
+ }
+ break;
+ case gr_block::TPP_ONE_TO_ONE:
+ // tags from input i only go to output i
+ // this requires d->ninputs() == d->noutputs; this is checked when this
+ // type of tag-propagation system is selected in gr_block_detail
+ if(d->ninputs() == d->noutputs()) {
+ for(int i = 0; i < d->ninputs(); i++) {
+ d->get_tags_in_range(rtags, i, start_nitems_read[i],
+ d->nitems_read(i));
+
+ std::vector<gr_tag_t>::iterator t;
+ for(t = rtags.begin(); t != rtags.end(); t++) {
+ gr_tag_t new_tag = *t;
+ new_tag.offset *= rrate;
+ d->output(i)->add_item_tag(new_tag);
+ }
+ }
+ }
+ else {
+ std::cerr << "Error: gr_block_executor: propagation_policy 'ONE-TO-ONE' requires ninputs == noutputs" << std::endl;
+ return false;
+ }
+
+ break;
+ default:
+ return true;
+ }
+ return true;
+}
+
+gr_block_executor::gr_block_executor (gr_block_sptr block, int max_noutput_items)
+ : d_block(block), d_log(0), d_max_noutput_items(max_noutput_items)
+{
+ if (ENABLE_LOGGING){
+ std::string name = str(boost::format("sst-%03d.log") % which_scheduler++);
+ d_log = new std::ofstream(name.c_str());
+ std::unitbuf(*d_log); // make it unbuffered...
+ *d_log << "gr_block_executor: "
+ << d_block << std::endl;
+ }
+
+#ifdef GR_PERFORMANCE_COUNTERS
+ gr_prefs *prefs = gr_prefs::singleton();
+ d_use_pc = prefs->get_bool("PerfCounters", "on", false);
+#endif /* GR_PERFORMANCE_COUNTERS */
+
+ d_block->start(); // enable any drivers, etc.
+}
+
+gr_block_executor::~gr_block_executor ()
+{
+ if (ENABLE_LOGGING)
+ delete d_log;
+
+ d_block->stop(); // stop any drivers, etc.
+}
+
+gr_block_executor::state
+gr_block_executor::run_one_iteration()
+{
+ int noutput_items;
+ int max_items_avail;
+ int max_noutput_items = d_max_noutput_items;
+ int new_alignment=0;
+ int alignment_state=-1;
+
+ gr_block *m = d_block.get();
+ gr_block_detail *d = m->detail().get();
+
+ LOG(*d_log << std::endl << m);
+
+ if (d->done()){
+ assert(0);
+ return DONE;
+ }
+
+ if (d->source_p ()){
+ d_ninput_items_required.resize (0);
+ d_ninput_items.resize (0);
+ d_input_items.resize (0);
+ d_input_done.resize(0);
+ d_output_items.resize (d->noutputs ());
+ d_start_nitems_read.resize(0);
+
+ // determine the minimum available output space
+ noutput_items = min_available_space (d, m->output_multiple (), m->min_noutput_items ());
+ noutput_items = std::min(noutput_items, max_noutput_items);
+ LOG(*d_log << " source\n noutput_items = " << noutput_items << std::endl);
+ if (noutput_items == -1) // we're done
+ goto were_done;
+
+ if (noutput_items == 0){ // we're output blocked
+ LOG(*d_log << " BLKD_OUT\n");
+ return BLKD_OUT;
+ }
+
+ goto setup_call_to_work; // jump to common code
+ }
+
+ else if (d->sink_p ()){
+ d_ninput_items_required.resize (d->ninputs ());
+ d_ninput_items.resize (d->ninputs ());
+ d_input_items.resize (d->ninputs ());
+ d_input_done.resize(d->ninputs());
+ d_output_items.resize (0);
+ d_start_nitems_read.resize(d->ninputs());
+ LOG(*d_log << " sink\n");
+
+ max_items_avail = 0;
+ for (int i = 0; i < d->ninputs (); i++){
+ {
+ /*
+ * Acquire the mutex and grab local copies of items_available and done.
+ */
+ gruel::scoped_lock guard(*d->input(i)->mutex());
+ d_ninput_items[i] = d->input(i)->items_available();
+ d_input_done[i] = d->input(i)->done();
+ }
+
+ LOG(*d_log << " d_ninput_items[" << i << "] = " << d_ninput_items[i] << std::endl);
+ LOG(*d_log << " d_input_done[" << i << "] = " << d_input_done[i] << std::endl);
+
+ if (d_ninput_items[i] < m->output_multiple() && d_input_done[i])
+ goto were_done;
+
+ max_items_avail = std::max (max_items_avail, d_ninput_items[i]);
+ }
+
+ // take a swag at how much output we can sink
+ noutput_items = (int) (max_items_avail * m->relative_rate ());
+ noutput_items = round_down (noutput_items, m->output_multiple ());
+ noutput_items = std::min(noutput_items, max_noutput_items);
+ LOG(*d_log << " max_items_avail = " << max_items_avail << std::endl);
+ LOG(*d_log << " noutput_items = " << noutput_items << std::endl);
+
+ if (noutput_items == 0){ // we're blocked on input
+ LOG(*d_log << " BLKD_IN\n");
+ return BLKD_IN;
+ }
+
+ goto try_again; // Jump to code shared with regular case.
+ }
+
+ else {
+ // do the regular thing
+ d_ninput_items_required.resize (d->ninputs ());
+ d_ninput_items.resize (d->ninputs ());
+ d_input_items.resize (d->ninputs ());
+ d_input_done.resize(d->ninputs());
+ d_output_items.resize (d->noutputs ());
+ d_start_nitems_read.resize(d->ninputs());
+
+ max_items_avail = 0;
+ for (int i = 0; i < d->ninputs (); i++){
+ {
+ /*
+ * Acquire the mutex and grab local copies of items_available and done.
+ */
+ gruel::scoped_lock guard(*d->input(i)->mutex());
+ d_ninput_items[i] = d->input(i)->items_available ();
+ d_input_done[i] = d->input(i)->done();
+ }
+ max_items_avail = std::max (max_items_avail, d_ninput_items[i]);
+ }
+
+ // determine the minimum available output space
+ noutput_items = min_available_space (d, m->output_multiple (), m->min_noutput_items ());
+ if (ENABLE_LOGGING){
+ *d_log << " regular ";
+ if (m->relative_rate() >= 1.0)
+ *d_log << "1:" << m->relative_rate() << std::endl;
+ else
+ *d_log << 1.0/m->relative_rate() << ":1\n";
+ *d_log << " max_items_avail = " << max_items_avail << std::endl;
+ *d_log << " noutput_items = " << noutput_items << std::endl;
+ }
+ if (noutput_items == -1) // we're done
+ goto were_done;
+
+ if (noutput_items == 0){ // we're output blocked
+ LOG(*d_log << " BLKD_OUT\n");
+ return BLKD_OUT;
+ }
+
+ try_again:
+ if (m->fixed_rate()){
+ // try to work it forward starting with max_items_avail.
+ // We want to try to consume all the input we've got.
+ int reqd_noutput_items = m->fixed_rate_ninput_to_noutput(max_items_avail);
+
+ // only test this if we specifically set the output_multiple
+ if(m->output_multiple_set())
+ reqd_noutput_items = round_down(reqd_noutput_items, m->output_multiple());
+
+ if (reqd_noutput_items > 0 && reqd_noutput_items <= noutput_items)
+ noutput_items = reqd_noutput_items;
+
+ // if we need this many outputs, overrule the max_noutput_items setting
+ max_noutput_items = std::max(m->output_multiple(), max_noutput_items);
+ }
+ noutput_items = std::min(noutput_items, max_noutput_items);
+
+ // Check if we're still unaligned; use up items until we're
+ // aligned again. Otherwise, make sure we set the alignment
+ // requirement.
+ if(!m->output_multiple_set()) {
+ if(m->is_unaligned()) {
+ // When unaligned, don't just set noutput_items to the remaining
+ // samples to meet alignment; this causes too much overhead in
+ // requiring a premature call back here. Set the maximum amount
+ // of samples to handle unalignment and get us back aligned.
+ if(noutput_items >= m->unaligned()) {
+ noutput_items = round_up(noutput_items, m->alignment()) \
+ - (m->alignment() - m->unaligned());
+ new_alignment = 0;
+ }
+ else {
+ new_alignment = m->unaligned() - noutput_items;
+ }
+ alignment_state = 0;
+ }
+ else if(noutput_items < m->alignment()) {
+ // if we don't have enough for an aligned call, keep track of
+ // misalignment, set unaligned flag, and proceed.
+ new_alignment = m->alignment() - noutput_items;
+ m->set_unaligned(new_alignment);
+ m->set_is_unaligned(true);
+ alignment_state = 1;
+ }
+ else {
+ // enough to round down to the nearest alignment and process.
+ noutput_items = round_down(noutput_items, m->alignment());
+ m->set_is_unaligned(false);
+ alignment_state = 2;
+ }
+ }
+
+ // ask the block how much input they need to produce noutput_items
+ m->forecast (noutput_items, d_ninput_items_required);
+
+ // See if we've got sufficient input available
+
+ int i;
+ for (i = 0; i < d->ninputs (); i++)
+ if (d_ninput_items_required[i] > d_ninput_items[i]) // not enough
+ break;
+
+ if (i < d->ninputs ()){ // not enough input on input[i]
+ // if we can, try reducing the size of our output request
+ if (noutput_items > m->output_multiple ()){
+ noutput_items /= 2;
+ noutput_items = round_up (noutput_items, m->output_multiple ());
+ goto try_again;
+ }
+
+ // We're blocked on input
+ LOG(*d_log << " BLKD_IN\n");
+ if (d_input_done[i]) // If the upstream block is done, we're done
+ goto were_done;
+
+ // Is it possible to ever fulfill this request?
+ if (d_ninput_items_required[i] > d->input(i)->max_possible_items_available ()){
+ // Nope, never going to happen...
+ std::cerr << "\nsched: <gr_block " << m->name()
+ << " (" << m->unique_id() << ")>"
+ << " is requesting more input data\n"
+ << " than we can provide.\n"
+ << " ninput_items_required = "
+ << d_ninput_items_required[i] << "\n"
+ << " max_possible_items_available = "
+ << d->input(i)->max_possible_items_available() << "\n"
+ << " If this is a filter, consider reducing the number of taps.\n";
+ goto were_done;
+ }
+
+ // If we were made unaligned in this round but return here without
+ // processing; reset the unalignment claim before next entry.
+ if(alignment_state == 1) {
+ m->set_unaligned(0);
+ m->set_is_unaligned(false);
+ }
+ return BLKD_IN;
+ }
+
+ // We've got enough data on each input to produce noutput_items.
+ // Finish setting up the call to work.
+
+ for (int i = 0; i < d->ninputs (); i++)
+ d_input_items[i] = d->input(i)->read_pointer();
+
+ setup_call_to_work:
+
+ d->d_produce_or = 0;
+ for (int i = 0; i < d->noutputs (); i++)
+ d_output_items[i] = d->output(i)->write_pointer();
+
+ // determine where to start looking for new tags
+ for (int i = 0; i < d->ninputs(); i++)
+ d_start_nitems_read[i] = d->nitems_read(i);
+
+#ifdef GR_PERFORMANCE_COUNTERS
+ if(d_use_pc)
+ d->start_perf_counters();
+#endif /* GR_PERFORMANCE_COUNTERS */
+
+ // Do the actual work of the block
+ int n = m->general_work (noutput_items, d_ninput_items,
+ d_input_items, d_output_items);
+
+#ifdef GR_PERFORMANCE_COUNTERS
+ if(d_use_pc)
+ d->stop_perf_counters(noutput_items, n);
+#endif /* GR_PERFORMANCE_COUNTERS */
+
+ LOG(*d_log << " general_work: noutput_items = " << noutput_items
+ << " result = " << n << std::endl);
+
+ // Adjust number of unaligned items left to process
+ if(m->is_unaligned()) {
+ m->set_unaligned(new_alignment);
+ m->set_is_unaligned(m->unaligned() != 0);
+ }
+
+ if(!propagate_tags(m->tag_propagation_policy(), d,
+ d_start_nitems_read, m->relative_rate(),
+ d_returned_tags))
+ goto were_done;
+
+ if (n == gr_block::WORK_DONE)
+ goto were_done;
+
+ if (n != gr_block::WORK_CALLED_PRODUCE)
+ d->produce_each (n); // advance write pointers
+
+ if (d->d_produce_or > 0) // block produced something
+ return READY;
+
+ // We didn't produce any output even though we called general_work.
+ // We have (most likely) consumed some input.
+
+ /*
+ // If this is a source, it's broken.
+ if (d->source_p()){
+ std::cerr << "gr_block_executor: source " << m
+ << " produced no output. We're marking it DONE.\n";
+ // FIXME maybe we ought to raise an exception...
+ goto were_done;
+ }
+ */
+
+ // Have the caller try again...
+ return READY_NO_OUTPUT;
+ }
+ assert (0);
+
+ were_done:
+ LOG(*d_log << " were_done\n");
+ d->set_done (true);
+ return DONE;
+}
diff --git a/gnuradio-runtime/lib/gr_block_executor.h b/gnuradio-runtime/lib/gr_block_executor.h
new file mode 100644
index 0000000000..7d5c4949a3
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_block_executor.h
@@ -0,0 +1,78 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2008 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_BLOCK_EXECUTOR_H
+#define INCLUDED_GR_BLOCK_EXECUTOR_H
+
+#include <gr_runtime_api.h>
+#include <gr_runtime_types.h>
+#include <fstream>
+#include <gr_tags.h>
+
+//class gr_block_executor;
+//typedef boost::shared_ptr<gr_block_executor> gr_block_executor_sptr;
+
+
+/*!
+ * \brief Manage the execution of a single block.
+ * \ingroup internal
+ */
+
+class GR_RUNTIME_API gr_block_executor {
+protected:
+ gr_block_sptr d_block; // The block we're trying to run
+ std::ofstream *d_log;
+
+ // These are allocated here so we don't have to on each iteration
+
+ gr_vector_int d_ninput_items_required;
+ gr_vector_int d_ninput_items;
+ gr_vector_const_void_star d_input_items;
+ std::vector<bool> d_input_done;
+ gr_vector_void_star d_output_items;
+ std::vector<uint64_t> d_start_nitems_read; //stores where tag counts are before work
+ std::vector<gr_tag_t> d_returned_tags;
+ int d_max_noutput_items;
+
+#ifdef GR_PERFORMANCE_COUNTERS
+ bool d_use_pc;
+#endif /* GR_PERFORMANCE_COUNTERS */
+
+ public:
+ gr_block_executor(gr_block_sptr block, int max_noutput_items=100000);
+ ~gr_block_executor ();
+
+ enum state {
+ READY, // We made progress; everything's cool.
+ READY_NO_OUTPUT, // We consumed some input, but produced no output.
+ BLKD_IN, // no progress; we're blocked waiting for input data.
+ BLKD_OUT, // no progress; we're blocked waiting for output buffer space.
+ DONE, // we're done; don't call me again.
+ };
+
+ /*
+ * \brief Run one iteration.
+ */
+ state run_one_iteration();
+};
+
+#endif /* INCLUDED_GR_BLOCK_EXECUTOR_H */
diff --git a/gnuradio-runtime/lib/gr_block_gateway.cc b/gnuradio-runtime/lib/gr_block_gateway.cc
new file mode 100644
index 0000000000..79b42803af
--- /dev/null
+++ b/gnuradio-runtime/lib/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-runtime/lib/gr_block_registry.cc b/gnuradio-runtime/lib/gr_block_registry.cc
new file mode 100644
index 0000000000..eaa770dcaf
--- /dev/null
+++ b/gnuradio-runtime/lib/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::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::dict_delete(d_ref_map, pmt::intern(block->symbol_name()));
+ if(block->alias_set()){
+ d_ref_map = pmt::dict_delete(d_ref_map, 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(dict_has_key(d_ref_map, pmt::intern(name))){
+ throw std::runtime_error("symbol already exists, can not re-use!");
+ }
+ d_ref_map = dict_add(d_ref_map, pmt::intern(name), pmt::make_any(block));
+}
+
+gr_basic_block_sptr gr_block_registry::block_lookup(pmt::pmt_t symbol){
+ pmt::pmt_t ref = dict_ref(d_ref_map, symbol, pmt::PMT_NIL);
+ if(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::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-runtime/lib/gr_buffer.cc b/gnuradio-runtime/lib/gr_buffer.cc
new file mode 100644
index 0000000000..369959d65f
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_buffer.cc
@@ -0,0 +1,347 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2009,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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_buffer.h>
+#include <gr_vmcircbuf.h>
+#include <gr_math.h>
+#include <stdexcept>
+#include <iostream>
+#include <assert.h>
+#include <algorithm>
+#include <boost/math/common_factor_rt.hpp>
+
+static long s_buffer_count = 0; // counts for debugging storage mgmt
+static long s_buffer_reader_count = 0;
+
+// ----------------------------------------------------------------------------
+// Notes on storage management
+//
+// Pretty much all the fundamental classes are now using the
+// shared_ptr stuff for automatic reference counting. To ensure that
+// no mistakes are made, we make the constructors for classes private,
+// and then provide a free factory function that returns a smart
+// pointer to the desired class.
+//
+// gr_buffer and gr_buffer_reader are no exceptions. However, they
+// both want pointers to each other, and unless we do something, we'll
+// never delete any of them because of the circular structure.
+// They'll always have a reference count of at least one. We could
+// use boost::weak_ptr's from gr_buffer to gr_buffer_reader but that
+// introduces it's own problems. (gr_buffer_reader's destructor needs
+// to call gr_buffer::drop_reader, but has no easy way to get a
+// shared_ptr to itself.)
+//
+// Instead, we solve this problem by having gr_buffer hold a raw
+// pointer to gr_buffer_reader in its d_reader vector.
+// gr_buffer_reader's destructor calls gr_buffer::drop_reader, so
+// we're never left with an dangling pointer. gr_buffer_reader still
+// has a shared_ptr to the buffer ensuring that the buffer doesn't go
+// away under it. However, when the reference count of a
+// gr_buffer_reader goes to zero, we can successfully reclaim it.
+// ----------------------------------------------------------------------------
+
+
+/*
+ * Compute the minimum number of buffer items that work (i.e.,
+ * address space wrap-around works). To work is to satisfy this
+ * contraint for integer buffer_size and k:
+ *
+ * type_size * nitems == k * page_size
+ */
+static long
+minimum_buffer_items (long type_size, long page_size)
+{
+ return page_size / boost::math::gcd (type_size, page_size);
+}
+
+
+gr_buffer::gr_buffer (int nitems, size_t sizeof_item, gr_block_sptr link)
+ : d_base (0), d_bufsize (0), d_vmcircbuf (0),
+ d_sizeof_item (sizeof_item), d_link(link),
+ d_write_index (0), d_abs_write_offset(0), d_done (false),
+ d_last_min_items_read(0)
+{
+ if (!allocate_buffer (nitems, sizeof_item))
+ throw std::bad_alloc ();
+
+ s_buffer_count++;
+}
+
+gr_buffer_sptr
+gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link)
+{
+ return gr_buffer_sptr (new gr_buffer (nitems, sizeof_item, link));
+}
+
+gr_buffer::~gr_buffer ()
+{
+ delete d_vmcircbuf;
+ assert (d_readers.size() == 0);
+ s_buffer_count--;
+}
+
+/*!
+ * sets d_vmcircbuf, d_base, d_bufsize.
+ * returns true iff successful.
+ */
+bool
+gr_buffer::allocate_buffer (int nitems, size_t sizeof_item)
+{
+ int orig_nitems = nitems;
+
+ // Any buffersize we come up with must be a multiple of min_nitems.
+
+ int granularity = gr_vmcircbuf_sysconfig::granularity ();
+ int min_nitems = minimum_buffer_items (sizeof_item, granularity);
+
+ // Round-up nitems to a multiple of min_nitems.
+
+ if (nitems % min_nitems != 0)
+ nitems = ((nitems / min_nitems) + 1) * min_nitems;
+
+ // If we rounded-up a whole bunch, give the user a heads up.
+ // This only happens if sizeof_item is not a power of two.
+
+ if (nitems > 2 * orig_nitems && nitems * (int) sizeof_item > granularity){
+ std::cerr << "gr_buffer::allocate_buffer: warning: tried to allocate\n"
+ << " " << orig_nitems << " items of size "
+ << sizeof_item << ". Due to alignment requirements\n"
+ << " " << nitems << " were allocated. If this isn't OK, consider padding\n"
+ << " your structure to a power-of-two bytes.\n"
+ << " On this platform, our allocation granularity is " << granularity << " bytes.\n";
+ }
+
+ d_bufsize = nitems;
+ d_vmcircbuf = gr_vmcircbuf_sysconfig::make (d_bufsize * d_sizeof_item);
+ if (d_vmcircbuf == 0){
+ std::cerr << "gr_buffer::allocate_buffer: failed to allocate buffer of size "
+ << d_bufsize * d_sizeof_item / 1024 << " KB\n";
+ return false;
+ }
+
+ d_base = (char *) d_vmcircbuf->pointer_to_first_copy ();
+ return true;
+}
+
+
+int
+gr_buffer::space_available ()
+{
+ if (d_readers.empty ())
+ return d_bufsize - 1; // See comment below
+
+ else {
+
+ // Find out the maximum amount of data available to our readers
+
+ int most_data = d_readers[0]->items_available ();
+ uint64_t min_items_read = d_readers[0]->nitems_read();
+ for (size_t i = 1; i < d_readers.size (); i++) {
+ most_data = std::max (most_data, d_readers[i]->items_available ());
+ min_items_read = std::min(min_items_read, d_readers[i]->nitems_read());
+ }
+
+ if(min_items_read != d_last_min_items_read) {
+ prune_tags(d_last_min_items_read);
+ d_last_min_items_read = min_items_read;
+ }
+
+ // The -1 ensures that the case d_write_index == d_read_index is
+ // unambiguous. It indicates that there is no data for the reader
+
+ return d_bufsize - most_data - 1;
+ }
+}
+
+void *
+gr_buffer::write_pointer ()
+{
+ return &d_base[d_write_index * d_sizeof_item];
+}
+
+void
+gr_buffer::update_write_pointer (int nitems)
+{
+ gruel::scoped_lock guard(*mutex());
+ d_write_index = index_add (d_write_index, nitems);
+ d_abs_write_offset += nitems;
+}
+
+void
+gr_buffer::set_done (bool done)
+{
+ gruel::scoped_lock guard(*mutex());
+ d_done = done;
+}
+
+gr_buffer_reader_sptr
+gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link)
+{
+ if (nzero_preload < 0)
+ throw std::invalid_argument("gr_buffer_add_reader: nzero_preload must be >= 0");
+
+ gr_buffer_reader_sptr r (new gr_buffer_reader (buf,
+ buf->index_sub(buf->d_write_index,
+ nzero_preload),
+ link));
+ buf->d_readers.push_back (r.get ());
+
+ return r;
+}
+
+void
+gr_buffer::drop_reader (gr_buffer_reader *reader)
+{
+ // isn't C++ beautiful... GAG!
+
+ std::vector<gr_buffer_reader *>::iterator result =
+ std::find (d_readers.begin (), d_readers.end (), reader);
+
+ if (result == d_readers.end ())
+ throw std::invalid_argument ("gr_buffer::drop_reader"); // we didn't find it...
+
+ d_readers.erase (result);
+}
+
+void
+gr_buffer::add_item_tag(const gr_tag_t &tag)
+{
+ gruel::scoped_lock guard(*mutex());
+ d_item_tags.push_back(tag);
+}
+
+void
+gr_buffer::remove_item_tag(const gr_tag_t &tag)
+{
+ gruel::scoped_lock guard(*mutex());
+ for (std::deque<gr_tag_t>::iterator it = d_item_tags.begin(); it != d_item_tags.end(); ++it) {
+ if (*it == tag) {
+ d_item_tags.erase(it);
+ break;
+ }
+ }
+}
+
+void
+gr_buffer::prune_tags(uint64_t max_time)
+{
+ /* NOTE: this function _should_ lock the mutex before editing
+ d_item_tags. In practice, this function is only called at
+ runtime by min_available_space in gr_block_executor.cc,
+ which locks the mutex itself.
+
+ If this function is used elsewhere, remember to lock the
+ buffer's mutex al la the scoped_lock line below.
+ */
+ //gruel::scoped_lock guard(*mutex());
+ std::deque<gr_tag_t>::iterator itr = d_item_tags.begin();
+
+ uint64_t item_time;
+
+ // Since tags are not guarenteed to be in any particular order,
+ // we need to erase here instead of pop_front. An erase in the
+ // middle invalidates all iterators; so this resets the iterator
+ // to find more. Mostly, we wil be erasing from the front and
+ // therefore lose little time this way.
+ while(itr != d_item_tags.end()) {
+ item_time = (*itr).offset;
+ if(item_time < max_time) {
+ d_item_tags.erase(itr);
+ itr = d_item_tags.begin();
+ }
+ else
+ itr++;
+ }
+}
+
+long
+gr_buffer_ncurrently_allocated ()
+{
+ return s_buffer_count;
+}
+
+// ----------------------------------------------------------------------------
+
+gr_buffer_reader::gr_buffer_reader(gr_buffer_sptr buffer, unsigned int read_index,
+ gr_block_sptr link)
+ : d_buffer(buffer), d_read_index(read_index), d_abs_read_offset(0), d_link(link)
+{
+ s_buffer_reader_count++;
+}
+
+gr_buffer_reader::~gr_buffer_reader ()
+{
+ d_buffer->drop_reader(this);
+ s_buffer_reader_count--;
+}
+
+int
+gr_buffer_reader::items_available () const
+{
+ return d_buffer->index_sub (d_buffer->d_write_index, d_read_index);
+}
+
+const void *
+gr_buffer_reader::read_pointer ()
+{
+ return &d_buffer->d_base[d_read_index * d_buffer->d_sizeof_item];
+}
+
+void
+gr_buffer_reader::update_read_pointer (int nitems)
+{
+ gruel::scoped_lock guard(*mutex());
+ d_read_index = d_buffer->index_add (d_read_index, nitems);
+ d_abs_read_offset += nitems;
+}
+
+void
+gr_buffer_reader::get_tags_in_range(std::vector<gr_tag_t> &v,
+ uint64_t abs_start,
+ uint64_t abs_end)
+{
+ gruel::scoped_lock guard(*mutex());
+
+ v.resize(0);
+ std::deque<gr_tag_t>::iterator itr = d_buffer->get_tags_begin();
+
+ uint64_t item_time;
+ while(itr != d_buffer->get_tags_end()) {
+ item_time = (*itr).offset;
+
+ if((item_time >= abs_start) && (item_time < abs_end)) {
+ v.push_back(*itr);
+ }
+
+ itr++;
+ }
+}
+
+long
+gr_buffer_reader_ncurrently_allocated ()
+{
+ return s_buffer_reader_count;
+}
diff --git a/gnuradio-runtime/lib/gr_circular_file.cc b/gnuradio-runtime/lib/gr_circular_file.cc
new file mode 100644
index 0000000000..6f710c49b1
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_circular_file.cc
@@ -0,0 +1,203 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gr_circular_file.h>
+
+#include <unistd.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include <algorithm>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+static const int HEADER_SIZE = 4096;
+static const int HEADER_MAGIC = 0xEB021026;
+
+static const int HD_MAGIC = 0;
+static const int HD_HEADER_SIZE = 1; // integer offsets into header
+static const int HD_BUFFER_SIZE = 2;
+static const int HD_BUFFER_BASE = 3;
+static const int HD_BUFFER_CURRENT = 4;
+
+gr_circular_file::gr_circular_file (const char *filename,
+ bool writable, int size)
+ : d_fd (-1), d_header (0), d_buffer (0), d_mapped_size (0), d_bytes_read (0)
+{
+ int mm_prot;
+ if (writable){
+#ifdef HAVE_MMAP
+ mm_prot = PROT_READ | PROT_WRITE;
+#endif
+ d_fd = open (filename, O_CREAT | O_RDWR | O_TRUNC, 0664);
+ if (d_fd < 0){
+ perror (filename);
+ exit (1);
+ }
+#ifdef HAVE_MMAP /* FIXME */
+ if(ftruncate (d_fd, size + HEADER_SIZE) != 0) {
+ perror (filename);
+ exit (1);
+ }
+#endif
+ }
+ else {
+#ifdef HAVE_MMAP
+ mm_prot = PROT_READ;
+#endif
+ d_fd = open (filename, O_RDONLY);
+ if (d_fd < 0){
+ perror (filename);
+ exit (1);
+ }
+ }
+
+ struct stat statbuf;
+ if (fstat (d_fd, &statbuf) < 0){
+ perror (filename);
+ exit (1);
+ }
+
+ if (statbuf.st_size < HEADER_SIZE){
+ fprintf (stderr, "%s: file too small to be circular buffer\n", filename);
+ exit (1);
+ }
+
+ d_mapped_size = statbuf.st_size;
+#ifdef HAVE_MMAP
+ void *p = mmap (0, d_mapped_size, mm_prot, MAP_SHARED, d_fd, 0);
+ if (p == MAP_FAILED){
+ perror ("gr_circular_file: mmap failed");
+ exit (1);
+ }
+
+ d_header = (int *) p;
+#else
+ perror ("gr_circular_file: mmap unsupported by this system");
+ exit (1);
+#endif
+
+ if (writable){ // init header
+
+ if (size < 0){
+ fprintf (stderr, "gr_circular_buffer: size must be > 0 when writable\n");
+ exit (1);
+ }
+
+ d_header[HD_MAGIC] = HEADER_MAGIC;
+ d_header[HD_HEADER_SIZE] = HEADER_SIZE;
+ d_header[HD_BUFFER_SIZE] = size;
+ d_header[HD_BUFFER_BASE] = HEADER_SIZE; // right after header
+ d_header[HD_BUFFER_CURRENT] = 0;
+ }
+
+ // sanity check (the asserts are a bit unforgiving...)
+
+ assert (d_header[HD_MAGIC] == HEADER_MAGIC);
+ assert (d_header[HD_HEADER_SIZE] == HEADER_SIZE);
+ assert (d_header[HD_BUFFER_SIZE] > 0);
+ assert (d_header[HD_BUFFER_BASE] >= d_header[HD_HEADER_SIZE]);
+ assert (d_header[HD_BUFFER_BASE] + d_header[HD_BUFFER_SIZE] <= d_mapped_size);
+ assert (d_header[HD_BUFFER_CURRENT] >= 0 &&
+ d_header[HD_BUFFER_CURRENT] < d_header[HD_BUFFER_SIZE]);
+
+ d_bytes_read = 0;
+ d_buffer = (unsigned char *) d_header + d_header[HD_BUFFER_BASE];
+}
+
+gr_circular_file::~gr_circular_file ()
+{
+#ifdef HAVE_MMAP
+ if (munmap ((char *) d_header, d_mapped_size) < 0){
+ perror ("gr_circular_file: munmap");
+ exit (1);
+ }
+#endif
+ close (d_fd);
+}
+
+bool
+gr_circular_file::write (void *vdata, int nbytes)
+{
+ unsigned char *data = (unsigned char *) vdata;
+ int buffer_size = d_header[HD_BUFFER_SIZE];
+ int buffer_current = d_header[HD_BUFFER_CURRENT];
+
+ while (nbytes > 0){
+ int n = std::min (nbytes, buffer_size - buffer_current);
+ memcpy (d_buffer + buffer_current, data, n);
+
+ buffer_current += n;
+ if (buffer_current >= buffer_size)
+ buffer_current = 0;
+
+ data += n;
+ nbytes -= n;
+ }
+
+ d_header[HD_BUFFER_CURRENT] = buffer_current;
+ return true;
+}
+
+int
+gr_circular_file::read (void *vdata, int nbytes)
+{
+ unsigned char *data = (unsigned char *) vdata;
+ int buffer_current = d_header[HD_BUFFER_CURRENT];
+ int buffer_size = d_header[HD_BUFFER_SIZE];
+ int total = 0;
+
+ nbytes = std::min (nbytes, buffer_size - d_bytes_read);
+
+ while (nbytes > 0){
+ int offset = (buffer_current + d_bytes_read) % buffer_size;
+ int n = std::min (nbytes, buffer_size - offset);
+ memcpy (data, d_buffer + offset, n);
+ data += n;
+ d_bytes_read += n;
+ total += n;
+ nbytes -= n;
+ }
+ return total;
+}
+
+void
+gr_circular_file::reset_read_pointer ()
+{
+ d_bytes_read = 0;
+}
diff --git a/gnuradio-runtime/lib/gr_circular_file.h b/gnuradio-runtime/lib/gr_circular_file.h
new file mode 100644
index 0000000000..2b61bf2711
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_circular_file.h
@@ -0,0 +1,60 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002 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_CIRCULAR_FILE_H_
+#define _GR_CIRCULAR_FILE_H_
+
+#include <gr_runtime_api.h>
+
+/*
+ * writes input data into a circular buffer on disk.
+ *
+ * the file contains a fixed header:
+ * 0x0000: int32 magic (0xEB021026)
+ * 0x0004: int32 size in bytes of header (constant 4096)
+ * 0x0008: int32 size in bytes of circular buffer (not including header)
+ * 0x000C: int32 file offset to beginning of circular buffer
+ * 0x0010: int32 byte offset from beginning of circular buffer to
+ * current start of data
+ *
+ */
+class GR_RUNTIME_API gr_circular_file {
+ int d_fd;
+ int *d_header;
+ unsigned char *d_buffer;
+ int d_mapped_size;
+ int d_bytes_read;
+
+public:
+ gr_circular_file (const char *filename, bool writable = false, int size = 0);
+ ~gr_circular_file ();
+
+ bool write (void *data, int nbytes);
+
+ // returns # of bytes actually read or 0 if end of buffer, or -1 on error.
+ int read (void *data, int nbytes);
+
+ // reset read pointer to beginning of buffer.
+ void reset_read_pointer ();
+};
+
+#endif /* _GR_CIRCULAR_FILE_H_ */ \ No newline at end of file
diff --git a/gnuradio-runtime/lib/gr_constants.cc.in b/gnuradio-runtime/lib/gr_constants.cc.in
new file mode 100644
index 0000000000..b94f254d66
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_constants.cc.in
@@ -0,0 +1,57 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2009 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gr_constants.h>
+
+const std::string
+gr_prefix()
+{
+ return "@prefix@";
+}
+
+const std::string
+gr_sysconfdir()
+{
+ return "@SYSCONFDIR@";
+}
+
+const std::string
+gr_prefsdir()
+{
+ return "@GR_PREFSDIR@";
+}
+
+const std::string
+gr_build_date()
+{
+ return "@BUILD_DATE@";
+}
+
+const std::string
+gr_version()
+{
+ return "@VERSION@";
+}
diff --git a/gnuradio-runtime/lib/gr_dispatcher.cc b/gnuradio-runtime/lib/gr_dispatcher.cc
new file mode 100644
index 0000000000..96ebe9ad8b
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_dispatcher.cc
@@ -0,0 +1,193 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_dispatcher.h>
+#include <math.h>
+#include <errno.h>
+#include <stdio.h>
+
+#ifdef HAVE_SELECT
+# ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+# else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# endif
+# ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+# endif
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# endif
+# endif
+#endif
+
+
+static gr_dispatcher_sptr s_singleton;
+
+gr_dispatcher_sptr
+gr_make_dispatcher()
+{
+ return gr_dispatcher_sptr(new gr_dispatcher());
+}
+
+gr_dispatcher_sptr
+gr_dispatcher_singleton()
+{
+ if (s_singleton)
+ return s_singleton;
+
+ s_singleton = gr_make_dispatcher();
+ return s_singleton;
+}
+
+#if !defined(HAVE_SELECT) // Stub it out
+
+gr_dispatcher::gr_dispatcher()
+{
+}
+
+gr_dispatcher::~gr_dispatcher()
+{
+}
+
+bool
+gr_dispatcher::add_handler(gr_select_handler_sptr handler)
+{
+ return true;
+}
+
+bool
+gr_dispatcher::del_handler(gr_select_handler_sptr handler)
+{
+ return true;
+}
+
+bool
+gr_dispatcher::del_handler(gr_select_handler *handler)
+{
+ return true;
+}
+
+void
+gr_dispatcher::loop(double timeout)
+{
+}
+
+#else // defined(HAVE_SELECT)
+
+gr_dispatcher::gr_dispatcher()
+ : d_handler(FD_SETSIZE), d_max_index(-1)
+{
+}
+
+gr_dispatcher::~gr_dispatcher()
+{
+}
+
+bool
+gr_dispatcher::add_handler(gr_select_handler_sptr handler)
+{
+ int fd = handler->fd();
+ if (fd < 0 || fd >= FD_SETSIZE)
+ return false;
+
+ d_max_index = std::max(d_max_index, fd);
+ d_handler[fd] = handler;
+ return true;
+}
+
+bool
+gr_dispatcher::del_handler(gr_select_handler_sptr handler)
+{
+ return del_handler(handler.get());
+}
+
+bool
+gr_dispatcher::del_handler(gr_select_handler *handler)
+{
+ int fd = handler->fd();
+ if (fd < 0 || fd >= FD_SETSIZE)
+ return false;
+
+ d_handler[fd].reset();
+
+ if (fd == d_max_index){
+ int i;
+ for (i = fd - 1; i >= 0 && !d_handler[i]; i--)
+ ;
+ d_max_index = i;
+ }
+ return true;
+}
+
+
+void
+gr_dispatcher::loop(double timeout)
+{
+ struct timeval master;
+ struct timeval tmp;
+ fd_set rd_set;
+ fd_set wr_set;
+
+ double secs = floor (timeout);
+ master.tv_sec = (long) secs;
+ master.tv_usec = (long) ((timeout - secs) * 1e6);
+
+ while (d_max_index >= 0){
+ FD_ZERO(&rd_set);
+ FD_ZERO(&wr_set);
+
+ for (int i = 0; i <= d_max_index; i++){
+ if (d_handler[i] && d_handler[i]->readable())
+ FD_SET(i, &rd_set);
+ if (d_handler[i] && d_handler[i]->writable())
+ FD_SET(i, &wr_set);
+ }
+
+ tmp = master;
+ int retval = select(d_max_index+1, &rd_set, &wr_set, 0, &tmp);
+ if (retval == 0) // timed out with nothing ready
+ continue;
+ if (retval < 0){
+ if (errno == EINTR)
+ continue;
+ perror ("gr_dispatcher/select");
+ return;
+ }
+
+ for (int i = 0; i <= d_max_index; i++){
+ if (FD_ISSET(i, &rd_set))
+ if (d_handler[i])
+ d_handler[i]->handle_read();
+ if (FD_ISSET(i, &wr_set))
+ if (d_handler[i])
+ d_handler[i]->handle_write();
+ }
+ }
+}
+
+#endif
diff --git a/gnuradio-runtime/lib/gr_error_handler.cc b/gnuradio-runtime/lib/gr_error_handler.cc
new file mode 100644
index 0000000000..448682966e
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_error_handler.cc
@@ -0,0 +1,244 @@
+/* -*- 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.
+ */
+/*
+ * This code is based on error.cc from the "Click Modular Router".
+ * Original copyright follows:
+ */
+/*
+ * error.{cc,hh} -- flexible classes for error reporting
+ * Eddie Kohler
+ *
+ * Copyright (c) 1999-2000 Massachusetts Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, subject to the conditions
+ * listed in the Click LICENSE file. These conditions include: you must
+ * preserve this copyright notice, and you cannot mention the copyright
+ * holders in advertising related to the Software without their permission.
+ * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
+ * notice is a summary of the Click LICENSE file; the license in that file is
+ * legally binding.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_error_handler.h>
+#include <assert.h>
+#include <stdexcept>
+#include <unistd.h>
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+static gr_error_handler *s_default_handler = 0;
+static gr_error_handler *s_silent_handler = 0;
+
+bool
+gr_error_handler::has_default_handler()
+{
+ return s_default_handler != 0;
+}
+
+void
+gr_error_handler::set_default_handler(gr_error_handler *errh)
+{
+ s_default_handler = errh;
+}
+
+gr_error_handler *
+gr_error_handler::default_handler()
+{
+ assert (s_default_handler != 0);
+ return s_default_handler;
+}
+
+gr_error_handler *
+gr_error_handler::silent_handler()
+{
+ assert (s_silent_handler != 0);
+ return s_silent_handler;
+}
+
+// ----------------------------------------------------------------
+
+gr_error_handler::~gr_error_handler()
+{
+ // nop
+}
+
+void
+gr_error_handler::debug(const char *format, ...)
+{
+ va_list val;
+ va_start(val, format);
+ verror(ERR_DEBUG, format, val);
+ va_end(val);
+}
+
+void
+gr_error_handler::message(const char *format, ...)
+{
+ va_list val;
+ va_start(val, format);
+ verror(ERR_MESSAGE, format, val);
+ va_end(val);
+}
+
+void
+gr_error_handler::warning(const char *format, ...)
+{
+ va_list val;
+ va_start(val, format);
+ verror(ERR_WARNING, format, val);
+ va_end(val);
+}
+
+void
+gr_error_handler::error(const char *format, ...)
+{
+ va_list val;
+ va_start(val, format);
+ verror(ERR_ERROR, format, val);
+ va_end(val);
+}
+
+void
+gr_error_handler::fatal(const char *format, ...)
+{
+ va_list val;
+ va_start(val, format);
+ verror(ERR_FATAL, format, val);
+ va_end(val);
+}
+
+void
+gr_error_handler::verror(seriousness s, const char *format, va_list val)
+{
+ std::string text = make_text(s, format, val);
+ handle_text(s, text);
+ count_error(s);
+}
+
+void
+gr_error_handler::verror_text(seriousness s, const std::string &text)
+{
+ // text is already made
+ handle_text(s, text);
+ count_error(s);
+}
+
+std::string
+gr_error_handler::make_text(seriousness s, const char *format, va_list val)
+{
+ char text_buf[4096];
+ vsnprintf(text_buf, sizeof(text_buf), format, val);
+ text_buf[sizeof(text_buf)-1] = 0;
+ return text_buf;
+}
+
+// ----------------------------------------------------------------
+
+void
+gr_base_error_handler::count_error(seriousness s)
+{
+ if (s < ERR_WARNING)
+ /* do nothing */;
+ else if (s < ERR_ERROR)
+ d_nwarnings++;
+ else
+ d_nerrors++;
+}
+
+// ----------------------------------------------------------------
+
+gr_file_error_handler::gr_file_error_handler(FILE *file)
+ : d_file(file), d_fd(-1)
+{
+}
+
+gr_file_error_handler::gr_file_error_handler(int file_descriptor)
+{
+ d_fd = dup(file_descriptor); // so we can fclose it
+ if (d_fd == -1){
+ perror("gr_file_error_handler:dup");
+ throw std::invalid_argument("gr_file_error_handler:dup");
+ }
+ d_file = fdopen(d_fd, "w");
+ if (d_file == 0){
+ perror("gr_file_error_handler:fdopen");
+ throw std::invalid_argument("gr_file_error_handler:fdopen");
+ }
+}
+
+gr_file_error_handler::~gr_file_error_handler()
+{
+ if (d_fd != -1){
+ fclose(d_file);
+ }
+}
+
+void
+gr_file_error_handler::handle_text(seriousness s, const std::string &text)
+{
+ if (text.length() <= 0)
+ return;
+
+ fwrite(text.data(), 1, text.length(), d_file);
+ if (text[text.length()-1] != '\n')
+ fwrite("\n", 1, 1, d_file);
+
+ if (d_fd != -1)
+ fflush(d_file); // keep synced with any other users of fd
+}
+
+
+// ----------------------------------------------------------------
+// static error handlers
+//
+
+class gr_silent_error_handler : public gr_base_error_handler
+{
+public:
+ gr_silent_error_handler() {}
+ void handle_text(seriousness s, const std::string &str);
+};
+
+void
+gr_silent_error_handler::handle_text(seriousness s, const std::string &str)
+{
+ // nop
+}
+
+class force_init {
+public:
+ force_init()
+ {
+ s_default_handler = new gr_file_error_handler(stdout);
+ s_silent_handler = new gr_silent_error_handler();
+ }
+};
+
+static force_init kludge;
diff --git a/gnuradio-runtime/lib/gr_fast_atan2f.cc b/gnuradio-runtime/lib/gr_fast_atan2f.cc
new file mode 100644
index 0000000000..8b7bfea12e
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_fast_atan2f.cc
@@ -0,0 +1,199 @@
+/* -*- 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_math.h> // declaration is in here
+#include <cmath>
+
+#define REAL float
+
+/***************************************************************************/
+/* Constant definitions */
+/***************************************************************************/
+
+#define TAN_MAP_RES 0.003921569 /* (smallest non-zero value in table) */
+#define RAD_PER_DEG 0.017453293
+#define TAN_MAP_SIZE 256
+
+/* arctangents from 0 to pi/4 radians */
+static REAL
+fast_atan_table[257] = {
+ 0.000000e+00, 3.921549e-03, 7.842976e-03, 1.176416e-02,
+ 1.568499e-02, 1.960533e-02, 2.352507e-02, 2.744409e-02,
+ 3.136226e-02, 3.527947e-02, 3.919560e-02, 4.311053e-02,
+ 4.702413e-02, 5.093629e-02, 5.484690e-02, 5.875582e-02,
+ 6.266295e-02, 6.656816e-02, 7.047134e-02, 7.437238e-02,
+ 7.827114e-02, 8.216752e-02, 8.606141e-02, 8.995267e-02,
+ 9.384121e-02, 9.772691e-02, 1.016096e-01, 1.054893e-01,
+ 1.093658e-01, 1.132390e-01, 1.171087e-01, 1.209750e-01,
+ 1.248376e-01, 1.286965e-01, 1.325515e-01, 1.364026e-01,
+ 1.402496e-01, 1.440924e-01, 1.479310e-01, 1.517652e-01,
+ 1.555948e-01, 1.594199e-01, 1.632403e-01, 1.670559e-01,
+ 1.708665e-01, 1.746722e-01, 1.784728e-01, 1.822681e-01,
+ 1.860582e-01, 1.898428e-01, 1.936220e-01, 1.973956e-01,
+ 2.011634e-01, 2.049255e-01, 2.086818e-01, 2.124320e-01,
+ 2.161762e-01, 2.199143e-01, 2.236461e-01, 2.273716e-01,
+ 2.310907e-01, 2.348033e-01, 2.385093e-01, 2.422086e-01,
+ 2.459012e-01, 2.495869e-01, 2.532658e-01, 2.569376e-01,
+ 2.606024e-01, 2.642600e-01, 2.679104e-01, 2.715535e-01,
+ 2.751892e-01, 2.788175e-01, 2.824383e-01, 2.860514e-01,
+ 2.896569e-01, 2.932547e-01, 2.968447e-01, 3.004268e-01,
+ 3.040009e-01, 3.075671e-01, 3.111252e-01, 3.146752e-01,
+ 3.182170e-01, 3.217506e-01, 3.252758e-01, 3.287927e-01,
+ 3.323012e-01, 3.358012e-01, 3.392926e-01, 3.427755e-01,
+ 3.462497e-01, 3.497153e-01, 3.531721e-01, 3.566201e-01,
+ 3.600593e-01, 3.634896e-01, 3.669110e-01, 3.703234e-01,
+ 3.737268e-01, 3.771211e-01, 3.805064e-01, 3.838825e-01,
+ 3.872494e-01, 3.906070e-01, 3.939555e-01, 3.972946e-01,
+ 4.006244e-01, 4.039448e-01, 4.072558e-01, 4.105574e-01,
+ 4.138496e-01, 4.171322e-01, 4.204054e-01, 4.236689e-01,
+ 4.269229e-01, 4.301673e-01, 4.334021e-01, 4.366272e-01,
+ 4.398426e-01, 4.430483e-01, 4.462443e-01, 4.494306e-01,
+ 4.526070e-01, 4.557738e-01, 4.589307e-01, 4.620778e-01,
+ 4.652150e-01, 4.683424e-01, 4.714600e-01, 4.745676e-01,
+ 4.776654e-01, 4.807532e-01, 4.838312e-01, 4.868992e-01,
+ 4.899573e-01, 4.930055e-01, 4.960437e-01, 4.990719e-01,
+ 5.020902e-01, 5.050985e-01, 5.080968e-01, 5.110852e-01,
+ 5.140636e-01, 5.170320e-01, 5.199904e-01, 5.229388e-01,
+ 5.258772e-01, 5.288056e-01, 5.317241e-01, 5.346325e-01,
+ 5.375310e-01, 5.404195e-01, 5.432980e-01, 5.461666e-01,
+ 5.490251e-01, 5.518738e-01, 5.547124e-01, 5.575411e-01,
+ 5.603599e-01, 5.631687e-01, 5.659676e-01, 5.687566e-01,
+ 5.715357e-01, 5.743048e-01, 5.770641e-01, 5.798135e-01,
+ 5.825531e-01, 5.852828e-01, 5.880026e-01, 5.907126e-01,
+ 5.934128e-01, 5.961032e-01, 5.987839e-01, 6.014547e-01,
+ 6.041158e-01, 6.067672e-01, 6.094088e-01, 6.120407e-01,
+ 6.146630e-01, 6.172755e-01, 6.198784e-01, 6.224717e-01,
+ 6.250554e-01, 6.276294e-01, 6.301939e-01, 6.327488e-01,
+ 6.352942e-01, 6.378301e-01, 6.403565e-01, 6.428734e-01,
+ 6.453808e-01, 6.478788e-01, 6.503674e-01, 6.528466e-01,
+ 6.553165e-01, 6.577770e-01, 6.602282e-01, 6.626701e-01,
+ 6.651027e-01, 6.675261e-01, 6.699402e-01, 6.723452e-01,
+ 6.747409e-01, 6.771276e-01, 6.795051e-01, 6.818735e-01,
+ 6.842328e-01, 6.865831e-01, 6.889244e-01, 6.912567e-01,
+ 6.935800e-01, 6.958943e-01, 6.981998e-01, 7.004964e-01,
+ 7.027841e-01, 7.050630e-01, 7.073330e-01, 7.095943e-01,
+ 7.118469e-01, 7.140907e-01, 7.163258e-01, 7.185523e-01,
+ 7.207701e-01, 7.229794e-01, 7.251800e-01, 7.273721e-01,
+ 7.295557e-01, 7.317307e-01, 7.338974e-01, 7.360555e-01,
+ 7.382053e-01, 7.403467e-01, 7.424797e-01, 7.446045e-01,
+ 7.467209e-01, 7.488291e-01, 7.509291e-01, 7.530208e-01,
+ 7.551044e-01, 7.571798e-01, 7.592472e-01, 7.613064e-01,
+ 7.633576e-01, 7.654008e-01, 7.674360e-01, 7.694633e-01,
+ 7.714826e-01, 7.734940e-01, 7.754975e-01, 7.774932e-01,
+ 7.794811e-01, 7.814612e-01, 7.834335e-01, 7.853983e-01,
+ 7.853983e-01
+ };
+
+
+/*****************************************************************************
+Function: Arc tangent
+
+Syntax: angle = fast_atan2(y, x);
+REAL y y component of input vector
+REAL x x component of input vector
+REAL angle angle of vector (x, y) in radians
+
+Description: This function calculates the angle of the vector (x,y) based
+on a table lookup and linear interpolation. The table uses
+a 256 point table covering -45 to +45 degrees and uses
+symetry to determine the final angle value in the range of
+-180 to 180 degrees. Note that this function uses the small
+angle approximation for values close to zero. This routine
+calculates the arc tangent with an average error of
++/- 0.045 degrees.
+*****************************************************************************/
+
+REAL
+gr_fast_atan2f(REAL y, REAL x)
+{
+ REAL x_abs, y_abs, z;
+ REAL alpha, angle, base_angle;
+ int index;
+
+ /* don't divide by zero! */ // FIXME could get hosed with -0.0
+ if ((y == 0.0) && (x == 0.0))
+ return 0.0;
+
+ /* normalize to +/- 45 degree range */
+ y_abs = fabs(y);
+ x_abs = fabs(x);
+ //z = (y_abs < x_abs ? y_abs / x_abs : x_abs / y_abs);
+ if (y_abs < x_abs)
+ z = y_abs / x_abs;
+ else
+ z = x_abs / y_abs;
+
+ /* when ratio approaches the table resolution, the angle is */
+ /* best approximated with the argument itself... */
+ if (z < TAN_MAP_RES)
+ base_angle = z;
+ else {
+ /* find index and interpolation value */
+ alpha = z * (REAL) TAN_MAP_SIZE - .5;
+ index = (int) alpha;
+ alpha -= (REAL) index;
+ /* determine base angle based on quadrant and */
+ /* add or subtract table value from base angle based on quadrant */
+ base_angle = fast_atan_table[index];
+ base_angle +=
+ (fast_atan_table[index + 1] - fast_atan_table[index]) * alpha;
+ }
+
+ if (x_abs > y_abs) { /* -45 -> 45 or 135 -> 225 */
+ if (x >= 0.0) { /* -45 -> 45 */
+ if (y >= 0.0)
+ angle = base_angle; /* 0 -> 45, angle OK */
+ else
+ angle = -base_angle; /* -45 -> 0, angle = -angle */
+ } else { /* 135 -> 180 or 180 -> -135 */
+ angle = 3.14159265358979323846;
+ if (y >= 0.0)
+ angle -= base_angle; /* 135 -> 180, angle = 180 - angle */
+ else
+ angle = base_angle - angle; /* 180 -> -135, angle = angle - 180 */
+ }
+ } else { /* 45 -> 135 or -135 -> -45 */
+ if (y >= 0.0) { /* 45 -> 135 */
+ angle = 1.57079632679489661923;
+ if (x >= 0.0)
+ angle -= base_angle; /* 45 -> 90, angle = 90 - angle */
+ else
+ angle += base_angle; /* 90 -> 135, angle = 90 + angle */
+ } else { /* -135 -> -45 */
+ angle = -1.57079632679489661923;
+ if (x >= 0.0)
+ angle += base_angle; /* -90 -> -45, angle = -90 + angle */
+ else
+ angle -= base_angle; /* -135 -> -90, angle = -90 - angle */
+ }
+ }
+
+#ifdef ZERO_TO_TWOPI
+ if (angle < 0)
+ return (angle + TWOPI);
+ else
+ return (angle);
+#else
+ return (angle);
+#endif
+}
+
diff --git a/gnuradio-runtime/lib/gr_feval.cc b/gnuradio-runtime/lib/gr_feval.cc
new file mode 100644
index 0000000000..89f09984cf
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_feval.cc
@@ -0,0 +1,132 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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_feval.h>
+
+gr_feval_dd::~gr_feval_dd(){}
+
+double
+gr_feval_dd::eval(double x)
+{
+ return 0;
+}
+
+double
+gr_feval_dd::calleval(double x)
+{
+ return eval(x);
+}
+
+// ----------------------------------------------------------------
+
+gr_feval_cc::~gr_feval_cc(){}
+
+gr_complex
+gr_feval_cc::eval(gr_complex x)
+{
+ return 0;
+}
+
+gr_complex
+gr_feval_cc::calleval(gr_complex x)
+{
+ return eval(x);
+}
+
+// ----------------------------------------------------------------
+
+gr_feval_ll::~gr_feval_ll(){}
+
+long
+gr_feval_ll::eval(long x)
+{
+ return 0;
+}
+
+long
+gr_feval_ll::calleval(long x)
+{
+ return eval(x);
+}
+
+// ----------------------------------------------------------------
+
+gr_feval::~gr_feval(){}
+
+void
+gr_feval::eval(void)
+{
+ // nop
+}
+
+void
+gr_feval::calleval(void)
+{
+ eval();
+}
+
+// ----------------------------------------------------------------
+
+gr_feval_p::~gr_feval_p(){}
+
+void
+gr_feval_p::eval(pmt::pmt_t x)
+{
+ // nop
+}
+
+void
+gr_feval_p::calleval(pmt::pmt_t x)
+{
+ eval(x);
+}
+
+/*
+ * Trivial examples showing C++ (transparently) calling Python
+ */
+double
+gr_feval_dd_example(gr_feval_dd *f, double x)
+{
+ return f->calleval(x);
+}
+
+gr_complex
+gr_feval_cc_example(gr_feval_cc *f, gr_complex x)
+{
+ return f->calleval(x);
+}
+
+long
+gr_feval_ll_example(gr_feval_ll *f, long x)
+{
+ return f->calleval(x);
+}
+
+void
+gr_feval_example(gr_feval *f)
+{
+ f->calleval();
+}
diff --git a/gnuradio-runtime/lib/gr_flat_flowgraph.cc b/gnuradio-runtime/lib/gr_flat_flowgraph.cc
new file mode 100644
index 0000000000..de1e227ef0
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_flat_flowgraph.cc
@@ -0,0 +1,427 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 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_flat_flowgraph.h>
+#include <gr_block_detail.h>
+#include <gr_io_signature.h>
+#include <gr_buffer.h>
+#include <gr_prefs.h>
+#include <volk/volk.h>
+#include <iostream>
+#include <map>
+#include <boost/format.hpp>
+
+#define GR_FLAT_FLOWGRAPH_DEBUG 0
+
+// 32Kbyte buffer size between blocks
+#define GR_FIXED_BUFFER_SIZE (32*(1L<<10))
+
+static const unsigned int s_fixed_buffer_size = GR_FIXED_BUFFER_SIZE;
+
+gr_flat_flowgraph_sptr
+gr_make_flat_flowgraph()
+{
+ return gr_flat_flowgraph_sptr(new gr_flat_flowgraph());
+}
+
+gr_flat_flowgraph::gr_flat_flowgraph()
+{
+}
+
+gr_flat_flowgraph::~gr_flat_flowgraph()
+{
+}
+
+void
+gr_flat_flowgraph::setup_connections()
+{
+ gr_basic_block_vector_t blocks = calc_used_blocks();
+
+ // Assign block details to blocks
+ for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++)
+ cast_to_block_sptr(*p)->set_detail(allocate_block_detail(*p));
+
+ // Connect inputs to outputs for each block
+ for(gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
+ connect_block_inputs(*p);
+
+ gr_block_sptr block = cast_to_block_sptr(*p);
+ block->set_unaligned(0);
+ 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::cons(i->dst().block()->alias_pmt(), i->dst().port()) );
+ }
+
+}
+
+gr_block_detail_sptr
+gr_flat_flowgraph::allocate_block_detail(gr_basic_block_sptr block)
+{
+ int ninputs = calc_used_ports(block, true).size();
+ 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++) {
+ 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.
+ grblock->set_max_output_buffer(i, buffer->bufsize());
+ }
+
+ return detail;
+}
+
+gr_buffer_sptr
+gr_flat_flowgraph::allocate_buffer(gr_basic_block_sptr block, int port)
+{
+ gr_block_sptr grblock = cast_to_block_sptr(block);
+ if (!grblock)
+ throw std::runtime_error("allocate_buffer found non-gr_block");
+ int item_size = block->output_signature()->sizeof_stream_item(port);
+
+ // *2 because we're now only filling them 1/2 way in order to
+ // increase the available parallelism when using the TPB scheduler.
+ // (We're double buffering, where we used to single buffer)
+ int nitems = s_fixed_buffer_size * 2 / item_size;
+
+ // Make sure there are at least twice the output_multiple no. of items
+ if (nitems < 2*grblock->output_multiple()) // Note: this means output_multiple()
+ nitems = 2*grblock->output_multiple(); // can't be changed by block dynamically
+
+ // If any downstream blocks are decimators and/or have a large output_multiple,
+ // ensure we have a buffer at least twice their decimation factor*output_multiple
+ gr_basic_block_vector_t blocks = calc_downstream_blocks(block, port);
+
+ // limit buffer size if indicated
+ 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)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(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!");
+ }
+
+ for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
+ gr_block_sptr dgrblock = cast_to_block_sptr(*p);
+ if (!dgrblock)
+ throw std::runtime_error("allocate_buffer found non-gr_block");
+
+ double decimation = (1.0/dgrblock->relative_rate());
+ int multiple = dgrblock->output_multiple();
+ int history = dgrblock->history();
+ nitems = std::max(nitems, static_cast<int>(2*(decimation*multiple+history)));
+ }
+
+// std::cout << "gr_make_buffer(" << nitems << ", " << item_size << ", " << grblock << "\n";
+ return gr_make_buffer(nitems, item_size, grblock);
+}
+
+void
+gr_flat_flowgraph::connect_block_inputs(gr_basic_block_sptr block)
+{
+ gr_block_sptr grblock = cast_to_block_sptr(block);
+ if (!grblock)
+ throw std::runtime_error("connect_block_inputs found non-gr_block");
+
+ // Get its detail and edges that feed into it
+ gr_block_detail_sptr detail = grblock->detail();
+ gr_edge_vector_t in_edges = calc_upstream_edges(block);
+
+ // For each edge that feeds into it
+ for (gr_edge_viter_t e = in_edges.begin(); e != in_edges.end(); e++) {
+ // Set the buffer reader on the destination port to the output
+ // buffer on the source port
+ int dst_port = e->dst().port();
+ int src_port = e->src().port();
+ gr_basic_block_sptr src_block = e->src().block();
+ gr_block_sptr src_grblock = cast_to_block_sptr(src_block);
+ if (!src_grblock)
+ throw std::runtime_error("connect_block_inputs found non-gr_block");
+ gr_buffer_sptr src_buffer = src_grblock->detail()->output(src_port);
+
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "Setting input " << dst_port << " from edge " << (*e) << std::endl;
+
+ detail->set_input(dst_port, gr_buffer_add_reader(src_buffer, grblock->history()-1, grblock));
+ }
+}
+
+void
+gr_flat_flowgraph::merge_connections(gr_flat_flowgraph_sptr old_ffg)
+{
+ // Allocate block details if needed. Only new blocks that aren't pruned out
+ // by flattening will need one; existing blocks still in the new flowgraph will
+ // already have one.
+ for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {
+ gr_block_sptr block = cast_to_block_sptr(*p);
+
+ if (!block->detail()) {
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "merge: allocating new detail for block " << (*p) << std::endl;
+ block->set_detail(allocate_block_detail(block));
+ }
+ else
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "merge: reusing original detail for block " << (*p) << std::endl;
+ }
+
+ // Calculate the old edges that will be going away, and clear the buffer readers
+ // on the RHS.
+ for (gr_edge_viter_t old_edge = old_ffg->d_edges.begin(); old_edge != old_ffg->d_edges.end(); old_edge++) {
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "merge: testing old edge " << (*old_edge) << "...";
+
+ gr_edge_viter_t new_edge;
+ for (new_edge = d_edges.begin(); new_edge != d_edges.end(); new_edge++)
+ if (new_edge->src() == old_edge->src() &&
+ new_edge->dst() == old_edge->dst())
+ break;
+
+ if (new_edge == d_edges.end()) { // not found in new edge list
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "not in new edge list" << std::endl;
+ // zero the buffer reader on RHS of old edge
+ gr_block_sptr block(cast_to_block_sptr(old_edge->dst().block()));
+ int port = old_edge->dst().port();
+ block->detail()->set_input(port, gr_buffer_reader_sptr());
+ }
+ else {
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "found in new edge list" << std::endl;
+ }
+ }
+
+ // Now connect inputs to outputs, reusing old buffer readers if they exist
+ for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {
+ gr_block_sptr block = cast_to_block_sptr(*p);
+
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "merge: merging " << (*p) << "...";
+
+ if (old_ffg->has_block_p(*p)) {
+ // Block exists in old flow graph
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "used in old flow graph" << std::endl;
+ gr_block_detail_sptr detail = block->detail();
+
+ // Iterate through the inputs and see what needs to be done
+ int ninputs = calc_used_ports(block, true).size(); // Might be different now
+ for (int i = 0; i < ninputs; i++) {
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "Checking input " << block << ":" << i << "...";
+ gr_edge edge = calc_upstream_edge(*p, i);
+
+ // Fish out old buffer reader and see if it matches correct buffer from edge list
+ gr_block_sptr src_block = cast_to_block_sptr(edge.src().block());
+ gr_block_detail_sptr src_detail = src_block->detail();
+ gr_buffer_sptr src_buffer = src_detail->output(edge.src().port());
+ gr_buffer_reader_sptr old_reader;
+ if (i < detail->ninputs()) // Don't exceed what the original detail has
+ old_reader = detail->input(i);
+
+ // If there's a match, use it
+ if (old_reader && (src_buffer == old_reader->buffer())) {
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "matched, reusing" << std::endl;
+ }
+ else {
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "needs a new reader" << std::endl;
+
+ // Create new buffer reader and assign
+ detail->set_input(i, gr_buffer_add_reader(src_buffer, block->history()-1, block));
+ }
+ }
+ }
+ else {
+ // Block is new, it just needs buffer readers at this point
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "new block" << std::endl;
+ connect_block_inputs(block);
+
+ // Make sure all buffers are aligned
+ setup_buffer_alignment(block);
+ }
+
+ // Now deal with the fact that the block details might have changed numbers of
+ // inputs and outputs vs. in the old flowgraph.
+ }
+}
+
+void
+gr_flat_flowgraph::setup_buffer_alignment(gr_block_sptr block)
+{
+ const int alignment = volk_get_alignment();
+ for(int i = 0; i < block->detail()->ninputs(); i++) {
+ void *r = (void*)block->detail()->input(i)->read_pointer();
+ unsigned long int ri = (unsigned long int)r % alignment;
+ //std::cerr << "reader: " << r << " alignment: " << ri << std::endl;
+ if(ri != 0) {
+ size_t itemsize = block->detail()->input(i)->get_sizeof_item();
+ block->detail()->input(i)->update_read_pointer(alignment-ri/itemsize);
+ }
+ block->set_unaligned(0);
+ block->set_is_unaligned(false);
+ }
+
+ for(int i = 0; i < block->detail()->noutputs(); i++) {
+ void *w = (void*)block->detail()->output(i)->write_pointer();
+ unsigned long int wi = (unsigned long int)w % alignment;
+ //std::cerr << "writer: " << w << " alignment: " << wi << std::endl;
+ if(wi != 0) {
+ size_t itemsize = block->detail()->output(i)->get_sizeof_item();
+ block->detail()->output(i)->update_write_pointer(alignment-wi/itemsize);
+ }
+ block->set_unaligned(0);
+ block->set_is_unaligned(false);
+ }
+}
+
+std::string
+gr_flat_flowgraph::edge_list()
+{
+ std::stringstream s;
+ for(gr_edge_viter_t e = d_edges.begin(); e != d_edges.end(); e++)
+ s << (*e) << std::endl;
+ return s.str();
+}
+
+void gr_flat_flowgraph::dump()
+{
+ for (gr_edge_viter_t e = d_edges.begin(); e != d_edges.end(); e++)
+ std::cout << " edge: " << (*e) << std::endl;
+
+ for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {
+ std::cout << " block: " << (*p) << std::endl;
+ gr_block_detail_sptr detail = cast_to_block_sptr(*p)->detail();
+ std::cout << " detail @" << detail << ":" << std::endl;
+
+ int ni = detail->ninputs();
+ int no = detail->noutputs();
+ for (int i = 0; i < no; i++) {
+ gr_buffer_sptr buffer = detail->output(i);
+ std::cout << " output " << i << ": " << buffer << std::endl;
+ }
+
+ for (int i = 0; i < ni; i++) {
+ gr_buffer_reader_sptr reader = detail->input(i);
+ std::cout << " reader " << i << ": " << reader
+ << " reading from buffer=" << reader->buffer() << std::endl;
+ }
+ }
+
+}
+
+gr_block_vector_t
+gr_flat_flowgraph::make_block_vector(gr_basic_block_vector_t &blocks)
+{
+ gr_block_vector_t result;
+ for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
+ result.push_back(cast_to_block_sptr(*p));
+ }
+
+ 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++;
+ }
+ }
+ }
+}
+
+void
+gr_flat_flowgraph::enable_pc_rpc()
+{
+#ifdef GR_PERFORMANCE_COUNTERS
+ if(gr_prefs::singleton()->get_bool("PerfCounters", "on", false)) {
+ gr_basic_block_viter_t p;
+ for(p = d_blocks.begin(); p != d_blocks.end(); p++) {
+ gr_block_sptr block = cast_to_block_sptr(*p);
+ if(!block->is_pc_rpc_set())
+ block->setup_pc_rpc();
+ }
+ }
+#endif /* GR_PERFORMANCE_COUNTERS */
+}
diff --git a/gnuradio-runtime/lib/gr_flat_flowgraph.h b/gnuradio-runtime/lib/gr_flat_flowgraph.h
new file mode 100644
index 0000000000..9c47a77e23
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_flat_flowgraph.h
@@ -0,0 +1,89 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2007 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_FLAT_FLOWGRAPH_H
+#define INCLUDED_GR_FLAT_FLOWGRAPH_H
+
+#include <gr_runtime_api.h>
+#include <gr_flowgraph.h>
+#include <gr_block.h>
+
+// Create a shared pointer to a heap allocated gr_flat_flowgraph
+// (types defined in gr_runtime_types.h)
+GR_RUNTIME_API gr_flat_flowgraph_sptr gr_make_flat_flowgraph();
+
+/*!
+ *\brief Class specializing gr_flat_flowgraph that has all nodes
+ * as gr_blocks, with no hierarchy
+ * \ingroup internal
+ */
+class GR_RUNTIME_API gr_flat_flowgraph : public gr_flowgraph
+{
+public:
+ friend GR_RUNTIME_API gr_flat_flowgraph_sptr gr_make_flat_flowgraph();
+
+ // Destruct an arbitrary gr_flat_flowgraph
+ ~gr_flat_flowgraph();
+
+ // 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);
+
+ // Return a string list of edges
+ std::string edge_list();
+
+ void dump();
+
+ /*!
+ * Make a vector of gr_block from a vector of gr_basic_block
+ */
+ 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);
+
+ /*!
+ * Enables export of perf. counters to ControlPort on all blocks in
+ * the flowgraph.
+ */
+ void enable_pc_rpc();
+
+private:
+ gr_flat_flowgraph();
+
+ gr_block_detail_sptr allocate_block_detail(gr_basic_block_sptr block);
+ gr_buffer_sptr allocate_buffer(gr_basic_block_sptr block, int port);
+ void connect_block_inputs(gr_basic_block_sptr block);
+
+ /* When reusing a flowgraph's blocks, this call makes sure all of the
+ * buffer's are aligned at the machine's alignment boundary and tells
+ * the blocks that they are aligned.
+ *
+ * Called from both setup_connections and merge_connections for
+ * start and restarts.
+ */
+ void setup_buffer_alignment(gr_block_sptr block);
+};
+
+#endif /* INCLUDED_GR_FLAT_FLOWGRAPH_H */
diff --git a/gnuradio-runtime/lib/gr_flowgraph.cc b/gnuradio-runtime/lib/gr_flowgraph.cc
new file mode 100644
index 0000000000..63a2084802
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_flowgraph.cc
@@ -0,0 +1,515 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_flowgraph.h>
+#include <gr_io_signature.h>
+#include <stdexcept>
+#include <sstream>
+#include <iterator>
+
+#define GR_FLOWGRAPH_DEBUG 0
+
+gr_edge::~gr_edge()
+{
+}
+
+gr_flowgraph_sptr gr_make_flowgraph()
+{
+ return gr_flowgraph_sptr(new gr_flowgraph());
+}
+
+gr_flowgraph::gr_flowgraph()
+{
+}
+
+gr_flowgraph::~gr_flowgraph()
+{
+}
+
+// FIXME: move to libgruel as a utility function
+template<class T>
+static
+std::vector<T>
+unique_vector(std::vector<T> v)
+{
+ std::vector<T> result;
+ std::insert_iterator<std::vector<T> > inserter(result, result.begin());
+
+ sort(v.begin(), v.end());
+ unique_copy(v.begin(), v.end(), inserter);
+ return result;
+}
+
+void
+gr_flowgraph::connect(const gr_endpoint &src, const gr_endpoint &dst)
+{
+ check_valid_port(src.block()->output_signature(), src.port());
+ check_valid_port(dst.block()->input_signature(), dst.port());
+ check_dst_not_used(dst);
+ check_type_match(src, dst);
+
+ // All ist klar, Herr Kommisar
+ d_edges.push_back(gr_edge(src,dst));
+}
+
+void
+gr_flowgraph::disconnect(const gr_endpoint &src, const gr_endpoint &dst)
+{
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+ if (src == p->src() && dst == p->dst()) {
+ d_edges.erase(p);
+ return;
+ }
+ }
+
+ std::stringstream msg;
+ msg << "cannot disconnect edge " << gr_edge(src, dst) << ", not found";
+ throw std::invalid_argument(msg.str());
+}
+
+void
+gr_flowgraph::validate()
+{
+ d_blocks = calc_used_blocks();
+
+ for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {
+ std::vector<int> used_ports;
+ int ninputs, noutputs;
+
+ if (GR_FLOWGRAPH_DEBUG)
+ std::cout << "Validating block: " << (*p) << std::endl;
+
+ used_ports = calc_used_ports(*p, true); // inputs
+ ninputs = used_ports.size();
+ check_contiguity(*p, used_ports, true); // inputs
+
+ used_ports = calc_used_ports(*p, false); // outputs
+ noutputs = used_ports.size();
+ check_contiguity(*p, used_ports, false); // outputs
+
+ if (!((*p)->check_topology(ninputs, noutputs))) {
+ std::stringstream msg;
+ msg << "check topology failed on " << (*p)
+ << " using ninputs=" << ninputs
+ << ", noutputs=" << noutputs;
+ throw std::runtime_error(msg.str());
+ }
+ }
+}
+
+void
+gr_flowgraph::clear()
+{
+ // Boost shared pointers will deallocate as needed
+ d_blocks.clear();
+ d_edges.clear();
+}
+
+void
+gr_flowgraph::check_valid_port(gr_io_signature_sptr sig, int port)
+{
+ std::stringstream msg;
+
+ if (port < 0) {
+ msg << "negative port number " << port << " is invalid";
+ throw std::invalid_argument(msg.str());
+ }
+
+ int max = sig->max_streams();
+ if (max != gr_io_signature::IO_INFINITE && port >= max) {
+ msg << "port number " << port << " exceeds max of ";
+ if (max == 0)
+ msg << "(none)";
+ else
+ msg << max-1;
+ throw std::invalid_argument(msg.str());
+ }
+}
+
+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)
+{
+ // A destination is in use if it is already on the edge list
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
+ if (p->dst() == dst) {
+ std::stringstream msg;
+ msg << "destination already in use by edge " << (*p);
+ throw std::invalid_argument(msg.str());
+ }
+}
+
+void
+gr_flowgraph::check_type_match(const gr_endpoint &src, const gr_endpoint &dst)
+{
+ int src_size = src.block()->output_signature()->sizeof_stream_item(src.port());
+ int dst_size = dst.block()->input_signature()->sizeof_stream_item(dst.port());
+
+ if (src_size != dst_size) {
+ std::stringstream msg;
+ msg << "itemsize mismatch: " << src << " using " << src_size
+ << ", " << dst << " using " << dst_size;
+ throw std::invalid_argument(msg.str());
+ }
+}
+
+gr_basic_block_vector_t
+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());
+ tmp.push_back(p->dst().block());
+ }
+
+ return unique_vector<gr_basic_block_sptr>(tmp);
+}
+
+std::vector<int>
+gr_flowgraph::calc_used_ports(gr_basic_block_sptr block, bool check_inputs)
+{
+ std::vector<int> tmp;
+
+ // Collect all seen ports
+ gr_edge_vector_t edges = calc_connections(block, check_inputs);
+ for (gr_edge_viter_t p = edges.begin(); p != edges.end(); p++) {
+ if (check_inputs == true)
+ tmp.push_back(p->dst().port());
+ else
+ tmp.push_back(p->src().port());
+ }
+
+ return unique_vector<int>(tmp);
+}
+
+gr_edge_vector_t
+gr_flowgraph::calc_connections(gr_basic_block_sptr block, bool check_inputs)
+{
+ gr_edge_vector_t result;
+
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+ if (check_inputs) {
+ if (p->dst().block() == block)
+ result.push_back(*p);
+ }
+ else {
+ if (p->src().block() == block)
+ result.push_back(*p);
+ }
+ }
+
+ return result; // assumes no duplicates
+}
+
+void
+gr_flowgraph::check_contiguity(gr_basic_block_sptr block,
+ const std::vector<int> &used_ports,
+ bool check_inputs)
+{
+ std::stringstream msg;
+
+ gr_io_signature_sptr sig =
+ check_inputs ? block->input_signature() : block->output_signature();
+
+ int nports = used_ports.size();
+ int min_ports = sig->min_streams();
+ int max_ports = sig->max_streams();
+
+ if (nports == 0 && min_ports == 0)
+ return;
+
+ if (nports < min_ports) {
+ msg << block << ": insufficient connected "
+ << (check_inputs ? "input ports " : "output ports ")
+ << "(" << min_ports << " needed, " << nports << " connected)";
+ throw std::runtime_error(msg.str());
+ }
+
+ if (nports > max_ports && max_ports != gr_io_signature::IO_INFINITE) {
+ msg << block << ": too many connected "
+ << (check_inputs ? "input ports " : "output ports ")
+ << "(" << max_ports << " allowed, " << nports << " connected)";
+ throw std::runtime_error(msg.str());
+ }
+
+ if (used_ports[nports-1]+1 != nports) {
+ for (int i = 0; i < nports; i++) {
+ if (used_ports[i] != i) {
+ msg << block << ": missing connection "
+ << (check_inputs ? "to input port " : "from output port ")
+ << i;
+ throw std::runtime_error(msg.str());
+ }
+ }
+ }
+}
+
+gr_basic_block_vector_t
+gr_flowgraph::calc_downstream_blocks(gr_basic_block_sptr block, int port)
+{
+ gr_basic_block_vector_t tmp;
+
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
+ if (p->src() == gr_endpoint(block, port))
+ tmp.push_back(p->dst().block());
+
+ return unique_vector<gr_basic_block_sptr>(tmp);
+}
+
+gr_basic_block_vector_t
+gr_flowgraph::calc_downstream_blocks(gr_basic_block_sptr block)
+{
+ gr_basic_block_vector_t tmp;
+
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
+ if (p->src().block() == block)
+ tmp.push_back(p->dst().block());
+
+ return unique_vector<gr_basic_block_sptr>(tmp);
+}
+
+gr_edge_vector_t
+gr_flowgraph::calc_upstream_edges(gr_basic_block_sptr block)
+{
+ gr_edge_vector_t result;
+
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
+ if (p->dst().block() == block)
+ result.push_back(*p);
+
+ return result; // Assume no duplicates
+}
+
+bool
+gr_flowgraph::has_block_p(gr_basic_block_sptr block)
+{
+ gr_basic_block_viter_t result;
+ result = std::find(d_blocks.begin(), d_blocks.end(), block);
+ return (result != d_blocks.end());
+}
+
+gr_edge
+gr_flowgraph::calc_upstream_edge(gr_basic_block_sptr block, int port)
+{
+ gr_edge result;
+
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+ if (p->dst() == gr_endpoint(block, port)) {
+ result = (*p);
+ break;
+ }
+ }
+
+ return result;
+}
+
+std::vector<gr_basic_block_vector_t>
+gr_flowgraph::partition()
+{
+ std::vector<gr_basic_block_vector_t> result;
+ gr_basic_block_vector_t blocks = calc_used_blocks();
+ gr_basic_block_vector_t graph;
+
+ while (blocks.size() > 0) {
+ graph = calc_reachable_blocks(blocks[0], blocks);
+ assert(graph.size());
+ result.push_back(topological_sort(graph));
+
+ for (gr_basic_block_viter_t p = graph.begin(); p != graph.end(); p++)
+ blocks.erase(find(blocks.begin(), blocks.end(), *p));
+ }
+
+ return result;
+}
+
+gr_basic_block_vector_t
+gr_flowgraph::calc_reachable_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks)
+{
+ gr_basic_block_vector_t result;
+
+ // Mark all blocks as unvisited
+ for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++)
+ (*p)->set_color(gr_basic_block::WHITE);
+
+ // Recursively mark all reachable blocks
+ reachable_dfs_visit(block, blocks);
+
+ // Collect all the blocks that have been visited
+ for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++)
+ if ((*p)->color() == gr_basic_block::BLACK)
+ result.push_back(*p);
+
+ return result;
+}
+
+// Recursively mark all reachable blocks from given block and block list
+void
+gr_flowgraph::reachable_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks)
+{
+ // Mark the current one as visited
+ block->set_color(gr_basic_block::BLACK);
+
+ // Recurse into adjacent vertices
+ gr_basic_block_vector_t adjacent = calc_adjacent_blocks(block, blocks);
+
+ for (gr_basic_block_viter_t p = adjacent.begin(); p != adjacent.end(); p++)
+ if ((*p)->color() == gr_basic_block::WHITE)
+ reachable_dfs_visit(*p, blocks);
+}
+
+// Return a list of block adjacent to a given block along any edge
+gr_basic_block_vector_t
+gr_flowgraph::calc_adjacent_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks)
+{
+ gr_basic_block_vector_t tmp;
+
+ // Find any blocks that are inputs or outputs
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+ if (p->src().block() == block)
+ tmp.push_back(p->dst().block());
+ if (p->dst().block() == block)
+ tmp.push_back(p->src().block());
+ }
+
+ return unique_vector<gr_basic_block_sptr>(tmp);
+}
+
+gr_basic_block_vector_t
+gr_flowgraph::topological_sort(gr_basic_block_vector_t &blocks)
+{
+ gr_basic_block_vector_t tmp;
+ gr_basic_block_vector_t result;
+ tmp = sort_sources_first(blocks);
+
+ // Start 'em all white
+ for (gr_basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++)
+ (*p)->set_color(gr_basic_block::WHITE);
+
+ for (gr_basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) {
+ if ((*p)->color() == gr_basic_block::WHITE)
+ topological_dfs_visit(*p, result);
+ }
+
+ reverse(result.begin(), result.end());
+ return result;
+}
+
+gr_basic_block_vector_t
+gr_flowgraph::sort_sources_first(gr_basic_block_vector_t &blocks)
+{
+ gr_basic_block_vector_t sources, nonsources, result;
+
+ for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
+ if (source_p(*p))
+ sources.push_back(*p);
+ else
+ nonsources.push_back(*p);
+ }
+
+ for (gr_basic_block_viter_t p = sources.begin(); p != sources.end(); p++)
+ result.push_back(*p);
+
+ for (gr_basic_block_viter_t p = nonsources.begin(); p != nonsources.end(); p++)
+ result.push_back(*p);
+
+ return result;
+}
+
+bool
+gr_flowgraph::source_p(gr_basic_block_sptr block)
+{
+ return (calc_upstream_edges(block).size() == 0);
+}
+
+void
+gr_flowgraph::topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &output)
+{
+ block->set_color(gr_basic_block::GREY);
+ gr_basic_block_vector_t blocks(calc_downstream_blocks(block));
+
+ for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
+ switch ((*p)->color()) {
+ case gr_basic_block::WHITE:
+ topological_dfs_visit(*p, output);
+ break;
+
+ case gr_basic_block::GREY:
+ throw std::runtime_error("flow graph has loops!");
+
+ case gr_basic_block::BLACK:
+ continue;
+
+ default:
+ throw std::runtime_error("invalid color on block!");
+ }
+ }
+
+ block->set_color(gr_basic_block::BLACK);
+ 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-runtime/lib/gr_fxpt.cc b/gnuradio-runtime/lib/gr_fxpt.cc
new file mode 100644
index 0000000000..2ea8520e6b
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_fxpt.cc
@@ -0,0 +1,35 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_fxpt.h>
+
+const float gr_fxpt::s_sine_table[1 << NBITS][2] = {
+#include "sine_table.h"
+};
+
+const float gr_fxpt::PI = 3.14159265358979323846;
+const float gr_fxpt::TWO_TO_THE_31 = 2147483648.0;
+
diff --git a/gnuradio-runtime/lib/gr_hier_block2.cc b/gnuradio-runtime/lib/gr_hier_block2.cc
new file mode 100644
index 0000000000..9e924fdaf5
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_hier_block2.cc
@@ -0,0 +1,153 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2007,2008 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_hier_block2.h>
+#include <gr_io_signature.h>
+#include <gr_hier_block2_detail.h>
+#include <iostream>
+
+#define GR_HIER_BLOCK2_DEBUG 0
+
+
+gr_hier_block2_sptr
+gr_make_hier_block2(const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature)
+{
+ return gnuradio::get_initial_sptr(new gr_hier_block2(name, input_signature, output_signature));
+}
+
+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)),
+ 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);
+}
+
+gr_hier_block2::~gr_hier_block2()
+{
+ delete d_detail;
+}
+
+gr_hier_block2::opaque_self
+gr_hier_block2::self()
+{
+ return shared_from_this();
+}
+
+gr_hier_block2_sptr
+gr_hier_block2::to_hier_block2()
+{
+ return cast_to_hier_block2_sptr(shared_from_this());
+}
+
+void
+gr_hier_block2::connect(gr_basic_block_sptr block)
+{
+ d_detail->connect(block);
+}
+
+void
+gr_hier_block2::connect(gr_basic_block_sptr src, int src_port,
+ gr_basic_block_sptr dst, int dst_port)
+{
+ d_detail->connect(src, src_port, dst, dst_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::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::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);
+}
+
+void
+gr_hier_block2::disconnect(gr_basic_block_sptr src, int src_port,
+ gr_basic_block_sptr dst, int dst_port)
+{
+ d_detail->disconnect(src, src_port, dst, dst_port);
+}
+
+void
+gr_hier_block2::disconnect_all()
+{
+ d_detail->disconnect_all();
+}
+
+void
+gr_hier_block2::lock()
+{
+ d_detail->lock();
+}
+
+void
+gr_hier_block2::unlock()
+{
+ d_detail->unlock();
+}
+
+
+gr_flat_flowgraph_sptr
+gr_hier_block2::flatten() const
+{
+ gr_flat_flowgraph_sptr new_ffg = gr_make_flat_flowgraph();
+ d_detail->flatten_aux(new_ffg);
+ return new_ffg;
+}
diff --git a/gnuradio-runtime/lib/gr_hier_block2_detail.cc b/gnuradio-runtime/lib/gr_hier_block2_detail.cc
new file mode 100644
index 0000000000..c8564f6698
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_hier_block2_detail.cc
@@ -0,0 +1,641 @@
+/*
+ * Copyright 2006,2007,2009 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_hier_block2_detail.h>
+#include <gr_io_signature.h>
+#include <gr_prefs.h>
+#include <stdexcept>
+#include <sstream>
+#include <boost/format.hpp>
+
+#define GR_HIER_BLOCK2_DETAIL_DEBUG 0
+
+gr_hier_block2_detail::gr_hier_block2_detail(gr_hier_block2 *owner) :
+ d_owner(owner),
+ d_parent_detail(0),
+ d_fg(gr_make_flowgraph())
+{
+ int min_inputs = owner->input_signature()->min_streams();
+ int max_inputs = owner->input_signature()->max_streams();
+ int min_outputs = owner->output_signature()->min_streams();
+ int max_outputs = owner->output_signature()->max_streams();
+
+ if (max_inputs == gr_io_signature::IO_INFINITE ||
+ max_outputs == gr_io_signature::IO_INFINITE ||
+ (min_inputs != max_inputs) ||(min_outputs != max_outputs) ) {
+ std::stringstream msg;
+ msg << "Hierarchical blocks do not yet support arbitrary or"
+ << " variable numbers of inputs or outputs (" << d_owner->name() << ")";
+ throw std::runtime_error(msg.str());
+ }
+
+ d_inputs = std::vector<gr_endpoint_vector_t>(max_inputs);
+ 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
+}
+
+void
+gr_hier_block2_detail::connect(gr_basic_block_sptr block)
+{
+ std::stringstream msg;
+
+ // Check if duplicate
+ if (std::find(d_blocks.begin(), d_blocks.end(), block) != d_blocks.end()) {
+ msg << "Block " << block << " already connected.";
+ throw std::invalid_argument(msg.str());
+ }
+
+ // Check if has inputs or outputs
+ if (block->input_signature()->max_streams() != 0 ||
+ block->output_signature()->max_streams() != 0) {
+ msg << "Block " << block << " must not have any input or output ports";
+ throw std::invalid_argument(msg.str());
+ }
+
+ gr_hier_block2_sptr hblock(cast_to_hier_block2_sptr(block));
+
+ if (hblock && hblock.get() != d_owner) {
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "connect: block is hierarchical, setting parent to " << this << std::endl;
+ hblock->d_detail->d_parent_detail = this;
+ }
+
+ d_blocks.push_back(block);
+}
+
+void
+gr_hier_block2_detail::connect(gr_basic_block_sptr src, int src_port,
+ gr_basic_block_sptr dst, int dst_port)
+{
+ std::stringstream msg;
+
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "connecting: " << gr_endpoint(src, src_port)
+ << " -> " << gr_endpoint(dst, dst_port) << std::endl;
+
+ if (src.get() == dst.get())
+ throw std::invalid_argument("connect: src and destination blocks cannot be the same");
+
+ 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;
+ }
+
+ // Connections to block inputs or outputs
+ int max_port;
+ if (src.get() == d_owner) {
+ max_port = src->input_signature()->max_streams();
+ if ((max_port != -1 && (src_port >= max_port)) || src_port < 0) {
+ msg << "source port " << src_port << " out of range for " << src;
+ throw std::invalid_argument(msg.str());
+ }
+
+ return connect_input(src_port, dst_port, dst);
+ }
+
+ if (dst.get() == d_owner) {
+ max_port = dst->output_signature()->max_streams();
+ if ((max_port != -1 && (dst_port >= max_port)) || dst_port < 0) {
+ msg << "destination port " << dst_port << " out of range for " << dst;
+ throw std::invalid_argument(msg.str());
+ }
+
+ return connect_output(dst_port, src_port, src);
+ }
+
+ // Internal connections
+ d_fg->connect(src, src_port, dst, dst_port);
+
+ // TODO: connects to NC
+}
+
+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::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::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
+ for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {
+ if (*p == block) {
+ d_blocks.erase(p);
+
+ gr_hier_block2_sptr hblock(cast_to_hier_block2_sptr(block));
+ if (block && block.get() != d_owner) {
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "disconnect: block is hierarchical, clearing parent" << std::endl;
+ hblock->d_detail->d_parent_detail = 0;
+ }
+
+ return;
+ }
+ }
+
+ // Otherwise find all edges containing block
+ gr_edge_vector_t edges, tmp = d_fg->edges();
+ gr_edge_vector_t::iterator p;
+ for (p = tmp.begin(); p != tmp.end(); p++) {
+ if ((*p).src().block() == block || (*p).dst().block() == block) {
+ edges.push_back(*p);
+
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "disconnect: block found in edge " << (*p) << std::endl;
+ }
+ }
+
+ if (edges.size() == 0) {
+ std::stringstream msg;
+ msg << "cannot disconnect block " << block << ", not found";
+ throw std::invalid_argument(msg.str());
+ }
+
+ for (p = edges.begin(); p != edges.end(); p++) {
+ disconnect((*p).src().block(), (*p).src().port(),
+ (*p).dst().block(), (*p).dst().port());
+ }
+}
+
+void
+gr_hier_block2_detail::disconnect(gr_basic_block_sptr src, int src_port,
+ gr_basic_block_sptr dst, int dst_port)
+{
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "disconnecting: " << gr_endpoint(src, src_port)
+ << " -> " << gr_endpoint(dst, dst_port) << std::endl;
+
+ if (src.get() == dst.get())
+ throw std::invalid_argument("disconnect: source and destination blocks cannot be the same");
+
+ 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 << "disconnect: src is hierarchical, clearing parent" << std::endl;
+ src_block->d_detail->d_parent_detail = 0;
+ }
+
+ if (dst_block && dst.get() != d_owner) {
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "disconnect: dst is hierarchical, clearing parent" << std::endl;
+ dst_block->d_detail->d_parent_detail = 0;
+ }
+
+ if (src.get() == d_owner)
+ return disconnect_input(src_port, dst_port, dst);
+
+ if (dst.get() == d_owner)
+ return disconnect_output(dst_port, src_port, src);
+
+ // Internal connections
+ d_fg->disconnect(src, src_port, dst, dst_port);
+}
+
+void
+gr_hier_block2_detail::connect_input(int my_port, int port, gr_basic_block_sptr block)
+{
+ std::stringstream msg;
+
+ if (my_port < 0 || my_port >= (signed)d_inputs.size()) {
+ msg << "input port " << my_port << " out of range for " << block;
+ throw std::invalid_argument(msg.str());
+ }
+
+ gr_endpoint_vector_t &endps = d_inputs[my_port];
+ gr_endpoint endp(block, port);
+
+ gr_endpoint_viter_t p = std::find(endps.begin(), endps.end(), endp);
+ if (p != endps.end()) {
+ msg << "external input port " << my_port << " already wired to " << endp;
+ throw std::invalid_argument(msg.str());
+ }
+
+ endps.push_back(endp);
+}
+
+void
+gr_hier_block2_detail::connect_output(int my_port, int port, gr_basic_block_sptr block)
+{
+ std::stringstream msg;
+
+ if (my_port < 0 || my_port >= (signed)d_outputs.size()) {
+ msg << "output port " << my_port << " out of range for " << block;
+ throw std::invalid_argument(msg.str());
+ }
+
+ if (d_outputs[my_port].block()) {
+ msg << "external output port " << my_port << " already connected from "
+ << d_outputs[my_port];
+ throw std::invalid_argument(msg.str());
+ }
+
+ d_outputs[my_port] = gr_endpoint(block, port);
+}
+
+void
+gr_hier_block2_detail::disconnect_input(int my_port, int port, gr_basic_block_sptr block)
+{
+ std::stringstream msg;
+
+ if (my_port < 0 || my_port >= (signed)d_inputs.size()) {
+ msg << "input port number " << my_port << " out of range for " << block;
+ throw std::invalid_argument(msg.str());
+ }
+
+ gr_endpoint_vector_t &endps = d_inputs[my_port];
+ gr_endpoint endp(block, port);
+
+ gr_endpoint_viter_t p = std::find(endps.begin(), endps.end(), endp);
+ if (p == endps.end()) {
+ msg << "external input port " << my_port << " not connected to " << endp;
+ throw std::invalid_argument(msg.str());
+ }
+
+ endps.erase(p);
+}
+
+void
+gr_hier_block2_detail::disconnect_output(int my_port, int port, gr_basic_block_sptr block)
+{
+ std::stringstream msg;
+
+ if (my_port < 0 || my_port >= (signed)d_outputs.size()) {
+ msg << "output port number " << my_port << " out of range for " << block;
+ throw std::invalid_argument(msg.str());
+ }
+
+ if (d_outputs[my_port].block() != block) {
+ msg << "block " << block << " not assigned to output "
+ << my_port << ", can't disconnect";
+ throw std::invalid_argument(msg.str());
+ }
+
+ d_outputs[my_port] = gr_endpoint();
+}
+
+gr_endpoint_vector_t
+gr_hier_block2_detail::resolve_port(int port, bool is_input)
+{
+ std::stringstream msg;
+
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "Resolving port " << port << " as an "
+ << (is_input ? "input" : "output")
+ << " of " << d_owner->name() << std::endl;
+
+ gr_endpoint_vector_t result;
+
+ if (is_input) {
+ if (port < 0 || port >= (signed)d_inputs.size()) {
+ msg << "resolve_port: hierarchical block '" << d_owner->name()
+ << "': input " << port << " is out of range";
+ throw std::runtime_error(msg.str());
+ }
+
+ if (d_inputs[port].empty()) {
+ msg << "resolve_port: hierarchical block '" << d_owner->name()
+ << "': input " << port << " is not connected internally";
+ throw std::runtime_error(msg.str());
+ }
+
+ gr_endpoint_vector_t &endps = d_inputs[port];
+ gr_endpoint_viter_t p;
+ for (p = endps.begin(); p != endps.end(); p++) {
+ gr_endpoint_vector_t tmp = resolve_endpoint(*p, true);
+ std::copy(tmp.begin(), tmp.end(), back_inserter(result));
+ }
+ }
+ else {
+ if (port < 0 || port >= (signed)d_outputs.size()) {
+ msg << "resolve_port: hierarchical block '" << d_owner->name()
+ << "': output " << port << " is out of range";
+ throw std::runtime_error(msg.str());
+ }
+
+ if (d_outputs[port] == gr_endpoint()) {
+ msg << "resolve_port: hierarchical block '" << d_owner->name()
+ << "': output " << port << " is not connected internally";
+ throw std::runtime_error(msg.str());
+ }
+
+ result = resolve_endpoint(d_outputs[port], false);
+ }
+
+ if (result.empty()) {
+ msg << "resolve_port: hierarchical block '" << d_owner->name()
+ << "': unable to resolve "
+ << (is_input ? "input port " : "output port ")
+ << port;
+ throw std::runtime_error(msg.str());
+ }
+
+ return result;
+}
+
+void
+gr_hier_block2_detail::disconnect_all()
+{
+ d_fg->clear();
+ d_blocks.clear();
+ d_inputs.clear();
+ d_outputs.clear();
+}
+
+gr_endpoint_vector_t
+gr_hier_block2_detail::resolve_endpoint(const gr_endpoint &endp, bool is_input) const
+{
+ std::stringstream msg;
+ gr_endpoint_vector_t result;
+
+ // Check if endpoint is a leaf node
+ if (cast_to_block_sptr(endp.block())) {
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "Block " << endp.block() << " is a leaf node, returning." << std::endl;
+ result.push_back(endp);
+ return result;
+ }
+
+ // Check if endpoint is a hierarchical block
+ gr_hier_block2_sptr hier_block2(cast_to_hier_block2_sptr(endp.block()));
+ if (hier_block2) {
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "Resolving endpoint " << endp << " as an "
+ << (is_input ? "input" : "output")
+ << ", recursing" << std::endl;
+ return hier_block2->d_detail->resolve_port(endp.port(), is_input);
+ }
+
+ msg << "unable to resolve" << (is_input ? " input " : " output ")
+ << "endpoint " << endp;
+ throw std::runtime_error(msg.str());
+}
+
+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;
+
+ // 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;
+
+ // Only run setup_rpc if ControlPort config param is enabled.
+ bool ctrlport_on = gr_prefs::singleton()->get_bool("ControlPort", "on", false);
+
+ // For every block (gr_block and gr_hier_block2), set up the RPC
+ // interface.
+ for(p = edges.begin(); p != edges.end(); p++) {
+ gr_basic_block_sptr b;
+ b = p->src().block();
+
+ if(ctrlport_on) {
+ if(!b->is_rpc_set()) {
+ b->setup_rpc();
+ b->rpc_set();
+ }
+ }
+
+ b = p->dst().block();
+ if(ctrlport_on) {
+ if(!b->is_rpc_set()) {
+ b->setup_rpc();
+ b->rpc_set();
+ }
+ }
+ }
+
+ 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)
+ std::cout << "Flattening edge " << (*p) << std::endl;
+
+ gr_endpoint_vector_t src_endps = resolve_endpoint(p->src(), false);
+ gr_endpoint_vector_t dst_endps = resolve_endpoint(p->dst(), true);
+
+ gr_endpoint_viter_t s, d;
+ for (s = src_endps.begin(); s != src_endps.end(); s++) {
+ for (d = dst_endps.begin(); d != dst_endps.end(); d++) {
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << (*s) << "->" << (*d) << std::endl;
+ sfg->connect(*s, *d);
+ }
+ }
+ }
+
+ // 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
+ gr_basic_block_vector_t tmp = d_fg->calc_used_blocks();
+
+ // First add the list of singleton blocks
+ std::vector<gr_basic_block_sptr>::const_iterator b; // Because flatten_aux is const
+ for (b = d_blocks.begin(); b != d_blocks.end(); b++)
+ tmp.push_back(*b);
+
+ // Now add the list of connected input blocks
+ std::stringstream msg;
+ for (unsigned int i = 0; i < d_inputs.size(); i++) {
+ if (d_inputs[i].size() == 0) {
+ msg << "In hierarchical block " << d_owner->name() << ", input " << i
+ << " is not connected internally";
+ throw std::runtime_error(msg.str());
+ }
+
+ for (unsigned int j = 0; j < d_inputs[i].size(); j++)
+ tmp.push_back(d_inputs[i][j].block());
+ }
+
+ for (unsigned int i = 0; i < d_outputs.size(); i++) {
+ gr_basic_block_sptr blk = d_outputs[i].block();
+ if (!blk) {
+ msg << "In hierarchical block " << d_owner->name() << ", output " << i
+ << " is not connected internally";
+ throw std::runtime_error(msg.str());
+ }
+ tmp.push_back(blk);
+ }
+ sort(tmp.begin(), tmp.end());
+
+ std::insert_iterator<gr_basic_block_vector_t> inserter(blocks, blocks.begin());
+ unique_copy(tmp.begin(), tmp.end(), inserter);
+
+ // 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 && (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);
+ }
+ }
+}
+
+void
+gr_hier_block2_detail::lock()
+{
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "lock: entered in " << this << std::endl;
+
+ if (d_parent_detail)
+ d_parent_detail->lock();
+ else
+ d_owner->lock();
+}
+
+void
+gr_hier_block2_detail::unlock()
+{
+ if (GR_HIER_BLOCK2_DETAIL_DEBUG)
+ std::cout << "unlock: entered in " << this << std::endl;
+
+ if (d_parent_detail)
+ d_parent_detail->unlock();
+ else
+ d_owner->unlock();
+}
+
diff --git a/gnuradio-runtime/lib/gr_hier_block2_detail.h b/gnuradio-runtime/lib/gr_hier_block2_detail.h
new file mode 100644
index 0000000000..d08fe20ac0
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_hier_block2_detail.h
@@ -0,0 +1,74 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2007,2009 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_HIER_BLOCK2_DETAIL_H
+#define INCLUDED_GR_HIER_BLOCK2_DETAIL_H
+
+#include <gr_runtime_api.h>
+#include <gr_hier_block2.h>
+#include <gr_flat_flowgraph.h>
+#include <boost/utility.hpp>
+
+/*!
+ * \ingroup internal
+ */
+class GR_RUNTIME_API gr_hier_block2_detail : boost::noncopyable
+{
+public:
+ gr_hier_block2_detail(gr_hier_block2 *owner);
+ ~gr_hier_block2_detail();
+
+ 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);
+ void disconnect_all();
+ void lock();
+ void unlock();
+ void flatten_aux(gr_flat_flowgraph_sptr sfg) const;
+
+private:
+
+ // Private implementation data
+ gr_hier_block2 *d_owner;
+ gr_hier_block2_detail *d_parent_detail;
+ gr_flowgraph_sptr d_fg;
+ std::vector<gr_endpoint_vector_t> d_inputs; // Multiple internal endpoints per external input
+ 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);
+ void disconnect_output(int my_port, int port, gr_basic_block_sptr block);
+
+ gr_endpoint_vector_t resolve_port(int port, bool is_input);
+ gr_endpoint_vector_t resolve_endpoint(const gr_endpoint &endp, bool is_input) const;
+};
+
+#endif /* INCLUDED_GR_HIER_BLOCK2_DETAIL_H */
diff --git a/gnuradio-runtime/lib/gr_io_signature.cc b/gnuradio-runtime/lib/gr_io_signature.cc
new file mode 100644
index 0000000000..6ac9acd17d
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_io_signature.cc
@@ -0,0 +1,112 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007 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_io_signature.h>
+#include <stdexcept>
+#include <iostream>
+
+gr_io_signature_sptr
+gr_make_io_signaturev(int min_streams, int max_streams,
+ const std::vector<int> &sizeof_stream_items)
+{
+ return gr_io_signature_sptr (new gr_io_signature (min_streams, max_streams,
+ sizeof_stream_items));
+}
+
+gr_io_signature_sptr
+gr_make_io_signature(int min_streams, int max_streams,
+ int sizeof_stream_item)
+{
+ std::vector<int> sizeof_items(1);
+ sizeof_items[0] = sizeof_stream_item;
+ return gr_make_io_signaturev(min_streams, max_streams, sizeof_items);
+}
+
+gr_io_signature_sptr
+gr_make_io_signature2(int min_streams, int max_streams,
+ int sizeof_stream_item1,
+ int sizeof_stream_item2)
+{
+ std::vector<int> sizeof_items(2);
+ sizeof_items[0] = sizeof_stream_item1;
+ sizeof_items[1] = sizeof_stream_item2;
+ return gr_make_io_signaturev(min_streams, max_streams, sizeof_items);
+}
+
+gr_io_signature_sptr
+gr_make_io_signature3(int min_streams, int max_streams,
+ int sizeof_stream_item1,
+ int sizeof_stream_item2,
+ int sizeof_stream_item3)
+{
+ std::vector<int> sizeof_items(3);
+ sizeof_items[0] = sizeof_stream_item1;
+ sizeof_items[1] = sizeof_stream_item2;
+ sizeof_items[2] = sizeof_stream_item3;
+ return gr_make_io_signaturev(min_streams, max_streams, sizeof_items);
+}
+
+// ------------------------------------------------------------------------
+
+
+gr_io_signature::gr_io_signature (int min_streams, int max_streams,
+ const std::vector<int> &sizeof_stream_items)
+{
+ if (min_streams < 0
+ || (max_streams != IO_INFINITE && max_streams < min_streams))
+ throw std::invalid_argument ("gr_io_signature(1)");
+
+ if (sizeof_stream_items.size() < 1)
+ throw std::invalid_argument("gr_io_signature(2)");
+
+ for (size_t i = 0; i < sizeof_stream_items.size(); i++){
+ if (max_streams != 0 && sizeof_stream_items[i] < 1)
+ throw std::invalid_argument("gr_io_signature(3)");
+ }
+
+ d_min_streams = min_streams;
+ d_max_streams = max_streams;
+ d_sizeof_stream_item = sizeof_stream_items;
+}
+
+gr_io_signature::~gr_io_signature ()
+{
+}
+
+int
+gr_io_signature::sizeof_stream_item (int _index) const
+{
+ if (_index < 0)
+ throw std::invalid_argument ("gr_io_signature::sizeof_stream_item");
+
+ size_t index = _index;
+ return d_sizeof_stream_item[std::min(index, d_sizeof_stream_item.size() - 1)];
+}
+
+std::vector<int>
+gr_io_signature::sizeof_stream_items() const
+{
+ return d_sizeof_stream_item;
+}
diff --git a/gnuradio-runtime/lib/gr_local_sighandler.cc b/gnuradio-runtime/lib/gr_local_sighandler.cc
new file mode 100644
index 0000000000..fb31742e13
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_local_sighandler.cc
@@ -0,0 +1,187 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_local_sighandler.h>
+#include <stdexcept>
+#include <stdio.h>
+#include <string.h>
+
+
+gr_local_sighandler::gr_local_sighandler (int signum,
+ void (*new_handler)(int))
+ : d_signum (signum)
+{
+#ifdef HAVE_SIGACTION
+ struct sigaction new_action;
+ memset (&new_action, 0, sizeof (new_action));
+
+ new_action.sa_handler = new_handler;
+ sigemptyset (&new_action.sa_mask);
+ new_action.sa_flags = 0;
+
+ if (sigaction (d_signum, &new_action, &d_old_action) < 0){
+ perror ("sigaction (install new)");
+ throw std::runtime_error ("sigaction");
+ }
+#endif
+}
+
+gr_local_sighandler::~gr_local_sighandler ()
+{
+#ifdef HAVE_SIGACTION
+ if (sigaction (d_signum, &d_old_action, 0) < 0){
+ perror ("sigaction (restore old)");
+ throw std::runtime_error ("sigaction");
+ }
+#endif
+}
+
+void
+gr_local_sighandler::throw_signal (int signum)
+{
+ throw gr_signal (signum);
+}
+
+/*
+ * Semi-hideous way to may a signal number into a signal name
+ */
+
+#define SIGNAME(x) case x: return #x
+
+std::string
+gr_signal::name () const
+{
+ char tmp[128];
+
+ switch (signal ()){
+#ifdef SIGHUP
+ SIGNAME (SIGHUP);
+#endif
+#ifdef SIGINT
+ SIGNAME (SIGINT);
+#endif
+#ifdef SIGQUIT
+ SIGNAME (SIGQUIT);
+#endif
+#ifdef SIGILL
+ SIGNAME (SIGILL);
+#endif
+#ifdef SIGTRAP
+ SIGNAME (SIGTRAP);
+#endif
+#ifdef SIGABRT
+ SIGNAME (SIGABRT);
+#endif
+#ifdef SIGBUS
+ SIGNAME (SIGBUS);
+#endif
+#ifdef SIGFPE
+ SIGNAME (SIGFPE);
+#endif
+#ifdef SIGKILL
+ SIGNAME (SIGKILL);
+#endif
+#ifdef SIGUSR1
+ SIGNAME (SIGUSR1);
+#endif
+#ifdef SIGSEGV
+ SIGNAME (SIGSEGV);
+#endif
+#ifdef SIGUSR2
+ SIGNAME (SIGUSR2);
+#endif
+#ifdef SIGPIPE
+ SIGNAME (SIGPIPE);
+#endif
+#ifdef SIGALRM
+ SIGNAME (SIGALRM);
+#endif
+#ifdef SIGTERM
+ SIGNAME (SIGTERM);
+#endif
+#ifdef SIGSTKFLT
+ SIGNAME (SIGSTKFLT);
+#endif
+#ifdef SIGCHLD
+ SIGNAME (SIGCHLD);
+#endif
+#ifdef SIGCONT
+ SIGNAME (SIGCONT);
+#endif
+#ifdef SIGSTOP
+ SIGNAME (SIGSTOP);
+#endif
+#ifdef SIGTSTP
+ SIGNAME (SIGTSTP);
+#endif
+#ifdef SIGTTIN
+ SIGNAME (SIGTTIN);
+#endif
+#ifdef SIGTTOU
+ SIGNAME (SIGTTOU);
+#endif
+#ifdef SIGURG
+ SIGNAME (SIGURG);
+#endif
+#ifdef SIGXCPU
+ SIGNAME (SIGXCPU);
+#endif
+#ifdef SIGXFSZ
+ SIGNAME (SIGXFSZ);
+#endif
+#ifdef SIGVTALRM
+ SIGNAME (SIGVTALRM);
+#endif
+#ifdef SIGPROF
+ SIGNAME (SIGPROF);
+#endif
+#ifdef SIGWINCH
+ SIGNAME (SIGWINCH);
+#endif
+#ifdef SIGIO
+ SIGNAME (SIGIO);
+#endif
+#ifdef SIGPWR
+ SIGNAME (SIGPWR);
+#endif
+#ifdef SIGSYS
+ SIGNAME (SIGSYS);
+#endif
+ default:
+#if defined (HAVE_SNPRINTF)
+#if defined (SIGRTMIN) && defined (SIGRTMAX)
+ if (signal () >= SIGRTMIN && signal () <= SIGRTMAX){
+ snprintf (tmp, sizeof (tmp), "SIGRTMIN + %d", signal ());
+ return tmp;
+ }
+#endif
+ snprintf (tmp, sizeof (tmp), "SIGNAL %d", signal ());
+ return tmp;
+#else
+ return "Unknown signal";
+#endif
+ }
+}
diff --git a/gnuradio-runtime/lib/gr_local_sighandler.h b/gnuradio-runtime/lib/gr_local_sighandler.h
new file mode 100644
index 0000000000..a49ee031ca
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_local_sighandler.h
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_LOCAL_SIGHANDLER_H
+#define INCLUDED_GR_LOCAL_SIGHANDLER_H
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#include <gr_runtime_api.h>
+#include <string>
+
+/*!
+ * \brief Get and set signal handler.
+ *
+ * \ingroup internal
+ * Constructor installs new handler, destructor reinstalls
+ * original value.
+ */
+class GR_RUNTIME_API gr_local_sighandler {
+ int d_signum;
+#ifdef HAVE_SIGACTION
+ struct sigaction d_old_action;
+#endif
+public:
+ gr_local_sighandler (int signum, void (*new_handler)(int));
+ ~gr_local_sighandler ();
+
+ /* throw gr_signal (signum) */
+ static void throw_signal (int signum);
+};
+
+/*!
+ * \brief Representation of signal.
+ */
+class GR_RUNTIME_API gr_signal
+{
+ int d_signum;
+public:
+ gr_signal (int signum) : d_signum (signum) {}
+ int signal () const { return d_signum; }
+ std::string name () const;
+};
+
+#endif /* INCLUDED_GR_LOCAL_SIGHANDLER_H */
diff --git a/gnuradio-runtime/lib/gr_logger.cc b/gnuradio-runtime/lib/gr_logger.cc
new file mode 100644
index 0000000000..7e0116d036
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_logger.cc
@@ -0,0 +1,291 @@
+/* -*- 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.
+ */
+
+/*******************************************************************************
+* Author: Mark Plett
+* Description:
+* The gr_log module wraps the log4cpp library for logging in gnuradio.
+*******************************************************************************/
+
+#include <gr_logger.h>
+#include <stdexcept>
+#include <algorithm>
+
+#ifdef ENABLE_GR_LOG
+#ifdef HAVE_LOG4CPP
+
+/**************************** BEGIN LOG4CPP HELPERS ***************************/
+/* Logger config class. This is a singleton that controls how log4cpp is configured
+ * If watch_period>0 a thread is started to watch teh config file for changes.
+ */
+
+// Getters of logger_config
+logger_config&
+logger_config::get_instance(void){
+ static logger_config instance;
+ return instance;
+};
+
+std::string
+logger_config::get_filename(){
+ logger_config& in=get_instance();
+ return in.filename;
+};
+
+unsigned int
+logger_config::get_watch_period(){
+ logger_config& in=get_instance();
+ return in.watch_period;
+};
+
+// Method to watch config file for changes
+void logger_config::watch_file(std::string filename,unsigned int watch_period){
+ std::time_t last_write(boost::filesystem::last_write_time(filename));
+ std::time_t current_time(0);
+ while(true){
+ try{
+ current_time = boost::filesystem::last_write_time(filename);
+ if(current_time>last_write){
+ std::cout<<"GNURadio Reloading logger configuration:"<<filename<<std::endl;
+ last_write = current_time;
+// Should we wipe out all old configuration or just add the new? Just adding...
+// logger_reset_config();
+ logger_load_config(filename);
+ };
+ boost::this_thread::sleep(boost::posix_time::time_duration(0,0,watch_period,0));
+ }
+ catch(const boost::thread_interrupted&){
+ std::cout<<"GNURadio leaving logger config file watch."<<std::endl;
+ break;
+ };
+ };
+};
+
+// Method to load the confifuration. It only loads if the filename or watch has changed
+void logger_config::load_config(std::string filename,unsigned int watch_period){
+ logger_config& instance = get_instance();
+// Only reconfigure if filename or watch has changed
+ if(instance.filename!=filename || watch_period!=instance.watch_period){
+ instance.filename = filename;
+ instance.watch_period = watch_period;
+// Stop any file watching thread
+ if(instance.watch_thread!=NULL) stop_watch();
+// Load configuration
+ std::cout<<"GNURadio Loading logger configuration:"<<instance.filename<<std::endl;
+ logger_load_config(instance.filename);
+// Start watch if required
+ if(instance.watch_period>0){
+ instance.watch_thread = new boost::thread(watch_file,instance.filename,instance.watch_period);
+ }
+ };
+};
+
+// Method to stop the watcher thread
+void logger_config::stop_watch(){
+ logger_config& instance = get_instance();
+ if(instance.watch_thread){
+ instance.watch_thread->interrupt();
+ instance.watch_thread->join();
+ delete(instance.watch_thread);
+ instance.watch_thread=NULL;
+ };
+};
+
+// Method to reset logger configuration
+void
+logger_config::reset_config(void){
+ logger_config& instance = get_instance();
+ stop_watch();
+ std::vector<log4cpp::Category*> *loggers = log4cpp::Category::getCurrentCategories();
+ std::vector<log4cpp::Category*>::iterator logger = loggers->begin();
+// We can't destroy categories but we can neuter them by removing all appenders.
+ for (;logger!=loggers->end();logger++){
+ (*logger)->removeAllAppenders();
+ };
+ instance.filename=std::string("");
+ instance.watch_period=0;
+}
+
+/***************** Functions to call log4cpp methods *************************/
+
+gr_logger_ptr
+logger_get_logger(std::string name)
+{
+ if(log4cpp::Category::exists(name)){
+ gr_logger_ptr logger = &log4cpp::Category::getInstance(name);
+ return logger;
+ }
+ else
+ {
+ gr_logger_ptr logger = &log4cpp::Category::getInstance(name);
+ logger->setPriority(log4cpp::Priority::NOTSET);
+ return logger;
+ };
+};
+
+void
+logger_load_config(const std::string &config_filename)
+{
+ if(config_filename.size() != 0) {
+ try
+ {
+ log4cpp::PropertyConfigurator::configure(config_filename);
+ }
+ catch( log4cpp::ConfigureFailure &e )
+ {
+ std::cout << "Logger config failed :" << e.what() << std::endl;
+ }
+ };
+}
+
+void
+logger_set_level(gr_logger_ptr logger, const std::string &level)
+{
+ std::string nocase = level;
+ std::transform(level.begin(), level.end(), nocase.begin(), ::tolower);
+
+ if(nocase == "off" || nocase == "notset")
+ logger_set_level(logger, log4cpp::Priority::NOTSET);
+ else if(nocase == "all" || nocase == "debug")
+ logger_set_level(logger, log4cpp::Priority::DEBUG);
+ else if(nocase == "info")
+ logger_set_level(logger, log4cpp::Priority::INFO);
+ else if(nocase == "notice")
+ logger_set_level(logger, log4cpp::Priority::NOTICE);
+ else if(nocase == "warn")
+ logger_set_level(logger, log4cpp::Priority::WARN);
+ else if(nocase == "error")
+ logger_set_level(logger, log4cpp::Priority::ERROR);
+ else if(nocase == "crit")
+ logger_set_level(logger, log4cpp::Priority::CRIT);
+ else if(nocase == "alert")
+ logger_set_level(logger, log4cpp::Priority::ALERT);
+ else if(nocase=="fatal")
+ logger_set_level(logger, log4cpp::Priority::FATAL);
+ else if(nocase == "emerg")
+ logger_set_level(logger, log4cpp::Priority::EMERG);
+ else
+ throw std::runtime_error("logger_set_level: Bad level type.\n");
+}
+
+void
+logger_set_level(gr_logger_ptr logger, log4cpp::Priority::Value level)
+{
+ logger->setPriority(level);
+}
+
+void
+logger_get_level(gr_logger_ptr logger, std::string &level)
+{
+ log4cpp::Priority::Value levelPtr = logger->getPriority();
+ if(levelPtr == log4cpp::Priority::NOTSET) level = "noset";
+ if(levelPtr == log4cpp::Priority::DEBUG) level = "debug";
+ if(levelPtr == log4cpp::Priority::INFO) level = "info";
+ if(levelPtr == log4cpp::Priority::NOTICE) level = "notice";
+ if(levelPtr == log4cpp::Priority::WARN) level = "warn";
+ if(levelPtr == log4cpp::Priority::ERROR) level = "error";
+ if(levelPtr == log4cpp::Priority::CRIT) level = "crit";
+ if(levelPtr == log4cpp::Priority::ALERT) level = "alert";
+ if(levelPtr == log4cpp::Priority::FATAL) level = "fatal";
+ if(levelPtr == log4cpp::Priority::EMERG) level = "emerg";
+};
+
+void
+logger_get_level(gr_logger_ptr logger,log4cpp::Priority::Value level)
+{
+ level = logger->getPriority();
+}
+
+void
+logger_add_console_appender(gr_logger_ptr logger,std::string target,std::string pattern)
+{
+
+ log4cpp::PatternLayout* layout = new log4cpp::PatternLayout();
+ log4cpp::Appender* app;
+ if(target=="stdout")
+ app = new log4cpp::OstreamAppender("ConsoleAppender::",&std::cout);
+ else
+ app = new log4cpp::OstreamAppender("ConsoleAppender::",&std::cerr);
+
+ layout->setConversionPattern(pattern);
+ app->setLayout(layout);
+ logger->setAppender(app);
+
+}
+
+void
+logger_add_file_appender(gr_logger_ptr logger,std::string filename,bool append,std::string pattern)
+{
+
+ log4cpp::PatternLayout* layout = new log4cpp::PatternLayout();
+ log4cpp::Appender* app = new
+ log4cpp::FileAppender("FileAppender::"+filename,
+ filename);
+ layout->setConversionPattern(pattern);
+ app->setLayout(layout);
+ logger->setAppender(app);
+
+}
+
+void
+logger_add_rollingfile_appender(gr_logger_ptr logger,std::string filename,
+ size_t filesize,int bkup_index,bool append,mode_t mode,std::string pattern)
+{
+ log4cpp::PatternLayout* layout = new log4cpp::PatternLayout();
+ log4cpp::Appender* app = new
+ log4cpp::RollingFileAppender("RollFileAppender::"+filename,filename,filesize,bkup_index,append,mode);
+ layout->setConversionPattern(pattern);
+ app->setLayout(layout);
+ logger->setAppender(app);
+}
+
+std::vector<std::string>
+logger_get_logger_names(void){
+ std::vector<std::string> names;
+ std::vector<log4cpp::Category*> *loggers = log4cpp::Category::getCurrentCategories();
+ std::vector<log4cpp::Category*>::iterator logger = loggers->begin();
+
+ for (;logger!=loggers->end();logger++){
+ names.push_back((*logger)->getName());
+ };
+ return names;
+
+}
+
+#endif /* HAVE_LOG4CPP */
+
+/****** Start Methods to provide Python the capabilities of the macros ********/
+void gr_logger_config(const std::string config_filename, unsigned int watch_period){
+ GR_CONFIG_AND_WATCH_LOGGER(config_filename,watch_period);
+};
+std::vector<std::string> gr_logger_get_logger_names(void){
+ std::vector<std::string> names;
+ GR_GET_LOGGER_NAMES(names);
+ return names;
+};
+void gr_logger_reset_config(void){
+ GR_RESET_CONFIGURATION();
+};
+
+// Remaining capability provided by gr_logger class in gr_logger.h
+
+#endif /* ENABLE_GR_LOGGER */
diff --git a/gnuradio-runtime/lib/gr_message.cc b/gnuradio-runtime/lib/gr_message.cc
new file mode 100644
index 0000000000..a99dcd7653
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_message.cc
@@ -0,0 +1,78 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <gr_message.h>
+#include <assert.h>
+#include <string.h>
+
+static long s_ncurrently_allocated = 0;
+
+gr_message_sptr
+gr_make_message (long type, double arg1, double arg2, size_t length)
+{
+ return gr_message_sptr (new gr_message (type, arg1, arg2, length));
+}
+
+gr_message_sptr
+gr_make_message_from_string(const std::string s, long type, double arg1, double arg2)
+{
+ gr_message_sptr m = gr_make_message(type, arg1, arg2, s.size());
+ memcpy(m->msg(), s.data(), s.size());
+ return m;
+}
+
+
+gr_message::gr_message (long type, double arg1, double arg2, size_t length)
+ : d_type(type), d_arg1(arg1), d_arg2(arg2)
+{
+ if (length == 0)
+ d_buf_start = d_msg_start = d_msg_end = d_buf_end = 0;
+ else {
+ d_buf_start = new unsigned char [length];
+ d_msg_start = d_buf_start;
+ d_msg_end = d_buf_end = d_buf_start + length;
+ }
+ s_ncurrently_allocated++;
+}
+
+gr_message::~gr_message ()
+{
+ assert (d_next == 0);
+ delete [] d_buf_start;
+ d_msg_start = d_msg_end = d_buf_end = 0;
+ s_ncurrently_allocated--;
+}
+
+std::string
+gr_message::to_string() const
+{
+ return std::string((char *)d_msg_start, length());
+}
+
+long
+gr_message_ncurrently_allocated ()
+{
+ return s_ncurrently_allocated;
+}
diff --git a/gnuradio-runtime/lib/gr_misc.cc b/gnuradio-runtime/lib/gr_misc.cc
new file mode 100644
index 0000000000..1ed2a03d7f
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_misc.cc
@@ -0,0 +1,65 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <gr_misc.h>
+
+unsigned int
+gr_rounduppow2(unsigned int n)
+{
+ int i;
+ for (i=0;((n-1)>>i) != 0;i++)
+ ;
+ return 1<<i;
+}
+
+// ----------------------------------------------------------------
+
+void
+gr_zero_vector(std::vector<float> &v)
+{
+ for(unsigned int i=0; i < v.size(); i++)
+ v[i] = 0;
+}
+
+void
+gr_zero_vector(std::vector<double> &v)
+{
+ for(unsigned int i=0; i < v.size(); i++)
+ v[i] = 0;
+}
+
+void
+gr_zero_vector(std::vector<int> &v)
+{
+ for(unsigned int i=0; i < v.size(); i++)
+ v[i] = 0;
+}
+
+void
+gr_zero_vector(std::vector<gr_complex> &v)
+{
+ for(unsigned int i=0; i < v.size(); i++)
+ v[i] = 0;
+}
diff --git a/gnuradio-runtime/lib/gr_misc.h b/gnuradio-runtime/lib/gr_misc.h
new file mode 100644
index 0000000000..182ae87de6
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_misc.h
@@ -0,0 +1,39 @@
+/* -*- 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.
+ */
+
+#ifndef INCLUDED_GR_MISC_H
+#define INCLUDED_GR_MISC_H
+
+#include <gr_runtime_api.h>
+#include <gr_types.h>
+
+GR_RUNTIME_API unsigned int
+gr_rounduppow2(unsigned int n);
+
+// FIXME should be template
+GR_RUNTIME_API void gr_zero_vector(std::vector<float> &v);
+GR_RUNTIME_API void gr_zero_vector(std::vector<double> &v);
+GR_RUNTIME_API void gr_zero_vector(std::vector<int> &v);
+GR_RUNTIME_API void gr_zero_vector(std::vector<gr_complex> &v);
+
+
+#endif /* INCLUDED_GR_MISC_H */
diff --git a/gnuradio-runtime/lib/gr_msg_accepter.cc b/gnuradio-runtime/lib/gr_msg_accepter.cc
new file mode 100644
index 0000000000..93d5fb20e8
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_msg_accepter.cc
@@ -0,0 +1,59 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gr_msg_accepter.h>
+#include <gr_block.h>
+#include <gr_block_detail.h>
+#include <gr_hier_block2.h>
+#include <stdexcept>
+
+using namespace pmt;
+
+gr_msg_accepter::gr_msg_accepter()
+{
+}
+
+gr_msg_accepter::~gr_msg_accepter()
+{
+ // NOP, required as virtual destructor
+}
+
+void
+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->_post(which_port,msg);
+ return;
+ }
+ gr_hier_block2 *p2 = dynamic_cast<gr_hier_block2 *>(this);
+ if (p2){
+ // FIXME do the right thing
+ return;
+ }
+
+ throw std::runtime_error("unknown derived class");
+}
diff --git a/gnuradio-runtime/lib/gr_msg_handler.cc b/gnuradio-runtime/lib/gr_msg_handler.cc
new file mode 100644
index 0000000000..0f93497088
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_msg_handler.cc
@@ -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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <gr_msg_handler.h>
+
+gr_msg_handler::~gr_msg_handler ()
+{
+}
diff --git a/gnuradio-runtime/lib/gr_msg_queue.cc b/gnuradio-runtime/lib/gr_msg_queue.cc
new file mode 100644
index 0000000000..0cf0467715
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_msg_queue.cc
@@ -0,0 +1,125 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2009 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_msg_queue.h>
+#include <stdexcept>
+
+gr_msg_queue_sptr
+gr_make_msg_queue(unsigned int limit)
+{
+ return gr_msg_queue_sptr (new gr_msg_queue(limit));
+}
+
+gr_msg_queue::gr_msg_queue(unsigned int limit)
+ : d_not_empty(), d_not_full(),
+ /*d_head(0), d_tail(0),*/ d_count(0), d_limit(limit)
+{
+}
+
+gr_msg_queue::~gr_msg_queue()
+{
+ flush ();
+}
+
+void
+gr_msg_queue::insert_tail(gr_message_sptr msg)
+{
+ if (msg->d_next)
+ throw std::invalid_argument("gr_msg_queue::insert_tail: msg already in queue");
+
+ gruel::scoped_lock guard(d_mutex);
+
+ while (full_p())
+ d_not_full.wait(guard);
+
+ if (d_tail == 0){
+ d_tail = d_head = msg;
+ //msg->d_next = 0;
+ msg->d_next.reset();
+ }
+ else {
+ d_tail->d_next = msg;
+ d_tail = msg;
+ //msg->d_next = 0;
+ msg->d_next.reset();
+ }
+ d_count++;
+ d_not_empty.notify_one();
+}
+
+gr_message_sptr
+gr_msg_queue::delete_head()
+{
+ gruel::scoped_lock guard(d_mutex);
+ gr_message_sptr m;
+
+ while ((m = d_head) == 0)
+ d_not_empty.wait(guard);
+
+ d_head = m->d_next;
+ if (d_head == 0){
+ //d_tail = 0;
+ d_tail.reset();
+ }
+
+ d_count--;
+ // m->d_next = 0;
+ m->d_next.reset();
+ d_not_full.notify_one();
+ return m;
+}
+
+gr_message_sptr
+gr_msg_queue::delete_head_nowait()
+{
+ gruel::scoped_lock guard(d_mutex);
+ gr_message_sptr m;
+
+ if ((m = d_head) == 0){
+ //return 0;
+ return gr_message_sptr();
+ }
+
+ d_head = m->d_next;
+ if (d_head == 0){
+ //d_tail = 0;
+ d_tail.reset();
+ }
+
+ d_count--;
+ //m->d_next = 0;
+ m->d_next.reset();
+ d_not_full.notify_one();
+ return m;
+}
+
+void
+gr_msg_queue::flush()
+{
+ gr_message_sptr m;
+
+ while ((m = delete_head_nowait ()) != 0)
+ ;
+}
diff --git a/gnuradio-runtime/lib/gr_pagesize.cc b/gnuradio-runtime/lib/gr_pagesize.cc
new file mode 100644
index 0000000000..e31e05ca70
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_pagesize.cc
@@ -0,0 +1,56 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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_pagesize.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#if defined(_WIN32) && defined(HAVE_GETPAGESIZE)
+extern "C" size_t getpagesize(void);
+#endif
+
+int
+gr_pagesize ()
+{
+ static int s_pagesize = -1;
+
+ if (s_pagesize == -1){
+#if defined(HAVE_GETPAGESIZE)
+ s_pagesize = getpagesize ();
+#elif defined (HAVE_SYSCONF)
+ s_pagesize = sysconf (_SC_PAGESIZE);
+ if (s_pagesize == -1){
+ perror ("_SC_PAGESIZE");
+ s_pagesize = 4096;
+ }
+#else
+ fprintf (stderr, "gr_pagesize: no info; setting pagesize = 4096\n");
+ s_pagesize = 4096;
+#endif
+ }
+ return s_pagesize;
+}
+
diff --git a/gnuradio-runtime/lib/gr_pagesize.h b/gnuradio-runtime/lib/gr_pagesize.h
new file mode 100644
index 0000000000..d14cb22b1b
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_pagesize.h
@@ -0,0 +1,34 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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_PAGESIZE_H_
+#define _GR_PAGESIZE_H_
+
+#include <gr_runtime_api.h>
+
+/*!
+ * \brief return the page size in bytes
+ */
+
+GR_RUNTIME_API int gr_pagesize ();
+
+
+#endif /* _GR_PAGESIZE_H_ */ \ No newline at end of file
diff --git a/gnuradio-runtime/lib/gr_preferences.cc b/gnuradio-runtime/lib/gr_preferences.cc
new file mode 100644
index 0000000000..a0f5616603
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_preferences.cc
@@ -0,0 +1,108 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2010,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_preferences.h>
+#include <gr_sys_paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+namespace fs = boost::filesystem;
+
+/*
+ * The simplest thing that could possibly work:
+ * the key is the filename; the value is the file contents.
+ */
+
+static const char *
+pathname (const char *key)
+{
+ static fs::path path;
+ path = fs::path(gr_appdata_path()) / ".gnuradio" / "prefs" / key;
+ return path.string().c_str();
+}
+
+static void
+ensure_dir_path ()
+{
+ fs::path path = fs::path(gr_appdata_path()) / ".gnuradio";
+ if (!fs::is_directory(path)) fs::create_directory(path);
+
+ path = path / "prefs";
+ if (!fs::is_directory(path)) fs::create_directory(path);
+}
+
+const char *
+gr_preferences::get (const char *key)
+{
+ static char buf[1024];
+
+ FILE *fp = fopen (pathname (key), "r");
+ if (fp == 0) {
+ perror (pathname (key));
+ return 0;
+ }
+
+ memset (buf, 0, sizeof (buf));
+ size_t ret = fread (buf, 1, sizeof (buf) - 1, fp);
+ if(ret == 0) {
+ if(ferror(fp) != 0) {
+ perror (pathname (key));
+ fclose (fp);
+ return 0;
+ }
+ }
+ fclose (fp);
+ return buf;
+}
+
+void
+gr_preferences::set (const char *key, const char *value)
+{
+ ensure_dir_path ();
+
+ FILE *fp = fopen (pathname (key), "w");
+ if (fp == 0){
+ perror (pathname (key));
+ return;
+ }
+
+ size_t ret = fwrite (value, 1, strlen (value), fp);
+ if(ret == 0) {
+ if(ferror(fp) != 0) {
+ perror (pathname (key));
+ fclose (fp);
+ return;
+ }
+ }
+ fclose (fp);
+};
diff --git a/gnuradio-runtime/lib/gr_prefs.cc b/gnuradio-runtime/lib/gr_prefs.cc
new file mode 100644
index 0000000000..8a79c3335f
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_prefs.cc
@@ -0,0 +1,391 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2013 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_prefs.h>
+#include <gr_sys_paths.h>
+#include <gr_constants.h>
+#include <algorithm>
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/fstream.hpp>
+namespace fs = boost::filesystem;
+
+/*
+ * Stub implementations
+ */
+
+static gr_prefs s_default_singleton;
+static gr_prefs *s_singleton = &s_default_singleton;
+
+gr_prefs *
+gr_prefs::singleton()
+{
+ return s_singleton;
+}
+
+void
+gr_prefs::set_singleton(gr_prefs *p)
+{
+ s_singleton = p;
+}
+
+gr_prefs::gr_prefs()
+{
+ _read_files();
+}
+
+gr_prefs::~gr_prefs()
+{
+ // nop
+}
+
+std::vector<std::string>
+gr_prefs::_sys_prefs_filenames()
+{
+ std::vector<std::string> fnames;
+
+ fs::path dir = gr_prefsdir();
+ if(!fs::is_directory(dir))
+ return fnames;
+
+ fs::directory_iterator diritr(dir);
+ while(diritr != fs::directory_iterator()) {
+ fs::path p = *diritr++;
+ if(p.extension() != ".swp")
+ fnames.push_back(p.string());
+ }
+ std::sort(fnames.begin(), fnames.end());
+
+ // Find if there is a ~/.gnuradio/config.conf file and add this to
+ // the end of the file list to override any preferences in the
+ // installed path config files.
+ fs::path homedir = fs::path(gr_appdata_path());
+ homedir = homedir/".gnuradio/config.conf";
+ if(fs::exists(homedir)) {
+ fnames.push_back(homedir.string());
+ }
+
+ return fnames;
+}
+
+void
+gr_prefs::_read_files()
+{
+ std::string config;
+
+ std::vector<std::string> filenames = _sys_prefs_filenames();
+ std::vector<std::string>::iterator sitr;
+ char tmp[1024];
+ for(sitr = filenames.begin(); sitr != filenames.end(); sitr++) {
+ fs::ifstream fin(*sitr);
+ while(!fin.eof()) {
+ fin.getline(tmp, 1024);
+ std::string t(tmp);
+ // ignore empty lines or lines of just comments
+ if((t.size() > 0) && (t[0] != '#')) {
+ // remove any comments in the line
+ size_t hash = t.find("#");
+
+ // Use hash marks at the end of each segment as a delimiter
+ config += t.substr(0, hash) + '#';
+ }
+ }
+ fin.close();
+ }
+
+ // Remove all whitespace.
+ config.erase(std::remove_if(config.begin(), config.end(), ::isspace), config.end());
+
+ // Convert the string into a map
+ _convert_to_map(config);
+}
+
+void
+gr_prefs::_convert_to_map(const std::string &conf)
+{
+ // Convert the string into an map of maps
+ // Map is structured as {section name: map of options}
+ // And options map is simply: {option name: option value}
+ std::string sub = conf;
+ size_t sec_start = sub.find("[");
+ while(sec_start != std::string::npos) {
+ sub = sub.substr(sec_start);
+
+ size_t sec_end = sub.find("]");
+ if(sec_end == std::string::npos)
+ throw std::runtime_error("Config file error: Mismatched section label.\n");
+
+ std::string sec = sub.substr(1, sec_end-1);
+ size_t next_sec_start = sub.find("[", sec_end);
+ std::string subsec = sub.substr(sec_end+1, next_sec_start-sec_end-2);
+
+ std::transform(sec.begin(), sec.end(), sec.begin(), ::tolower);
+
+ std::map<std::string, std::string> options_map = d_config_map[sec];
+ size_t next_opt = 0;
+ size_t next_val = 0;
+ next_opt = subsec.find("#");
+ while(next_opt < subsec.size()-1) {
+ next_val = subsec.find("=", next_opt);
+ std::string option = subsec.substr(next_opt+1, next_val-next_opt-1);
+
+ next_opt = subsec.find("#", next_val);
+ std::string value = subsec.substr(next_val+1, next_opt-next_val-1);
+
+ std::transform(option.begin(), option.end(), option.begin(), ::tolower);
+ options_map[option] = value;
+ }
+
+ d_config_map[sec] = options_map;
+
+ sec_start = sub.find("[", sec_end);
+ }
+}
+
+std::string
+gr_prefs::to_string()
+{
+ gr_config_map_itr sections;
+ gr_config_map_elem_itr options;
+ std::stringstream s;
+
+ for(sections = d_config_map.begin(); sections != d_config_map.end(); sections++) {
+ s << "[" << sections->first << "]" << std::endl;
+ for(options = sections->second.begin(); options != sections->second.end(); options++) {
+ s << options->first << " = " << options->second << std::endl;
+ }
+ s << std::endl;
+ }
+
+ return s.str();
+}
+
+void
+gr_prefs::save()
+{
+ std::string conf = to_string();
+
+ fs::path homedir = fs::path(gr_appdata_path());
+ homedir = homedir/".gnuradio/config.conf";
+ fs::ofstream fout(homedir);
+ fout << conf;
+ fout.close();
+}
+
+char *
+gr_prefs::option_to_env(std::string section, std::string option)
+{
+ std::stringstream envname;
+ std::string secname=section, optname=option;
+
+ std::transform(section.begin(), section.end(), secname.begin(), ::toupper);
+ std::transform(option.begin(), option.end(), optname.begin(), ::toupper);
+ envname << "GR_CONF_" << secname << "_" << optname;
+
+ return getenv(envname.str().c_str());
+}
+
+bool
+gr_prefs::has_section(const std::string &section)
+{
+ std::string s = section;
+ std::transform(section.begin(), section.end(), s.begin(), ::tolower);
+ return d_config_map.count(s) > 0;
+}
+
+bool
+gr_prefs::has_option(const std::string &section, const std::string &option)
+{
+ if(option_to_env(section, option))
+ return true;
+
+ if(has_section(section)) {
+ std::string s = section;
+ std::transform(section.begin(), section.end(), s.begin(), ::tolower);
+
+ std::string o = option;
+ std::transform(option.begin(), option.end(), o.begin(), ::tolower);
+
+ gr_config_map_itr sec = d_config_map.find(s);
+ return sec->second.count(o) > 0;
+ }
+ else {
+ return false;
+ }
+}
+
+const std::string
+gr_prefs::get_string(const std::string &section, const std::string &option,
+ const std::string &default_val)
+{
+ char *env = option_to_env(section, option);
+ if(env)
+ return std::string(env);
+
+ if(has_option(section, option)) {
+ std::string s = section;
+ std::transform(section.begin(), section.end(), s.begin(), ::tolower);
+
+ std::string o = option;
+ std::transform(option.begin(), option.end(), o.begin(), ::tolower);
+
+ gr_config_map_itr sec = d_config_map.find(s);
+ gr_config_map_elem_itr opt = sec->second.find(o);
+ return opt->second;
+ }
+ else {
+ return default_val;
+ }
+}
+
+void
+gr_prefs::set_string(const std::string &section, const std::string &option,
+ const std::string &val)
+{
+ std::string s = section;
+ std::transform(section.begin(), section.end(), s.begin(), ::tolower);
+
+ std::string o = option;
+ std::transform(option.begin(), option.end(), o.begin(), ::tolower);
+
+ std::map<std::string, std::string> opt_map = d_config_map[s];
+
+ opt_map[o] = val;
+
+ d_config_map[s] = opt_map;
+}
+
+bool
+gr_prefs::get_bool(const std::string &section, const std::string &option, bool default_val)
+{
+ if(has_option(section, option)) {
+ std::string str = get_string(section, option, "");
+ if(str == "") {
+ return default_val;
+ }
+ std::transform(str.begin(), str.end(), str.begin(), ::tolower);
+ if((str == "true") || (str == "on") || (str == "1"))
+ return true;
+ else if((str == "false") || (str == "off") || (str == "0"))
+ return false;
+ else
+ return default_val;
+ }
+ else {
+ return default_val;
+ }
+}
+
+void
+gr_prefs::set_bool(const std::string &section, const std::string &option, bool val)
+{
+ std::string s = section;
+ std::transform(section.begin(), section.end(), s.begin(), ::tolower);
+
+ std::string o = option;
+ std::transform(option.begin(), option.end(), o.begin(), ::tolower);
+
+ std::map<std::string, std::string> opt_map = d_config_map[s];
+
+ std::stringstream sstr;
+ sstr << (val == true);
+ opt_map[o] = sstr.str();
+
+ d_config_map[s] = opt_map;
+}
+
+long
+gr_prefs::get_long(const std::string &section, const std::string &option, long default_val)
+{
+ if(has_option(section, option)) {
+ std::string str = get_string(section, option, "");
+ if(str == "") {
+ return default_val;
+ }
+ std::stringstream sstr(str);
+ long n;
+ sstr >> n;
+ return n;
+ }
+ else {
+ return default_val;
+ }
+}
+
+void
+gr_prefs::set_long(const std::string &section, const std::string &option, long val)
+{
+ std::string s = section;
+ std::transform(section.begin(), section.end(), s.begin(), ::tolower);
+
+ std::string o = option;
+ std::transform(option.begin(), option.end(), o.begin(), ::tolower);
+
+ std::map<std::string, std::string> opt_map = d_config_map[s];
+
+ std::stringstream sstr;
+ sstr << val;
+ opt_map[o] = sstr.str();
+
+ d_config_map[s] = opt_map;
+}
+
+double
+gr_prefs::get_double(const std::string &section, const std::string &option, double default_val)
+{
+ if(has_option(section, option)) {
+ std::string str = get_string(section, option, "");
+ if(str == "") {
+ return default_val;
+ }
+ std::stringstream sstr(str);
+ double n;
+ sstr >> n;
+ return n;
+ }
+ else {
+ return default_val;
+ }
+}
+
+void
+gr_prefs::set_double(const std::string &section, const std::string &option, double val)
+{
+ std::string s = section;
+ std::transform(section.begin(), section.end(), s.begin(), ::tolower);
+
+ std::string o = option;
+ std::transform(option.begin(), option.end(), o.begin(), ::tolower);
+
+ std::map<std::string, std::string> opt_map = d_config_map[s];
+
+ std::stringstream sstr;
+ sstr << val;
+ opt_map[o] = sstr.str();
+
+ d_config_map[s] = opt_map;
+}
diff --git a/gnuradio-runtime/lib/gr_random.cc b/gnuradio-runtime/lib/gr_random.cc
new file mode 100644
index 0000000000..323839acc7
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_random.cc
@@ -0,0 +1,183 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002 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.
+ */
+
+/*
+ * Copyright 1997 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. M.I.T. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <math.h>
+#include <gr_random.h>
+
+#define IA 16807
+#define IM 2147483647
+#define AM (1.0/IM)
+#define IQ 127773
+#define IR 2836
+#define NDIV (1+(IM-1)/NTAB)
+#define EPS 1.2e-7
+#define RNMX (1.0-EPS)
+
+
+gr_random::gr_random (long seed)
+{
+ reseed (seed);
+}
+
+void
+gr_random::reseed (long seed)
+{
+ d_seed = seed;
+ d_iy = 0;
+ for (int i = 0; i < NTAB; i++)
+ d_iv[i] = 0;
+ d_iset = 0;
+ d_gset = 0;
+}
+
+/*
+ * This looks like it returns a uniform random deviate between 0.0 and 1.0
+ * It looks similar to code from "Numerical Recipes in C".
+ */
+float gr_random::ran1()
+{
+ int j;
+ long k;
+ float temp;
+
+ if (d_seed <= 0 || !d_iy) {
+ if (-d_seed < 1)
+ d_seed=1;
+ else
+ d_seed = -d_seed;
+ for (j=NTAB+7;j>=0;j--) {
+ k=d_seed/IQ;
+ d_seed=IA*(d_seed-k*IQ)-IR*k;
+ if (d_seed < 0)
+ d_seed += IM;
+ if (j < NTAB)
+ d_iv[j] = d_seed;
+ }
+ d_iy=d_iv[0];
+ }
+ k=(d_seed)/IQ;
+ d_seed=IA*(d_seed-k*IQ)-IR*k;
+ if (d_seed < 0)
+ d_seed += IM;
+ j=d_iy/NDIV;
+ d_iy=d_iv[j];
+ d_iv[j] = d_seed;
+ temp=AM * d_iy;
+ if (temp > RNMX)
+ temp = RNMX;
+ return temp;
+}
+
+/*
+ * Returns a normally distributed deviate with zero mean and variance 1.
+ * Also looks like it's from "Numerical Recipes in C".
+ */
+float gr_random::gasdev()
+{
+ float fac,rsq,v1,v2;
+ d_iset = 1 - d_iset;
+ if (d_iset) {
+ do {
+ v1=2.0*ran1()-1.0;
+ v2=2.0*ran1()-1.0;
+ rsq=v1*v1+v2*v2;
+ } while (rsq >= 1.0 || rsq == 0.0);
+ fac= sqrt(-2.0*log(rsq)/rsq);
+ d_gset=v1*fac;
+ return v2*fac;
+ }
+ return d_gset;
+}
+
+/*
+ * Copied from The KC7WW / OH2BNS Channel Simulator
+ * FIXME Need to check how good this is at some point
+ */
+
+float gr_random::laplacian()
+{
+ float z = ran1();
+ if (z < 0.5)
+ return log(2.0 * z) / M_SQRT2;
+ else
+ return -log(2.0 * (1.0 - z)) / M_SQRT2;
+}
+
+/*
+ * Copied from The KC7WW / OH2BNS Channel Simulator
+ * FIXME Need to check how good this is at some point
+ */
+
+ // 5 => scratchy, 8 => Geiger
+
+float gr_random::impulse(float factor = 5)
+{
+ float z = -M_SQRT2 * log(ran1());
+ if (fabsf(z) <= factor)
+ return 0.0;
+ else
+ return z;
+}
+
+/*
+ * Complex rayleigh is really gaussian I and gaussian Q
+ * It can also be generated by real rayleigh magnitude and
+ * uniform random angle
+ * Adapted from The KC7WW / OH2BNS Channel Simulator
+ * FIXME Need to check how good this is at some point
+ */
+
+gr_complex gr_random::rayleigh_complex()
+{
+ return gr_complex(gasdev(),gasdev());
+}
+
+/* Other option
+ mag = rayleigh();
+ ang = 2.0 * M_PI * RNG();
+ *Rx = rxx * cos(z);
+ *Iy = rxx * sin(z);
+*/
+
+
+float gr_random::rayleigh()
+{
+ return sqrt(-2.0 * log(ran1()));
+}
diff --git a/gnuradio-runtime/lib/gr_random.h b/gnuradio-runtime/lib/gr_random.h
new file mode 100644
index 0000000000..783c05f920
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_random.h
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002 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_RANDOM_H
+#define INCLUDED_GR_RANDOM_H
+
+#include <gr_runtime_api.h>
+#include <gr_complex.h>
+
+/*!
+ * \brief pseudo random number generator
+ * \ingroup math_blk
+ */
+class GR_RUNTIME_API gr_random {
+protected:
+ static const int NTAB = 32;
+ long d_seed;
+ long d_iy;
+ long d_iv[NTAB];
+ int d_iset;
+ float d_gset;
+
+
+public:
+ gr_random (long seed=3021);
+
+ void reseed (long seed);
+
+ /*!
+ * \brief uniform random deviate in the range [0.0, 1.0)
+ */
+ float ran1 ();
+
+ /*!
+ * \brief normally distributed deviate with zero mean and variance 1
+ */
+ float gasdev ();
+
+ float laplacian ();
+ float impulse (float factor);
+ float rayleigh ();
+ gr_complex rayleigh_complex ();
+};
+
+#endif /* INCLUDED_GR_RANDOM_H */
+
diff --git a/gnuradio-runtime/lib/gr_realtime.cc b/gnuradio-runtime/lib/gr_realtime.cc
new file mode 100644
index 0000000000..75b497999d
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_realtime.cc
@@ -0,0 +1,32 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2007,2008 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_realtime.h>
+
+gr_rt_status_t
+gr_enable_realtime_scheduling()
+{
+ return gruel::enable_realtime_scheduling();
+}
diff --git a/gnuradio-runtime/lib/gr_reverse.cc b/gnuradio-runtime/lib/gr_reverse.cc
new file mode 100644
index 0000000000..08c588cb55
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_reverse.cc
@@ -0,0 +1,60 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_reverse.h>
+
+
+std::vector<float>
+gr_reverse (const std::vector<float> &taps)
+{
+ int size = taps.size ();
+ std::vector<float> new_taps(size);
+
+ if (size == 0)
+ return new_taps;
+
+ for (int i = 0; i < size; i++)
+ new_taps[i] = taps[size - i - 1];
+
+ return new_taps;
+}
+
+
+std::vector<gr_complex>
+gr_reverse (const std::vector<gr_complex> &taps)
+{
+ int size = taps.size ();
+ std::vector<gr_complex> new_taps(size);
+
+ if (size == 0)
+ return new_taps;
+
+ for (int i = 0; i < size; i++)
+ new_taps[i] = taps[size - i - 1];
+
+ return new_taps;
+}
+
diff --git a/gnuradio-runtime/lib/gr_reverse.h b/gnuradio-runtime/lib/gr_reverse.h
new file mode 100644
index 0000000000..aa8619619f
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_reverse.h
@@ -0,0 +1,34 @@
+/* -*- 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.
+ */
+#ifndef INCLUDED_GR_REVERSE_H
+#define INCLUDED_GR_REVERSE_H
+
+#include <gr_runtime_api.h>
+#include <vector>
+#include <gr_complex.h>
+
+// reverse the order of taps
+std::vector<float> gr_reverse (const std::vector<float> &taps);
+std::vector<gr_complex> gr_reverse (const std::vector<gr_complex> &taps);
+
+
+#endif /* INCLUDED_GR_REVERSE_H */
diff --git a/gnuradio-runtime/lib/gr_scheduler.cc b/gnuradio-runtime/lib/gr_scheduler.cc
new file mode 100644
index 0000000000..c691f5d99f
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_scheduler.cc
@@ -0,0 +1,33 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <gr_scheduler.h>
+
+gr_scheduler::gr_scheduler(gr_flat_flowgraph_sptr ffg, int max_noutput_items)
+{
+}
+
+gr_scheduler::~gr_scheduler()
+{
+}
diff --git a/gnuradio-runtime/lib/gr_scheduler.h b/gnuradio-runtime/lib/gr_scheduler.h
new file mode 100644
index 0000000000..097f575c21
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_scheduler.h
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef INCLUDED_GR_SCHEDULER_H
+#define INCLUDED_GR_SCHEDULER_H
+
+#include <gr_runtime_api.h>
+#include <boost/utility.hpp>
+#include <gr_block.h>
+#include <gr_flat_flowgraph.h>
+
+
+class gr_scheduler;
+typedef boost::shared_ptr<gr_scheduler> gr_scheduler_sptr;
+
+
+/*!
+ * \brief Abstract scheduler that takes a flattened flow graph and runs it.
+ *
+ * Preconditions: details, buffers and buffer readers have been assigned.
+ */
+class GR_RUNTIME_API gr_scheduler : boost::noncopyable
+{
+
+public:
+ /*!
+ * \brief Construct a scheduler and begin evaluating the graph.
+ *
+ * The scheduler will continue running until all blocks until they
+ * report that they are done or the stop method is called.
+ */
+ gr_scheduler(gr_flat_flowgraph_sptr ffg, int max_noutput_items);
+
+ virtual ~gr_scheduler();
+
+ /*!
+ * \brief Tell the scheduler to stop executing.
+ */
+ virtual void stop() = 0;
+
+ /*!
+ * \brief Block until the graph is done.
+ */
+ virtual void wait() = 0;
+};
+
+#endif /* INCLUDED_GR_SCHEDULER_H */
diff --git a/gnuradio-runtime/lib/gr_scheduler_sts.cc b/gnuradio-runtime/lib/gr_scheduler_sts.cc
new file mode 100644
index 0000000000..2c96def6d1
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_scheduler_sts.cc
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <gr_scheduler_sts.h>
+#include <gr_single_threaded_scheduler.h>
+#include <gruel/thread_body_wrapper.h>
+
+class sts_container
+{
+ gr_block_vector_t d_blocks;
+
+public:
+
+ sts_container(gr_block_vector_t blocks)
+ : d_blocks(blocks) {}
+
+ void operator()()
+ {
+ gr_make_single_threaded_scheduler(d_blocks)->run();
+ }
+};
+
+
+gr_scheduler_sptr
+gr_scheduler_sts::make(gr_flat_flowgraph_sptr ffg, int max_noutput_items)
+{
+ return gr_scheduler_sptr(new gr_scheduler_sts(ffg, max_noutput_items));
+}
+
+gr_scheduler_sts::gr_scheduler_sts(gr_flat_flowgraph_sptr ffg, int max_noutput_items)
+ : gr_scheduler(ffg, max_noutput_items)
+{
+ // Split the flattened flow graph into discrete partitions, each
+ // of which is topologically sorted.
+
+ std::vector<gr_basic_block_vector_t> graphs = ffg->partition();
+
+ // For each partition, create a thread to evaluate it using
+ // an instance of the gr_single_threaded_scheduler
+
+ for (std::vector<gr_basic_block_vector_t>::iterator p = graphs.begin();
+ p != graphs.end(); p++) {
+
+ gr_block_vector_t blocks = gr_flat_flowgraph::make_block_vector(*p);
+ d_threads.create_thread(
+ gruel::thread_body_wrapper<sts_container>(sts_container(blocks),
+ "single-threaded-scheduler"));
+ }
+}
+
+gr_scheduler_sts::~gr_scheduler_sts()
+{
+ stop();
+}
+
+void
+gr_scheduler_sts::stop()
+{
+ d_threads.interrupt_all();
+}
+
+void
+gr_scheduler_sts::wait()
+{
+ d_threads.join_all();
+}
diff --git a/gnuradio-runtime/lib/gr_scheduler_sts.h b/gnuradio-runtime/lib/gr_scheduler_sts.h
new file mode 100644
index 0000000000..43b97b62c1
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_scheduler_sts.h
@@ -0,0 +1,63 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_GR_SCHEDULER_STS_H
+#define INCLUDED_GR_SCHEDULER_STS_H
+
+#include <gr_runtime_api.h>
+#include <gr_scheduler.h>
+#include <gruel/thread_group.h>
+
+/*!
+ * \brief Concrete scheduler that uses the single_threaded_scheduler
+ */
+class GR_RUNTIME_API gr_scheduler_sts : public gr_scheduler
+{
+ gruel::thread_group d_threads;
+
+protected:
+ /*!
+ * \brief Construct a scheduler and begin evaluating the graph.
+ *
+ * The scheduler will continue running until all blocks until they
+ * report that they are done or the stop method is called.
+ */
+ gr_scheduler_sts(gr_flat_flowgraph_sptr ffg, int max_noutput_items);
+
+public:
+ static gr_scheduler_sptr make(gr_flat_flowgraph_sptr ffg, int max_noutput_items);
+
+ ~gr_scheduler_sts();
+
+ /*!
+ * \brief Tell the scheduler to stop executing.
+ */
+ void stop();
+
+ /*!
+ * \brief Block until the graph is done.
+ */
+ void wait();
+};
+
+
+
+
+#endif /* INCLUDED_GR_SCHEDULER_STS_H */
diff --git a/gnuradio-runtime/lib/gr_scheduler_tpb.cc b/gnuradio-runtime/lib/gr_scheduler_tpb.cc
new file mode 100644
index 0000000000..2824eb1b3b
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_scheduler_tpb.cc
@@ -0,0 +1,103 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <gr_scheduler_tpb.h>
+#include <gr_tpb_thread_body.h>
+#include <gruel/thread_body_wrapper.h>
+#include <sstream>
+
+/*
+ * You know, a lambda expression would be sooo much easier...
+ */
+class tpb_container
+{
+ gr_block_sptr d_block;
+ int d_max_noutput_items;
+
+public:
+ tpb_container(gr_block_sptr block, int max_noutput_items)
+ : d_block(block), d_max_noutput_items(max_noutput_items) {}
+
+ void operator()()
+ {
+ gr_tpb_thread_body body(d_block, d_max_noutput_items);
+ }
+};
+
+
+gr_scheduler_sptr
+gr_scheduler_tpb::make(gr_flat_flowgraph_sptr ffg, int max_noutput_items)
+{
+ return gr_scheduler_sptr(new gr_scheduler_tpb(ffg, max_noutput_items));
+}
+
+gr_scheduler_tpb::gr_scheduler_tpb(gr_flat_flowgraph_sptr ffg, int max_noutput_items)
+ : gr_scheduler(ffg, max_noutput_items)
+{
+ // Get a topologically sorted vector of all the blocks in use.
+ // Being topologically sorted probably isn't going to matter, but
+ // there's a non-zero chance it might help...
+
+ gr_basic_block_vector_t used_blocks = ffg->calc_used_blocks();
+ used_blocks = ffg->topological_sort(used_blocks);
+ gr_block_vector_t blocks = gr_flat_flowgraph::make_block_vector(used_blocks);
+
+ // Ensure that the done flag is clear on all blocks
+
+ for (size_t i = 0; i < blocks.size(); i++){
+ blocks[i]->detail()->set_done(false);
+ }
+
+ // Fire off a thead for each block
+
+ for (size_t i = 0; i < blocks.size(); i++){
+ std::stringstream name;
+ name << "thread-per-block[" << i << "]: " << blocks[i];
+
+ // If set, use internal value instead of global value
+ if(blocks[i]->is_set_max_noutput_items())
+ max_noutput_items = blocks[i]->max_noutput_items();
+
+ d_threads.create_thread(
+ gruel::thread_body_wrapper<tpb_container>(tpb_container(blocks[i], max_noutput_items),
+ name.str()));
+ }
+}
+
+gr_scheduler_tpb::~gr_scheduler_tpb()
+{
+ stop();
+}
+
+void
+gr_scheduler_tpb::stop()
+{
+ d_threads.interrupt_all();
+}
+
+void
+gr_scheduler_tpb::wait()
+{
+ d_threads.join_all();
+}
diff --git a/gnuradio-runtime/lib/gr_scheduler_tpb.h b/gnuradio-runtime/lib/gr_scheduler_tpb.h
new file mode 100644
index 0000000000..d978dd28e1
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_scheduler_tpb.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_GR_SCHEDULER_TPB_H
+#define INCLUDED_GR_SCHEDULER_TPB_H
+
+#include <gr_runtime_api.h>
+#include <gr_scheduler.h>
+#include <gruel/thread_group.h>
+
+/*!
+ * \brief Concrete scheduler that uses a kernel thread-per-block
+ */
+class GR_RUNTIME_API gr_scheduler_tpb : public gr_scheduler
+{
+ gruel::thread_group d_threads;
+
+protected:
+ /*!
+ * \brief Construct a scheduler and begin evaluating the graph.
+ *
+ * The scheduler will continue running until all blocks until they
+ * report that they are done or the stop method is called.
+ */
+ gr_scheduler_tpb(gr_flat_flowgraph_sptr ffg, int max_noutput_items);
+
+public:
+ static gr_scheduler_sptr make(gr_flat_flowgraph_sptr ffg, int max_noutput_items=100000);
+
+ ~gr_scheduler_tpb();
+
+ /*!
+ * \brief Tell the scheduler to stop executing.
+ */
+ void stop();
+
+ /*!
+ * \brief Block until the graph is done.
+ */
+ void wait();
+};
+
+
+#endif /* INCLUDED_GR_SCHEDULER_TPB_H */
diff --git a/gnuradio-runtime/lib/gr_select_handler.cc b/gnuradio-runtime/lib/gr_select_handler.cc
new file mode 100644
index 0000000000..0fc86354a6
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_select_handler.cc
@@ -0,0 +1,36 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_select_handler.h>
+
+gr_select_handler::gr_select_handler(int fd)
+ : d_fd(fd)
+{
+}
+
+gr_select_handler::~gr_select_handler()
+{
+}
diff --git a/gnuradio-runtime/lib/gr_sincos.c b/gnuradio-runtime/lib/gr_sincos.c
new file mode 100644
index 0000000000..a8d01b0da4
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_sincos.c
@@ -0,0 +1,83 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE // ask for GNU extensions if available
+#endif
+
+#include <gr_sincos.h>
+#include <math.h>
+
+// ----------------------------------------------------------------
+
+#if defined (HAVE_SINCOS)
+
+void
+gr_sincos (double x, double *sinx, double *cosx)
+{
+ sincos (x, sinx, cosx);
+}
+
+#else
+
+void
+gr_sincos (double x, double *sinx, double *cosx)
+{
+ *sinx = sin (x);
+ *cosx = cos (x);
+}
+
+#endif
+
+// ----------------------------------------------------------------
+
+#if defined (HAVE_SINCOSF)
+
+void
+gr_sincosf (float x, float *sinx, float *cosx)
+{
+ sincosf (x, sinx, cosx);
+}
+
+#elif defined (HAVE_SINF) && defined (HAVE_COSF)
+
+void
+gr_sincosf (float x, float *sinx, float *cosx)
+{
+ *sinx = sinf (x);
+ *cosx = cosf (x);
+}
+
+#else
+
+void
+gr_sincosf (float x, float *sinx, float *cosx)
+{
+ *sinx = sin (x);
+ *cosx = cos (x);
+}
+
+#endif
diff --git a/gnuradio-runtime/lib/gr_single_threaded_scheduler.cc b/gnuradio-runtime/lib/gr_single_threaded_scheduler.cc
new file mode 100644
index 0000000000..1bb9e9b0a8
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_single_threaded_scheduler.cc
@@ -0,0 +1,364 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_single_threaded_scheduler.h>
+#include <gr_block.h>
+#include <gr_block_detail.h>
+#include <gr_buffer.h>
+#include <boost/thread.hpp>
+#include <boost/format.hpp>
+#include <iostream>
+#include <limits>
+#include <assert.h>
+#include <stdio.h>
+
+// must be defined to either 0 or 1
+#define ENABLE_LOGGING 0
+
+#if (ENABLE_LOGGING)
+#define LOG(x) do { x; } while(0)
+#else
+#define LOG(x) do {;} while(0)
+#endif
+
+static int which_scheduler = 0;
+
+gr_single_threaded_scheduler_sptr
+gr_make_single_threaded_scheduler (const std::vector<gr_block_sptr> &blocks)
+{
+ return
+ gr_single_threaded_scheduler_sptr (new gr_single_threaded_scheduler (blocks));
+}
+
+gr_single_threaded_scheduler::gr_single_threaded_scheduler (
+ const std::vector<gr_block_sptr> &blocks)
+ : d_blocks (blocks), d_enabled (true), d_log(0)
+{
+ if (ENABLE_LOGGING){
+ std::string name = str(boost::format("sst-%d.log") % which_scheduler++);
+ d_log = new std::ofstream(name.c_str());
+ *d_log << "gr_single_threaded_scheduler: "
+ << d_blocks.size ()
+ << " blocks\n";
+ }
+}
+
+gr_single_threaded_scheduler::~gr_single_threaded_scheduler ()
+{
+ if (ENABLE_LOGGING)
+ delete d_log;
+}
+
+void
+gr_single_threaded_scheduler::run ()
+{
+ // d_enabled = true; // KLUDGE
+ main_loop ();
+}
+
+void
+gr_single_threaded_scheduler::stop ()
+{
+ if (0)
+ std::cout << "gr_singled_threaded_scheduler::stop() "
+ << this << std::endl;
+ d_enabled = false;
+}
+
+inline static unsigned int
+round_up (unsigned int n, unsigned int multiple)
+{
+ return ((n + multiple - 1) / multiple) * multiple;
+}
+
+inline static unsigned int
+round_down (unsigned int n, unsigned int multiple)
+{
+ return (n / multiple) * multiple;
+}
+
+//
+// Return minimum available write space in all our downstream buffers
+// or -1 if we're output blocked and the output we're blocked
+// on is done.
+//
+static int
+min_available_space (gr_block_detail *d, int output_multiple)
+{
+ int min_space = std::numeric_limits<int>::max();
+
+ for (int i = 0; i < d->noutputs (); i++){
+ int n = round_down (d->output(i)->space_available (), output_multiple);
+ if (n == 0){ // We're blocked on output.
+ if (d->output(i)->done()){ // Downstream is done, therefore we're done.
+ return -1;
+ }
+ return 0;
+ }
+ min_space = std::min (min_space, n);
+ }
+ return min_space;
+}
+
+void
+gr_single_threaded_scheduler::main_loop ()
+{
+ static const int DEFAULT_CAPACITY = 16;
+
+ int noutput_items;
+ gr_vector_int ninput_items_required (DEFAULT_CAPACITY);
+ gr_vector_int ninput_items (DEFAULT_CAPACITY);
+ gr_vector_const_void_star input_items (DEFAULT_CAPACITY);
+ gr_vector_void_star output_items (DEFAULT_CAPACITY);
+ unsigned int bi;
+ unsigned int nalive;
+ int max_items_avail;
+ bool made_progress_last_pass;
+ bool making_progress;
+
+ for (unsigned i = 0; i < d_blocks.size (); i++)
+ d_blocks[i]->detail()->set_done (false); // reset any done flags
+
+ for (unsigned i = 0; i < d_blocks.size (); i++) // enable any drivers, etc.
+ d_blocks[i]->start();
+
+
+ bi = 0;
+ made_progress_last_pass = true;
+ making_progress = false;
+
+ // Loop while there are still blocks alive
+
+ nalive = d_blocks.size ();
+ while (d_enabled && nalive > 0){
+
+ if (boost::this_thread::interruption_requested())
+ break;
+
+ gr_block *m = d_blocks[bi].get ();
+ gr_block_detail *d = m->detail().get ();
+
+ LOG(*d_log << std::endl << m);
+
+ if (d->done ())
+ goto next_block;
+
+ if (d->source_p ()){
+ // Invoke sources as a last resort. As long as the previous pass
+ // made progress, don't call a source.
+ if (made_progress_last_pass){
+ LOG(*d_log << " Skipping source\n");
+ goto next_block;
+ }
+
+ ninput_items_required.resize (0);
+ ninput_items.resize (0);
+ input_items.resize (0);
+ output_items.resize (d->noutputs ());
+
+ // determine the minimum available output space
+ noutput_items = min_available_space (d, m->output_multiple ());
+ LOG(*d_log << " source\n noutput_items = " << noutput_items << std::endl);
+ if (noutput_items == -1) // we're done
+ goto were_done;
+
+ if (noutput_items == 0){ // we're output blocked
+ LOG(*d_log << " BLKD_OUT\n");
+ goto next_block;
+ }
+
+ goto setup_call_to_work; // jump to common code
+ }
+
+ else if (d->sink_p ()){
+ ninput_items_required.resize (d->ninputs ());
+ ninput_items.resize (d->ninputs ());
+ input_items.resize (d->ninputs ());
+ output_items.resize (0);
+ LOG(*d_log << " sink\n");
+
+ max_items_avail = 0;
+ for (int i = 0; i < d->ninputs (); i++){
+ ninput_items[i] = d->input(i)->items_available();
+ //if (ninput_items[i] == 0 && d->input(i)->done())
+ if (ninput_items[i] < m->output_multiple() && d->input(i)->done())
+ goto were_done;
+
+ max_items_avail = std::max (max_items_avail, ninput_items[i]);
+ }
+
+ // take a swag at how much output we can sink
+ noutput_items = (int) (max_items_avail * m->relative_rate ());
+ noutput_items = round_down (noutput_items, m->output_multiple ());
+ LOG(*d_log << " max_items_avail = " << max_items_avail << std::endl);
+ LOG(*d_log << " noutput_items = " << noutput_items << std::endl);
+
+ if (noutput_items == 0){ // we're blocked on input
+ LOG(*d_log << " BLKD_IN\n");
+ goto next_block;
+ }
+
+ goto try_again; // Jump to code shared with regular case.
+ }
+
+ else {
+ // do the regular thing
+ ninput_items_required.resize (d->ninputs ());
+ ninput_items.resize (d->ninputs ());
+ input_items.resize (d->ninputs ());
+ output_items.resize (d->noutputs ());
+
+ max_items_avail = 0;
+ for (int i = 0; i < d->ninputs (); i++){
+ ninput_items[i] = d->input(i)->items_available ();
+ max_items_avail = std::max (max_items_avail, ninput_items[i]);
+ }
+
+ // determine the minimum available output space
+ noutput_items = min_available_space (d, m->output_multiple ());
+ if (ENABLE_LOGGING){
+ *d_log << " regular ";
+ if (m->relative_rate() >= 1.0)
+ *d_log << "1:" << m->relative_rate() << std::endl;
+ else
+ *d_log << 1.0/m->relative_rate() << ":1\n";
+ *d_log << " max_items_avail = " << max_items_avail << std::endl;
+ *d_log << " noutput_items = " << noutput_items << std::endl;
+ }
+ if (noutput_items == -1) // we're done
+ goto were_done;
+
+ if (noutput_items == 0){ // we're output blocked
+ LOG(*d_log << " BLKD_OUT\n");
+ goto next_block;
+ }
+
+#if 0
+ // Compute best estimate of noutput_items that we can really use.
+ noutput_items =
+ std::min ((unsigned) noutput_items,
+ std::max ((unsigned) m->output_multiple(),
+ round_up ((unsigned) (max_items_avail * m->relative_rate()),
+ m->output_multiple ())));
+
+ LOG(*d_log << " revised noutput_items = " << noutput_items << std::endl);
+#endif
+
+ try_again:
+ if (m->fixed_rate()){
+ // try to work it forward starting with max_items_avail.
+ // We want to try to consume all the input we've got.
+ int reqd_noutput_items = m->fixed_rate_ninput_to_noutput(max_items_avail);
+ reqd_noutput_items = round_up(reqd_noutput_items, m->output_multiple());
+ if (reqd_noutput_items > 0 && reqd_noutput_items <= noutput_items)
+ noutput_items = reqd_noutput_items;
+ }
+
+ // ask the block how much input they need to produce noutput_items
+ m->forecast (noutput_items, ninput_items_required);
+
+ // See if we've got sufficient input available
+
+ int i;
+ for (i = 0; i < d->ninputs (); i++)
+ if (ninput_items_required[i] > ninput_items[i]) // not enough
+ break;
+
+ if (i < d->ninputs ()){ // not enough input on input[i]
+ // if we can, try reducing the size of our output request
+ if (noutput_items > m->output_multiple ()){
+ noutput_items /= 2;
+ noutput_items = round_up (noutput_items, m->output_multiple ());
+ goto try_again;
+ }
+
+ // We're blocked on input
+ LOG(*d_log << " BLKD_IN\n");
+ if (d->input(i)->done()) // If the upstream block is done, we're done
+ goto were_done;
+
+ // Is it possible to ever fulfill this request?
+ if (ninput_items_required[i] > d->input(i)->max_possible_items_available ()){
+ // Nope, never going to happen...
+ std::cerr << "\nsched: <gr_block " << m->name()
+ << " (" << m->unique_id() << ")>"
+ << " is requesting more input data\n"
+ << " than we can provide.\n"
+ << " ninput_items_required = "
+ << ninput_items_required[i] << "\n"
+ << " max_possible_items_available = "
+ << d->input(i)->max_possible_items_available() << "\n"
+ << " If this is a filter, consider reducing the number of taps.\n";
+ goto were_done;
+ }
+
+ goto next_block;
+ }
+
+ // We've got enough data on each input to produce noutput_items.
+ // Finish setting up the call to work.
+
+ for (int i = 0; i < d->ninputs (); i++)
+ input_items[i] = d->input(i)->read_pointer();
+
+ setup_call_to_work:
+
+ for (int i = 0; i < d->noutputs (); i++)
+ output_items[i] = d->output(i)->write_pointer();
+
+ // Do the actual work of the block
+ int n = m->general_work (noutput_items, ninput_items,
+ input_items, output_items);
+ LOG(*d_log << " general_work: noutput_items = " << noutput_items
+ << " result = " << n << std::endl);
+
+ if (n == -1) // block is done
+ goto were_done;
+
+ d->produce_each (n); // advance write pointers
+ if (n > 0)
+ making_progress = true;
+
+ goto next_block;
+ }
+ assert (0);
+
+ were_done:
+ LOG(*d_log << " were_done\n");
+ d->set_done (true);
+ nalive--;
+
+ next_block:
+ if (++bi >= d_blocks.size ()){
+ bi = 0;
+ made_progress_last_pass = making_progress;
+ making_progress = false;
+ }
+ }
+
+ for (unsigned i = 0; i < d_blocks.size (); i++) // disable any drivers, etc.
+ d_blocks[i]->stop();
+}
diff --git a/gnuradio-runtime/lib/gr_sptr_magic.cc b/gnuradio-runtime/lib/gr_sptr_magic.cc
new file mode 100644
index 0000000000..7fdadf24a2
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_sptr_magic.cc
@@ -0,0 +1,72 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,2009 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <gr_sptr_magic.h>
+#include <gr_hier_block2.h>
+#include <map>
+#include <stdexcept>
+
+
+#include <gruel/thread.h>
+
+namespace gnuradio {
+
+ static gruel::mutex s_mutex;
+ typedef std::map<gr_basic_block*, gr_basic_block_sptr> sptr_map;
+ static sptr_map s_map;
+
+ void
+ detail::sptr_magic::create_and_stash_initial_sptr(gr_hier_block2 *p)
+ {
+ gr_basic_block_sptr sptr(p);
+ gruel::scoped_lock guard(s_mutex);
+ s_map.insert(sptr_map::value_type(static_cast<gr_basic_block *>(p), sptr));
+ }
+
+
+ gr_basic_block_sptr
+ detail::sptr_magic::fetch_initial_sptr(gr_basic_block *p)
+ {
+ /*
+ * If p isn't a subclass of gr_hier_block2, just create the
+ * shared ptr and return it.
+ */
+ gr_hier_block2 *hb2 = dynamic_cast<gr_hier_block2 *>(p);
+ if (!hb2){
+ return gr_basic_block_sptr(p);
+ }
+
+ /*
+ * p is a subclass of gr_hier_block2, thus we've already created the shared pointer
+ * and stashed it away. Fish it out and return it.
+ */
+ gruel::scoped_lock guard(s_mutex);
+ sptr_map::iterator pos = s_map.find(static_cast<gr_basic_block *>(p));
+ if (pos == s_map.end())
+ throw std::invalid_argument("gr_sptr_magic: invalid pointer!");
+
+ gr_basic_block_sptr sptr = pos->second;
+ s_map.erase(pos);
+ return sptr;
+ }
+};
diff --git a/gnuradio-runtime/lib/gr_sync_block.cc b/gnuradio-runtime/lib/gr_sync_block.cc
new file mode 100644
index 0000000000..94efcdc8ee
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_sync_block.cc
@@ -0,0 +1,68 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_sync_block.h>
+
+gr_sync_block::gr_sync_block (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature)
+ : gr_block(name, input_signature, output_signature)
+{
+ set_fixed_rate(true);
+}
+
+
+void
+gr_sync_block::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+{
+ unsigned ninputs = ninput_items_required.size();
+ for (unsigned i = 0; i < ninputs; i++)
+ ninput_items_required[i] = fixed_rate_noutput_to_ninput (noutput_items);
+}
+
+int
+gr_sync_block::fixed_rate_noutput_to_ninput(int noutput_items)
+{
+ return noutput_items + history() - 1;
+}
+
+int
+gr_sync_block::fixed_rate_ninput_to_noutput(int ninput_items)
+{
+ return std::max(0, ninput_items - (int)history() + 1);
+}
+
+int
+gr_sync_block::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ int r = work (noutput_items, input_items, output_items);
+ if (r > 0)
+ consume_each (r);
+ return r;
+}
diff --git a/gnuradio-runtime/lib/gr_sync_decimator.cc b/gnuradio-runtime/lib/gr_sync_decimator.cc
new file mode 100644
index 0000000000..a0f907db53
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_sync_decimator.cc
@@ -0,0 +1,69 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_sync_decimator.h>
+
+gr_sync_decimator::gr_sync_decimator (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature,
+ unsigned decimation)
+ : gr_sync_block (name, input_signature, output_signature)
+{
+ set_decimation (decimation);
+}
+
+void
+gr_sync_decimator::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+{
+ unsigned ninputs = ninput_items_required.size ();
+ for (unsigned i = 0; i < ninputs; i++)
+ ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items);
+}
+
+int
+gr_sync_decimator::fixed_rate_noutput_to_ninput(int noutput_items)
+{
+ return noutput_items * decimation() + history() - 1;
+}
+
+int
+gr_sync_decimator::fixed_rate_ninput_to_noutput(int ninput_items)
+{
+ return std::max(0, ninput_items - (int)history() + 1) / decimation();
+}
+
+int
+gr_sync_decimator::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ int r = work (noutput_items, input_items, output_items);
+ if (r > 0)
+ consume_each (r * decimation ());
+ return r;
+}
+
diff --git a/gnuradio-runtime/lib/gr_sync_interpolator.cc b/gnuradio-runtime/lib/gr_sync_interpolator.cc
new file mode 100644
index 0000000000..ece873c14a
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_sync_interpolator.cc
@@ -0,0 +1,70 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2008 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_sync_interpolator.h>
+
+gr_sync_interpolator::gr_sync_interpolator (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature,
+ unsigned interpolation)
+ : gr_sync_block (name, input_signature, output_signature)
+{
+ set_interpolation (interpolation);
+}
+
+void
+gr_sync_interpolator::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+{
+ unsigned ninputs = ninput_items_required.size ();
+ for (unsigned i = 0; i < ninputs; i++)
+ ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items);
+}
+
+int
+gr_sync_interpolator::fixed_rate_noutput_to_ninput(int noutput_items)
+{
+ return noutput_items / interpolation() + history() - 1;
+}
+
+int
+gr_sync_interpolator::fixed_rate_ninput_to_noutput(int ninput_items)
+{
+ return std::max(0, ninput_items - (int)history() + 1) * interpolation();
+}
+
+int
+gr_sync_interpolator::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ int r = work (noutput_items, input_items, output_items);
+ if (r > 0)
+ consume_each (r / interpolation ());
+ return r;
+}
+
+
diff --git a/gnuradio-runtime/lib/gr_sys_paths.cc b/gnuradio-runtime/lib/gr_sys_paths.cc
new file mode 100644
index 0000000000..b4918af33d
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_sys_paths.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gr_sys_paths.h>
+#include <cstdlib> //getenv
+#include <cstdio> //P_tmpdir (maybe)
+
+const char *gr_tmp_path(){
+ const char *path;
+
+ //first case, try TMP environment variable
+ path = getenv("TMP");
+ if (path) return path;
+
+ //second case, try P_tmpdir when its defined
+ #ifdef P_tmpdir
+ if (P_tmpdir) return P_tmpdir;
+ #endif /*P_tmpdir*/
+
+ //fall-through case, nothing worked
+ return "/tmp";
+}
+
+const char *gr_appdata_path(){
+ const char *path;
+
+ //first case, try HOME environment variable (unix)
+ path = getenv("HOME");
+ if (path) return path;
+
+ //second case, try APPDATA environment variable (windows)
+ path = getenv("APPDATA");
+ if (path) return path;
+
+ //fall-through case, nothing worked
+ return gr_tmp_path();
+}
diff --git a/gnuradio-runtime/lib/gr_tagged_stream_block.cc b/gnuradio-runtime/lib/gr_tagged_stream_block.cc
new file mode 100644
index 0000000000..32b6a09033
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_tagged_stream_block.cc
@@ -0,0 +1,144 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 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_block.h>
+
+gr_tagged_stream_block::gr_tagged_stream_block (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature,
+ const std::string &length_tag_key)
+ : gr_block(name, input_signature, output_signature),
+ d_length_tag_key(pmt::string_to_symbol(length_tag_key)),
+ d_n_input_items_reqd(input_signature->min_streams(), 0),
+ d_length_tag_key_str(length_tag_key)
+{
+}
+
+
+// This is evil hackery: We trick the scheduler into creating the right number of input items
+void
+gr_tagged_stream_block::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+{
+ unsigned ninputs = ninput_items_required.size();
+ for (unsigned i = 0; i < ninputs; i++) {
+ if (i < d_n_input_items_reqd.size() && d_n_input_items_reqd[i] != 0) {
+ ninput_items_required[i] = d_n_input_items_reqd[i];
+ } else {
+ // If there's no item, there's no tag--so there must at least be one!
+ ninput_items_required[i] = std::max(1, (int) std::floor((double) noutput_items / relative_rate() + 0.5));
+ }
+ }
+}
+
+
+void
+gr_tagged_stream_block::parse_length_tags(
+ const std::vector<std::vector<gr_tag_t> > &tags,
+ gr_vector_int &n_input_items_reqd
+){
+ for (unsigned i = 0; i < tags.size(); i++) {
+ for (unsigned k = 0; k < tags[i].size(); k++) {
+ if (tags[i][k].key == d_length_tag_key) {
+ n_input_items_reqd[i] = pmt::to_long(tags[i][k].value);
+ remove_item_tag(i, tags[i][k]);
+ }
+ }
+ }
+}
+
+
+int
+gr_tagged_stream_block::calculate_output_stream_length(const gr_vector_int &ninput_items)
+{
+ int noutput_items = *std::max_element(ninput_items.begin(), ninput_items.end());
+ return (int) std::floor(relative_rate() * noutput_items + 0.5);
+}
+
+
+void
+gr_tagged_stream_block::update_length_tags(int n_produced, int n_ports)
+{
+ for (int i = 0; i < n_ports; i++) {
+ add_item_tag(i, nitems_written(i),
+ d_length_tag_key,
+ pmt::from_long(n_produced)
+ );
+ }
+ return;
+}
+
+
+int
+gr_tagged_stream_block::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ if (d_length_tag_key_str.empty()) {
+ return work(noutput_items, ninput_items, input_items, output_items);
+ }
+
+ if (d_n_input_items_reqd[0] == 0) { // Otherwise, it's already set from a previous call
+ std::vector<std::vector<gr_tag_t> > tags(input_items.size(), std::vector<gr_tag_t>());
+ for (unsigned i = 0; i < input_items.size(); i++) {
+ get_tags_in_range(tags[i], i, nitems_read(i), nitems_read(i)+1);
+ }
+ d_n_input_items_reqd.assign(input_items.size(), -1);
+ parse_length_tags(tags, d_n_input_items_reqd);
+ }
+ for (unsigned i = 0; i < input_items.size(); i++) {
+ if (d_n_input_items_reqd[i] == -1) {
+ throw std::runtime_error("Missing length tag.");
+ }
+ if (d_n_input_items_reqd[i] > ninput_items[i]) {
+ return 0;
+ }
+ }
+
+ int min_output_size = calculate_output_stream_length(d_n_input_items_reqd);
+ if (noutput_items < min_output_size) {
+ set_min_noutput_items(min_output_size);
+ return 0;
+ }
+ set_min_noutput_items(1);
+
+ // WORK CALLED HERE //
+ int n_produced = work(noutput_items, d_n_input_items_reqd, input_items, output_items);
+ //////////////////////
+
+ if (n_produced == WORK_DONE) {
+ return n_produced;
+ }
+ for (int i = 0; i < (int) d_n_input_items_reqd.size(); i++) {
+ consume(i, d_n_input_items_reqd[i]);
+ }
+ update_length_tags(n_produced, output_items.size());
+
+ d_n_input_items_reqd.assign(input_items.size(), 0);
+
+ return n_produced;
+}
+
diff --git a/gnuradio-runtime/lib/gr_test.cc b/gnuradio-runtime/lib/gr_test.cc
new file mode 100644
index 0000000000..cd5ef83611
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_test.cc
@@ -0,0 +1,177 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_test.h>
+#include <gr_io_signature.h>
+#include <stdexcept>
+#include <iostream>
+#include <string.h>
+
+gr_test_sptr gr_make_test (const std::string &name,
+ int min_inputs, int max_inputs, unsigned int sizeof_input_item,
+ int min_outputs, int max_outputs, unsigned int sizeof_output_item,
+ unsigned int history,unsigned int output_multiple,double relative_rate,
+ bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type)
+{
+ return gnuradio::get_initial_sptr(new gr_test (name, min_inputs,max_inputs,sizeof_input_item,
+ min_outputs,max_outputs,sizeof_output_item,
+ history,output_multiple,relative_rate,fixed_rate,cons_type, prod_type));
+}
+
+ gr_test::gr_test (const std::string &name,int min_inputs, int max_inputs, unsigned int sizeof_input_item,
+ int min_outputs, int max_outputs, unsigned int sizeof_output_item,
+ unsigned int history,unsigned int output_multiple,double relative_rate,
+ bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type): gr_block (name,
+ gr_make_io_signature (min_inputs, max_inputs, sizeof_input_item),
+ gr_make_io_signature (min_outputs, max_outputs, sizeof_output_item)),
+ d_sizeof_input_item(sizeof_input_item),
+ d_sizeof_output_item(sizeof_output_item),
+ d_check_topology(true),
+ d_consume_type(cons_type),
+ d_min_consume(0),
+ d_max_consume(0),
+ d_produce_type(prod_type),
+ d_min_produce(0),
+ d_max_produce(0)
+ {
+ set_history(history);
+ set_output_multiple(output_multiple);
+ set_relative_rate(relative_rate);
+ set_fixed_rate(fixed_rate);
+ }
+
+int
+gr_test::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ //touch all inputs and outputs to detect segfaults
+ unsigned ninputs = input_items.size ();
+ unsigned noutputs= output_items.size();
+ for (unsigned i = 0; i < ninputs; i++)
+ {
+ char * in=(char *)input_items[i];
+ if (ninput_items[i]< (int)(noutput_items+history()))
+ {
+ std::cerr << "ERROR: ninput_items[" << i << "] < noutput_items+history()" << std::endl;
+ std::cerr << "ninput_items[" << i << "] = " << ninput_items[i] << std::endl;
+ std::cerr << "noutput_items+history() = " << noutput_items+history() << std::endl;
+ std::cerr << "noutput_items = " << noutput_items << std::endl;
+ std::cerr << "history() = " << history() << std::endl;
+ throw std::runtime_error ("gr_test");
+ } else
+ {
+ for (int j=0;j<ninput_items[i];j++)
+ {
+ //Touch every available input_item
+ //We use a class variable to avoid the compiler to optimize this away
+ for(unsigned int k=0;k<d_sizeof_input_item;k++)
+ d_temp= in[j*d_sizeof_input_item+k];
+ }
+ switch (d_consume_type)
+ {
+ case CONSUME_NOUTPUT_ITEMS:
+ consume(i,noutput_items);
+ break;
+ case CONSUME_NOUTPUT_ITEMS_LIMIT_MAX:
+ consume(i,std::min(noutput_items,d_max_consume));
+ break;
+ case CONSUME_NOUTPUT_ITEMS_LIMIT_MIN:
+ consume(i,std::min(std::max(noutput_items,d_min_consume),ninput_items[i]));
+ break;
+ case CONSUME_ALL_AVAILABLE:
+ consume(i,ninput_items[i]);
+ break;
+ case CONSUME_ALL_AVAILABLE_LIMIT_MAX:
+ consume(i,std::min(ninput_items[i],d_max_consume));
+ break;
+/* //This could result in segfault, uncomment if you want to test this
+ case CONSUME_ALL_AVAILABLE_LIMIT_MIN:
+ consume(i,std::max(ninput_items[i],d_max_consume));
+ break;*/
+ case CONSUME_ZERO:
+ consume(i,0);
+ break;
+ case CONSUME_ONE:
+ consume(i,1);
+ break;
+ case CONSUME_MINUS_ONE:
+ consume(i,-1);
+ break;
+ default:
+ consume(i,noutput_items);
+ }
+ }
+ }
+ for (unsigned i = 0; i < noutputs; i++)
+ {
+ char * out=(char *)output_items[i];
+ {
+ for (int j=0;j<noutput_items;j++)
+ {
+ //Touch every available output_item
+ for(unsigned int k=0;k<d_sizeof_output_item;k++)
+ out[j*d_sizeof_input_item+k]=0;
+ }
+ }
+ }
+ //Now copy input to output until max ninputs or max noutputs is reached
+ int common_nports=std::min(ninputs,noutputs);
+ if(d_sizeof_output_item==d_sizeof_input_item)
+ for (int i = 0; i < common_nports; i++)
+ {
+ memcpy(output_items[i],input_items[i],noutput_items*d_sizeof_input_item);
+ }
+ int noutput_items_produced=0;
+ switch (d_produce_type){
+ case PRODUCE_NOUTPUT_ITEMS:
+ noutput_items_produced=noutput_items;
+ break;
+ case PRODUCE_NOUTPUT_ITEMS_LIMIT_MAX:
+ noutput_items_produced=std::min(noutput_items,d_max_produce);
+ break;
+/* //This could result in segfault, uncomment if you want to test this
+ case PRODUCE_NOUTPUT_ITEMS_LIMIT_MIN:
+ noutput_items_produced=std::max(noutput_items,d_min_produce);
+ break;*/
+ case PRODUCE_ZERO:
+ noutput_items_produced=0;
+ break;
+ case PRODUCE_ONE:
+ noutput_items_produced=1;
+ break;
+ case PRODUCE_MINUS_ONE:
+ noutput_items_produced=-1;
+ break;
+ default:
+ noutput_items_produced=noutput_items;
+ }
+ return noutput_items_produced;
+ }
+
+
+
diff --git a/gnuradio-runtime/lib/gr_test.h b/gnuradio-runtime/lib/gr_test.h
new file mode 100644
index 0000000000..2276ab1967
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_test.h
@@ -0,0 +1,195 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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_TEST_H
+#define INCLUDED_GR_TEST_H
+
+#include <gr_runtime_api.h>
+#include <gr_block.h>
+#include <string>
+#include "gr_test_types.h"
+
+class gr_test;
+typedef boost::shared_ptr<gr_test> gr_test_sptr;
+
+// public constructor
+GR_RUNTIME_API gr_test_sptr gr_make_test (const std::string &name=std::string("gr_test"),
+ int min_inputs=1, int max_inputs=1, unsigned int sizeof_input_item=1,
+ int min_outputs=1, int max_outputs=1, unsigned int sizeof_output_item=1,
+ unsigned int history=1,unsigned int output_multiple=1,double relative_rate=1.0,
+ bool fixed_rate=true,gr_consume_type_t cons_type=CONSUME_NOUTPUT_ITEMS, gr_produce_type_t prod_type=PRODUCE_NOUTPUT_ITEMS);
+
+/*!
+ * \brief Test class for testing runtime system (setting up buffers and such.)
+ * \ingroup misc
+ *
+ * This block does not do any usefull actual data processing.
+ * It just exposes setting all standard block parameters using the contructor or public methods.
+ *
+ * This block can be usefull when testing the runtime system.
+ * You can force this block to have a large history, decimation
+ * factor and/or large output_multiple.
+ * The runtime system should detect this and create large enough buffers
+ * all through the signal chain.
+ */
+class GR_RUNTIME_API gr_test : public gr_block {
+
+ public:
+
+ ~gr_test (){}
+
+int general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ // ----------------------------------------------------------------
+ // override these to define your behavior
+ // ----------------------------------------------------------------
+
+ /*!
+ * \brief Estimate input requirements given output request
+ *
+ * \param noutput_items number of output items to produce
+ * \param ninput_items_required number of input items required on each input stream
+ *
+ * Given a request to product \p noutput_items, estimate the number of
+ * data items required on each input stream. The estimate doesn't have
+ * to be exact, but should be close.
+ */
+ void forecast (int noutput_items,
+ gr_vector_int &ninput_items_required)
+ {
+ unsigned ninputs = ninput_items_required.size ();
+ for (unsigned i = 0; i < ninputs; i++)
+ ninput_items_required[i] = (int)((double)noutput_items / relative_rate()) + (int)history();
+ }
+
+
+ /*!
+ * \brief Force check topology to return true or false.
+ *
+ * \param check_topology value to return when check_topology is called (true or false)
+ * default check_topology returns true
+ *
+ */
+ void set_check_topology (bool check_topology){ d_check_topology=check_topology;}
+
+ /*!
+ * \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.
+ */
+ bool check_topology (int ninputs, int noutputs) { return d_check_topology;}
+
+ // ----------------------------------------------------------------
+ /*
+ * The following two methods provide special case info to the
+ * scheduler in the event that a block has a fixed input to output
+ * ratio. gr_sync_block, gr_sync_decimator and gr_sync_interpolator
+ * override these. If you're fixed rate, subclass one of those.
+ */
+ /*!
+ * \brief Given ninput samples, return number of output samples that will be produced.
+ * N.B. this is only defined if fixed_rate returns true.
+ * Generally speaking, you don't need to override this.
+ */
+ int fixed_rate_ninput_to_noutput(int ninput) { return (int)((double)ninput/relative_rate()); }
+
+ /*!
+ * \brief Given noutput samples, return number of input samples required to produce noutput.
+ * N.B. this is only defined if fixed_rate returns true.
+ */
+ int fixed_rate_noutput_to_ninput(int noutput) { return (int)((double)noutput*relative_rate()); }
+
+ /*!
+ * \brief Set if fixed rate should return true.
+ * N.B. This is normally a private method but we make it available here as public.
+ */
+ void set_fixed_rate_public(bool fixed_rate){ set_fixed_rate(fixed_rate);}
+
+ /*!
+ * \brief Set the consume pattern.
+ *
+ * \param cons_type which consume pattern to use
+ */
+ void set_consume_type (gr_consume_type_t cons_type) { d_consume_type=cons_type;}
+
+ /*!
+ * \brief Set the consume limit.
+ *
+ * \param limit min or maximum items to consume (depending on consume_type)
+ */
+ void set_consume_limit (unsigned int limit) { d_min_consume=limit; d_max_consume=limit;}
+
+ /*!
+ * \brief Set the produce pattern.
+ *
+ * \param prod_type which produce pattern to use
+ */
+ void set_produce_type (gr_produce_type_t prod_type) { d_produce_type=prod_type;}
+
+ /*!
+ * \brief Set the produce limit.
+ *
+ * \param limit min or maximum items to produce (depending on produce_type)
+ */
+ void set_produce_limit (unsigned int limit) { d_min_produce=limit; d_max_produce=limit;}
+
+ // ----------------------------------------------------------------------------
+
+
+
+ protected:
+ unsigned int d_sizeof_input_item;
+ unsigned int d_sizeof_output_item;
+ bool d_check_topology;
+ char d_temp;
+ gr_consume_type_t d_consume_type;
+ int d_min_consume;
+ int d_max_consume;
+ gr_produce_type_t d_produce_type;
+ int d_min_produce;
+ int d_max_produce;
+ gr_test (const std::string &name,int min_inputs, int max_inputs, unsigned int sizeof_input_item,
+ int min_outputs, int max_outputs, unsigned int sizeof_output_item,
+ unsigned int history,unsigned int output_multiple,double relative_rate,
+ bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type);
+
+
+
+ friend GR_RUNTIME_API gr_test_sptr gr_make_test (const std::string &name,int min_inputs, int max_inputs, unsigned int sizeof_input_item,
+ int min_outputs, int max_outputs, unsigned int sizeof_output_item,
+ unsigned int history,unsigned int output_multiple,double relative_rate,
+ bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type);
+};
+
+
+
+#endif /* INCLUDED_GR_TEST_H */
diff --git a/gnuradio-runtime/lib/gr_test_types.h b/gnuradio-runtime/lib/gr_test_types.h
new file mode 100644
index 0000000000..04f38f7b26
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_test_types.h
@@ -0,0 +1,46 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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_TEST_TYPES_H
+#define INCLUDED_GR_TEST_TYPES_H
+
+typedef enum {
+ CONSUME_NOUTPUT_ITEMS=0,
+ CONSUME_NOUTPUT_ITEMS_LIMIT_MAX=1,
+ CONSUME_NOUTPUT_ITEMS_LIMIT_MIN=2,
+ CONSUME_ALL_AVAILABLE=3,
+ CONSUME_ALL_AVAILABLE_LIMIT_MAX=4,
+ /*CONSUME_ALL_AVAILABLE_LIMIT_MIN=5,*/
+ CONSUME_ZERO=6,
+ CONSUME_ONE=7,
+ CONSUME_MINUS_ONE=8
+ } gr_consume_type_t;
+
+typedef enum {
+ PRODUCE_NOUTPUT_ITEMS=0,
+ PRODUCE_NOUTPUT_ITEMS_LIMIT_MAX=1,
+ /*PRODUCE_NOUTPUT_ITEMS_LIMIT_MIN=2,*/
+ PRODUCE_ZERO=6,
+ PRODUCE_ONE=7,
+ PRODUCE_MINUS_ONE=8
+ } gr_produce_type_t;
+
+#endif /* INCLUDED_GR_TEST_TYPES_H */
diff --git a/gnuradio-runtime/lib/gr_top_block.cc b/gnuradio-runtime/lib/gr_top_block.cc
new file mode 100644
index 0000000000..c6118bcfdd
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_top_block.cc
@@ -0,0 +1,160 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 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 <unistd.h>
+#include <gr_top_block.h>
+#include <gr_top_block_impl.h>
+#include <gr_io_signature.h>
+#include <gr_prefs.h>
+#include <iostream>
+
+gr_top_block_sptr
+gr_make_top_block(const std::string &name)
+{
+ return gnuradio::get_initial_sptr(new gr_top_block(name));
+}
+
+gr_top_block::gr_top_block(const std::string &name)
+ : gr_hier_block2(name,
+ gr_make_io_signature(0,0,0),
+ gr_make_io_signature(0,0,0))
+
+{
+ d_impl = new gr_top_block_impl(this);
+}
+
+gr_top_block::~gr_top_block()
+{
+ stop();
+ wait();
+
+ delete d_impl;
+}
+
+void
+gr_top_block::start(int max_noutput_items)
+{
+ d_impl->start(max_noutput_items);
+
+ if(gr_prefs::singleton()->get_bool("ControlPort", "on", false)) {
+ setup_rpc();
+ }
+}
+
+void
+gr_top_block::stop()
+{
+ d_impl->stop();
+}
+
+void
+gr_top_block::wait()
+{
+ d_impl->wait();
+}
+
+void
+gr_top_block::run(int max_noutput_items)
+{
+ start(max_noutput_items);
+ wait();
+}
+
+void
+gr_top_block::lock()
+{
+ d_impl->lock();
+}
+
+void
+gr_top_block::unlock()
+{
+ d_impl->unlock();
+}
+
+std::string
+gr_top_block::edge_list()
+{
+ return d_impl->edge_list();
+}
+
+void
+gr_top_block::dump()
+{
+ d_impl->dump();
+}
+
+int
+gr_top_block::max_noutput_items()
+{
+ return d_impl->max_noutput_items();
+}
+
+void
+gr_top_block::set_max_noutput_items(int nmax)
+{
+ d_impl->set_max_noutput_items(nmax);
+}
+
+gr_top_block_sptr
+gr_top_block::to_top_block()
+{
+ return cast_to_top_block_sptr(shared_from_this());
+}
+
+void
+gr_top_block::setup_rpc()
+{
+#ifdef GR_CTRLPORT
+ // Getters
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_top_block, int>(
+ alias(), "max nouptut_items",
+ &gr_top_block::max_noutput_items,
+ pmt::mp(0), pmt::mp(8192), pmt::mp(8192),
+ "items", "Max number of output items",
+ RPC_PRIVLVL_MIN, DISPNULL)));
+
+ if(gr_prefs::singleton()->get_bool("ControlPort", "edges_list", false)) {
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_top_block, std::string>(
+ alias(), "edge list",
+ &gr_top_block::edge_list,
+ pmt::mp(""), pmt::mp(""), pmt::mp(""),
+ "edges", "List of edges in the graph",
+ RPC_PRIVLVL_MIN, DISPNULL)));
+ }
+
+ // Setters
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_set<gr_top_block, int>(
+ alias(), "max noutput_items",
+ &gr_top_block::set_max_noutput_items,
+ pmt::mp(0), pmt::mp(8192), pmt::mp(8192),
+ "items", "Max number of output items",
+ RPC_PRIVLVL_MIN, DISPNULL)));
+#endif /* GR_CTRLPORT */
+}
diff --git a/gnuradio-runtime/lib/gr_top_block_impl.cc b/gnuradio-runtime/lib/gr_top_block_impl.cc
new file mode 100644
index 0000000000..b6d427ce27
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_top_block_impl.cc
@@ -0,0 +1,211 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 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_top_block.h>
+#include <gr_top_block_impl.h>
+#include <gr_flat_flowgraph.h>
+#include <gr_scheduler_sts.h>
+#include <gr_scheduler_tpb.h>
+#include <gr_prefs.h>
+
+#include <stdexcept>
+#include <iostream>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#define GR_TOP_BLOCK_IMPL_DEBUG 0
+
+
+typedef gr_scheduler_sptr (*scheduler_maker)(gr_flat_flowgraph_sptr ffg,
+ int max_noutput_items);
+
+static struct scheduler_table {
+ const char *name;
+ scheduler_maker f;
+} scheduler_table[] = {
+ { "TPB", gr_scheduler_tpb::make }, // first entry is default
+ { "STS", gr_scheduler_sts::make }
+};
+
+static gr_scheduler_sptr
+make_scheduler(gr_flat_flowgraph_sptr ffg, int max_noutput_items)
+{
+ static scheduler_maker factory = 0;
+
+ if (factory == 0){
+ char *v = getenv("GR_SCHEDULER");
+ if (!v)
+ factory = scheduler_table[0].f; // use default
+ else {
+ for (size_t i = 0; i < sizeof(scheduler_table)/sizeof(scheduler_table[0]); i++){
+ if (strcmp(v, scheduler_table[i].name) == 0){
+ factory = scheduler_table[i].f;
+ break;
+ }
+ }
+ if (factory == 0){
+ std::cerr << "warning: Invalid GR_SCHEDULER environment variable value \""
+ << v << "\". Using \"" << scheduler_table[0].name << "\"\n";
+ factory = scheduler_table[0].f;
+ }
+ }
+ }
+ return factory(ffg, max_noutput_items);
+}
+
+
+gr_top_block_impl::gr_top_block_impl(gr_top_block *owner)
+ : d_owner(owner), d_ffg(),
+ d_state(IDLE), d_lock_count(0)
+{
+}
+
+gr_top_block_impl::~gr_top_block_impl()
+{
+ d_owner = 0;
+}
+
+void
+gr_top_block_impl::start(int max_noutput_items)
+{
+ gruel::scoped_lock l(d_mutex);
+
+ d_max_noutput_items = max_noutput_items;
+
+ if (d_state != IDLE)
+ throw std::runtime_error("top_block::start: top block already running or wait() not called after previous stop()");
+
+ if (d_lock_count > 0)
+ throw std::runtime_error("top_block::start: can't start with flow graph locked");
+
+ // Create new flat flow graph by flattening hierarchy
+ d_ffg = d_owner->flatten();
+
+ // Validate new simple flow graph and wire it up
+ d_ffg->validate();
+ d_ffg->setup_connections();
+
+ // Only export perf. counters if ControlPort config param is enabled
+ // and if the PerfCounter option 'export' is turned on.
+ gr_prefs *p = gr_prefs::singleton();
+ if(p->get_bool("ControlPort", "on", false) && p->get_bool("PerfCounters", "export", false))
+ d_ffg->enable_pc_rpc();
+
+ d_scheduler = make_scheduler(d_ffg, d_max_noutput_items);
+ d_state = RUNNING;
+}
+
+void
+gr_top_block_impl::stop()
+{
+ if (d_scheduler)
+ d_scheduler->stop();
+}
+
+
+void
+gr_top_block_impl::wait()
+{
+ if (d_scheduler)
+ d_scheduler->wait();
+
+ d_state = IDLE;
+}
+
+// N.B. lock() and unlock() cannot be called from a flow graph thread or
+// deadlock will occur when reconfiguration happens
+void
+gr_top_block_impl::lock()
+{
+ gruel::scoped_lock lock(d_mutex);
+ d_lock_count++;
+}
+
+void
+gr_top_block_impl::unlock()
+{
+ gruel::scoped_lock lock(d_mutex);
+
+ if (d_lock_count <= 0){
+ d_lock_count = 0; // fix it, then complain
+ throw std::runtime_error("unpaired unlock() call");
+ }
+
+ d_lock_count--;
+ if (d_lock_count > 0 || d_state == IDLE) // nothing to do
+ return;
+
+ restart();
+}
+
+/*
+ * restart is called with d_mutex held
+ */
+void
+gr_top_block_impl::restart()
+{
+ stop(); // Stop scheduler and wait for completion
+ wait();
+
+ // Create new simple flow graph
+ gr_flat_flowgraph_sptr new_ffg = d_owner->flatten();
+ new_ffg->validate(); // check consistency, sanity, etc
+ new_ffg->merge_connections(d_ffg); // reuse buffers, etc
+ d_ffg = new_ffg;
+
+ // Create a new scheduler to execute it
+ d_scheduler = make_scheduler(d_ffg, d_max_noutput_items);
+ d_state = RUNNING;
+}
+
+std::string
+gr_top_block_impl::edge_list()
+{
+ if(d_ffg)
+ return d_ffg->edge_list();
+ else
+ return "";
+}
+
+void
+gr_top_block_impl::dump()
+{
+ if (d_ffg)
+ d_ffg->dump();
+}
+
+int
+gr_top_block_impl::max_noutput_items()
+{
+ return d_max_noutput_items;
+}
+
+void
+gr_top_block_impl::set_max_noutput_items(int nmax)
+{
+ d_max_noutput_items = nmax;
+}
diff --git a/gnuradio-runtime/lib/gr_top_block_impl.h b/gnuradio-runtime/lib/gr_top_block_impl.h
new file mode 100644
index 0000000000..7293531090
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_top_block_impl.h
@@ -0,0 +1,88 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 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_TOP_BLOCK_IMPL_H
+#define INCLUDED_GR_TOP_BLOCK_IMPL_H
+
+#include <gr_runtime_api.h>
+#include <gr_scheduler.h>
+#include <gruel/thread.h>
+
+/*!
+ *\brief Abstract implementation details of gr_top_block
+ * \ingroup internal
+ *
+ * The actual implementation of gr_top_block. Separate class allows
+ * decoupling of changes from dependent classes.
+ *
+ */
+class GR_RUNTIME_API gr_top_block_impl
+{
+public:
+ gr_top_block_impl(gr_top_block *owner);
+ ~gr_top_block_impl();
+
+ // Create and start scheduler threads
+ void start(int max_noutput_items=100000000);
+
+ // Signal scheduler threads to stop
+ void stop();
+
+ // Wait for scheduler threads to exit
+ void wait();
+
+ // Lock the top block to allow reconfiguration
+ void lock();
+
+ // Unlock the top block at end of reconfiguration
+ void unlock();
+
+ // Return a string list of edges
+ std::string edge_list();
+
+ // Dump the flowgraph to stdout
+ void dump();
+
+ // Get the number of max noutput_items in the flowgraph
+ int max_noutput_items();
+
+ // Set the maximum number of noutput_items in the flowgraph
+ void set_max_noutput_items(int nmax);
+
+protected:
+
+ enum tb_state { IDLE, RUNNING };
+
+ gr_top_block *d_owner;
+ gr_flat_flowgraph_sptr d_ffg;
+ gr_scheduler_sptr d_scheduler;
+
+ gruel::mutex d_mutex; // protects d_state and d_lock_count
+ tb_state d_state;
+ int d_lock_count;
+ int d_max_noutput_items;
+
+private:
+ void restart();
+};
+
+#endif /* INCLUDED_GR_TOP_BLOCK_IMPL_H */
diff --git a/gnuradio-runtime/lib/gr_tpb_detail.cc b/gnuradio-runtime/lib/gr_tpb_detail.cc
new file mode 100644
index 0000000000..46eb6bbe0d
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_tpb_detail.cc
@@ -0,0 +1,70 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,2009 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <gr_tpb_detail.h>
+#include <gr_block.h>
+#include <gr_block_detail.h>
+#include <gr_buffer.h>
+
+using namespace pmt;
+
+/*
+ * We assume that no worker threads are ever running when the
+ * graph structure is being manipulated, thus it's safe for us to poke
+ * around in our neighbors w/o holding any locks.
+ */
+
+void
+gr_tpb_detail::notify_upstream(gr_block_detail *d)
+{
+ // For each of our inputs, tell the guy upstream that we've consumed
+ // some input, and that he most likely has more output buffer space
+ // available.
+
+ for (size_t i = 0; i < d->d_input.size(); i++){
+ // Can you say, "pointer chasing?"
+ d->d_input[i]->buffer()->link()->detail()->d_tpb.set_output_changed();
+ }
+}
+
+void
+gr_tpb_detail::notify_downstream(gr_block_detail *d)
+{
+ // For each of our outputs, tell the guys downstream that they have
+ // new input available.
+
+ for (size_t i = 0; i < d->d_output.size(); i++){
+ gr_buffer_sptr buf = d->d_output[i];
+ for (size_t j = 0, k = buf->nreaders(); j < k; j++)
+ buf->reader(j)->link()->detail()->d_tpb.set_input_changed();
+ }
+}
+
+void
+gr_tpb_detail::notify_neighbors(gr_block_detail *d)
+{
+ notify_downstream(d);
+ notify_upstream(d);
+}
+
diff --git a/gnuradio-runtime/lib/gr_tpb_thread_body.cc b/gnuradio-runtime/lib/gr_tpb_thread_body.cc
new file mode 100644
index 0000000000..679fd15124
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_tpb_thread_body.cc
@@ -0,0 +1,151 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,2009,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <gr_tpb_thread_body.h>
+#include <gr_prefs.h>
+#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;
+
+ gr_block_detail *d = block->detail().get();
+ gr_block_executor::state s;
+ pmt_t msg;
+
+ d->threaded = true;
+ d->thread = gruel::get_current_thread_id();
+
+ gr_prefs *p = gr_prefs::singleton();
+ size_t max_nmsgs = static_cast<size_t>(p->get_long("DEFAULT", "max_messages", 100));
+
+ // Set thread affinity if it was set before fg was started.
+ if(block->processor_affinity().size() > 0) {
+ gruel::thread_bind_to_processor(d->thread, block->processor_affinity());
+ }
+
+ while (1){
+ boost::this_thread::interruption_point();
+
+ // handle any queued up messages
+ //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 )
+ {
+ // Check if we have a message handler attached before getting
+ // any messages. This is mostly a protection for the unknown
+ // startup sequence of the threads.
+ if(block->has_msg_handler(i.first)) {
+ while ((msg = block->delete_head_nowait(i.first))){
+ block->dispatch_msg(i.first,msg);
+ }
+ }
+ else {
+ // If we don't have a handler but are building up messages,
+ // prune the queue from the front to keep memory in check.
+ if(block->nmsgs(i.first) > max_nmsgs)
+ msg = block->delete_head_nowait(i.first);
+ }
+ }
+
+ d->d_tpb.clear_changed();
+ // 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.
+ d->d_tpb.notify_neighbors(d);
+ break;
+
+ case gr_block_executor::READY_NO_OUTPUT: // Notify upstream only
+ d->d_tpb.notify_upstream(d);
+ break;
+
+ case gr_block_executor::DONE: // Game over.
+ d->d_tpb.notify_neighbors(d);
+ return;
+
+ case gr_block_executor::BLKD_IN: // Wait for input.
+ {
+ gruel::scoped_lock guard(d->d_tpb.mutex);
+ while (!d->d_tpb.input_changed){
+
+ // wait for input or message
+ while(!d->d_tpb.input_changed && block->empty_p())
+ d->d_tpb.input_cond.wait(guard);
+
+ // handle all pending messages
+ 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;
+
+
+ case gr_block_executor::BLKD_OUT: // Wait for output buffer space.
+ {
+ gruel::scoped_lock guard(d->d_tpb.mutex);
+ while (!d->d_tpb.output_changed){
+
+ // wait for output room or message
+ while(!d->d_tpb.output_changed && block->empty_p())
+ d->d_tpb.output_cond.wait(guard);
+
+ // handle all pending messages
+ 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;
+
+ default:
+ assert(0);
+ }
+ }
+}
+
+gr_tpb_thread_body::~gr_tpb_thread_body()
+{
+}
diff --git a/gnuradio-runtime/lib/gr_tpb_thread_body.h b/gnuradio-runtime/lib/gr_tpb_thread_body.h
new file mode 100644
index 0000000000..6ecb022f69
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_tpb_thread_body.h
@@ -0,0 +1,46 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_GR_TPB_THREAD_BODY_H
+#define INCLUDED_GR_TPB_THREAD_BODY_H
+
+#include <gr_runtime_api.h>
+#include <gr_block_executor.h>
+#include <gr_block.h>
+#include <gr_block_detail.h>
+
+/*!
+ * \brief The body of each thread-per-block thread.
+ *
+ * One of these is instantiated in its own thread for each block. The
+ * constructor turns into the main loop which returns when the block is
+ * done or is interrupted.
+ */
+
+class GR_RUNTIME_API gr_tpb_thread_body {
+ gr_block_executor d_exec;
+
+public:
+ gr_tpb_thread_body(gr_block_sptr block, int max_noutput_items=100000);
+ ~gr_tpb_thread_body();
+};
+
+
+#endif /* INCLUDED_GR_TPB_THREAD_BODY_H */
diff --git a/gnuradio-runtime/lib/gr_vco.h b/gnuradio-runtime/lib/gr_vco.h
new file mode 100644
index 0000000000..3ceaf15dd4
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_vco.h
@@ -0,0 +1,94 @@
+/* -*- 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.
+ */
+#ifndef _GR_VCO_H_
+#define _GR_VCO_H_
+
+
+#include <vector>
+#include <gr_sincos.h>
+#include <cmath>
+#include <gr_complex.h>
+
+/*!
+ * \brief base class template for Voltage Controlled Oscillator (VCO)
+ * \ingroup misc
+ */
+
+//FIXME Eventually generalize this to fixed point
+
+template<class o_type, class i_type>
+class gr_vco {
+public:
+ gr_vco () : d_phase (0) {}
+
+ virtual ~gr_vco () {}
+
+ // radians
+ void set_phase (double angle) {
+ d_phase = angle;
+ }
+
+ void adjust_phase (double delta_phase) {
+ d_phase += delta_phase;
+ if (fabs (d_phase) > M_PI){
+
+ while (d_phase > M_PI)
+ d_phase -= 2*M_PI;
+
+ while (d_phase < -M_PI)
+ d_phase += 2*M_PI;
+ }
+ }
+
+ double get_phase () const { return d_phase; }
+
+ // compute sin and cos for current phase angle
+ void sincos (float *sinx, float *cosx) const;
+
+ // compute cos or sin for current phase angle
+ float cos () const { return std::cos (d_phase); }
+ float sin () const { return std::sin (d_phase); }
+
+ // compute a block at a time
+ void cos (float *output, const float *input, int noutput_items, double k, double ampl = 1.0);
+
+protected:
+ double d_phase;
+};
+
+template<class o_type, class i_type>
+void
+gr_vco<o_type,i_type>::sincos (float *sinx, float *cosx) const
+{
+ gr_sincosf (d_phase, sinx, cosx);
+}
+
+template<class o_type, class i_type>
+void
+gr_vco<o_type,i_type>::cos (float *output, const float *input, int noutput_items, double k, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = cos() * ampl;
+ adjust_phase(input[i] * k);
+ }
+}
+#endif /* _GR_VCO_H_ */
diff --git a/gnuradio-runtime/lib/gr_vmcircbuf.cc b/gnuradio-runtime/lib/gr_vmcircbuf.cc
new file mode 100644
index 0000000000..522d9515d0
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_vmcircbuf.cc
@@ -0,0 +1,295 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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_vmcircbuf.h>
+#include <assert.h>
+#include <stdexcept>
+#include <gr_preferences.h>
+#include <stdio.h>
+#include <string.h>
+#include <gr_local_sighandler.h>
+#include <vector>
+#include <boost/format.hpp>
+
+// all the factories we know about
+#include <gr_vmcircbuf_createfilemapping.h>
+#include <gr_vmcircbuf_sysv_shm.h>
+#include <gr_vmcircbuf_mmap_shm_open.h>
+#include <gr_vmcircbuf_mmap_tmpfile.h>
+
+static const char *FACTORY_PREF_KEY = "gr_vmcircbuf_default_factory";
+
+gr_vmcircbuf::~gr_vmcircbuf ()
+{
+}
+
+gr_vmcircbuf_factory::~gr_vmcircbuf_factory ()
+{
+}
+
+// ----------------------------------------------------------------
+
+static gr_vmcircbuf_factory *s_default_factory = 0;
+
+gr_vmcircbuf_factory *
+gr_vmcircbuf_sysconfig::get_default_factory ()
+{
+ if (s_default_factory)
+ return s_default_factory;
+
+ bool verbose = false;
+
+ std::vector<gr_vmcircbuf_factory *> all = all_factories ();
+
+ const char *name = gr_preferences::get (FACTORY_PREF_KEY);
+
+ if (name){
+ for (unsigned int i = 0; i < all.size (); i++){
+ if (strcmp (name, all[i]->name ()) == 0){
+ s_default_factory = all[i];
+ if (verbose)
+ fprintf (stderr, "gr_vmcircbuf_sysconfig: using %s\n",
+ s_default_factory->name ());
+ return s_default_factory;
+ }
+ }
+ }
+
+ // either we don't have a default, or the default named is not in our
+ // list of factories. Find the first factory that works.
+
+ if (verbose)
+ fprintf (stderr, "gr_vmcircbuf_sysconfig: finding a working factory...\n");
+
+ for (unsigned int i = 0; i < all.size (); i++){
+ if (test_factory (all[i], verbose)){
+ set_default_factory (all[i]);
+ return s_default_factory;
+ }
+ }
+
+ // We're screwed!
+
+ fprintf (stderr, "gr_vmcircbuf_sysconfig: unable to find a working factory!\n");
+ throw std::runtime_error ("gr_vmcircbuf_sysconfig");
+}
+
+std::vector<gr_vmcircbuf_factory *>
+gr_vmcircbuf_sysconfig::all_factories ()
+{
+ std::vector<gr_vmcircbuf_factory *> result;
+
+ result.push_back (gr_vmcircbuf_createfilemapping_factory::singleton ());
+#ifdef TRY_SHM_VMCIRCBUF
+ result.push_back (gr_vmcircbuf_sysv_shm_factory::singleton ());
+ result.push_back (gr_vmcircbuf_mmap_shm_open_factory::singleton ());
+#endif
+ result.push_back (gr_vmcircbuf_mmap_tmpfile_factory::singleton ());
+
+ return result;
+}
+
+void
+gr_vmcircbuf_sysconfig::set_default_factory (gr_vmcircbuf_factory *f)
+{
+ gr_preferences::set (FACTORY_PREF_KEY, f->name ());
+ s_default_factory = f;
+}
+
+
+// ------------------------------------------------------------------------
+// test code for vmcircbuf factories
+// ------------------------------------------------------------------------
+
+static void
+init_buffer (gr_vmcircbuf *c, int counter, int size)
+{
+ unsigned int *p = (unsigned int *) c->pointer_to_first_copy ();
+ for (unsigned int i = 0; i < size / sizeof (int); i++)
+ p[i] = counter + i;
+}
+
+static bool
+check_mapping (gr_vmcircbuf *c, int counter, int size, const char *msg, bool verbose)
+{
+ bool ok = true;
+
+ if (verbose)
+ fprintf (stderr, "... %s", msg);
+
+ unsigned int *p1 = (unsigned int *) c->pointer_to_first_copy ();
+ unsigned int *p2 = (unsigned int *) c->pointer_to_second_copy ();
+
+ // fprintf (stderr, "p1 = %p, p2 = %p\n", p1, p2);
+
+ for (unsigned int i = 0; i < size / sizeof (int); i++){
+ if (p1[i] != counter + i){
+ ok = false;
+ if (verbose)
+ fprintf (stderr, " p1[%d] == %u, expected %u\n", i, p1[i], counter + i);
+ break;
+ }
+ if (p2[i] != counter + i){
+ if (verbose)
+ fprintf (stderr, " p2[%d] == %u, expected %u\n", i, p2[i], counter + i);
+ ok = false;
+ break;
+ }
+ }
+
+ if (ok && verbose){
+ fprintf (stderr, " OK\n");
+ }
+ return ok;
+}
+
+static const char *
+memsize (int size)
+{
+ static std::string buf;
+ if (size >= (1 << 20)){
+ buf = str(boost::format("%dMB") % (size / (1 << 20)));
+ }
+ else if (size >= (1 << 10)){
+ buf = str(boost::format("%dKB") % (size / (1 << 10)));
+ }
+ else {
+ buf = str(boost::format("%d") % size);
+ }
+ return buf.c_str();
+}
+
+static bool
+test_a_bunch (gr_vmcircbuf_factory *factory, int n, int size, int *start_ptr, bool verbose)
+{
+ bool ok = true;
+ std::vector<int> counter(n);
+ std::vector<gr_vmcircbuf *> c(n);
+ int cum_size = 0;
+
+ for (int i = 0; i < n; i++){
+ counter[i] = *start_ptr;
+ *start_ptr += size;
+ if ((c[i] = factory->make (size)) == 0){
+ if (verbose)
+ fprintf (stderr,
+ "Failed to allocate gr_vmcircbuf number %d of size %d (cum = %s)\n",
+ i + 1, size, memsize (cum_size));
+ return false;
+ }
+ init_buffer (c[i], counter[i], size);
+ cum_size += size;
+ }
+
+ for (int i = 0; i < n; i++){
+ std::string msg = str(boost::format("test_a_bunch_%dx%s[%d]") % n % memsize (size) % i);
+ ok &= check_mapping (c[i], counter[i], size, msg.c_str(), verbose);
+ }
+
+ for (int i = 0; i < n; i++){
+ delete c[i];
+ c[i] = 0;
+ }
+
+ return ok;
+}
+
+static bool
+standard_tests (gr_vmcircbuf_factory *f, int verbose)
+{
+ if (verbose >= 1)
+ fprintf (stderr, "Testing %s...\n", f->name ());
+
+ bool v = verbose >= 2;
+ int granularity = f->granularity ();
+ int start = 0;
+ bool ok = true;
+
+ ok &= test_a_bunch (f, 1, 1 * granularity, &start, v); // 1 x 4KB = 4KB
+
+ if (ok){
+ ok &= test_a_bunch (f, 64, 4 * granularity, &start, v); // 64 x 16KB = 1MB
+ ok &= test_a_bunch (f, 4, 4 * (1L << 20), &start, v); // 4 x 4MB = 16MB
+// ok &= test_a_bunch (f, 256, 256 * (1L << 10), &start, v); // 256 x 256KB = 64MB
+ }
+
+ if (verbose >= 1)
+ fprintf (stderr, "....... %s: %s", f->name (), ok ? "OK\n" : "Doesn't work\n");
+
+ return ok;
+}
+
+bool
+gr_vmcircbuf_sysconfig::test_factory (gr_vmcircbuf_factory *f, int verbose)
+{
+ // Install local signal handlers for SIGSEGV and SIGBUS.
+ // If something goes wrong, these signals may be invoked.
+
+#ifdef SIGSEGV
+ gr_local_sighandler sigsegv (SIGSEGV, gr_local_sighandler::throw_signal);
+#endif
+#ifdef SIGBUS
+ gr_local_sighandler sigbus (SIGBUS, gr_local_sighandler::throw_signal);
+#endif
+#ifdef SIGSYS
+ gr_local_sighandler sigsys (SIGSYS, gr_local_sighandler::throw_signal);
+#endif
+
+ try {
+ return standard_tests (f, verbose);
+ }
+ catch (gr_signal &sig){
+ if (verbose){
+ fprintf (stderr, "....... %s: %s", f->name (), "Doesn't work\n");
+ fprintf (stderr,
+ "gr_vmcircbuf_factory::test_factory (%s): caught %s\n",
+ f->name (), sig.name().c_str());
+ return false;
+ }
+ }
+ catch (...){
+ if (verbose){
+ fprintf (stderr, "....... %s: %s", f->name (), "Doesn't work\n");
+ fprintf (stderr,
+ "gr_vmcircbuf_factory::test_factory (%s): some kind of uncaught exception\n",
+ f->name ());
+ }
+ return false;
+ }
+ return false; // never gets here. shut compiler up.
+}
+
+bool
+gr_vmcircbuf_sysconfig::test_all_factories (int verbose)
+{
+ bool ok = false;
+
+ std::vector<gr_vmcircbuf_factory *> all = all_factories ();
+
+ for (unsigned int i = 0; i < all.size (); i++)
+ ok |= test_factory (all[i], verbose);
+
+ return ok;
+}
diff --git a/gnuradio-runtime/lib/gr_vmcircbuf.h b/gnuradio-runtime/lib/gr_vmcircbuf.h
new file mode 100644
index 0000000000..e7f492a8bd
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_vmcircbuf.h
@@ -0,0 +1,122 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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_VMCIRCBUF_H_
+#define _GR_VMCIRCBUF_H_
+
+#include <gr_runtime_api.h>
+#include <vector>
+
+/*!
+ * \brief abstract class to implement doubly mapped virtual memory circular buffers
+ * \ingroup internal
+ */
+class GR_RUNTIME_API gr_vmcircbuf {
+ protected:
+ int d_size;
+ char *d_base;
+
+ // CREATORS
+ gr_vmcircbuf (int size) : d_size (size), d_base (0) {};
+
+ public:
+ virtual ~gr_vmcircbuf ();
+
+ // ACCESSORS
+ void *pointer_to_first_copy () const { return d_base; }
+ void *pointer_to_second_copy () const { return d_base + d_size; }
+};
+
+/*!
+ * \brief abstract factory for creating circular buffers
+ */
+class GR_RUNTIME_API gr_vmcircbuf_factory {
+ protected:
+ gr_vmcircbuf_factory () {};
+ virtual ~gr_vmcircbuf_factory ();
+
+ public:
+
+ /*!
+ * \brief return name of this factory
+ */
+ virtual const char *name () const = 0;
+
+ /*!
+ * \brief return granularity of mapping, typically equal to page size
+ */
+ virtual int granularity () = 0;
+
+ /*!
+ * \brief return a gr_vmcircbuf, or 0 if unable.
+ *
+ * Call this to create a doubly mapped circular buffer.
+ */
+ virtual gr_vmcircbuf *make (int size) = 0;
+};
+
+/*
+ * \brief pulls together all implementations of gr_vmcircbuf
+ */
+class GR_RUNTIME_API gr_vmcircbuf_sysconfig {
+ public:
+
+ /*
+ * \brief return the single instance of the default factory.
+ *
+ * returns the default factory to use if it's already defined,
+ * else find the first working factory and use it.
+ */
+ static gr_vmcircbuf_factory *get_default_factory ();
+
+
+ static int granularity () { return get_default_factory()->granularity(); }
+ static gr_vmcircbuf *make (int size) { return get_default_factory()->make(size); }
+
+
+ // N.B. not all factories are guaranteed to work.
+ // It's too hard to check everything at config time, so we check at runtime
+ static std::vector<gr_vmcircbuf_factory *> all_factories ();
+
+ // make this factory the default
+ static void set_default_factory (gr_vmcircbuf_factory *f);
+
+ /*!
+ * \brief Does this factory really work?
+ *
+ * verbose = 0: silent
+ * verbose = 1: names of factories tested and results
+ * verbose = 2: all intermediate results
+ */
+ static bool test_factory (gr_vmcircbuf_factory *f, int verbose);
+
+ /*!
+ * \brief Test all factories, return true if at least one of them works
+ * verbose = 0: silent
+ * verbose = 1: names of factories tested and results
+ * verbose = 2: all intermediate results
+ */
+ static bool test_all_factories (int verbose);
+};
+
+
+#endif /* _GR_VMCIRCBUF_H_ */
diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_createfilemapping.cc b/gnuradio-runtime/lib/gr_vmcircbuf_createfilemapping.cc
new file mode 100644
index 0000000000..1b4d9700a5
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_vmcircbuf_createfilemapping.cc
@@ -0,0 +1,204 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2005,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdexcept>
+#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <errno.h>
+#include <stdio.h>
+#include <gr_pagesize.h>
+#include <gr_vmcircbuf_createfilemapping.h>
+#include <boost/format.hpp>
+
+#ifdef HAVE_CREATEFILEMAPPING
+// Print Windows error (could/should be global?)
+static void
+werror( char *where, DWORD last_error )
+{
+ char buf[1024];
+
+ FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ last_error,
+ 0, // default language
+ buf,
+ sizeof(buf)/sizeof(TCHAR), // buffer size
+ NULL );
+ fprintf( stderr, "%s: Error %d: %s", where, last_error, buf );
+ return;
+}
+#endif
+
+
+gr_vmcircbuf_createfilemapping::gr_vmcircbuf_createfilemapping (int size)
+ : gr_vmcircbuf (size)
+{
+#if !defined(HAVE_CREATEFILEMAPPING)
+ fprintf (stderr, "%s: createfilemapping is not available\n",__FUNCTION__);
+ throw std::runtime_error ("gr_vmcircbuf_createfilemapping");
+#else
+ static int s_seg_counter = 0;
+
+ if (size <= 0 || (size % gr_pagesize ()) != 0){
+ fprintf (stderr, "gr_vmcircbuf_createfilemapping: invalid size = %d\n", size);
+ throw std::runtime_error ("gr_vmcircbuf_createfilemapping");
+ }
+
+ std::string seg_name = str(boost::format("/gnuradio-%d-%d") % getpid () % s_seg_counter);
+
+ d_handle = CreateFileMapping(INVALID_HANDLE_VALUE, // use paging file
+ NULL, // default security
+ PAGE_READWRITE, // read/write access
+ 0, // max. object size
+ size, // buffer size
+ seg_name.c_str()); // name of mapping object
+
+ s_seg_counter++;
+ if (d_handle == NULL || d_handle == INVALID_HANDLE_VALUE){
+ std::string msg = str(boost::format(
+ "gr_vmcircbuf_mmap_createfilemapping: CreateFileMapping [%s]") %
+ seg_name );
+ werror((char *) msg.c_str(), GetLastError() );
+ throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping");
+ }
+
+ // Allocate virtual memory of the needed size, then free it so we can use it
+ LPVOID first_tmp;
+ first_tmp = VirtualAlloc( NULL, 2*size, MEM_RESERVE, PAGE_NOACCESS );
+ if (first_tmp == NULL){
+ werror( "gr_vmcircbuf_mmap_createfilemapping: VirtualAlloc", GetLastError());
+ CloseHandle(d_handle); // cleanup
+ throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping");
+ }
+
+ if (VirtualFree(first_tmp, 0, MEM_RELEASE) == 0){
+ werror( "gr_vmcircbuf_mmap_createfilemapping: VirtualFree", GetLastError());
+ CloseHandle(d_handle); // cleanup
+ throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping");
+ }
+
+ d_first_copy = MapViewOfFileEx((HANDLE)d_handle, // handle to map object
+ FILE_MAP_WRITE, // read/write permission
+ 0,
+ 0,
+ size,
+ first_tmp);
+ if (d_first_copy != first_tmp){
+ werror( "gr_vmcircbuf_mmap_createfilemapping: MapViewOfFileEx(1)", GetLastError());
+ CloseHandle(d_handle); // cleanup
+ throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping");
+ }
+
+ d_second_copy = MapViewOfFileEx((HANDLE)d_handle, // handle to map object
+ FILE_MAP_WRITE, // read/write permission
+ 0,
+ 0,
+ size,
+ (char *)first_tmp + size);//(LPVOID) ((char *)d_first_copy + size));
+
+ if (d_second_copy != (char *)first_tmp + size){
+ werror( "gr_vmcircbuf_mmap_createfilemapping: MapViewOfFileEx(2)", GetLastError());
+ UnmapViewOfFile(d_first_copy);
+ CloseHandle(d_handle); // cleanup
+ throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping");
+ }
+
+#ifdef DEBUG
+ fprintf (stderr,"gr_vmcircbuf_mmap_createfilemapping: contiguous? mmap %p %p %p %p\n",
+ (char *)d_first_copy, (char *)d_second_copy, size, (char *)d_first_copy + size);
+#endif
+
+ // Now remember the important stuff
+ d_base = (char *) d_first_copy;
+ d_size = size;
+#endif /*HAVE_CREATEFILEMAPPING*/
+}
+
+gr_vmcircbuf_createfilemapping::~gr_vmcircbuf_createfilemapping ()
+{
+#ifdef HAVE_CREATEFILEMAPPING
+ if (UnmapViewOfFile(d_first_copy) == 0)
+ {
+ werror("gr_vmcircbuf_createfilemapping: UnmapViewOfFile(d_first_copy)", GetLastError());
+ }
+ d_base=NULL;
+ if (UnmapViewOfFile(d_second_copy) == 0)
+ {
+ werror("gr_vmcircbuf_createfilemapping: UnmapViewOfFile(d_second_copy)", GetLastError());
+ }
+ //d_second=NULL;
+ CloseHandle(d_handle);
+#endif
+}
+
+// ----------------------------------------------------------------
+// The factory interface
+// ----------------------------------------------------------------
+
+
+gr_vmcircbuf_factory *gr_vmcircbuf_createfilemapping_factory::s_the_factory = 0;
+
+gr_vmcircbuf_factory *
+gr_vmcircbuf_createfilemapping_factory::singleton ()
+{
+ if (s_the_factory)
+ return s_the_factory;
+ s_the_factory = new gr_vmcircbuf_createfilemapping_factory ();
+ return s_the_factory;
+}
+
+int
+gr_vmcircbuf_createfilemapping_factory::granularity ()
+{
+#ifdef HAVE_CREATEFILEMAPPING
+ // return 65536;//TODO, check, is this needed or can we just use gr_pagesize()
+ SYSTEM_INFO system_info;
+ GetSystemInfo(&system_info);
+ //fprintf(stderr,"win32 AllocationGranularity %p\n",(int)system_info.dwAllocationGranularity);
+ return (int)system_info.dwAllocationGranularity;
+#else
+ return gr_pagesize ();
+#endif
+}
+
+gr_vmcircbuf *
+gr_vmcircbuf_createfilemapping_factory::make (int size)
+{
+ try
+ {
+ return new gr_vmcircbuf_createfilemapping (size);
+ }
+ catch (...)
+ {
+ return 0;
+ }
+}
diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_createfilemapping.h b/gnuradio-runtime/lib/gr_vmcircbuf_createfilemapping.h
new file mode 100644
index 0000000000..a4bb5cbe92
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_vmcircbuf_createfilemapping.h
@@ -0,0 +1,76 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,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.
+ */
+
+#ifndef _GR_VMCIRCBUF_CREATEFILEMAPPING_H_
+#define _GR_VMCIRCBUF_CREATEFILEMAPPING_H_
+
+#include <gr_runtime_api.h>
+#include <gr_vmcircbuf.h>
+
+#ifdef HAVE_CREATEFILEMAPPING
+#include <windows.h>
+#endif
+/*!
+ * \brief concrete class to implement circular buffers with mmap and shm_open
+ * \ingroup internal
+ */
+class GR_RUNTIME_API gr_vmcircbuf_createfilemapping : public gr_vmcircbuf
+{
+ public:
+ // CREATORS
+ gr_vmcircbuf_createfilemapping (int size);
+ virtual ~gr_vmcircbuf_createfilemapping ();
+#ifdef HAVE_CREATEFILEMAPPING
+ private:
+ HANDLE d_handle;
+ LPVOID d_first_copy;
+ LPVOID d_second_copy;
+#endif
+};
+
+/*!
+ * \brief concrete factory for circular buffers built using mmap and shm_open
+ */
+class GR_RUNTIME_API gr_vmcircbuf_createfilemapping_factory : public gr_vmcircbuf_factory
+{
+ private:
+ static gr_vmcircbuf_factory *s_the_factory;
+
+ public:
+ static gr_vmcircbuf_factory *singleton ();
+
+ virtual const char *name () const { return "gr_vmcircbuf_createfilemapping_factory"; }
+
+ /*!
+ * \brief return granularity of mapping, typically equal to page size
+ */
+ virtual int granularity ();
+
+ /*!
+ * \brief return a gr_vmcircbuf, or 0 if unable.
+ *
+ * Call this to create a doubly mapped circular buffer.
+ */
+ virtual gr_vmcircbuf *make (int size);
+};
+
+#endif /* _GR_VMCIRCBUF_CREATEFILEMAPPING_H_ */
diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_mmap_shm_open.cc b/gnuradio-runtime/lib/gr_vmcircbuf_mmap_shm_open.cc
new file mode 100644
index 0000000000..3d170081d0
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_vmcircbuf_mmap_shm_open.cc
@@ -0,0 +1,205 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <gr_vmcircbuf_mmap_shm_open.h>
+#include <stdexcept>
+#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <errno.h>
+#include <stdio.h>
+#include <gr_pagesize.h>
+#include <gr_sys_paths.h>
+
+
+gr_vmcircbuf_mmap_shm_open::gr_vmcircbuf_mmap_shm_open (int size)
+ : gr_vmcircbuf (size)
+{
+#if !defined(HAVE_MMAP) || !defined(HAVE_SHM_OPEN)
+ fprintf (stderr, "gr_vmcircbuf_mmap_shm_open: mmap or shm_open is not available\n");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open");
+#else
+ static int s_seg_counter = 0;
+
+ if (size <= 0 || (size % gr_pagesize ()) != 0){
+ fprintf (stderr, "gr_vmcircbuf_mmap_shm_open: invalid size = %d\n", size);
+ throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open");
+ }
+
+ int shm_fd = -1;
+ char seg_name[1024];
+ static bool portable_format = true;
+
+ // open a new named shared memory segment
+
+ while (1){
+ if (portable_format){
+
+ // This is the POSIX recommended "portable format".
+ // Of course the "portable format" doesn't work on some systems...
+
+ snprintf (seg_name, sizeof (seg_name),
+ "/gnuradio-%d-%d", getpid (), s_seg_counter);
+ }
+ else {
+
+ // Where the "portable format" doesn't work, we try building
+ // a full filesystem pathname pointing into a suitable temporary directory.
+
+ snprintf (seg_name, sizeof (seg_name),
+ "%s/gnuradio-%d-%d", gr_tmp_path (), getpid (), s_seg_counter);
+ }
+
+ shm_fd = shm_open (seg_name, O_RDWR | O_CREAT | O_EXCL, 0600);
+ if (shm_fd == -1 && errno == EACCES && portable_format){
+ portable_format = false;
+ continue; // try again using "non-portable format"
+ }
+
+ s_seg_counter++;
+
+ if (shm_fd == -1){
+ if (errno == EEXIST) // Named segment already exists (shouldn't happen). Try again
+ continue;
+
+ char msg[1024];
+ snprintf (msg, sizeof (msg), "gr_vmcircbuf_mmap_shm_open: shm_open [%s]", seg_name);
+ perror (msg);
+ throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open");
+ }
+ break;
+ }
+
+ // We've got a new shared memory segment fd open.
+ // Now set it's length to 2x what we really want and mmap it in.
+
+ if (ftruncate (shm_fd, (off_t) 2 * size) == -1){
+ close (shm_fd); // cleanup
+ perror ("gr_vmcircbuf_mmap_shm_open: ftruncate (1)");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open");
+ }
+
+ void *first_copy = mmap (0, 2 * size,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ shm_fd, (off_t) 0);
+
+ if (first_copy == MAP_FAILED){
+ close (shm_fd); // cleanup
+ perror ("gr_vmcircbuf_mmap_shm_open: mmap (1)");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open");
+ }
+
+ // unmap the 2nd half
+ if (munmap ((char *) first_copy + size, size) == -1){
+ close (shm_fd); // cleanup
+ perror ("gr_vmcircbuf_mmap_shm_open: munmap (1)");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open");
+ }
+
+ // map the first half into the now available hole where the
+ // second half used to be.
+
+ void *second_copy = mmap ((char *) first_copy + size, size,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ shm_fd, (off_t) 0);
+
+ if (second_copy == MAP_FAILED){
+ close (shm_fd); // cleanup
+ perror ("gr_vmcircbuf_mmap_shm_open: mmap (2)");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open");
+ }
+
+#if 0 // OS/X doesn't allow you to resize the segment
+
+ // cut the shared memory segment down to size
+ if (ftruncate (shm_fd, (off_t) size) == -1){
+ close (shm_fd); // cleanup
+ perror ("gr_vmcircbuf_mmap_shm_open: ftruncate (2)");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open");
+ }
+#endif
+
+ close (shm_fd); // fd no longer needed. The mapping is retained.
+
+ if (shm_unlink (seg_name) == -1){ // unlink the seg_name.
+ perror ("gr_vmcircbuf_mmap_shm_open: shm_unlink");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open");
+ }
+
+ // Now remember the important stuff
+
+ d_base = (char *) first_copy;
+ d_size = size;
+#endif
+}
+
+gr_vmcircbuf_mmap_shm_open::~gr_vmcircbuf_mmap_shm_open ()
+{
+#if defined(HAVE_MMAP)
+ if (munmap (d_base, 2 * d_size) == -1){
+ perror ("gr_vmcircbuf_mmap_shm_open: munmap (2)");
+ }
+#endif
+}
+
+// ----------------------------------------------------------------
+// The factory interface
+// ----------------------------------------------------------------
+
+
+gr_vmcircbuf_factory *gr_vmcircbuf_mmap_shm_open_factory::s_the_factory = 0;
+
+gr_vmcircbuf_factory *
+gr_vmcircbuf_mmap_shm_open_factory::singleton ()
+{
+ if (s_the_factory)
+ return s_the_factory;
+
+ s_the_factory = new gr_vmcircbuf_mmap_shm_open_factory ();
+ return s_the_factory;
+}
+
+int
+gr_vmcircbuf_mmap_shm_open_factory::granularity ()
+{
+ return gr_pagesize ();
+}
+
+gr_vmcircbuf *
+gr_vmcircbuf_mmap_shm_open_factory::make (int size)
+{
+ try {
+ return new gr_vmcircbuf_mmap_shm_open (size);
+ }
+ catch (...){
+ return 0;
+ }
+}
diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_mmap_shm_open.h b/gnuradio-runtime/lib/gr_vmcircbuf_mmap_shm_open.h
new file mode 100644
index 0000000000..d35df80839
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_vmcircbuf_mmap_shm_open.h
@@ -0,0 +1,67 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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_VMCIRCBUF_MMAP_SHM_OPEN_H_
+#define _GR_VMCIRCBUF_MMAP_SHM_OPEN_H_
+
+#include <gr_runtime_api.h>
+#include <gr_vmcircbuf.h>
+
+/*!
+ * \brief concrete class to implement circular buffers with mmap and shm_open
+ * \ingroup internal
+ */
+class GR_RUNTIME_API gr_vmcircbuf_mmap_shm_open : public gr_vmcircbuf {
+ public:
+
+ // CREATORS
+
+ gr_vmcircbuf_mmap_shm_open (int size);
+ virtual ~gr_vmcircbuf_mmap_shm_open ();
+};
+
+/*!
+ * \brief concrete factory for circular buffers built using mmap and shm_open
+ */
+class GR_RUNTIME_API gr_vmcircbuf_mmap_shm_open_factory : public gr_vmcircbuf_factory {
+ private:
+ static gr_vmcircbuf_factory *s_the_factory;
+
+ public:
+ static gr_vmcircbuf_factory *singleton ();
+
+ virtual const char *name () const { return "gr_vmcircbuf_mmap_shm_open_factory"; }
+
+ /*!
+ * \brief return granularity of mapping, typically equal to page size
+ */
+ virtual int granularity ();
+
+ /*!
+ * \brief return a gr_vmcircbuf, or 0 if unable.
+ *
+ * Call this to create a doubly mapped circular buffer.
+ */
+ virtual gr_vmcircbuf *make (int size);
+};
+
+#endif /* _GR_VMCIRCBUF_MMAP_SHM_OPEN_H_ */
diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_mmap_tmpfile.cc b/gnuradio-runtime/lib/gr_vmcircbuf_mmap_tmpfile.cc
new file mode 100644
index 0000000000..35de64699e
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_vmcircbuf_mmap_tmpfile.cc
@@ -0,0 +1,197 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <gr_vmcircbuf_mmap_tmpfile.h>
+#include <stdexcept>
+#include <assert.h>
+#include <unistd.h>
+#include <stdlib.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <gr_pagesize.h>
+#include <gr_sys_paths.h>
+
+gr_vmcircbuf_mmap_tmpfile::gr_vmcircbuf_mmap_tmpfile (int size)
+ : gr_vmcircbuf (size)
+{
+#if !defined(HAVE_MMAP)
+ fprintf (stderr, "gr_vmcircbuf_mmap_tmpfile: mmap or mkstemp is not available\n");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
+#else
+
+ if (size <= 0 || (size % gr_pagesize ()) != 0){
+ fprintf (stderr, "gr_vmcircbuf_mmap_tmpfile: invalid size = %d\n", size);
+ throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
+ }
+
+ int seg_fd = -1;
+ char seg_name[1024];
+
+ static int s_seg_counter = 0;
+
+
+ // open a temporary file that we'll map in a bit later
+
+ while (1){
+ snprintf (seg_name, sizeof (seg_name),
+ "%s/gnuradio-%d-%d-XXXXXX", gr_tmp_path (), getpid (), s_seg_counter);
+ s_seg_counter++;
+
+ seg_fd = open (seg_name, O_RDWR | O_CREAT | O_EXCL, 0600);
+ if (seg_fd == -1){
+ if (errno == EEXIST) // File already exists (shouldn't happen). Try again
+ continue;
+
+ char msg[1024];
+ snprintf (msg, sizeof (msg),
+ "gr_vmcircbuf_mmap_tmpfile: open [%s]", seg_name);
+ perror (msg);
+ throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
+ }
+ break;
+ }
+
+ if (unlink (seg_name) == -1){
+ perror ("gr_vmcircbuf_mmap_tmpfile: unlink");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
+ }
+
+ // We've got a valid file descriptor to a tmp file.
+ // Now set it's length to 2x what we really want and mmap it in.
+
+ if (ftruncate (seg_fd, (off_t) 2 * size) == -1){
+ close (seg_fd); // cleanup
+ perror ("gr_vmcircbuf_mmap_tmpfile: ftruncate (1)");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
+ }
+
+ void *first_copy = mmap (0, 2 * size,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ seg_fd, (off_t) 0);
+
+ if (first_copy == MAP_FAILED){
+ close (seg_fd); // cleanup
+ perror ("gr_vmcircbuf_mmap_tmpfile: mmap (1)");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
+ }
+
+ // unmap the 2nd half
+ if (munmap ((char *) first_copy + size, size) == -1){
+ close (seg_fd); // cleanup
+ perror ("gr_vmcircbuf_mmap_tmpfile: munmap (1)");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
+ }
+
+ // map the first half into the now available hole where the
+ // second half used to be.
+
+ void *second_copy = mmap ((char *) first_copy + size, size,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ seg_fd, (off_t) 0);
+
+ if (second_copy == MAP_FAILED){
+ munmap(first_copy, size); // cleanup
+ close (seg_fd);
+ perror ("gr_vmcircbuf_mmap_tmpfile: mmap (2)");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
+ }
+
+ // check for contiguity
+ if ((char *) second_copy != (char *) first_copy + size){
+ munmap(first_copy, size); // cleanup
+ munmap(second_copy, size);
+ close (seg_fd);
+ perror ("gr_vmcircbuf_mmap_tmpfile: non-contiguous second copy");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
+ }
+
+ // cut the tmp file down to size
+ if (ftruncate (seg_fd, (off_t) size) == -1){
+ munmap(first_copy, size); // cleanup
+ munmap(second_copy, size);
+ close (seg_fd);
+ perror ("gr_vmcircbuf_mmap_tmpfile: ftruncate (2)");
+ throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile");
+ }
+
+ close (seg_fd); // fd no longer needed. The mapping is retained.
+
+ // Now remember the important stuff
+
+ d_base = (char *) first_copy;
+ d_size = size;
+#endif
+}
+
+gr_vmcircbuf_mmap_tmpfile::~gr_vmcircbuf_mmap_tmpfile ()
+{
+#if defined(HAVE_MMAP)
+ if (munmap (d_base, 2 * d_size) == -1){
+ perror ("gr_vmcircbuf_mmap_tmpfile: munmap (2)");
+ }
+#endif
+}
+
+// ----------------------------------------------------------------
+// The factory interface
+// ----------------------------------------------------------------
+
+
+gr_vmcircbuf_factory *gr_vmcircbuf_mmap_tmpfile_factory::s_the_factory = 0;
+
+gr_vmcircbuf_factory *
+gr_vmcircbuf_mmap_tmpfile_factory::singleton ()
+{
+ if (s_the_factory)
+ return s_the_factory;
+
+ s_the_factory = new gr_vmcircbuf_mmap_tmpfile_factory ();
+ return s_the_factory;
+}
+
+int
+gr_vmcircbuf_mmap_tmpfile_factory::granularity ()
+{
+ return gr_pagesize ();
+}
+
+gr_vmcircbuf *
+gr_vmcircbuf_mmap_tmpfile_factory::make (int size)
+{
+ try {
+ return new gr_vmcircbuf_mmap_tmpfile (size);
+ }
+ catch (...){
+ return 0;
+ }
+}
diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_mmap_tmpfile.h b/gnuradio-runtime/lib/gr_vmcircbuf_mmap_tmpfile.h
new file mode 100644
index 0000000000..cd865734f2
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_vmcircbuf_mmap_tmpfile.h
@@ -0,0 +1,67 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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_VMCIRCBUF_MMAP_TMPFILE_H_
+#define _GR_VMCIRCBUF_MMAP_TMPFILE_H_
+
+#include <gr_runtime_api.h>
+#include <gr_vmcircbuf.h>
+
+/*!
+ * \brief concrete class to implement circular buffers with mmap and shm_open
+ * \ingroup internal
+ */
+class GR_RUNTIME_API gr_vmcircbuf_mmap_tmpfile : public gr_vmcircbuf {
+ public:
+
+ // CREATORS
+
+ gr_vmcircbuf_mmap_tmpfile (int size);
+ virtual ~gr_vmcircbuf_mmap_tmpfile ();
+};
+
+/*!
+ * \brief concrete factory for circular buffers built using mmap and shm_open
+ */
+class GR_RUNTIME_API gr_vmcircbuf_mmap_tmpfile_factory : public gr_vmcircbuf_factory {
+ private:
+ static gr_vmcircbuf_factory *s_the_factory;
+
+ public:
+ static gr_vmcircbuf_factory *singleton ();
+
+ virtual const char *name () const { return "gr_vmcircbuf_mmap_tmpfile_factory"; }
+
+ /*!
+ * \brief return granularity of mapping, typically equal to page size
+ */
+ virtual int granularity ();
+
+ /*!
+ * \brief return a gr_vmcircbuf, or 0 if unable.
+ *
+ * Call this to create a doubly mapped circular buffer.
+ */
+ virtual gr_vmcircbuf *make (int size);
+};
+
+#endif /* _GR_VMCIRCBUF_MMAP_TMPFILE_H_ */
diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_sysv_shm.cc b/gnuradio-runtime/lib/gr_vmcircbuf_sysv_shm.cc
new file mode 100644
index 0000000000..d9cf75e70f
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_vmcircbuf_sysv_shm.cc
@@ -0,0 +1,194 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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_vmcircbuf_sysv_shm.h>
+#include <stdexcept>
+#include <assert.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#ifdef HAVE_SYS_IPC_H
+#include <sys/ipc.h>
+#endif
+#ifdef HAVE_SYS_SHM_H
+#include <sys/shm.h>
+#endif
+#include <errno.h>
+#include <stdio.h>
+#include <gr_pagesize.h>
+
+
+gr_vmcircbuf_sysv_shm::gr_vmcircbuf_sysv_shm (int size)
+ : gr_vmcircbuf (size)
+{
+#if !defined(HAVE_SYS_SHM_H)
+ fprintf (stderr, "gr_vmcircbuf_sysv_shm: sysv shared memory is not available\n");
+ throw std::runtime_error ("gr_vmcircbuf_sysv_shm");
+#else
+
+ int pagesize = gr_pagesize();
+
+ if (size <= 0 || (size % pagesize) != 0){
+ fprintf (stderr, "gr_vmcircbuf_sysv_shm: invalid size = %d\n", size);
+ throw std::runtime_error ("gr_vmcircbuf_sysv_shm");
+ }
+
+ int shmid_guard = -1;
+ int shmid1 = -1;
+ int shmid2 = -1;
+
+ // We use this as a guard page. We'll map it read-only on both ends of the buffer.
+ // Ideally we'd map it no access, but I don't think that's possible with SysV
+ if ((shmid_guard = shmget (IPC_PRIVATE, pagesize, IPC_CREAT | 0400)) == -1){
+ perror ("gr_vmcircbuf_sysv_shm: shmget (0)");
+ throw std::runtime_error ("gr_vmcircbuf_sysv_shm");
+ }
+
+ if ((shmid2 = shmget (IPC_PRIVATE, 2 * size + 2 * pagesize, IPC_CREAT | 0700)) == -1){
+ perror ("gr_vmcircbuf_sysv_shm: shmget (1)");
+ shmctl (shmid_guard, IPC_RMID, 0);
+ throw std::runtime_error ("gr_vmcircbuf_sysv_shm");
+ }
+
+ if ((shmid1 = shmget (IPC_PRIVATE, size, IPC_CREAT | 0700)) == -1){
+ perror ("gr_vmcircbuf_sysv_shm: shmget (2)");
+ shmctl (shmid_guard, IPC_RMID, 0);
+ shmctl (shmid2, IPC_RMID, 0);
+ throw std::runtime_error ("gr_vmcircbuf_sysv_shm");
+ }
+
+ void *first_copy = shmat (shmid2, 0, 0);
+ if (first_copy == (void *) -1){
+ perror ("gr_vmcircbuf_sysv_shm: shmat (1)");
+ shmctl (shmid_guard, IPC_RMID, 0);
+ shmctl (shmid2, IPC_RMID, 0);
+ shmctl (shmid1, IPC_RMID, 0);
+ throw std::runtime_error ("gr_vmcircbuf_sysv_shm");
+ }
+
+ shmctl (shmid2, IPC_RMID, 0);
+
+ // There may be a race between our detach and attach.
+ //
+ // If the system allocates all shared memory segments at the same
+ // virtual addresses in all processes and if the system allocates
+ // some other segment to first_copy or first_copoy + size between
+ // our detach and attach, the attaches below could fail [I've never
+ // seen it fail for this reason].
+
+ shmdt (first_copy);
+
+ // first read-only guard page
+ if (shmat (shmid_guard, first_copy, SHM_RDONLY) == (void *) -1){
+ perror ("gr_vmcircbuf_sysv_shm: shmat (2)");
+ shmctl (shmid_guard, IPC_RMID, 0);
+ shmctl (shmid1, IPC_RMID, 0);
+ throw std::runtime_error ("gr_vmcircbuf_sysv_shm");
+ }
+
+ // first copy
+ if (shmat (shmid1, (char *) first_copy + pagesize, 0) == (void *) -1){
+ perror ("gr_vmcircbuf_sysv_shm: shmat (3)");
+ shmctl (shmid_guard, IPC_RMID, 0);
+ shmctl (shmid1, IPC_RMID, 0);
+ shmdt (first_copy);
+ throw std::runtime_error ("gr_vmcircbuf_sysv_shm");
+ }
+
+ // second copy
+ if (shmat (shmid1, (char *) first_copy + pagesize + size, 0) == (void *) -1){
+ perror ("gr_vmcircbuf_sysv_shm: shmat (4)");
+ shmctl (shmid_guard, IPC_RMID, 0);
+ shmctl (shmid1, IPC_RMID, 0);
+ shmdt ((char *)first_copy + pagesize);
+ throw std::runtime_error ("gr_vmcircbuf_sysv_shm");
+ }
+
+ // second read-only guard page
+ if (shmat (shmid_guard, (char *) first_copy + pagesize + 2 * size, SHM_RDONLY) == (void *) -1){
+ perror ("gr_vmcircbuf_sysv_shm: shmat (5)");
+ shmctl (shmid_guard, IPC_RMID, 0);
+ shmctl (shmid1, IPC_RMID, 0);
+ shmdt (first_copy);
+ shmdt ((char *)first_copy + pagesize);
+ shmdt ((char *)first_copy + pagesize + size);
+ throw std::runtime_error ("gr_vmcircbuf_sysv_shm");
+ }
+
+ shmctl (shmid1, IPC_RMID, 0);
+ shmctl (shmid_guard, IPC_RMID, 0);
+
+ // Now remember the important stuff
+
+ d_base = (char *) first_copy + pagesize;
+ d_size = size;
+#endif
+}
+
+gr_vmcircbuf_sysv_shm::~gr_vmcircbuf_sysv_shm ()
+{
+#if defined(HAVE_SYS_SHM_H)
+ if (shmdt (d_base - gr_pagesize()) == -1
+ || shmdt (d_base) == -1
+ || shmdt (d_base + d_size) == -1
+ || shmdt (d_base + 2 * d_size) == -1){
+ perror ("gr_vmcircbuf_sysv_shm: shmdt (2)");
+ }
+#endif
+}
+
+// ----------------------------------------------------------------
+// The factory interface
+// ----------------------------------------------------------------
+
+
+gr_vmcircbuf_factory *gr_vmcircbuf_sysv_shm_factory::s_the_factory = 0;
+
+gr_vmcircbuf_factory *
+gr_vmcircbuf_sysv_shm_factory::singleton ()
+{
+ if (s_the_factory)
+ return s_the_factory;
+
+ s_the_factory = new gr_vmcircbuf_sysv_shm_factory ();
+ return s_the_factory;
+}
+
+int
+gr_vmcircbuf_sysv_shm_factory::granularity ()
+{
+ return gr_pagesize ();
+}
+
+gr_vmcircbuf *
+gr_vmcircbuf_sysv_shm_factory::make (int size)
+{
+ try {
+ return new gr_vmcircbuf_sysv_shm (size);
+ }
+ catch (...){
+ return 0;
+ }
+}
diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_sysv_shm.h b/gnuradio-runtime/lib/gr_vmcircbuf_sysv_shm.h
new file mode 100644
index 0000000000..abebd93f1c
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_vmcircbuf_sysv_shm.h
@@ -0,0 +1,67 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 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_VMCIRCBUF_SYSV_SHM_H_
+#define _GR_VMCIRCBUF_SYSV_SHM_H_
+
+#include <gr_runtime_api.h>
+#include <gr_vmcircbuf.h>
+
+/*!
+ * \brief concrete class to implement circular buffers with mmap and shm_open
+ * \ingroup internal
+ */
+class GR_RUNTIME_API gr_vmcircbuf_sysv_shm : public gr_vmcircbuf {
+ public:
+
+ // CREATORS
+
+ gr_vmcircbuf_sysv_shm (int size);
+ virtual ~gr_vmcircbuf_sysv_shm ();
+};
+
+/*!
+ * \brief concrete factory for circular buffers built using mmap and shm_open
+ */
+class GR_RUNTIME_API gr_vmcircbuf_sysv_shm_factory : public gr_vmcircbuf_factory {
+ private:
+ static gr_vmcircbuf_factory *s_the_factory;
+
+ public:
+ static gr_vmcircbuf_factory *singleton ();
+
+ virtual const char *name () const { return "gr_vmcircbuf_sysv_shm_factory"; }
+
+ /*!
+ * \brief return granularity of mapping, typically equal to page size
+ */
+ virtual int granularity ();
+
+ /*!
+ * \brief return a gr_vmcircbuf, or 0 if unable.
+ *
+ * Call this to create a doubly mapped circular buffer.
+ */
+ virtual gr_vmcircbuf *make (int size);
+};
+
+#endif /* _GR_VMCIRCBUF_SYSV_SHM_H_ */
diff --git a/gnuradio-runtime/lib/gri_debugger_hook.cc b/gnuradio-runtime/lib/gri_debugger_hook.cc
new file mode 100644
index 0000000000..d9270c435f
--- /dev/null
+++ b/gnuradio-runtime/lib/gri_debugger_hook.cc
@@ -0,0 +1,29 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gri_debugger_hook.h>
+
+void
+gri_debugger_hook ()
+{
+ // nop. set a breakpoint here
+}
diff --git a/gnuradio-runtime/lib/gri_debugger_hook.h b/gnuradio-runtime/lib/gri_debugger_hook.h
new file mode 100644
index 0000000000..6d31ed1b2c
--- /dev/null
+++ b/gnuradio-runtime/lib/gri_debugger_hook.h
@@ -0,0 +1,30 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GRI_DEBUGGER_HOOK_H
+#define INCLUDED_GRI_DEBUGGER_HOOK_H
+
+#include <gr_runtime_api.h>
+
+GR_RUNTIME_API void gri_debugger_hook ();
+
+#endif /* INCLUDED_GRI_DEBUGGER_HOOK_H */ \ No newline at end of file
diff --git a/gnuradio-runtime/lib/ice_application_base.cc b/gnuradio-runtime/lib/ice_application_base.cc
new file mode 100644
index 0000000000..88db6056c1
--- /dev/null
+++ b/gnuradio-runtime/lib/ice_application_base.cc
@@ -0,0 +1,43 @@
+/* -*- 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.
+ */
+
+#include <ice_application_base.h>
+
+int ice_application_common::d_reacquire_attributes(0);
+bool ice_application_common::d_main_called(false);
+bool ice_application_common::d_have_ice_config(false);
+boost::shared_ptr<boost::thread> ice_application_common::d_thread;
+std::string ice_application_common::d_endpointStr("");
+
+boost::shared_ptr<ice_application_common>
+ice_application_common::Instance()
+{
+ static boost::shared_ptr<ice_application_common>
+ instance(new ice_application_common());
+ return instance;
+}
+
+int ice_application_common::run(int, char**)
+{
+ communicator()->waitForShutdown();
+ return EXIT_SUCCESS;
+}
diff --git a/gnuradio-runtime/lib/malloc16.c b/gnuradio-runtime/lib/malloc16.c
new file mode 100644
index 0000000000..2cc6135e77
--- /dev/null
+++ b/gnuradio-runtime/lib/malloc16.c
@@ -0,0 +1,46 @@
+/* Wrapper functions for malloc/free that force 16-byte alignment
+ * See http://perso.club-internet.fr/matmac/sourcesc.htm
+
+ * Copyright 2001 Phil Karn, KA9Q
+ * May be used under the terms of the GNU Public License (GPL)
+ */
+
+#include "malloc16.h"
+#include <string.h>
+
+void *malloc16Align(int size){
+ void *p;
+ void **p1;
+
+ if((p = malloc(size+31)) == NULL)
+ return NULL;
+
+ /* Round up to next 16-byte boundary */
+ p1 = (void **)(((long)p + 31) & (~15));
+
+ /* Stash actual start of block just before ptr we return */
+ p1[-1] = p;
+
+ /* Return 16-byte aligned address */
+ return (void *)p1;
+}
+
+void *calloc16Align(size_t nmemb,size_t size){
+ int nbytes;
+ void *p;
+
+ nbytes = nmemb*size;
+ if((p = malloc16Align(nbytes)) == NULL)
+ return NULL;
+
+ memset(p,0,nbytes);
+ return p;
+}
+
+void free16Align(void *p){
+
+ if(p != NULL){
+ /* Retrieve pointer to actual start of block and free it */
+ free(((void **)p)[-1]);
+ }
+}
diff --git a/gnuradio-runtime/lib/malloc16.h b/gnuradio-runtime/lib/malloc16.h
new file mode 100644
index 0000000000..90d1eca77a
--- /dev/null
+++ b/gnuradio-runtime/lib/malloc16.h
@@ -0,0 +1,37 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002 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_runtime_api.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+
+GR_RUNTIME_API void *malloc16Align(int size);
+GR_RUNTIME_API void *calloc16Align(size_t nmemb,size_t size);
+GR_RUNTIME_API void free16Align(void *p);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gnuradio-runtime/lib/posix_memalign.cc b/gnuradio-runtime/lib/posix_memalign.cc
new file mode 100644
index 0000000000..aaeff78042
--- /dev/null
+++ b/gnuradio-runtime/lib/posix_memalign.cc
@@ -0,0 +1,114 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008,2009 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 "posix_memalign.h"
+
+#ifdef HAVE_MALLOC_H
+// for Cygwin valloc () prototype
+#include <malloc.h>
+#endif
+
+#ifndef HAVE_POSIX_MEMALIGN
+
+/* emulate posix_memalign functionality, to some degree */
+
+#include <errno.h>
+#include "gr_pagesize.h"
+
+int posix_memalign
+(void **memptr, size_t alignment, size_t size)
+{
+ /* emulate posix_memalign functionality, to some degree */
+
+ /* make sure the return handle is valid; return "bad address" if not valid */
+ if (memptr == 0)
+ return (EFAULT);
+ *memptr = (void*) 0;
+
+ /* make sure 'alignment' is a power of 2
+ * and multiple of sizeof (void*)
+ */
+
+ /* make sure 'alignment' is a multiple of sizeof (void*) */
+ if ((alignment % sizeof (void*)) != 0)
+ return (EINVAL);
+
+ /* make sure 'alignment' is a power of 2 */
+ if ((alignment & (alignment - 1)) != 0)
+ return (EINVAL);
+
+ /* good alignment */
+
+#if (ALIGNED_MALLOC != 0)
+
+ /* if 'malloc' is known to be aligned, and the desired 'alignment'
+ * matches is <= that provided by 'malloc', then use 'malloc'. This
+ * works on, e.g., Darwin 8 & 9: for which malloc is 16-byte aligned.
+ */
+ size_t am = (size_t) ALIGNED_MALLOC;
+ if (alignment <= am) {
+ /* make sure ALIGNED_MALLOC is a power of 2, to guarantee that the
+ * alignment is correct (since 'alignment' must be a power of 2).
+ */
+ if ((am & (am - 1)) != 0)
+ return (EINVAL);
+ /* good malloc alignment */
+ *memptr = malloc (size);
+ }
+
+#endif /* (ALIGNED_MALLOC != 0) */
+#ifdef HAVE_VALLOC
+
+ if (*memptr == (void*) 0) {
+ /* try valloc if it exists */
+ /* cheap and easy way to make sure alignment is met, so long as it
+ * is <= pagesize () */
+ if (alignment <= (size_t) gr_pagesize ()) {
+ *memptr = valloc (size);
+ }
+ }
+
+#endif /* HAVE_VALLOC */
+
+#if (ALIGNED_MALLOC == 0) && !defined (HAVE_VALLOC)
+ /* no posix_memalign, valloc, and malloc isn't known to be aligned
+ * (enough for the input arguments); no idea what to do.
+ */
+
+#error gnuradio-core/src/libmissing/posix_memalign.cc: Cannot find a way to alloc aligned memory.
+
+#endif
+
+ /* if the pointer wasn't allocated properly, return that there was
+ * not enough memory to allocate; otherwise, return OK (0).
+ */
+ if (*memptr == (void*) 0)
+ return (ENOMEM);
+ else
+ return (0);
+};
+
+#endif /* ! HAVE_POSIX_MEMALIGN */
diff --git a/gnuradio-runtime/lib/posix_memalign.h b/gnuradio-runtime/lib/posix_memalign.h
new file mode 100644
index 0000000000..ea79ced2ef
--- /dev/null
+++ b/gnuradio-runtime/lib/posix_memalign.h
@@ -0,0 +1,42 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 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 _POSIX_MEMALIGN_H_
+#define _POSIX_MEMALIGN_H_
+
+#include <stdlib.h>
+
+#ifndef HAVE_POSIX_MEMALIGN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int posix_memalign (void** memptr, size_t alignment, size_t size);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* ! HAVE_POSIX_MEMALIGN */
+
+#endif /* _POSIX_MEMALIGN_H_ */
diff --git a/gnuradio-runtime/lib/qa_gr_buffer.cc b/gnuradio-runtime/lib/qa_gr_buffer.cc
new file mode 100644
index 0000000000..c74baf398e
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_buffer.cc
@@ -0,0 +1,307 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <qa_gr_buffer.h>
+#include <gr_buffer.h>
+#include <cppunit/TestAssert.h>
+#include <stdlib.h>
+#include <gr_random.h>
+
+static void
+leak_check (void f ())
+{
+ long buffer_count = gr_buffer_ncurrently_allocated ();
+ long buffer_reader_count = gr_buffer_reader_ncurrently_allocated ();
+
+ f ();
+
+ CPPUNIT_ASSERT_EQUAL (buffer_reader_count, gr_buffer_reader_ncurrently_allocated ());
+ CPPUNIT_ASSERT_EQUAL (buffer_count, gr_buffer_ncurrently_allocated ());
+}
+
+
+// ----------------------------------------------------------------------------
+// test single writer, no readers...
+//
+
+static void
+t0_body ()
+{
+ int nitems = 4000 / sizeof (int);
+ int counter = 0;
+
+ gr_buffer_sptr buf(gr_make_buffer(nitems, sizeof (int), gr_block_sptr()));
+
+ int last_sa;
+ int sa;
+
+ sa = buf->space_available ();
+ CPPUNIT_ASSERT (sa > 0);
+ last_sa = sa;
+
+ for (int i = 0; i < 5; i++){
+ sa = buf->space_available ();
+ CPPUNIT_ASSERT_EQUAL (last_sa, sa);
+ last_sa = sa;
+
+ int *p = (int *) buf->write_pointer ();
+ CPPUNIT_ASSERT (p != 0);
+
+ for (int j = 0; j < sa; j++)
+ *p++ = counter++;
+
+ buf->update_write_pointer (sa);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// test single writer, single reader
+//
+
+static void
+t1_body ()
+ {
+ int nitems = 4000 / sizeof (int);
+ int write_counter = 0;
+ int read_counter = 0;
+
+ gr_buffer_sptr buf(gr_make_buffer(nitems, sizeof (int), gr_block_sptr()));
+ gr_buffer_reader_sptr r1 (gr_buffer_add_reader (buf, 0, gr_block_sptr()));
+
+
+ int sa;
+
+ // write 1/3 of buffer
+
+ sa = buf->space_available ();
+ CPPUNIT_ASSERT (sa > 0);
+
+ int *p = (int *) buf->write_pointer ();
+ CPPUNIT_ASSERT (p != 0);
+
+ for (int j = 0; j < sa/3; j++){
+ *p++ = write_counter++;
+ }
+ buf->update_write_pointer (sa/3);
+
+
+ // write the next 1/3 (1/2 of what's left)
+
+ sa = buf->space_available ();
+ CPPUNIT_ASSERT (sa > 0);
+
+ p = (int *) buf->write_pointer ();
+ CPPUNIT_ASSERT (p != 0);
+
+ for (int j = 0; j < sa/2; j++){
+ *p++ = write_counter++;
+ }
+ buf->update_write_pointer (sa/2);
+
+
+ // check that we can read it OK
+
+ int ia = r1->items_available ();
+ CPPUNIT_ASSERT_EQUAL (write_counter, ia);
+
+ int *rp = (int *) r1->read_pointer ();
+ CPPUNIT_ASSERT (rp != 0);
+
+ for (int i = 0; i < ia/2; i++){
+ CPPUNIT_ASSERT_EQUAL (read_counter, *rp);
+ read_counter++;
+ rp++;
+ }
+ r1->update_read_pointer (ia/2);
+
+ // read the rest
+
+ ia = r1->items_available ();
+ rp = (int *) r1->read_pointer ();
+ CPPUNIT_ASSERT (rp != 0);
+
+ for (int i = 0; i < ia; i++){
+ CPPUNIT_ASSERT_EQUAL (read_counter, *rp);
+ read_counter++;
+ rp++;
+ }
+ r1->update_read_pointer (ia);
+}
+
+// ----------------------------------------------------------------------------
+// single writer, single reader: check wrap-around
+//
+
+static void
+t2_body ()
+{
+ // 64K is the largest granularity we've seen so far (MS windows file mapping).
+ // This allows a bit of "white box testing"
+
+ int nitems = (64 * (1L << 10)) / sizeof (int); // 64K worth of ints
+
+ gr_buffer_sptr buf(gr_make_buffer (nitems, sizeof (int), gr_block_sptr()));
+ gr_buffer_reader_sptr r1 (gr_buffer_add_reader (buf, 0, gr_block_sptr()));
+
+ int read_counter = 0;
+ int write_counter = 0;
+ int n;
+ int *wp = 0;
+ int *rp = 0;
+
+ // Write 3/4 of buffer
+
+ n = (int) (buf->space_available () * 0.75);
+ wp = (int *) buf->write_pointer ();
+
+ for (int i = 0; i < n; i++)
+ *wp++ = write_counter++;
+ buf->update_write_pointer (n);
+
+ // Now read it all
+
+ int m = r1->items_available ();
+ CPPUNIT_ASSERT_EQUAL (n, m);
+ rp = (int *) r1->read_pointer ();
+
+ for (int i = 0; i < m; i++){
+ CPPUNIT_ASSERT_EQUAL (read_counter, *rp);
+ read_counter++;
+ rp++;
+ }
+ r1->update_read_pointer (m);
+
+ // Now write as much as we can.
+ // This will wrap around the buffer
+
+ n = buf->space_available ();
+ CPPUNIT_ASSERT_EQUAL (nitems - 1, n); // white box test
+ wp = (int *) buf->write_pointer ();
+
+ for (int i = 0; i < n; i++)
+ *wp++ = write_counter++;
+ buf->update_write_pointer (n);
+
+ // now read it all
+
+ m = r1->items_available ();
+ CPPUNIT_ASSERT_EQUAL (n, m);
+ rp = (int *) r1->read_pointer ();
+
+ for (int i = 0; i < m; i++){
+ CPPUNIT_ASSERT_EQUAL (read_counter, *rp);
+ read_counter++;
+ rp++;
+ }
+ r1->update_read_pointer (m);
+
+}
+
+// ----------------------------------------------------------------------------
+// single writer, N readers, randomized order and lengths
+// ----------------------------------------------------------------------------
+
+static void
+t3_body ()
+{
+ int nitems = (64 * (1L << 10)) / sizeof (int);
+
+ static const int N = 5;
+ gr_buffer_sptr buf(gr_make_buffer(nitems, sizeof (int), gr_block_sptr()));
+ gr_buffer_reader_sptr reader[N];
+ int read_counter[N];
+ int write_counter = 0;
+ gr_random random;
+
+ for (int i = 0; i < N; i++){
+ read_counter[i] = 0;
+ reader[i] = gr_buffer_add_reader (buf, 0, gr_block_sptr());
+ }
+
+ for (int lc = 0; lc < 1000; lc++){
+
+ // write some
+
+ int n = (int) (buf->space_available () * random.ran1 ());
+ int *wp = (int *) buf->write_pointer ();
+
+ for (int i = 0; i < n; i++)
+ *wp++ = write_counter++;
+
+ buf->update_write_pointer (n);
+
+ // pick a random reader and read some
+
+ int r = (int) (N * random.ran1 ());
+ CPPUNIT_ASSERT (0 <= r && r < N);
+
+ int m = reader[r]->items_available ();
+ int *rp = (int *) reader[r]->read_pointer ();
+
+ for (int i = 0; i < m; i++){
+ CPPUNIT_ASSERT_EQUAL (read_counter[r], *rp);
+ read_counter[r]++;
+ rp++;
+ }
+ reader[r]->update_read_pointer (m);
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+
+void
+qa_gr_buffer::t0 ()
+{
+ leak_check (t0_body);
+}
+
+void
+qa_gr_buffer::t1 ()
+{
+ leak_check (t1_body);
+}
+
+void
+qa_gr_buffer::t2 ()
+{
+ leak_check (t2_body);
+}
+
+void
+qa_gr_buffer::t3 ()
+{
+ leak_check (t3_body);
+}
+
+void
+qa_gr_buffer::t4 ()
+{
+}
+
+void
+qa_gr_buffer::t5 ()
+{
+}
diff --git a/gnuradio-runtime/lib/qa_gr_buffer.h b/gnuradio-runtime/lib/qa_gr_buffer.h
new file mode 100644
index 0000000000..2937c24b68
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_buffer.h
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_QA_GR_BUFFER_H
+#define INCLUDED_QA_GR_BUFFER_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gr_buffer : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gr_buffer);
+ CPPUNIT_TEST (t0);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST (t2);
+ CPPUNIT_TEST (t3);
+ CPPUNIT_TEST (t4);
+ CPPUNIT_TEST (t5);
+ CPPUNIT_TEST_SUITE_END ();
+
+
+ private:
+
+ void t0 ();
+ void t1 ();
+ void t2 ();
+ void t3 ();
+ void t4 ();
+ void t5 ();
+};
+
+
+
+#endif /* INCLUDED_QA_GR_BUFFER_H */
diff --git a/gnuradio-runtime/lib/qa_gr_circular_file.cc b/gnuradio-runtime/lib/qa_gr_circular_file.cc
new file mode 100644
index 0000000000..243e44784b
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_circular_file.cc
@@ -0,0 +1,72 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002 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 <qa_gr_circular_file.h>
+#include <gr_circular_file.h>
+#include <cppunit/TestAssert.h>
+#include <iostream>
+#include <stdio.h>
+#include <unistd.h>
+
+static const char *test_file = "qa_gr_circular_file.data";
+static const int BUFFER_SIZE = 8192;
+static const int NWRITE = 8192 * 9 / 8;
+
+void
+qa_gr_circular_file::t1 ()
+{
+#ifdef HAVE_MMAP
+ gr_circular_file *cf_writer;
+ gr_circular_file *cf_reader;
+
+ // write the data...
+
+ cf_writer = new gr_circular_file (test_file, true, BUFFER_SIZE * sizeof (short));
+
+ short sd;
+ for (int i = 0; i < NWRITE; i++){
+ sd = i;
+ cf_writer->write (&sd, sizeof (sd));
+ }
+
+ delete cf_writer;
+
+ // now read it back...
+
+ cf_reader = new gr_circular_file (test_file);
+ for (int i = 0; i < BUFFER_SIZE; i++){
+ int n = cf_reader->read (&sd, sizeof (sd));
+ CPPUNIT_ASSERT_EQUAL ((int) sizeof (sd), n);
+ CPPUNIT_ASSERT_EQUAL (NWRITE - BUFFER_SIZE + i, (int) sd);
+ }
+
+ int n = cf_reader->read (&sd, sizeof (sd));
+ CPPUNIT_ASSERT_EQUAL (0, n);
+
+ delete cf_reader;
+ unlink (test_file);
+#endif // HAVE_MMAP
+}
+
diff --git a/gnuradio-runtime/lib/qa_gr_circular_file.h b/gnuradio-runtime/lib/qa_gr_circular_file.h
new file mode 100644
index 0000000000..df35ab077b
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_circular_file.h
@@ -0,0 +1,40 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002 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 _QA_GR_CIRCULAR_FILE_H_
+#define _QA_GR_CIRCULAR_FILE_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gr_circular_file : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gr_circular_file);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void t1 ();
+
+};
+
+
+#endif /* _QA_GR_CIRCULAR_FILE_H_ */
diff --git a/gnuradio-runtime/lib/qa_gr_fxpt.cc b/gnuradio-runtime/lib/qa_gr_fxpt.cc
new file mode 100644
index 0000000000..7eac0d8964
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_fxpt.cc
@@ -0,0 +1,103 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <qa_gr_fxpt.h>
+#include <gr_fxpt.h>
+#include <cppunit/TestAssert.h>
+#include <iostream>
+#include <stdio.h>
+#include <unistd.h>
+#include <math.h>
+
+static const float SIN_COS_TOLERANCE = 1e-5;
+
+void
+qa_gr_fxpt::t0 ()
+{
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (M_PI/2, gr_fxpt::fixed_to_float (0x40000000), SIN_COS_TOLERANCE);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0, gr_fxpt::fixed_to_float (0x00000000), SIN_COS_TOLERANCE);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (-M_PI, gr_fxpt::fixed_to_float (0x80000000), SIN_COS_TOLERANCE);
+
+ if (0){
+ /*
+ * These are disabled because of some precision issues.
+ *
+ * Different compilers seem to have different opinions on whether
+ * the calulations are done single or double (or extended)
+ * precision. Any of the answers are fine for our real purpose, but
+ * sometimes the answer is off by a few bits at the bottom.
+ * Hence, the disabled check.
+ */
+ CPPUNIT_ASSERT_EQUAL ((gr_int32) 0x40000000, gr_fxpt::float_to_fixed (M_PI/2));
+ CPPUNIT_ASSERT_EQUAL ((gr_int32) 0, gr_fxpt::float_to_fixed (0));
+ CPPUNIT_ASSERT_EQUAL ((gr_int32) 0x80000000, gr_fxpt::float_to_fixed (-M_PI));
+ }
+}
+
+void
+qa_gr_fxpt::t1 ()
+{
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x00000000), SIN_COS_TOLERANCE);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0.707106781, gr_fxpt::sin (0x20000000), SIN_COS_TOLERANCE);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL ( 1, gr_fxpt::sin (0x40000000), SIN_COS_TOLERANCE);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0.707106781, gr_fxpt::sin (0x60000000), SIN_COS_TOLERANCE);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x7fffffff), SIN_COS_TOLERANCE);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x80000000), SIN_COS_TOLERANCE);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x80000001), SIN_COS_TOLERANCE);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (-1, gr_fxpt::sin (-0x40000000), SIN_COS_TOLERANCE);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (-0.707106781, gr_fxpt::sin (-0x20000000), SIN_COS_TOLERANCE);
+
+
+ for (float p = -M_PI; p < M_PI; p += 2 * M_PI / 3600){
+ float expected = sin (p);
+ float actual = gr_fxpt::sin (gr_fxpt::float_to_fixed (p));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (expected, actual, SIN_COS_TOLERANCE);
+ }
+}
+
+void
+qa_gr_fxpt::t2 ()
+{
+ for (float p = -M_PI; p < M_PI; p += 2 * M_PI / 3600){
+ float expected = cos (p);
+ float actual = gr_fxpt::cos (gr_fxpt::float_to_fixed (p));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (expected, actual, SIN_COS_TOLERANCE);
+ }
+}
+
+void
+qa_gr_fxpt::t3 ()
+{
+ for (float p = -M_PI; p < M_PI; p += 2 * M_PI / 3600){
+ float expected_sin = sin (p);
+ float expected_cos = cos (p);
+ float actual_sin;
+ float actual_cos;
+ gr_fxpt::sincos (gr_fxpt::float_to_fixed (p), &actual_sin, &actual_cos);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (expected_sin, actual_sin, SIN_COS_TOLERANCE);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (expected_cos, actual_cos, SIN_COS_TOLERANCE);
+ }
+}
diff --git a/gnuradio-runtime/lib/qa_gr_fxpt.h b/gnuradio-runtime/lib/qa_gr_fxpt.h
new file mode 100644
index 0000000000..72211563e7
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_fxpt.h
@@ -0,0 +1,48 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_QA_GR_FXPT_H
+#define INCLUDED_QA_GR_FXPT_H
+
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gr_fxpt : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gr_fxpt);
+ CPPUNIT_TEST (t0);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST (t2);
+ CPPUNIT_TEST (t3);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void t0 ();
+ void t1 ();
+ void t2 ();
+ void t3 ();
+
+};
+
+#endif /* INCLUDED_QA_GR_FXPT_H */
+
+
diff --git a/gnuradio-runtime/lib/qa_gr_fxpt_nco.cc b/gnuradio-runtime/lib/qa_gr_fxpt_nco.cc
new file mode 100644
index 0000000000..6f208eac80
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_fxpt_nco.cc
@@ -0,0 +1,119 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <qa_gr_fxpt_nco.h>
+#include <gr_fxpt_nco.h>
+#include <gr_nco.h>
+#include <cppunit/TestAssert.h>
+#include <iostream>
+#include <stdio.h>
+#include <unistd.h>
+#include <math.h>
+
+static const float SIN_COS_TOLERANCE = 1e-5;
+
+//static const float SIN_COS_FREQ = 5003;
+static const float SIN_COS_FREQ = 4096;
+
+static const int SIN_COS_BLOCK_SIZE = 100000;
+
+static double max_d(double a, double b)
+{
+ return fabs(a) > fabs(b) ? a : b;
+}
+
+void
+qa_gr_fxpt_nco::t0 ()
+{
+ gr_nco<float,float> ref_nco;
+ gr_fxpt_nco new_nco;
+ double max_error = 0, max_phase_error = 0;
+
+ ref_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ));
+ new_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ));
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_freq(), new_nco.get_freq(), SIN_COS_TOLERANCE);
+
+ for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){
+ float ref_sin = ref_nco.sin ();
+ float new_sin = new_nco.sin ();
+ //printf ("i = %6d\n", i);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_sin, new_sin, SIN_COS_TOLERANCE);
+
+ max_error = max_d (max_error, ref_sin-new_sin);
+
+ float ref_cos = ref_nco.cos ();
+ float new_cos = new_nco.cos ();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_cos, new_cos, SIN_COS_TOLERANCE);
+
+ max_error = max_d (max_error, ref_cos-new_cos);
+
+ ref_nco.step ();
+ new_nco.step ();
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_phase(), new_nco.get_phase(), SIN_COS_TOLERANCE);
+
+ max_phase_error = max_d (max_phase_error, ref_nco.get_phase()-new_nco.get_phase());
+ }
+ // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, max_phase_error);
+}
+
+void
+qa_gr_fxpt_nco::t1 ()
+{
+ gr_nco<float,float> ref_nco;
+ gr_fxpt_nco new_nco;
+ gr_complex ref_block[SIN_COS_BLOCK_SIZE];
+ gr_complex new_block[SIN_COS_BLOCK_SIZE];
+ double max_error = 0;
+
+ ref_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ));
+ new_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ));
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_freq(), new_nco.get_freq(), SIN_COS_TOLERANCE);
+
+ ref_nco.sincos ((gr_complex*)ref_block, SIN_COS_BLOCK_SIZE);
+ new_nco.sincos ((gr_complex*)new_block, SIN_COS_BLOCK_SIZE);
+
+ for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_block[i].real(), new_block[i].real(), SIN_COS_TOLERANCE);
+ max_error = max_d (max_error, ref_block[i].real()-new_block[i].real());
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_block[i].imag(), new_block[i].imag(), SIN_COS_TOLERANCE);
+ max_error = max_d (max_error, ref_block[i].imag()-new_block[i].imag());
+ }
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_phase(), new_nco.get_phase(), SIN_COS_TOLERANCE);
+ // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, max_phase_error);
+}
+
+void
+qa_gr_fxpt_nco::t2 ()
+{
+}
+
+void
+qa_gr_fxpt_nco::t3 ()
+{
+}
diff --git a/gnuradio-runtime/lib/qa_gr_fxpt_nco.h b/gnuradio-runtime/lib/qa_gr_fxpt_nco.h
new file mode 100644
index 0000000000..8998922bbb
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_fxpt_nco.h
@@ -0,0 +1,48 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_QA_GR_FXPT_NCO_H
+#define INCLUDED_QA_GR_FXPT_NCO_H
+
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gr_fxpt_nco : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gr_fxpt_nco);
+ CPPUNIT_TEST (t0);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST (t2);
+ CPPUNIT_TEST (t3);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void t0 ();
+ void t1 ();
+ void t2 ();
+ void t3 ();
+
+};
+
+#endif /* INCLUDED_QA_GR_FXPT_NCO_H */
+
+
diff --git a/gnuradio-runtime/lib/qa_gr_fxpt_vco.cc b/gnuradio-runtime/lib/qa_gr_fxpt_vco.cc
new file mode 100644
index 0000000000..5b6993a30c
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_fxpt_vco.cc
@@ -0,0 +1,110 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <qa_gr_fxpt_vco.h>
+#include <gr_fxpt_vco.h>
+#include <gr_vco.h>
+#include <cppunit/TestAssert.h>
+#include <iostream>
+#include <stdio.h>
+#include <unistd.h>
+#include <math.h>
+
+static const float SIN_COS_TOLERANCE = 1e-5;
+
+static const float SIN_COS_K = 0.42;
+static const float SIN_COS_AMPL = 0.8;
+
+static const int SIN_COS_BLOCK_SIZE = 100000;
+
+static double max_d(double a, double b)
+{
+ return fabs(a) > fabs(b) ? a : b;
+}
+
+void
+qa_gr_fxpt_vco::t0 ()
+{
+ gr_vco<float,float> ref_vco;
+ gr_fxpt_vco new_vco;
+ double max_error = 0, max_phase_error = 0;
+ float input[SIN_COS_BLOCK_SIZE];
+
+ for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){
+ input[i] = sin(double(i));
+ }
+
+ for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){
+ float ref_cos = ref_vco.cos ();
+ float new_cos = new_vco.cos ();
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_cos, new_cos, SIN_COS_TOLERANCE);
+
+ max_error = max_d (max_error, ref_cos-new_cos);
+
+ ref_vco.adjust_phase (input[i]);
+ new_vco.adjust_phase (input[i]);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_vco.get_phase(), new_vco.get_phase(), SIN_COS_TOLERANCE);
+
+ max_phase_error = max_d (max_phase_error, ref_vco.get_phase()-new_vco.get_phase());
+ }
+ // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, max_phase_error);
+}
+
+
+void
+qa_gr_fxpt_vco::t1 ()
+{
+ gr_vco<float,float> ref_vco;
+ gr_fxpt_vco new_vco;
+ float ref_block[SIN_COS_BLOCK_SIZE];
+ float new_block[SIN_COS_BLOCK_SIZE];
+ float input[SIN_COS_BLOCK_SIZE];
+ double max_error = 0;
+
+ for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){
+ input[i] = sin(double(i));
+ }
+
+ ref_vco.cos (ref_block, input, SIN_COS_BLOCK_SIZE, SIN_COS_K, SIN_COS_AMPL);
+ new_vco.cos (new_block, input, SIN_COS_BLOCK_SIZE, SIN_COS_K, SIN_COS_AMPL);
+
+ for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_block[i], new_block[i], SIN_COS_TOLERANCE);
+ max_error = max_d (max_error, ref_block[i]-new_block[i]);
+ }
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_vco.get_phase(), new_vco.get_phase(), SIN_COS_TOLERANCE);
+ // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, ref_vco.get_phase()-new_vco.get_phase());
+}
+
+void
+qa_gr_fxpt_vco::t2 ()
+{
+}
+
+void
+qa_gr_fxpt_vco::t3 ()
+{
+}
diff --git a/gnuradio-runtime/lib/qa_gr_fxpt_vco.h b/gnuradio-runtime/lib/qa_gr_fxpt_vco.h
new file mode 100644
index 0000000000..fab8022e36
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_fxpt_vco.h
@@ -0,0 +1,48 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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.
+ */
+#ifndef INCLUDED_QA_GR_FXPT_VCO_H
+#define INCLUDED_QA_GR_FXPT_VCO_H
+
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gr_fxpt_vco : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gr_fxpt_vco);
+ CPPUNIT_TEST (t0);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST (t2);
+ CPPUNIT_TEST (t3);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void t0 ();
+ void t1 ();
+ void t2 ();
+ void t3 ();
+
+};
+
+#endif /* INCLUDED_QA_GR_FXPT_VCO_H */
+
+
diff --git a/gnuradio-runtime/lib/qa_gr_io_signature.cc b/gnuradio-runtime/lib/qa_gr_io_signature.cc
new file mode 100644
index 0000000000..c1737ffb8e
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_io_signature.cc
@@ -0,0 +1,64 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <qa_gr_io_signature.h>
+#include <gr_io_signature.h>
+
+void
+qa_gr_io_signature::t0 ()
+{
+ gr_make_io_signature (1, 1, sizeof (int));
+}
+
+void
+qa_gr_io_signature::t1 ()
+{
+ gr_make_io_signature (3, 1, sizeof (int)); // throws std::invalid_argument
+}
+
+void
+qa_gr_io_signature::t2 ()
+{
+ gr_io_signature_sptr p =
+ gr_make_io_signature (3, gr_io_signature::IO_INFINITE, sizeof (int));
+
+ CPPUNIT_ASSERT_EQUAL (p->min_streams (), 3);
+ CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item (0), (int) sizeof (int));
+}
+
+void
+qa_gr_io_signature::t3 ()
+{
+ gr_io_signature_sptr p =
+ gr_make_io_signature3 (0, 5, 1, 2, 3);
+
+ CPPUNIT_ASSERT_EQUAL (p->min_streams (), 0);
+ CPPUNIT_ASSERT_EQUAL (p->max_streams (), 5);
+ CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(0), 1);
+ CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(1), 2);
+ CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(2), 3);
+ CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(3), 3);
+ CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(4), 3);
+}
diff --git a/gnuradio-runtime/lib/qa_gr_io_signature.h b/gnuradio-runtime/lib/qa_gr_io_signature.h
new file mode 100644
index 0000000000..9cd6bb5247
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_io_signature.h
@@ -0,0 +1,46 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_QA_GR_IO_SIGNATURE_H
+#define INCLUDED_QA_GR_IO_SIGNATURE_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+#include <stdexcept>
+
+class qa_gr_io_signature : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gr_io_signature);
+ CPPUNIT_TEST (t0);
+ CPPUNIT_TEST_EXCEPTION (t1, std::invalid_argument);
+ CPPUNIT_TEST (t2);
+ CPPUNIT_TEST (t3);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void t0 ();
+ void t1 ();
+ void t2 ();
+ void t3 ();
+};
+
+#endif /* INCLUDED_QA_GR_IO_SIGNATURE_H */
diff --git a/gnuradio-runtime/lib/qa_gr_logger.cc b/gnuradio-runtime/lib/qa_gr_logger.cc
new file mode 100644
index 0000000000..a8e4a1d766
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_logger.cc
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+/*
+ * This class gathers together all the test cases for the example
+ * directory into a single test suite. As you create new test cases,
+ * add them here.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qa_gr_logger.h>
+#include <gr_logger.h>
+
+void
+qa_gr_logger::t1()
+{
+#ifdef ENABLE_GR_LOG
+ // This doesn't really test anything, more just
+ // making sure nothing's gone horribly wrong.
+
+ GR_LOG_GETLOGGER(LOG,"main");
+ GR_ADD_CONSOLE_APPENDER("main","cout","%d{%H:%M:%S} : %m%n");
+ GR_LOG_NOTICE(LOG,"test from c++ NOTICE");
+ GR_LOG_DEBUG(LOG,"test from c++ DEBUG");
+ GR_LOG_INFO(LOG,"test from c++ INFO");
+ GR_LOG_WARN(LOG,"test from c++ WARN");
+ GR_LOG_ERROR(LOG,"test from c++ ERROR");
+ GR_LOG_FATAL(LOG,"test from c++ FATAL");
+ CPPUNIT_ASSERT(true);
+#endif
+}
diff --git a/gnuradio-runtime/lib/qa_gr_logger.h b/gnuradio-runtime/lib/qa_gr_logger.h
new file mode 100644
index 0000000000..b0d3711523
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_logger.h
@@ -0,0 +1,42 @@
+/* -*- 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 Example 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 Example Public License for more details.
+ *
+ * You should have received a copy of the GNU Example 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_QA_GR_LOG_H
+#define INCLUDED_QA_GR_LOG_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestSuite.h>
+
+//! collect all the tests for the example directory
+
+class qa_gr_logger : public CppUnit::TestCase {
+ public:
+ CPPUNIT_TEST_SUITE(qa_gr_logger);
+ CPPUNIT_TEST(t1);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ void t1();
+
+};
+
+#endif /* INCLUDED_QA_GR_LOG_H */
diff --git a/gnuradio-runtime/lib/qa_gr_math.cc b/gnuradio-runtime/lib/qa_gr_math.cc
new file mode 100644
index 0000000000..74d51b536e
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_math.cc
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2008 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_math.h>
+#include <qa_gr_math.h>
+#include <cppunit/TestAssert.h>
+#include <stdio.h>
+
+void
+qa_gr_math::test_binary_slicer1 ()
+{
+ float x[5] = {-1, -0.5, 0, 0.5, 1.0};
+ unsigned int z[5] = {0, 0, 1, 1, 1};
+ unsigned int y;
+
+ //printf("\nBinary\n");
+ for (unsigned int i = 0; i < 5; i++) {
+ y = gr_binary_slicer(x[i]);
+ //printf("in: %f out: %d desired: %d\n", x[i], y, z[i]);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9);
+ }
+
+ //printf("\nBranchless Binary\n");
+ for (unsigned int i = 0; i < 5; i++) {
+ y = gr_branchless_binary_slicer(x[i]);
+ //printf("in: %f out: %d desired: %d\n", x[i], y, z[i]);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9);
+ }
+}
+
+void
+qa_gr_math::test_quad_0deg_slicer1 ()
+{
+ gr_complex x[4] = {gr_complex(1, 0),
+ gr_complex(0, 1),
+ gr_complex(-1, 0),
+ gr_complex(0, -1)};
+
+ unsigned int z[4] = {0, 1, 2, 3};
+ unsigned int y;
+
+ //printf("\nQuad0\n");
+ for (unsigned int i = 0; i < 4; i++) {
+ y = gr_quad_0deg_slicer(x[i]);
+ //printf("in: %.4f+j%.4f out: %d desired: %d\n", x[i].real(), x[i].imag(), y, z[i]);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9);
+ }
+
+ //printf("\nBranchless Quad0\n");
+ for (unsigned int i = 0; i < 4; i++) {
+ y = gr_branchless_quad_0deg_slicer(x[i]);
+ //printf("in: %.4f+j%.4f out: %d desired: %d\n", x[i].real(), x[i].imag(), y, z[i]);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9);
+ }
+}
+
+void
+qa_gr_math::test_quad_45deg_slicer1 ()
+{
+ gr_complex x[4] = {gr_complex(0.707, 0.707),
+ gr_complex(-0.707, 0.707),
+ gr_complex(-0.707, -0.707),
+ gr_complex(0.707, -0.707)};
+
+ unsigned int z[4] = {0, 1, 2, 3};
+ unsigned int y;
+
+ //printf("\nQuad45\n");
+ for (unsigned int i = 0; i < 4; i++) {
+ y = gr_quad_45deg_slicer(x[i]);
+ //printf("in: %.4f+j%.4f out: %d desired: %d\n", x[i].real(), x[i].imag(), y, z[i]);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9);
+ }
+
+ //printf("\nBranchless Quad45\n");
+ for (unsigned int i = 0; i < 4; i++) {
+ y = gr_branchless_quad_45deg_slicer(x[i]);
+ //printf("in: %.4f+j%.4f out: %d desired: %d\n", x[i].real(), x[i].imag(), y, z[i]);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9);
+ }
+}
diff --git a/gnuradio-runtime/lib/qa_gr_math.h b/gnuradio-runtime/lib/qa_gr_math.h
new file mode 100644
index 0000000000..86858c03d5
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_math.h
@@ -0,0 +1,42 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 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 _QA_GR_MATH_H_
+#define _QA_GR_MATH_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gr_math : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE(qa_gr_math);
+ CPPUNIT_TEST(test_binary_slicer1);
+ CPPUNIT_TEST(test_quad_0deg_slicer1);
+ CPPUNIT_TEST(test_quad_45deg_slicer1);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ void test_binary_slicer1();
+ void test_quad_0deg_slicer1();
+ void test_quad_45deg_slicer1();
+};
+
+#endif /* _QA_GR_MATH_H_ */
diff --git a/gnuradio-runtime/lib/qa_gr_vmcircbuf.cc b/gnuradio-runtime/lib/qa_gr_vmcircbuf.cc
new file mode 100644
index 0000000000..e3b36d8829
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_vmcircbuf.cc
@@ -0,0 +1,40 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002 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 <qa_gr_vmcircbuf.h>
+#include <cppunit/TestAssert.h>
+#include <gr_vmcircbuf.h>
+#include <stdio.h>
+
+void
+qa_gr_vmcircbuf::test_all ()
+{
+ int verbose = 1; // summary
+
+ bool ok = gr_vmcircbuf_sysconfig::test_all_factories (verbose);
+
+ CPPUNIT_ASSERT_EQUAL (true, ok);
+}
diff --git a/gnuradio-runtime/lib/qa_gr_vmcircbuf.h b/gnuradio-runtime/lib/qa_gr_vmcircbuf.h
new file mode 100644
index 0000000000..3576660d5a
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_gr_vmcircbuf.h
@@ -0,0 +1,39 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef _QA_GR_VMCIRCBUF_H_
+#define _QA_GR_VMCIRCBUF_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gr_vmcircbuf : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gr_vmcircbuf);
+ CPPUNIT_TEST (test_all);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void test_all ();
+};
+
+
+#endif /* _QA_GR_VMCIRCBUF_H_ */
diff --git a/gnuradio-runtime/lib/qa_runtime.cc b/gnuradio-runtime/lib/qa_runtime.cc
new file mode 100644
index 0000000000..b15051c2ad
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_runtime.cc
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2002,2007,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * This class gathers together all the test cases for the gr
+ * directory into a single test suite. As you create new test cases,
+ * add them here.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <qa_runtime.h>
+#include <qa_gr_buffer.h>
+#include <qa_gr_circular_file.h>
+#include <qa_gr_fxpt.h>
+#include <qa_gr_fxpt_nco.h>
+#include <qa_gr_fxpt_vco.h>
+#include <qa_gr_io_signature.h>
+#include <qa_gr_logger.h>
+#include <qa_gr_math.h>
+#include <qa_gr_vmcircbuf.h>
+#include <qa_sincos.h>
+
+CppUnit::TestSuite *
+qa_runtime::suite ()
+{
+ CppUnit::TestSuite *s = new CppUnit::TestSuite ("runtime");
+
+ s->addTest (qa_gr_buffer::suite ());
+ s->addTest (qa_gr_circular_file::suite ());
+ s->addTest (qa_gr_fxpt::suite ());
+ s->addTest (qa_gr_fxpt_nco::suite ());
+ s->addTest (qa_gr_fxpt_vco::suite ());
+ s->addTest (qa_gr_io_signature::suite ());
+ s->addTest (qa_gr_logger::suite ());
+ s->addTest (qa_gr_math::suite ());
+ s->addTest (qa_gr_vmcircbuf::suite ());
+ s->addTest (qa_sincos::suite ());
+
+ return s;
+}
diff --git a/gnuradio-runtime/lib/qa_runtime.h b/gnuradio-runtime/lib/qa_runtime.h
new file mode 100644
index 0000000000..da71cbd0f4
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_runtime.h
@@ -0,0 +1,38 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002 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 _QA_RUNTIME_H_
+#define _QA_RUNTIME_H_
+
+#include <gruel/attributes.h>
+#include <cppunit/TestSuite.h>
+
+//! collect all the tests for the runtime directory
+
+class __GR_ATTR_EXPORT qa_runtime {
+ public:
+ //! return suite of tests for all of runtime directory
+ static CppUnit::TestSuite *suite ();
+};
+
+
+#endif /* _QA_RUNTIME_H_ */
diff --git a/gnuradio-runtime/lib/qa_sincos.cc b/gnuradio-runtime/lib/qa_sincos.cc
new file mode 100644
index 0000000000..54be957546
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_sincos.cc
@@ -0,0 +1,69 @@
+/* -*- 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 <qa_sincos.h>
+#include <gr_sincos.h>
+#include <gruel/attributes.h>
+#include <cppunit/TestAssert.h>
+#include <cmath>
+
+void
+qa_sincos::t1()
+{
+ static const unsigned int N = 1000;
+ double c_sin, c_cos;
+ double gr_sin, gr_cos;
+
+ for(unsigned i = 0; i < N; i++) {
+ double x = i/100.0;
+ c_sin = sin(x);
+ c_cos = cos(x);
+
+ gr_sincos(x, &gr_sin, &gr_cos);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(c_sin, gr_sin, 0.0001);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(c_cos, gr_cos, 0.0001);
+ }
+}
+
+void
+qa_sincos::t2()
+{
+ static const unsigned int N = 1000;
+ float c_sin, c_cos;
+ float gr_sin, gr_cos;
+
+ for(unsigned i = 0; i < N; i++) {
+ float x = i/100.0;
+ c_sin = sinf(x);
+ c_cos = cosf(x);
+
+ gr_sincosf(x, &gr_sin, &gr_cos);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(c_sin, gr_sin, 0.0001);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(c_cos, gr_cos, 0.0001);
+ }
+}
diff --git a/gnuradio-runtime/lib/qa_sincos.h b/gnuradio-runtime/lib/qa_sincos.h
new file mode 100644
index 0000000000..c54b75f97f
--- /dev/null
+++ b/gnuradio-runtime/lib/qa_sincos.h
@@ -0,0 +1,41 @@
+/* -*- 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 _QA_SINCOS_H_
+#define _QA_SINCOS_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_sincos : public CppUnit::TestCase
+{
+ CPPUNIT_TEST_SUITE(qa_sincos);
+ CPPUNIT_TEST(t1);
+ CPPUNIT_TEST(t2);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ void t1();
+ void t2();
+};
+
+#endif /* _QA_SINCOS_H_ */
diff --git a/gnuradio-runtime/lib/random.h b/gnuradio-runtime/lib/random.h
new file mode 100644
index 0000000000..c643c3e422
--- /dev/null
+++ b/gnuradio-runtime/lib/random.h
@@ -0,0 +1,38 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003, 2008 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 _RANDOM_H_
+#define _RANDOM_H_
+
+// While rand(3) specifies RAND_MAX, random(3) says that the output
+// ranges from 0 to 2^31-1 but does not specify a macro to denote
+// this. We define RANDOM_MAX for cleanliness. We must omit the
+// definition for systems that have made the same choice. (Note that
+// random(3) is from 4.2BSD, and not specified by POSIX.)
+
+#ifndef RANDOM_MAX
+static const int RANDOM_MAX = 2147483647; // 2^31-1
+#endif /* RANDOM_MAX */
+
+#include <stdlib.h>
+
+#endif // _RANDOM_H_
diff --git a/gnuradio-runtime/lib/rpcmanager.cc b/gnuradio-runtime/lib/rpcmanager.cc
new file mode 100644
index 0000000000..4d164b63f3
--- /dev/null
+++ b/gnuradio-runtime/lib/rpcmanager.cc
@@ -0,0 +1,72 @@
+/* -*- 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.
+ */
+
+#include <rpcmanager.h>
+#include <iostream>
+#include <stdexcept>
+
+bool rpcmanager::booter_registered(false);
+bool rpcmanager::aggregator_registered(false);
+rpcserver_booter_base* rpcmanager::boot(0);
+std::auto_ptr<rpcserver_booter_aggregator> rpcmanager::aggregator(0);
+
+rpcmanager::rpcmanager() {;}
+
+rpcmanager::~rpcmanager()
+{
+ if(boot)
+ delete boot;
+}
+
+rpcserver_booter_base*
+rpcmanager::get()
+{
+ if(aggregator_registered) {
+ return aggregator.get();
+ }
+ else if(booter_registered) {
+ return boot;
+ }
+ assert(booter_registered || aggregator_registered);
+ return boot;
+}
+
+void
+rpcmanager::register_booter(rpcserver_booter_base* booter)
+{
+ if(make_aggregator && !aggregator_registered) {
+ aggregator.reset(new rpcserver_booter_aggregator());
+ aggregator_registered = true;
+ }
+
+ if(aggregator_registered) {
+ rpcmanager::rpcserver_booter_base_sptr bootreg(booter);
+ aggregator->agg()->registerServer(bootreg);
+ }
+ else if(!booter_registered) {
+ boot = booter;
+ booter_registered = true;
+ }
+ else {
+ throw std::runtime_error("rpcmanager: Aggregator not in use, and a rpc booter is already registered\n");
+ }
+}
diff --git a/gnuradio-runtime/lib/rpcpmtconverters_ice.cc b/gnuradio-runtime/lib/rpcpmtconverters_ice.cc
new file mode 100644
index 0000000000..7c8b6041e9
--- /dev/null
+++ b/gnuradio-runtime/lib/rpcpmtconverters_ice.cc
@@ -0,0 +1,123 @@
+/* -*- 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.
+ */
+
+#include <rpcpmtconverters_ice.h>
+#include <Ice/Ice.h>
+#include <gnuradio.h>
+
+GNURadio::KnobPtr
+rpcpmtconverter::from_pmt(const pmt::pmt_t& knob, const Ice::Current& c)
+{
+ if(pmt::is_real(knob)) {
+ return new GNURadio::KnobD(Ice::Double(pmt::to_double(knob)));
+ }
+ else if(pmt::is_symbol(knob)) {
+ std::string stuff = pmt::symbol_to_string(knob);
+ return new GNURadio::KnobS(stuff);
+ }
+ else if(pmt::is_integer(knob)) {
+ return new GNURadio::KnobI(pmt::to_long(knob));
+ }
+ else if(pmt::is_bool(knob)) {
+ return new GNURadio::KnobB(pmt::to_bool(knob));
+ }
+ else if(pmt::is_uint64(knob)) {
+ return new GNURadio::KnobL(pmt::to_uint64(knob));
+ //const std::complex<float> *c32vector_elements(pmt_t v, size_t &len); //< len is in elements
+ }
+ else if(pmt::is_c32vector(knob)) { // c32 sent as interleaved floats
+ size_t size(pmt::length(knob));
+ const float* start((const float*) pmt::c32vector_elements(knob,size));
+ return new GNURadio::KnobVecF(std::vector<float>(start,start+size*2));
+ }
+ else if (pmt::is_s32vector(knob)) {
+ size_t size(pmt::length(knob));
+ const int* start((const int*) pmt::s32vector_elements(knob,size));
+ return new GNURadio::KnobVecI(std::vector<int>(start,start+size));
+ }
+ else if(pmt::is_f32vector(knob)) {
+ size_t size(pmt::length(knob));
+ const float* start((const float*) pmt::f32vector_elements(knob,size));
+ return new GNURadio::KnobVecF(std::vector<float>(start,start+size));
+ }
+ else if (pmt::is_u8vector(knob)) {
+ size_t size(pmt::length(knob));
+ const uint8_t* start((const uint8_t*) pmt::u8vector_elements(knob,size));
+ return new GNURadio::KnobVecC(std::vector<Ice::Byte>(start,start+size));
+ }
+ else {
+ std::cerr << "Error: Don't know how to handle Knob Type (from): " << std::endl; assert(0);}
+ //TODO: VECTORS!!!
+ return new GNURadio::Knob();
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt(const GNURadio::KnobPtr& knob, const Ice::Current& c)
+{
+ std::string id(knob->ice_id(c).substr(12));
+ if(id == "KnobD") {
+ GNURadio::KnobDPtr k(GNURadio::KnobDPtr::dynamicCast(knob));
+ return pmt::mp(k->value);
+ }
+ else if(id == "KnobF") {
+ GNURadio::KnobFPtr k(GNURadio::KnobFPtr::dynamicCast(knob));
+ return pmt::mp(k->value);
+ }
+ else if(id == "KnobI") {
+ GNURadio::KnobIPtr k(GNURadio::KnobIPtr::dynamicCast(knob));
+ return pmt::mp(k->value);
+ }
+ else if(id == "KnobS") {
+ GNURadio::KnobSPtr k(GNURadio::KnobSPtr::dynamicCast(knob));
+ return pmt::string_to_symbol(k->value);
+ }
+ else if(id == "KnobB") {
+ GNURadio::KnobBPtr k(GNURadio::KnobBPtr::dynamicCast(knob));
+ return pmt::mp(k->value);
+ }
+ else if(id == "KnobC") {
+ GNURadio::KnobCPtr k(GNURadio::KnobCPtr::dynamicCast(knob));
+ return pmt::mp(k->value);
+ }
+ else if(id == "KnobL") {
+ GNURadio::KnobLPtr k(GNURadio::KnobLPtr::dynamicCast(knob));
+ return pmt::mp((long)k->value);
+ }
+ else if(id == "KnobVecC") {
+ GNURadio::KnobVecCPtr k(GNURadio::KnobVecCPtr::dynamicCast(knob));
+ return pmt::init_u8vector(k->value.size(), &k->value[0]);
+ }
+ else if(id == "KnobVecI") {
+ GNURadio::KnobVecIPtr k(GNURadio::KnobVecIPtr::dynamicCast(knob));
+ return pmt::init_s32vector(k->value.size(), &k->value[0]);
+ }
+ //else if(id == "KnobVecF") {
+ // GNURadio::KnobVecFPtr k(GNURadio::KnobVecFPtr::dynamicCast(knob));
+ // return pmt::mp(k->value);
+ //TODO: FLOAT!!!
+ //TODO: VECTORS!!!
+ else {
+ std::cerr << "Error: Don't know how to handle Knob Type: " << id << std::endl; assert(0);
+ }
+
+ return pmt::pmt_t();
+}
diff --git a/gnuradio-runtime/lib/rpcserver_aggregator.cc b/gnuradio-runtime/lib/rpcserver_aggregator.cc
new file mode 100644
index 0000000000..d750d64905
--- /dev/null
+++ b/gnuradio-runtime/lib/rpcserver_aggregator.cc
@@ -0,0 +1,93 @@
+/* -*- 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.
+ */
+
+#include <rpcserver_aggregator.h>
+#include <rpcserver_booter_base.h>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+
+rpcserver_aggregator::rpcserver_aggregator()
+ : d_type(std::string("aggregator"))
+{;}
+
+rpcserver_aggregator::~rpcserver_aggregator()
+{;}
+
+const std::string&
+rpcserver_aggregator::type()
+{
+ return d_type;
+}
+
+const std::vector<std::string>&
+rpcserver_aggregator::registeredServers()
+{
+ return d_registeredServers;
+}
+
+void
+rpcserver_aggregator::registerConfigureCallback(const std::string &id,
+ const configureCallback_t callback)
+{
+ std::for_each(d_serverlist.begin(), d_serverlist.end(),
+ registerConfigureCallback_f<rpcmanager_base::rpcserver_booter_base_sptr, configureCallback_t>(id, callback));
+}
+
+void
+rpcserver_aggregator::unregisterConfigureCallback(const std::string &id)
+{
+ std::for_each(d_serverlist.begin(), d_serverlist.end(),
+ unregisterConfigureCallback_f<rpcmanager_base::rpcserver_booter_base_sptr, configureCallback_t>(id));
+}
+
+void
+rpcserver_aggregator::registerQueryCallback(const std::string &id, const queryCallback_t callback)
+{
+ std::for_each(d_serverlist.begin(), d_serverlist.end(),
+ registerQueryCallback_f<rpcmanager_base::rpcserver_booter_base_sptr, queryCallback_t>(id, callback));
+}
+
+void
+rpcserver_aggregator::unregisterQueryCallback(const std::string &id)
+{
+ std::for_each(d_serverlist.begin(), d_serverlist.end(),
+ unregisterQueryCallback_f<rpcmanager_base::rpcserver_booter_base_sptr, queryCallback_t>(id));
+}
+
+void
+rpcserver_aggregator::registerServer(rpcmanager_base::rpcserver_booter_base_sptr server)
+{
+ std::vector<std::string>::iterator it(std::find(d_registeredServers.begin(),
+ d_registeredServers.end(),
+ server->type()));
+ if(it != d_registeredServers.end()) {
+ d_serverlist.push_back(server);
+ d_registeredServers.push_back(server->type());
+ }
+ else {
+ std::stringstream s;
+ s << "rpcserver_aggregator::registerServer: server of type "
+ << server->type() << " already registered" << std::endl;
+ throw std::runtime_error(s.str().c_str());
+ }
+}
diff --git a/gnuradio-runtime/lib/rpcserver_booter_aggregator.cc b/gnuradio-runtime/lib/rpcserver_booter_aggregator.cc
new file mode 100644
index 0000000000..c4c1b03c15
--- /dev/null
+++ b/gnuradio-runtime/lib/rpcserver_booter_aggregator.cc
@@ -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.
+ */
+
+#include <rpcserver_booter_aggregator.h>
+
+rpcserver_booter_aggregator::rpcserver_booter_aggregator() :
+ d_type(std::string("aggregator")), server(new rpcserver_aggregator())
+{;}
+
+rpcserver_booter_aggregator::~rpcserver_booter_aggregator()
+{;}
+
+rpcserver_base*
+rpcserver_booter_aggregator::i()
+{
+ return &(*server);
+}
+
+const std::string&
+rpcserver_booter_aggregator::type()
+{
+ return d_type;
+}
+
+const std::vector<std::string>
+rpcserver_booter_aggregator::endpoints()
+{
+ std::vector<std::string> ep;
+ ep.push_back(std::string("TODO"));
+ return ep;
+}
+
+const std::vector<std::string>&
+rpcserver_booter_aggregator::registeredServers()
+{
+ return server->registeredServers();
+}
+
+rpcserver_aggregator*
+rpcserver_booter_aggregator::agg()
+{
+ return &(*server);
+}
diff --git a/gnuradio-runtime/lib/rpcserver_booter_ice.cc b/gnuradio-runtime/lib/rpcserver_booter_ice.cc
new file mode 100644
index 0000000000..7cc8cc8938
--- /dev/null
+++ b/gnuradio-runtime/lib/rpcserver_booter_ice.cc
@@ -0,0 +1,54 @@
+/* -*- 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.
+ */
+
+#include <rpcserver_ice.h>
+#include <rpcserver_booter_ice.h>
+
+namespace {
+ static const char* const CONTROL_PORT_CLASS("ice");
+ static const char* const CONTROL_PORT_NAME("ControlPort");
+ static const char* const ENDPOINT_NAME("gnuradio");
+};
+
+rpcserver_booter_ice::rpcserver_booter_ice() :
+ ice_server_template<rpcserver_base, rpcserver_ice,
+ rpcserver_booter_ice, GNURadio::ControlPortPtr>
+ (this, std::string(CONTROL_PORT_NAME), std::string(ENDPOINT_NAME)),
+ d_type(std::string(CONTROL_PORT_CLASS))
+{;}
+
+rpcserver_booter_ice::~rpcserver_booter_ice()
+{;}
+
+rpcserver_base*
+rpcserver_booter_ice::i()
+{
+ return ice_server_template<rpcserver_base, rpcserver_ice,
+ rpcserver_booter_ice, GNURadio::ControlPortPtr>::i();
+}
+
+const std::vector<std::string>
+rpcserver_booter_ice::endpoints()
+{
+ return ice_server_template<rpcserver_base, rpcserver_ice,
+ rpcserver_booter_ice, GNURadio::ControlPortPtr>::endpoints();
+}
diff --git a/gnuradio-runtime/lib/rpcserver_ice.cc b/gnuradio-runtime/lib/rpcserver_ice.cc
new file mode 100644
index 0000000000..12229a0688
--- /dev/null
+++ b/gnuradio-runtime/lib/rpcserver_ice.cc
@@ -0,0 +1,165 @@
+/* -*- 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.
+ */
+
+#include <rpcserver_ice.h>
+#include <IceUtil/IceUtil.h>
+#include <Ice/Ice.h>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <gruel/pmt.h>
+
+#define DEBUG 0
+
+using namespace rpcpmtconverter;
+
+rpcserver_ice::rpcserver_ice()
+{}
+
+rpcserver_ice::~rpcserver_ice()
+{}
+
+void
+rpcserver_ice::registerConfigureCallback(const std::string &id,
+ const configureCallback_t callback)
+{
+ {
+ ConfigureCallbackMap_t::const_iterator iter(d_setcallbackmap.find(id));
+ if(iter != d_setcallbackmap.end()) {
+ std::stringstream s;
+ s << "rpcserver_ice:: rpcserver_ice ERROR registering set, already registered: "
+ << id << std::endl;
+ throw std::runtime_error(s.str().c_str());
+ }
+ }
+
+ if(DEBUG)
+ std::cout << "rpcserver_ice registering set: " << id << std::endl;
+
+ d_setcallbackmap.insert(ConfigureCallbackMap_t::value_type(id, callback));
+}
+
+void
+rpcserver_ice::unregisterConfigureCallback(const std::string &id)
+{
+ ConfigureCallbackMap_t::iterator iter(d_setcallbackmap.find(id));
+ if(iter == d_setcallbackmap.end()) {
+ std::stringstream s;
+ s << "rpcserver_ice:: rpcserver_ice ERROR unregistering set, not registered: "
+ << id << std::endl;
+ throw std::runtime_error(s.str().c_str());
+ }
+
+ if(DEBUG)
+ std::cout << "rpcserver_ice unregistering set: " << id << std::endl;
+
+ d_setcallbackmap.erase(iter);
+}
+
+void
+rpcserver_ice::registerQueryCallback(const std::string &id,
+ const queryCallback_t callback)
+{
+ {
+ QueryCallbackMap_t::const_iterator iter(d_getcallbackmap.find(id));
+ if(iter != d_getcallbackmap.end()) {
+ std::stringstream s;
+ s << "rpcserver_ice:: rpcserver_ice ERROR registering get, already registered: "
+ << id << std::endl;
+ throw std::runtime_error(s.str().c_str());
+ }
+ }
+
+ if(DEBUG)
+ std::cout << "rpcserver_ice registering get: " << id << std::endl;
+
+ d_getcallbackmap.insert(QueryCallbackMap_t::value_type(id, callback));
+}
+
+void
+rpcserver_ice::unregisterQueryCallback(const std::string &id)
+{
+ QueryCallbackMap_t::iterator iter(d_getcallbackmap.find(id));
+ if(iter == d_getcallbackmap.end()) {
+ std::stringstream s;
+ s << "rpcserver_ice:: rpcserver_ice ERROR unregistering get, registered: "
+ << id << std::endl;
+ throw std::runtime_error(s.str().c_str());
+ }
+
+ if(DEBUG)
+ std::cout << "rpcserver_ice unregistering get: " << id << std::endl;
+
+ d_getcallbackmap.erase(iter);
+}
+
+void
+rpcserver_ice::set(const GNURadio::KnobMap& knobs, const Ice::Current& c)
+{
+ std::for_each(knobs.begin(), knobs.end(),
+ set_f<GNURadio::KnobMap::value_type,ConfigureCallbackMap_t>
+ (c, d_setcallbackmap, cur_priv));
+}
+
+GNURadio::KnobMap
+rpcserver_ice::get(const GNURadio::KnobIDList& knobs, const Ice::Current& c)
+{
+ GNURadio::KnobMap outknobs;
+
+ if(knobs.size() == 0) {
+ std::for_each(d_getcallbackmap.begin(), d_getcallbackmap.end(),
+ get_all_f<QueryCallbackMap_t::value_type, QueryCallbackMap_t, GNURadio::KnobMap>
+ (c, d_getcallbackmap, cur_priv, outknobs));
+ }
+ else {
+ std::for_each(knobs.begin(), knobs.end(),
+ get_f<GNURadio::KnobIDList::value_type, QueryCallbackMap_t>
+ (c, d_getcallbackmap, cur_priv, outknobs));
+ }
+ return outknobs;
+}
+
+GNURadio::KnobPropMap
+rpcserver_ice::properties(const GNURadio::KnobIDList& knobs, const Ice::Current& c)
+{
+ GNURadio::KnobPropMap outknobs;
+
+ if(knobs.size() == 0) {
+ std::for_each(d_getcallbackmap.begin(), d_getcallbackmap.end(),
+ properties_all_f<QueryCallbackMap_t::value_type,
+ QueryCallbackMap_t,GNURadio::KnobPropMap>(c, d_getcallbackmap, cur_priv, outknobs));
+ }
+ else {
+ std::for_each(knobs.begin(), knobs.end(),
+ properties_f<GNURadio::KnobIDList::value_type,
+ QueryCallbackMap_t, GNURadio::KnobPropMap>(c, d_getcallbackmap, cur_priv, outknobs));
+ }
+ return outknobs;
+}
+
+void
+rpcserver_ice::shutdown(const Ice::Current& c)
+{
+ if(DEBUG)
+ std::cout << "Shutting down..." << std::endl;
+ c.adapter->getCommunicator()->shutdown();
+}
diff --git a/gnuradio-runtime/lib/rpcserver_selector.cc b/gnuradio-runtime/lib/rpcserver_selector.cc
new file mode 100644
index 0000000000..362d5f060a
--- /dev/null
+++ b/gnuradio-runtime/lib/rpcserver_selector.cc
@@ -0,0 +1,40 @@
+/* -*- 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.
+ */
+
+#include <rpcserver_booter_aggregator.h>
+#include <rpcmanager.h>
+#include <rpcserver_selector.h>
+
+bool rpcmanager::make_aggregator(false);
+
+#ifdef RPCSERVER_ICE
+ #include <rpcserver_booter_ice.h>
+ rpcmanager::rpcserver_booter_register_helper<rpcserver_booter_ice> boot_ice;
+#endif
+
+#ifdef RPCSERVER_ERLANG
+ #error TODO ERLANG
+#endif
+
+#ifdef RPCSERVER_XMLRPC
+ #error TODO XMLRPC
+#endif
diff --git a/gnuradio-runtime/lib/sine_table.h b/gnuradio-runtime/lib/sine_table.h
new file mode 100644
index 0000000000..69834943bc
--- /dev/null
+++ b/gnuradio-runtime/lib/sine_table.h
@@ -0,0 +1,1025 @@
+ // max_error = 2.353084136763606e-06
+ { 2.925817799165007e-09, 7.219194364267018e-09 },
+ { 2.925707643778599e-09, 2.526699001579799e-07 },
+ { 2.925487337153070e-09, 1.191140162167675e-06 },
+ { 2.925156887582842e-09, 3.284585035595589e-06 },
+ { 2.924716307509151e-09, 6.994872605695784e-06 },
+ { 2.924165613519592e-09, 1.278374920658798e-05 },
+ { 2.923504826347475e-09, 2.111280464718590e-05 },
+ { 2.922733970871080e-09, 3.244343744537165e-05 },
+ { 2.921853076112655e-09, 4.723682007436170e-05 },
+ { 2.920862175237416e-09, 6.595386421935634e-05 },
+ { 2.919761305552202e-09, 8.905518605213658e-05 },
+ { 2.918550508504146e-09, 1.170010715193098e-04 },
+ { 2.917229829679050e-09, 1.502514416517192e-04 },
+ { 2.915799318799769e-09, 1.892658178912071e-04 },
+ { 2.914259029724184e-09, 2.345032874456615e-04 },
+ { 2.912609020443340e-09, 2.864224686607020e-04 },
+ { 2.910849353079123e-09, 3.454814764261432e-04 },
+ { 2.908980093882049e-09, 4.121378876027343e-04 },
+ { 2.907001313228646e-09, 4.868487064877691e-04 },
+ { 2.904913085618902e-09, 5.700703303049837e-04 },
+ { 2.902715489673383e-09, 6.622585147355725e-04 },
+ { 2.900408608130373e-09, 7.638683394782519e-04 },
+ { 2.897992527842612e-09, 8.753541738578119e-04 },
+ { 2.895467339774186e-09, 9.971696424604937e-04 },
+ { 2.892833138996999e-09, 1.129767590823255e-03 },
+ { 2.890090024687216e-09, 1.273600051161478e-03 },
+ { 2.887238100121550e-09, 1.429118208142094e-03 },
+ { 2.884277472673313e-09, 1.596772364709564e-03 },
+ { 2.881208253808507e-09, 1.777011907950626e-03 },
+ { 2.878030559081432e-09, 1.970285275029487e-03 },
+ { 2.874744508130554e-09, 2.177039919152579e-03 },
+ { 2.871350224673798e-09, 2.397722275614272e-03 },
+ { 2.867847836504030e-09, 2.632777727878843e-03 },
+ { 2.864237475484149e-09, 2.882650573737405e-03 },
+ { 2.860519277542297e-09, 3.147783991507308e-03 },
+ { 2.856693382666432e-09, 3.428620006328931e-03 },
+ { 2.852759934899389e-09, 3.725599456482154e-03 },
+ { 2.848719082333207e-09, 4.039161959812243e-03 },
+ { 2.844570977103752e-09, 4.369745880190706e-03 },
+ { 2.840315775384800e-09, 4.717788294077374e-03 },
+ { 2.835953637382310e-09, 5.083724957128360e-03 },
+ { 2.831484727328322e-09, 5.467990270896617e-03 },
+ { 2.826909213474759e-09, 5.871017249604038e-03 },
+ { 2.822227268087134e-09, 6.293237486988512e-03 },
+ { 2.817439067438018e-09, 6.735081123237729e-03 },
+ { 2.812544791800534e-09, 7.196976811989608e-03 },
+ { 2.807544625441273e-09, 7.679351687456759e-03 },
+ { 2.802438756613836e-09, 8.182631331563162e-03 },
+ { 2.797227377551135e-09, 8.707239741274575e-03 },
+ { 2.791910684458716e-09, 9.253599295902304e-03 },
+ { 2.786488877507140e-09, 9.822130724578715e-03 },
+ { 2.780962160824228e-09, 1.041325307382490e-02 },
+ { 2.775330742487884e-09, 1.102738367513773e-02 },
+ { 2.769594834517682e-09, 1.166493811278924e-02 },
+ { 2.763754652867477e-09, 1.232633019159818e-02 },
+ { 2.757810417416620e-09, 1.301197190494069e-02 },
+ { 2.751762351962413e-09, 1.372227340270610e-02 },
+ { 2.745610684210923e-09, 1.445764295952962e-02 },
+ { 2.739355645769094e-09, 1.521848694296229e-02 },
+ { 2.732997472135539e-09, 1.600520978188769e-02 },
+ { 2.726536402691907e-09, 1.681821393496225e-02 },
+ { 2.719972680693777e-09, 1.765789985920713e-02 },
+ { 2.713306553261610e-09, 1.852466597868779e-02 },
+ { 2.706538271371373e-09, 1.941890865333146e-02 },
+ { 2.699668089844909e-09, 2.034102214787814e-02 },
+ { 2.692696267340880e-09, 2.129139860085272e-02 },
+ { 2.685623066344263e-09, 2.227042799383416e-02 },
+ { 2.678448753157212e-09, 2.327849812064098e-02 },
+ { 2.671173597888530e-09, 2.431599455681316e-02 },
+ { 2.663797874443630e-09, 2.538330062913108e-02 },
+ { 2.656321860514457e-09, 2.648079738524795e-02 },
+ { 2.648745837568575e-09, 2.760886356354952e-02 },
+ { 2.641070090839117e-09, 2.876787556300114e-02 },
+ { 2.633294909313421e-09, 2.995820741329835e-02 },
+ { 2.625420585722845e-09, 3.118023074495535e-02 },
+ { 2.617447416531143e-09, 3.243431475972608e-02 },
+ { 2.609375701923643e-09, 3.372082620101990e-02 },
+ { 2.601205745795833e-09, 3.504012932452527e-02 },
+ { 2.592937855741933e-09, 3.639258586895711e-02 },
+ { 2.584572343043400e-09, 3.777855502693250e-02 },
+ { 2.576109522656942e-09, 3.919839341605197e-02 },
+ { 2.567549713203028e-09, 4.065245505002102e-02 },
+ { 2.558893236953688e-09, 4.214109131001403e-02 },
+ { 2.550140419820252e-09, 4.366465091617666e-02 },
+ { 2.541291591341445e-09, 4.522347989919473e-02 },
+ { 2.532347084670572e-09, 4.681792157215026e-02 },
+ { 2.523307236563343e-09, 4.844831650239501e-02 },
+ { 2.514172387364900e-09, 5.011500248369893e-02 },
+ { 2.504942880997064e-09, 5.181831450849345e-02 },
+ { 2.495619064945627e-09, 5.355858474024022e-02 },
+ { 2.486201290246928e-09, 5.533614248606705e-02 },
+ { 2.476689911475047e-09, 5.715131416942842e-02 },
+ { 2.467085286727668e-09, 5.900442330315692e-02 },
+ { 2.457387777613798e-09, 6.089579046229943e-02 },
+ { 2.447597749239101e-09, 6.282573325755320e-02 },
+ { 2.437715570192557e-09, 6.479456630859221e-02 },
+ { 2.427741612532542e-09, 6.680260121764925e-02 },
+ { 2.417676251773166e-09, 6.885014654319160e-02 },
+ { 2.407519866869294e-09, 7.093750777401114e-02 },
+ { 2.397272840203310e-09, 7.306498730310884e-02 },
+ { 2.386935557569868e-09, 7.523288440214027e-02 },
+ { 2.376508408161815e-09, 7.744149519577415e-02 },
+ { 2.365991784555363e-09, 7.969111263635709e-02 },
+ { 2.355386082695641e-09, 8.198202647865405e-02 },
+ { 2.344691701881232e-09, 8.431452325495814e-02 },
+ { 2.333909044749407e-09, 8.668888625021409e-02 },
+ { 2.323038517261246e-09, 8.910539547731611e-02 },
+ { 2.312080528685971e-09, 9.156432765274414e-02 },
+ { 2.301035491585642e-09, 9.406595617227698e-02 },
+ { 2.289903821799651e-09, 9.661055108691619e-02 },
+ { 2.278685938428940e-09, 9.919837907903295e-02 },
+ { 2.267382263820762e-09, 1.018297034385580e-01 },
+ { 2.255993223551837e-09, 1.045047840397028e-01 },
+ { 2.244519246413220e-09, 1.072238773174577e-01 },
+ { 2.232960764393620e-09, 1.099872362446146e-01 },
+ { 2.221318212663309e-09, 1.127951103088245e-01 },
+ { 2.209592029557811e-09, 1.156477454898748e-01 },
+ { 2.197782656561395e-09, 1.185453842371912e-01 },
+ { 2.185890538290176e-09, 1.214882654476019e-01 },
+ { 2.173916122475606e-09, 1.244766244431883e-01 },
+ { 2.161859859947797e-09, 1.275106929493488e-01 },
+ { 2.149722204618256e-09, 1.305906990731841e-01 },
+ { 2.137503613462743e-09, 1.337168672820376e-01 },
+ { 2.125204546504321e-09, 1.368894183821595e-01 },
+ { 2.112825466795944e-09, 1.401085694976751e-01 },
+ { 2.100366840402933e-09, 1.433745340497602e-01 },
+ { 2.087829136385612e-09, 1.466875217359607e-01 },
+ { 2.075212826781308e-09, 1.500477385098620e-01 },
+ { 2.062518386587093e-09, 1.534553865607503e-01 },
+ { 2.049746293741359e-09, 1.569106642937665e-01 },
+ { 2.036897029106193e-09, 1.604137663100403e-01 },
+ { 2.023971076449323e-09, 1.639648833871233e-01 },
+ { 2.010968922425217e-09, 1.675642024598467e-01 },
+ { 1.997891056557933e-09, 1.712119066008896e-01 },
+ { 1.984737971221581e-09, 1.749081750021970e-01 },
+ { 1.971510161622434e-09, 1.786531829561379e-01 },
+ { 1.958208125780130e-09, 1.824471018371070e-01 },
+ { 1.944832364508511e-09, 1.862900990834311e-01 },
+ { 1.931383381397782e-09, 1.901823381790926e-01 },
+ { 1.917861682794392e-09, 1.941239786363039e-01 },
+ { 1.904267777782611e-09, 1.981151759777950e-01 },
+ { 1.890602178165317e-09, 2.021560817195309e-01 },
+ { 1.876865398444616e-09, 2.062468433536743e-01 },
+ { 1.863057955802572e-09, 2.103876043317229e-01 },
+ { 1.849180370081465e-09, 2.145785040479915e-01 },
+ { 1.835233163764673e-09, 2.188196778231083e-01 },
+ { 1.821216861956509e-09, 2.231112568880342e-01 },
+ { 1.807131992362945e-09, 2.274533683680190e-01 },
+ { 1.792979085271234e-09, 2.318461352671018e-01 },
+ { 1.778758673530482e-09, 2.362896764525300e-01 },
+ { 1.764471292530943e-09, 2.407841066397789e-01 },
+ { 1.750117480184598e-09, 2.453295363773890e-01 },
+ { 1.735697776904342e-09, 2.499260720324433e-01 },
+ { 1.721212725583874e-09, 2.545738157760434e-01 },
+ { 1.706662871577097e-09, 2.592728655691494e-01 },
+ { 1.692048762677849e-09, 2.640233151485341e-01 },
+ { 1.677370949099090e-09, 2.688252540131204e-01 },
+ { 1.662629983452104e-09, 2.736787674105404e-01 },
+ { 1.647826420726167e-09, 2.785839363237506e-01 },
+ { 1.632960818266680e-09, 2.835408374583758e-01 },
+ { 1.618033735755429e-09, 2.885495432295704e-01 },
+ { 1.603045735188609e-09, 2.936101217498361e-01 },
+ { 1.587997380855918e-09, 2.987226368167127e-01 },
+ { 1.572889239319430e-09, 3.038871479007593e-01 },
+ { 1.557721879392051e-09, 3.091037101339017e-01 },
+ { 1.542495872116447e-09, 3.143723742978435e-01 },
+ { 1.527211790743024e-09, 3.196931868130269e-01 },
+ { 1.511870210708909e-09, 3.250661897274744e-01 },
+ { 1.496471709615926e-09, 3.304914207062036e-01 },
+ { 1.481016867208896e-09, 3.359689130207621e-01 },
+ { 1.465506265353924e-09, 3.414986955389885e-01 },
+ { 1.449940488016384e-09, 3.470807927151147e-01 },
+ { 1.434320121238994e-09, 3.527152245800635e-01 },
+ { 1.418645753119802e-09, 3.584020067320109e-01 },
+ { 1.402917973789838e-09, 3.641411503272979e-01 },
+ { 1.387137375391042e-09, 3.699326620714776e-01 },
+ { 1.371304552054134e-09, 3.757765442106153e-01 },
+ { 1.355420099875958e-09, 3.816727945230153e-01 },
+ { 1.339484616897137e-09, 3.876214063110671e-01 },
+ { 1.323498703079580e-09, 3.936223683933865e-01 },
+ { 1.307462960283922e-09, 3.996756650972121e-01 },
+ { 1.291377992246768e-09, 4.057812762511174e-01 },
+ { 1.275244404558188e-09, 4.119391771778626e-01 },
+ { 1.259062804638585e-09, 4.181493386877248e-01 },
+ { 1.242833801715929e-09, 4.244117270719281e-01 },
+ { 1.226558006803155e-09, 4.307263040962509e-01 },
+ { 1.210236032674760e-09, 4.370930269951803e-01 },
+ { 1.193868493843725e-09, 4.435118484661861e-01 },
+ { 1.177456006538695e-09, 4.499827166641340e-01 },
+ { 1.160999188680582e-09, 4.565055751961679e-01 },
+ { 1.144498659859216e-09, 4.630803631168164e-01 },
+ { 1.127955041310214e-09, 4.697070149232604e-01 },
+ { 1.111368955891417e-09, 4.763854605510119e-01 },
+ { 1.094741028059551e-09, 4.831156253697562e-01 },
+ { 1.078071883846871e-09, 4.898974301794375e-01 },
+ { 1.061362150836978e-09, 4.967307912069362e-01 },
+ { 1.044612458142151e-09, 5.036156201023686e-01 },
+ { 1.027823436378632e-09, 5.105518239364775e-01 },
+ { 1.010995717643647e-09, 5.175393051975563e-01 },
+ { 9.941299354913699e-10, 5.245779617890562e-01 },
+ { 9.772267249089968e-10, 5.316676870274011e-01 },
+ { 9.602867222926046e-10, 5.388083696401416e-01 },
+ { 9.433105654240147e-10, 5.459998937639375e-01 },
+ { 9.262988934458084e-10, 5.532421389435711e-01 },
+ { 9.092523468378193e-10, 5.605349801305876e-01 },
+ { 8.921715673928355e-10, 5.678782876825250e-01 },
+ { 8.750571981926701e-10, 5.752719273622372e-01 },
+ { 8.579098835836508e-10, 5.827157603377209e-01 },
+ { 8.407302691522673e-10, 5.902096431821322e-01 },
+ { 8.235190017016133e-10, 5.977534278737073e-01 },
+ { 8.062767292259225e-10, 6.053469617967722e-01 },
+ { 7.890041008871165e-10, 6.129900877421282e-01 },
+ { 7.717017669898175e-10, 6.206826439083659e-01 },
+ { 7.543703789572603e-10, 6.284244639030392e-01 },
+ { 7.370105893063053e-10, 6.362153767444958e-01 },
+ { 7.196230516231919e-10, 6.440552068636356e-01 },
+ { 7.022084205389746e-10, 6.519437741060674e-01 },
+ { 6.847673517046416e-10, 6.598808937346672e-01 },
+ { 6.673005017664976e-10, 6.678663764322770e-01 },
+ { 6.498085283416530e-10, 6.759000283046127e-01 },
+ { 6.322920899929834e-10, 6.839816508836737e-01 },
+ { 6.147518462045659e-10, 6.921110411311926e-01 },
+ { 5.971884573565851e-10, 7.002879914425926e-01 },
+ { 5.796025847007168e-10, 7.085122896509806e-01 },
+ { 5.619948903351406e-10, 7.167837190315758e-01 },
+ { 5.443660371796048e-10, 7.251020583063744e-01 },
+ { 5.267166889504394e-10, 7.334670816491009e-01 },
+ { 5.090475101356742e-10, 7.418785586903696e-01 },
+ { 4.913591659698399e-10, 7.503362545232619e-01 },
+ { 4.736523224091392e-10, 7.588399297089872e-01 },
+ { 4.559276461062478e-10, 7.673893402829834e-01 },
+ { 4.381858043851147e-10, 7.759842377612828e-01 },
+ { 4.204274652161870e-10, 7.846243691469355e-01 },
+ { 4.026532971908398e-10, 7.933094769370790e-01 },
+ { 3.848639694963359e-10, 8.020392991300200e-01 },
+ { 3.670601518910503e-10, 8.108135692324444e-01 },
+ { 3.492425146784233e-10, 8.196320162675177e-01 },
+ { 3.314117286825031e-10, 8.284943647824689e-01 },
+ { 3.135684652223755e-10, 8.374003348569865e-01 },
+ { 2.957133960867535e-10, 8.463496421118015e-01 },
+ { 2.778471935089361e-10, 8.553419977173513e-01 },
+ { 2.599705301412391e-10, 8.643771084029740e-01 },
+ { 2.420840790301135e-10, 8.734546764660205e-01 },
+ { 2.241885135902046e-10, 8.825743997817682e-01 },
+ { 2.062845075795238e-10, 8.917359718130367e-01 },
+ { 1.883727350736140e-10, 9.009390816205823e-01 },
+ { 1.704538704408269e-10, 9.101834138731877e-01 },
+ { 1.525285883160648e-10, 9.194686488588080e-01 },
+ { 1.345975635762696e-10, 9.287944624950824e-01 },
+ { 1.166614713141648e-10, 9.381605263410157e-01 },
+ { 9.872098681369190e-11, 9.475665076080466e-01 },
+ { 8.077678552380464e-11, 9.570120691722380e-01 },
+ { 6.282954303364090e-11, 9.664968695860140e-01 },
+ { 4.487993504668797e-11, 9.760205630906909e-01 },
+ { 2.692863735553042e-11, 9.855827996289697e-01 },
+ { 8.976325816439114e-12, 9.951832248577780e-01 },
+ { -8.976323676304494e-12, 1.004821480161519e+00 },
+ { -2.692863521550168e-11, 1.014497202665280e+00 },
+ { -4.487993290681805e-11, 1.024210025248670e+00 },
+ { -6.282954089398273e-11, 1.033959576559617e+00 },
+ { -8.077678338451706e-11, 1.043745481028715e+00 },
+ { -9.872098467477489e-11, 1.053567358883467e+00 },
+ { -1.166614691757772e-10, 1.063424826163223e+00 },
+ { -1.345975614383584e-10, 1.073317494734013e+00 },
+ { -1.525285861788948e-10, 1.083244972303963e+00 },
+ { -1.704538683042922e-10, 1.093206862438572e+00 },
+ { -1.883727329379793e-10, 1.103202764576806e+00 },
+ { -2.062845054446831e-10, 1.113232274046796e+00 },
+ { -2.241885114563697e-10, 1.123294982082432e+00 },
+ { -2.420840768973375e-10, 1.133390475839767e+00 },
+ { -2.599705280096278e-10, 1.143518338413855e+00 },
+ { -2.778471913784365e-10, 1.153678148855860e+00 },
+ { -2.957133939575774e-10, 1.163869482190458e+00 },
+ { -3.135684630945758e-10, 1.174091909433296e+00 },
+ { -3.314117265561857e-10, 1.184344997608959e+00 },
+ { -3.492425125535882e-10, 1.194628309769018e+00 },
+ { -3.670601497678034e-10, 1.204941405010466e+00 },
+ { -3.848639673748360e-10, 1.215283838494269e+00 },
+ { -4.026532950710339e-10, 1.225655161464298e+00 },
+ { -4.204274630982869e-10, 1.236054921266445e+00 },
+ { -4.381858022691734e-10, 1.246482661367958e+00 },
+ { -4.559276439922654e-10, 1.256937921377146e+00 },
+ { -4.736523202972214e-10, 1.267420237063216e+00 },
+ { -4.913591638600925e-10, 1.277929140376502e+00 },
+ { -5.090475080282032e-10, 1.288464159468706e+00 },
+ { -5.267166868452449e-10, 1.299024818713528e+00 },
+ { -5.443660350768455e-10, 1.309610638727845e+00 },
+ { -5.619948882348695e-10, 1.320221136392390e+00 },
+ { -5.796025826029868e-10, 1.330855824873457e+00 },
+ { -5.971884552615020e-10, 1.341514213644420e+00 },
+ { -6.147518441122357e-10, 1.352195808507556e+00 },
+ { -6.322920879034590e-10, 1.362900111616144e+00 },
+ { -6.498085262549874e-10, 1.373626621496939e+00 },
+ { -6.673004996827436e-10, 1.384374833072571e+00 },
+ { -6.847673496239581e-10, 1.395144237684605e+00 },
+ { -7.022084184613616e-10, 1.405934323116231e+00 },
+ { -7.196230495488082e-10, 1.416744573616104e+00 },
+ { -7.370105872352039e-10, 1.427574469921397e+00 },
+ { -7.543703768894941e-10, 1.438423489281758e+00 },
+ { -7.717017649255453e-10, 1.449291105483472e+00 },
+ { -7.890040988262324e-10, 1.460176788873383e+00 },
+ { -8.062767271686383e-10, 1.471080006383765e+00 },
+ { -8.235189996479819e-10, 1.482000221556656e+00 },
+ { -8.407302671024475e-10, 1.492936894569018e+00 },
+ { -8.579098815375368e-10, 1.503889482257845e+00 },
+ { -8.750571961505266e-10, 1.514857438145604e+00 },
+ { -8.921715653546624e-10, 1.525840212465756e+00 },
+ { -9.092523448036167e-10, 1.536837252188703e+00 },
+ { -9.262988914157881e-10, 1.547848001047890e+00 },
+ { -9.433105633981766e-10, 1.558871899565883e+00 },
+ { -9.602867202711075e-10, 1.569908385081254e+00 },
+ { -9.772267228916820e-10, 1.580956891774897e+00 },
+ { -9.941299334786078e-10, 1.592016850697478e+00 },
+ { -1.010995715635332e-09, 1.603087689796053e+00 },
+ { -1.027823434374870e-09, 1.614168833942028e+00 },
+ { -1.044612456143047e-09, 1.625259704958335e+00 },
+ { -1.061362148842745e-09, 1.636359721647526e+00 },
+ { -1.078071881857297e-09, 1.647468299819543e+00 },
+ { -1.094741026074900e-09, 1.658584852320419e+00 },
+ { -1.111368953911690e-09, 1.669708789060341e+00 },
+ { -1.127955039335462e-09, 1.680839517042381e+00 },
+ { -1.144498657889600e-09, 1.691976440391624e+00 },
+ { -1.160999186716154e-09, 1.703118960383971e+00 },
+ { -1.177456004579561e-09, 1.714266475475616e+00 },
+ { -1.193868491889832e-09, 1.725418381332405e+00 },
+ { -1.210236030726319e-09, 1.736574070859850e+00 },
+ { -1.226558004860220e-09, 1.747732934232508e+00 },
+ { -1.242833799778447e-09, 1.758894358924547e+00 },
+ { -1.259062802706714e-09, 1.770057729740021e+00 },
+ { -1.275244402631982e-09, 1.781222428842935e+00 },
+ { -1.291377990326492e-09, 1.792387835788660e+00 },
+ { -1.307462958369363e-09, 1.803553327553897e+00 },
+ { -1.323498701170897e-09, 1.814718278568759e+00 },
+ { -1.339484614994490e-09, 1.825882060747428e+00 },
+ { -1.355420097979292e-09, 1.837044043519582e+00 },
+ { -1.371304550163662e-09, 1.848203593862598e+00 },
+ { -1.387137373506711e-09, 1.859360076332671e+00 },
+ { -1.402917971911754e-09, 1.870512853097495e+00 },
+ { -1.418645751248018e-09, 1.881661283967967e+00 },
+ { -1.434320119373722e-09, 1.892804726431080e+00 },
+ { -1.449940486157623e-09, 1.903942535681972e+00 },
+ { -1.465506263501516e-09, 1.915074064656886e+00 },
+ { -1.481016865363264e-09, 1.926198664066737e+00 },
+ { -1.496471707776859e-09, 1.937315682428795e+00 },
+ { -1.511870208876724e-09, 1.948424466101625e+00 },
+ { -1.527211788917509e-09, 1.959524359317042e+00 },
+ { -1.542495870297867e-09, 1.970614704215133e+00 },
+ { -1.557721877580406e-09, 1.981694840876775e+00 },
+ { -1.572889237514880e-09, 1.992764107358707e+00 },
+ { -1.587997379058514e-09, 2.003821839726753e+00 },
+ { -1.603045733398246e-09, 2.014867372090665e+00 },
+ { -1.618033733972424e-09, 2.025900036638798e+00 },
+ { -1.632960816490822e-09, 2.036919163671778e+00 },
+ { -1.647826418957721e-09, 2.047924081638631e+00 },
+ { -1.662629981691070e-09, 2.058914117170269e+00 },
+ { -1.677370947345626e-09, 2.069888595116115e+00 },
+ { -1.692048760931849e-09, 2.080846838577820e+00 },
+ { -1.706662869838827e-09, 2.091788168946183e+00 },
+ { -1.721212723853279e-09, 2.102711905935372e+00 },
+ { -1.735697775181424e-09, 2.113617367619504e+00 },
+ { -1.750117478469621e-09, 2.124503870468520e+00 },
+ { -1.764471290823748e-09, 2.135370729383332e+00 },
+ { -1.778758671831281e-09, 2.146217257733207e+00 },
+ { -1.792979083579974e-09, 2.157042767390815e+00 },
+ { -1.807131990679890e-09, 2.167846568770014e+00 },
+ { -1.821216860281448e-09, 2.178627970860822e+00 },
+ { -1.835233162097977e-09, 2.189386281268046e+00 },
+ { -1.849180368423027e-09, 2.200120806246095e+00 },
+ { -1.863057954152340e-09, 2.210830850737588e+00 },
+ { -1.876865396802907e-09, 2.221515718409926e+00 },
+ { -1.890602176531920e-09, 2.232174711691990e+00 },
+ { -1.904267776157843e-09, 2.242807131812679e+00 },
+ { -1.917861681178094e-09, 2.253412278837029e+00 },
+ { -1.931383379790273e-09, 2.263989451705295e+00 },
+ { -1.944832362909578e-09, 2.274537948269257e+00 },
+ { -1.958208124189984e-09, 2.285057065331676e+00 },
+ { -1.971510160041235e-09, 2.295546098682665e+00 },
+ { -1.984737969649064e-09, 2.306004343138794e+00 },
+ { -1.997891054994522e-09, 2.316431092581699e+00 },
+ { -2.010968920870647e-09, 2.326825639994779e+00 },
+ { -2.023971074903858e-09, 2.337187277503834e+00 },
+ { -2.036897027569834e-09, 2.347515296413520e+00 },
+ { -2.049746292214264e-09, 2.357808987247877e+00 },
+ { -2.062518385069210e-09, 2.368067639787542e+00 },
+ { -2.075212825272584e-09, 2.378290543109652e+00 },
+ { -2.087829134886364e-09, 2.388476985626922e+00 },
+ { -2.100366838912949e-09, 2.398626255125417e+00 },
+ { -2.112825465315542e-09, 2.408737638805759e+00 },
+ { -2.125204545033289e-09, 2.418810423320288e+00 },
+ { -2.137503612001452e-09, 2.428843894814472e+00 },
+ { -2.149722203166389e-09, 2.438837338964302e+00 },
+ { -2.161859858505829e-09, 2.448790041018174e+00 },
+ { -2.173916121043380e-09, 2.458701285834241e+00 },
+ { -2.185890536867478e-09, 2.468570357921585e+00 },
+ { -2.197782655148702e-09, 2.478396541480230e+00 },
+ { -2.209592028154913e-09, 2.488179120439544e+00 },
+ { -2.221318211270522e-09, 2.497917378500214e+00 },
+ { -2.232960763010574e-09, 2.507610599172123e+00 },
+ { -2.244519245040444e-09, 2.517258065817044e+00 },
+ { -2.255993222189014e-09, 2.526859061686102e+00 },
+ { -2.267382262468209e-09, 2.536412869962689e+00 },
+ { -2.278685937086658e-09, 2.545918773800664e+00 },
+ { -2.289903820467374e-09, 2.555376056366064e+00 },
+ { -2.301035490263848e-09, 2.564784000877677e+00 },
+ { -2.312080527374447e-09, 2.574141890646339e+00 },
+ { -2.323038515960257e-09, 2.583449009117307e+00 },
+ { -2.333909043458635e-09, 2.592704639909166e+00 },
+ { -2.344691700601153e-09, 2.601908066856634e+00 },
+ { -2.355386081425938e-09, 2.611058574048749e+00 },
+ { -2.365991783296513e-09, 2.620155445872768e+00 },
+ { -2.376508406913500e-09, 2.629197967052127e+00 },
+ { -2.386935556332088e-09, 2.638185422689490e+00 },
+ { -2.397272838976436e-09, 2.647117098307332e+00 },
+ { -2.407519865653114e-09, 2.655992279887846e+00 },
+ { -2.417676250567891e-09, 2.664810253915885e+00 },
+ { -2.427741611338014e-09, 2.673570307418169e+00 },
+ { -2.437715569009093e-09, 2.682271728006635e+00 },
+ { -2.447597748066437e-09, 2.690913803917100e+00 },
+ { -2.457387776452357e-09, 2.699495824053297e+00 },
+ { -2.467085285577292e-09, 2.708017078025636e+00 },
+ { -2.476689910335470e-09, 2.716476856194105e+00 },
+ { -2.486201289118733e-09, 2.724874449709689e+00 },
+ { -2.495619063828443e-09, 2.733209150554255e+00 },
+ { -2.504942879891263e-09, 2.741480251583985e+00 },
+ { -2.514172386270163e-09, 2.749687046568741e+00 },
+ { -2.523307235480146e-09, 2.757828830235740e+00 },
+ { -2.532347083598520e-09, 2.765904898308531e+00 },
+ { -2.541291590280960e-09, 2.773914547551261e+00 },
+ { -2.550140418771202e-09, 2.781857075807392e+00 },
+ { -2.558893235915887e-09, 2.789731782043156e+00 },
+ { -2.567549712176927e-09, 2.797537966388929e+00 },
+ { -2.576109521642196e-09, 2.805274930179221e+00 },
+ { -2.584572342040407e-09, 2.812941975996573e+00 },
+ { -2.592937854750428e-09, 2.820538407710556e+00 },
+ { -2.601205744816134e-09, 2.828063530521908e+00 },
+ { -2.609375700955458e-09, 2.835516651001539e+00 },
+ { -2.617447415574869e-09, 2.842897077134583e+00 },
+ { -2.625420584778350e-09, 2.850204118359573e+00 },
+ { -2.633294908380520e-09, 2.857437085611509e+00 },
+ { -2.641070089918234e-09, 2.864595291363663e+00 },
+ { -2.648745836659391e-09, 2.871678049666939e+00 },
+ { -2.656321859617343e-09, 2.878684676194483e+00 },
+ { -2.663797873558322e-09, 2.885614488280000e+00 },
+ { -2.671173597015318e-09, 2.892466804962122e+00 },
+ { -2.678448752295859e-09, 2.899240947023252e+00 },
+ { -2.685623065495139e-09, 2.905936237033475e+00 },
+ { -2.692696266503800e-09, 2.912551999389617e+00 },
+ { -2.699668089019767e-09, 2.919087560358171e+00 },
+ { -2.706538270558513e-09, 2.925542248116882e+00 },
+ { -2.713306552460767e-09, 2.931915392794031e+00 },
+ { -2.719972679905295e-09, 2.938206326512581e+00 },
+ { -2.726536401915442e-09, 2.944414383428562e+00 },
+ { -2.732997471371516e-09, 2.950538899775061e+00 },
+ { -2.739355645017194e-09, 2.956579213900666e+00 },
+ { -2.745610683471516e-09, 2.962534666313284e+00 },
+ { -2.751762351235315e-09, 2.968404599718795e+00 },
+ { -2.757810416701751e-09, 2.974188359063684e+00 },
+ { -2.763754652165128e-09, 2.979885291576143e+00 },
+ { -2.769594833827588e-09, 2.985494746805227e+00 },
+ { -2.775330741810390e-09, 2.991016076664491e+00 },
+ { -2.780962160159068e-09, 2.996448635469842e+00 },
+ { -2.786488876854607e-09, 3.001791779983262e+00 },
+ { -2.791910683818570e-09, 3.007044869450794e+00 },
+ { -2.797227376923695e-09, 3.012207265645876e+00 },
+ { -2.802438755998943e-09, 3.017278332907412e+00 },
+ { -2.807544624838820e-09, 3.022257438182037e+00 },
+ { -2.812544791210840e-09, 3.027143951064684e+00 },
+ { -2.817439066860792e-09, 3.031937243837070e+00 },
+ { -2.822227267522746e-09, 3.036636691510884e+00 },
+ { -2.826909212922864e-09, 3.041241671864994e+00 },
+ { -2.831484726789317e-09, 3.045751565488710e+00 },
+ { -2.835953636855826e-09, 3.050165755818853e+00 },
+ { -2.840315774871260e-09, 3.054483629182857e+00 },
+ { -2.844570976602957e-09, 3.058704574835744e+00 },
+ { -2.848719081844986e-09, 3.062827985002047e+00 },
+ { -2.852759934424164e-09, 3.066853254915581e+00 },
+ { -2.856693382203833e-09, 3.070779782857041e+00 },
+ { -2.860519277092708e-09, 3.074606970196721e+00 },
+ { -2.864237475047239e-09, 3.078334221430809e+00 },
+ { -2.867847836080156e-09, 3.081960944223928e+00 },
+ { -2.871350224262603e-09, 3.085486549445314e+00 },
+ { -2.874744507732462e-09, 3.088910451211251e+00 },
+ { -2.878030558696270e-09, 3.092232066921130e+00 },
+ { -2.881208253436038e-09, 3.095450817298478e+00 },
+ { -2.884277472313999e-09, 3.098566126429974e+00 },
+ { -2.887238099774968e-09, 3.101577421802070e+00 },
+ { -2.890090024353816e-09, 3.104484134342861e+00 },
+ { -2.892833138676371e-09, 3.107285698457308e+00 },
+ { -2.895467339466766e-09, 3.109981552069083e+00 },
+ { -2.897992527547963e-09, 3.112571136655481e+00 },
+ { -2.900408607848946e-09, 3.115053897289195e+00 },
+ { -2.902715489404992e-09, 3.117429282673042e+00 },
+ { -2.904913085363323e-09, 3.119696745180238e+00 },
+ { -2.907001312986328e-09, 3.121855740892224e+00 },
+ { -2.908980093652563e-09, 3.123905729634218e+00 },
+ { -2.910849352862924e-09, 3.125846175016163e+00 },
+ { -2.912609020239985e-09, 3.127676544466606e+00 },
+ { -2.914259029534118e-09, 3.129396309273659e+00 },
+ { -2.915799318622574e-09, 3.131004944618667e+00 },
+ { -2.917229829515169e-09, 3.132501929616775e+00 },
+ { -2.918550508353347e-09, 3.133886747350606e+00 },
+ { -2.919761305414294e-09, 3.135158884909254e+00 },
+ { -2.920862175112829e-09, 3.136317833424958e+00 },
+ { -2.921853076000972e-09, 3.137363088107359e+00 },
+ { -2.922733970772719e-09, 3.138294148283254e+00 },
+ { -2.923504826262027e-09, 3.139110517429204e+00 },
+ { -2.924165613447473e-09, 3.139811703211207e+00 },
+ { -2.924716307449950e-09, 3.140397217517018e+00 },
+ { -2.925156887536978e-09, 3.140866576495489e+00 },
+ { -2.925487337120335e-09, 3.141219300588825e+00 },
+ { -2.925707643758784e-09, 3.141454914570261e+00 },
+ { -2.925817799158535e-09, 3.141572947579352e+00 },
+ { -2.925817799171455e-09, 3.141572933154836e+00 },
+ { -2.925707643798390e-09, 3.141454409272987e+00 },
+ { -2.925487337185779e-09, 3.141216918378770e+00 },
+ { -2.925156887628892e-09, 3.140860007424112e+00 },
+ { -2.924716307568119e-09, 3.140383227898687e+00 },
+ { -2.924165613591896e-09, 3.139786135867868e+00 },
+ { -2.923504826432903e-09, 3.139068292003385e+00 },
+ { -2.922733970969412e-09, 3.138229261619561e+00 },
+ { -2.921853076224321e-09, 3.137268614707029e+00 },
+ { -2.920862175361976e-09, 3.136185925964038e+00 },
+ { -2.919761305690083e-09, 3.134980774833275e+00 },
+ { -2.918550508654911e-09, 3.133652745531368e+00 },
+ { -2.917229829843137e-09, 3.132201427085629e+00 },
+ { -2.915799318976726e-09, 3.130626413363146e+00 },
+ { -2.914259029914435e-09, 3.128927303107136e+00 },
+ { -2.912609020646661e-09, 3.127103699965947e+00 },
+ { -2.910849353295315e-09, 3.125155212527586e+00 },
+ { -2.908980094111509e-09, 3.123081454351802e+00 },
+ { -2.907001313470937e-09, 3.120882043999591e+00 },
+ { -2.904913085874448e-09, 3.118556605068443e+00 },
+ { -2.902715489941767e-09, 3.116104766219928e+00 },
+ { -2.900408608411958e-09, 3.113526161214776e+00 },
+ { -2.897992528137022e-09, 3.110820428940251e+00 },
+ { -2.895467340081818e-09, 3.107987213444579e+00 },
+ { -2.892833139317615e-09, 3.105026163964191e+00 },
+ { -2.890090025020589e-09, 3.101936934956479e+00 },
+ { -2.887238100468092e-09, 3.098719186130021e+00 },
+ { -2.884277473032614e-09, 3.095372582472161e+00 },
+ { -2.881208254180937e-09, 3.091896794282404e+00 },
+ { -2.878030559466594e-09, 3.088291497198199e+00 },
+ { -2.874744508528832e-09, 3.084556372228054e+00 },
+ { -2.871350225084755e-09, 3.080691105776848e+00 },
+ { -2.867847836928063e-09, 3.076695389678615e+00 },
+ { -2.864237475921086e-09, 3.072568921221621e+00 },
+ { -2.860519277991847e-09, 3.068311403179147e+00 },
+ { -2.856693383129018e-09, 3.063922543837792e+00 },
+ { -2.852759935374575e-09, 3.059402057023109e+00 },
+ { -2.848719082821403e-09, 3.054749662130841e+00 },
+ { -2.844570977604520e-09, 3.049965084150782e+00 },
+ { -2.840315775898525e-09, 3.045048053697736e+00 },
+ { -2.835953637908582e-09, 3.039998307034967e+00 },
+ { -2.831484727867511e-09, 3.034815586104635e+00 },
+ { -2.826909214026628e-09, 3.029499638550941e+00 },
+ { -2.822227268651470e-09, 3.024050217748861e+00 },
+ { -2.817439068015245e-09, 3.018467082830179e+00 },
+ { -2.812544792390175e-09, 3.012749998707001e+00 },
+ { -2.807544626043751e-09, 3.006898736100911e+00 },
+ { -2.802438757228650e-09, 3.000913071564665e+00 },
+ { -2.797227378178760e-09, 2.994792787510961e+00 },
+ { -2.791910685098702e-09, 2.988537672233504e+00 },
+ { -2.786488878159805e-09, 2.982147519935565e+00 },
+ { -2.780962161489413e-09, 2.975622130750641e+00 },
+ { -2.775330743165298e-09, 2.968961310769028e+00 },
+ { -2.769594835207775e-09, 2.962164872061613e+00 },
+ { -2.763754653569747e-09, 2.955232632701135e+00 },
+ { -2.757810418131543e-09, 2.948164416789036e+00 },
+ { -2.751762352689432e-09, 2.940960054474719e+00 },
+ { -2.745610684950541e-09, 2.933619381982341e+00 },
+ { -2.739355646520809e-09, 2.926142241629213e+00 },
+ { -2.732997472899722e-09, 2.918528481852205e+00 },
+ { -2.726536403468318e-09, 2.910777957226018e+00 },
+ { -2.719972681482232e-09, 2.902890528487386e+00 },
+ { -2.713306554062453e-09, 2.894866062556452e+00 },
+ { -2.706538272184154e-09, 2.886704432555728e+00 },
+ { -2.699668090670078e-09, 2.878405517834426e+00 },
+ { -2.692696268177908e-09, 2.869969203985464e+00 },
+ { -2.685623067193599e-09, 2.861395382869544e+00 },
+ { -2.678448754018380e-09, 2.852683952631486e+00 },
+ { -2.671173598761847e-09, 2.843834817723832e+00 },
+ { -2.663797875328991e-09, 2.834847888922988e+00 },
+ { -2.656321861411517e-09, 2.825723083350459e+00 },
+ { -2.648745838477759e-09, 2.816460324492298e+00 },
+ { -2.641070091759922e-09, 2.807059542215146e+00 },
+ { -2.633294910246296e-09, 2.797520672788269e+00 },
+ { -2.625420586667340e-09, 2.787843658897949e+00 },
+ { -2.617447417487602e-09, 2.778028449668942e+00 },
+ { -2.609375702891616e-09, 2.768075000678399e+00 },
+ { -2.601205746775692e-09, 2.757983273976943e+00 },
+ { -2.592937856733464e-09, 2.747753238101915e+00 },
+ { -2.584572344046340e-09, 2.737384868096553e+00 },
+ { -2.576109523671634e-09, 2.726878145526201e+00 },
+ { -2.567549714229129e-09, 2.716233058492422e+00 },
+ { -2.558893237991435e-09, 2.705449601651722e+00 },
+ { -2.550140420869302e-09, 2.694527776227857e+00 },
+ { -2.541291592402089e-09, 2.683467590030445e+00 },
+ { -2.532347085742440e-09, 2.672269057466213e+00 },
+ { -2.523307237646751e-09, 2.660932199557362e+00 },
+ { -2.514172388459584e-09, 2.649457043952206e+00 },
+ { -2.504942882102813e-09, 2.637843624941622e+00 },
+ { -2.495619066062810e-09, 2.626091983472908e+00 },
+ { -2.486201291375123e-09, 2.614202167160335e+00 },
+ { -2.476689912614465e-09, 2.602174230302269e+00 },
+ { -2.467085287878098e-09, 2.590008233889805e+00 },
+ { -2.457387778775451e-09, 2.577704245623143e+00 },
+ { -2.447597750411553e-09, 2.565262339920002e+00 },
+ { -2.437715571376127e-09, 2.552682597931055e+00 },
+ { -2.427741613727123e-09, 2.539965107548168e+00 },
+ { -2.417676252978335e-09, 2.527109963417675e+00 },
+ { -2.407519868085581e-09, 2.514117266951687e+00 },
+ { -2.397272841430131e-09, 2.500987126335739e+00 },
+ { -2.386935558807595e-09, 2.487719656543254e+00 },
+ { -2.376508409410024e-09, 2.474314979341178e+00 },
+ { -2.365991785814531e-09, 2.460773223303822e+00 },
+ { -2.355386083965131e-09, 2.447094523817833e+00 },
+ { -2.344691703161363e-09, 2.433279023095734e+00 },
+ { -2.333909046040126e-09, 2.419326870180582e+00 },
+ { -2.323038518562289e-09, 2.405238220956597e+00 },
+ { -2.312080529997549e-09, 2.391013238157397e+00 },
+ { -2.301035492907384e-09, 2.376652091371587e+00 },
+ { -2.289903823131822e-09, 2.362154957053137e+00 },
+ { -2.278685939771276e-09, 2.347522018525197e+00 },
+ { -2.267382265173420e-09, 2.332753465990296e+00 },
+ { -2.255993224914501e-09, 2.317849496533128e+00 },
+ { -2.244519247786155e-09, 2.302810314130351e+00 },
+ { -2.232960765776561e-09, 2.287636129652823e+00 },
+ { -2.221318214056095e-09, 2.272327160873552e+00 },
+ { -2.209592030960763e-09, 2.256883632472565e+00 },
+ { -2.197782657974034e-09, 2.241305776039511e+00 },
+ { -2.185890539712767e-09, 2.225593830081461e+00 },
+ { -2.173916123907886e-09, 2.209748040023618e+00 },
+ { -2.161859861389976e-09, 2.193768658216360e+00 },
+ { -2.149722206070124e-09, 2.177655943935795e+00 },
+ { -2.137503614923981e-09, 2.161410163388424e+00 },
+ { -2.125204547975352e-09, 2.145031589714984e+00 },
+ { -2.112825468276292e-09, 2.128520502989477e+00 },
+ { -2.100366841892917e-09, 2.111877190225612e+00 },
+ { -2.087829137884807e-09, 2.095101945374541e+00 },
+ { -2.075212828290086e-09, 2.078195069329960e+00 },
+ { -2.062518388104923e-09, 2.061156869925600e+00 },
+ { -2.049746295268559e-09, 2.043987661939897e+00 },
+ { -2.036897030642658e-09, 2.026687767092888e+00 },
+ { -2.023971077994576e-09, 2.009257514048162e+00 },
+ { -2.010968923979840e-09, 1.991697238413571e+00 },
+ { -1.997891058121344e-09, 1.974007282737320e+00 },
+ { -1.984737972794098e-09, 1.956187996511354e+00 },
+ { -1.971510163203686e-09, 1.938239736166060e+00 },
+ { -1.958208127370276e-09, 1.920162865072273e+00 },
+ { -1.944832366107339e-09, 1.901957753535934e+00 },
+ { -1.931383383005451e-09, 1.883624778799427e+00 },
+ { -1.917861684410531e-09, 1.865164325035177e+00 },
+ { -1.904267779407432e-09, 1.846576783346324e+00 },
+ { -1.890602179798714e-09, 1.827862551760622e+00 },
+ { -1.876865400086483e-09, 1.809022035228338e+00 },
+ { -1.863057957452539e-09, 1.790055645617624e+00 },
+ { -1.849180371740008e-09, 1.770963801711725e+00 },
+ { -1.835233165431475e-09, 1.751746929201178e+00 },
+ { -1.821216863631569e-09, 1.732405460681919e+00 },
+ { -1.807131994045840e-09, 1.712939835648088e+00 },
+ { -1.792979086962494e-09, 1.693350500488565e+00 },
+ { -1.778758675229683e-09, 1.673637908477153e+00 },
+ { -1.764471294238191e-09, 1.653802519770021e+00 },
+ { -1.750117481899733e-09, 1.633844801396848e+00 },
+ { -1.735697778626995e-09, 1.613765227254186e+00 },
+ { -1.721212727314574e-09, 1.593564278099856e+00 },
+ { -1.706662873315474e-09, 1.573242441540939e+00 },
+ { -1.692048764423848e-09, 1.552800212030258e+00 },
+ { -1.677370950852395e-09, 1.532238090855187e+00 },
+ { -1.662629985213192e-09, 1.511556586131055e+00 },
+ { -1.647826422494560e-09, 1.490756212788764e+00 },
+ { -1.632960820042537e-09, 1.469837492568651e+00 },
+ { -1.618033737538645e-09, 1.448800954008929e+00 },
+ { -1.603045736978760e-09, 1.427647132435469e+00 },
+ { -1.587997382653428e-09, 1.406376569953373e+00 },
+ { -1.572889241124034e-09, 1.384989815432507e+00 },
+ { -1.557721881203696e-09, 1.363487424499449e+00 },
+ { -1.542495873934815e-09, 1.341869959524515e+00 },
+ { -1.527211792568486e-09, 1.320137989611176e+00 },
+ { -1.511870212541253e-09, 1.298292090581491e+00 },
+ { -1.496471711454994e-09, 1.276332844965754e+00 },
+ { -1.481016869054634e-09, 1.254260841988828e+00 },
+ { -1.465506267206068e-09, 1.232076677556547e+00 },
+ { -1.449940489875303e-09, 1.209780954243628e+00 },
+ { -1.434320123104372e-09, 1.187374281276747e+00 },
+ { -1.418645754991533e-09, 1.164857274523495e+00 },
+ { -1.402917975667710e-09, 1.142230556475749e+00 },
+ { -1.387137377275425e-09, 1.119494756236361e+00 },
+ { -1.371304553944712e-09, 1.096650509501278e+00 },
+ { -1.355420101772623e-09, 1.073698458546610e+00 },
+ { -1.339484618799891e-09, 1.050639252211352e+00 },
+ { -1.323498704988051e-09, 1.027473545880543e+00 },
+ { -1.307462962198534e-09, 1.004202001471034e+00 },
+ { -1.291377994167204e-09, 9.808252874104182e-01 },
+ { -1.275244406484394e-09, 9.573440786237052e-01 },
+ { -1.259062806570190e-09, 9.337590565128454e-01 },
+ { -1.242833803653464e-09, 9.100709089414796e-01 },
+ { -1.226558008746195e-09, 8.862803302125812e-01 },
+ { -1.210236034623253e-09, 8.623880210538113e-01 },
+ { -1.193868495797618e-09, 8.383946885959868e-01 },
+ { -1.177456008497777e-09, 8.143010463544786e-01 },
+ { -1.160999190645010e-09, 7.901078142102129e-01 },
+ { -1.144498661828833e-09, 7.658157183877095e-01 },
+ { -1.127955043284965e-09, 7.414254914366063e-01 },
+ { -1.111368957870986e-09, 7.169378722095157e-01 },
+ { -1.094741030044308e-09, 6.923536058430697e-01 },
+ { -1.078071885836393e-09, 6.676734437331688e-01 },
+ { -1.061362152831423e-09, 6.428981435165511e-01 },
+ { -1.044612460141255e-09, 6.180284690466404e-01 },
+ { -1.027823438382183e-09, 5.930651903718045e-01 },
+ { -1.010995719652015e-09, 5.680090837138436e-01 },
+ { -9.941299375042378e-10, 5.428609314418970e-01 },
+ { -9.772267269262058e-10, 5.176215220520872e-01 },
+ { -9.602867243141016e-10, 4.922916501421032e-01 },
+ { -9.433105674499058e-10, 4.668721163885412e-01 },
+ { -9.262988954758817e-10, 4.413637275202624e-01 },
+ { -9.092523488719689e-10, 4.157672962958654e-01 },
+ { -8.921715694311144e-10, 3.900836414778084e-01 },
+ { -8.750572002347607e-10, 3.643135878065193e-01 },
+ { -8.579098856296589e-10, 3.384579659762392e-01 },
+ { -8.407302712022458e-10, 3.125176126069478e-01 },
+ { -8.235190037551917e-10, 2.864933702193017e-01 },
+ { -8.062767312831008e-10, 2.603860872080448e-01 },
+ { -7.890041029479477e-10, 2.341966178147619e-01 },
+ { -7.717017690542486e-10, 2.079258220999725e-01 },
+ { -7.543703810250266e-10, 1.815745659161734e-01 },
+ { -7.370105913774597e-10, 1.551437208801425e-01 },
+ { -7.196230536974697e-10, 1.286341643433767e-01 },
+ { -7.022084226165876e-10, 1.020467793657360e-01 },
+ { -6.847673537853251e-10, 7.538245468350446e-02 },
+ { -6.673005038502516e-10, 4.864208468284503e-02 },
+ { -6.498085304282128e-10, 2.182656936863137e-02 },
+ { -6.322920920826137e-10, -5.063185663820913e-03 },
+ { -6.147518482969490e-10, -3.202626926150343e-02 },
+ { -5.971884594516681e-10, -5.906176474160862e-02 },
+ { -5.796025867984469e-10, -8.616874992366363e-02 },
+ { -5.619948924353588e-10, -1.133462971605448e-01 },
+ { -5.443660392823640e-10, -1.405934733692621e-01 },
+ { -5.267166910556339e-10, -1.679093400638023e-01 },
+ { -5.090475122431451e-10, -1.952929533862739e-01 },
+ { -4.913591680795342e-10, -2.227433641394564e-01 },
+ { -4.736523245210571e-10, -2.502596178194491e-01 },
+ { -4.559276482202303e-10, -2.778407546490776e-01 },
+ { -4.381858065011618e-10, -3.054858096104932e-01 },
+ { -4.204274673340870e-10, -3.331938124792702e-01 },
+ { -4.026532993105397e-10, -3.609637878577768e-01 },
+ { -3.848639716178888e-10, -3.887947552098022e-01 },
+ { -3.670601540142443e-10, -4.166857288948674e-01 },
+ { -3.492425168032583e-10, -4.446357182029681e-01 },
+ { -3.314117308088734e-10, -4.726437273896633e-01 },
+ { -3.135684673501752e-10, -5.007087557112619e-01 },
+ { -2.957133982159296e-10, -5.288297974607742e-01 },
+ { -2.778471956393828e-10, -5.570058420037128e-01 },
+ { -2.599705322729564e-10, -5.852358738143247e-01 },
+ { -2.420840811628366e-10, -6.135188725122560e-01 },
+ { -2.241885157240923e-10, -6.418538128986450e-01 },
+ { -2.062845097142585e-10, -6.702396649949099e-01 },
+ { -1.883727372093546e-10, -6.986753940779493e-01 },
+ { -1.704538725773087e-10, -7.271599607197149e-01 },
+ { -1.525285904532877e-10, -7.556923208240308e-01 },
+ { -1.345975657140748e-10, -7.842714256651911e-01 },
+ { -1.166614734526054e-10, -8.128962219265712e-01 },
+ { -9.872098895260891e-11, -8.415656517393372e-01 },
+ { -8.077678766314517e-11, -8.702786527215916e-01 },
+ { -6.282954517324612e-11, -8.990341580176152e-01 },
+ { -4.487993718655790e-11, -9.278310963373758e-01 },
+ { -2.692863949561210e-11, -9.566683919968972e-01 },
+ { -8.976327956520795e-12, -9.855449649582175e-01 },
+ { 8.976321536169872e-12, -1.014459730869357e+00 },
+ { 2.692863307547294e-11, -1.043411601105914e+00 },
+ { 4.487993076694813e-11, -1.072399482811314e+00 },
+ { 6.282953875437751e-11, -1.101422278938424e+00 },
+ { 8.077678124517653e-11, -1.130478888291020e+00 },
+ { 9.872098253591082e-11, -1.159568205565684e+00 },
+ { 1.166614670373367e-10, -1.188689121393192e+00 },
+ { 1.345975593005002e-10, -1.217840522381901e+00 },
+ { 1.525285840416718e-10, -1.247021291159495e+00 },
+ { 1.704538661678104e-10, -1.276230306415868e+00 },
+ { 1.883727308022916e-10, -1.305466442946703e+00 },
+ { 2.062845033098954e-10, -1.334728571696106e+00 },
+ { 2.241885093225349e-10, -1.364015559800721e+00 },
+ { 2.420840747645085e-10, -1.393326270633325e+00 },
+ { 2.599705258779635e-10, -1.422659563847049e+00 },
+ { 2.778471892479898e-10, -1.452014295419243e+00 },
+ { 2.957133918284542e-10, -1.481389317696831e+00 },
+ { 3.135684609667761e-10, -1.510783479440191e+00 },
+ { 3.314117244297624e-10, -1.540195625869043e+00 },
+ { 3.492425104288060e-10, -1.569624598707558e+00 },
+ { 3.670601476445565e-10, -1.599069236228850e+00 },
+ { 3.848639652533361e-10, -1.628528373302631e+00 },
+ { 4.026532929512281e-10, -1.658000841439269e+00 },
+ { 4.204274609803869e-10, -1.687485468837799e+00 },
+ { 4.381858001531792e-10, -1.716981080430596e+00 },
+ { 4.559276418782829e-10, -1.746486497931567e+00 },
+ { 4.736523181853565e-10, -1.776000539882225e+00 },
+ { 4.913591617503452e-10, -1.805522021699094e+00 },
+ { 5.090475059206794e-10, -1.835049755721194e+00 },
+ { 5.267166847401562e-10, -1.864582551257262e+00 },
+ { 5.443660329740862e-10, -1.894119214633676e+00 },
+ { 5.619948861345454e-10, -1.923658549242818e+00 },
+ { 5.796025805053097e-10, -1.953199355591180e+00 },
+ { 5.971884531664190e-10, -1.982740431347091e+00 },
+ { 6.147518420199055e-10, -2.012280571390674e+00 },
+ { 6.322920858139346e-10, -2.041818567861395e+00 },
+ { 6.498085241682158e-10, -2.071353210208005e+00 },
+ { 6.673004975990425e-10, -2.100883285238127e+00 },
+ { 6.847673475432746e-10, -2.130407577166309e+00 },
+ { 7.022084163838545e-10, -2.159924867664933e+00 },
+ { 7.196230474743716e-10, -2.189433935913779e+00 },
+ { 7.370105851640495e-10, -2.218933558650552e+00 },
+ { 7.543703748217808e-10, -2.248422510220072e+00 },
+ { 7.717017628611672e-10, -2.277899562625407e+00 },
+ { 7.890040967654542e-10, -2.307363485579104e+00 },
+ { 8.062767251113011e-10, -2.336813046552684e+00 },
+ { 8.235189975944034e-10, -2.366247010829556e+00 },
+ { 8.407302650525749e-10, -2.395664141553858e+00 },
+ { 8.579098794915287e-10, -2.425063199784153e+00 },
+ { 8.750571941082773e-10, -2.454442944543319e+00 },
+ { 8.921715633164894e-10, -2.483802132872044e+00 },
+ { 9.092523427695200e-10, -2.513139519878584e+00 },
+ { 9.262988893857148e-10, -2.542453858792682e+00 },
+ { 9.433105613723914e-10, -2.571743901017465e+00 },
+ { 9.602867182493987e-10, -2.601008396180870e+00 },
+ { 9.772267208744730e-10, -2.630246092190425e+00 },
+ { 9.941299314658458e-10, -2.659455735283526e+00 },
+ { 1.010995713627070e-09, -2.688636070081818e+00 },
+ { 1.027823432371055e-09, -2.717785839644439e+00 },
+ { 1.044612454143997e-09, -2.746903785521352e+00 },
+ { 1.061362146848353e-09, -2.775988647805256e+00 },
+ { 1.078071879867828e-09, -2.805039165187255e+00 },
+ { 1.094741024090249e-09, -2.834054075009077e+00 },
+ { 1.111368951931856e-09, -2.863032113318052e+00 },
+ { 1.127955037360817e-09, -2.891972014920939e+00 },
+ { 1.144498655920037e-09, -2.920872513436805e+00 },
+ { 1.160999184751779e-09, -2.949732341353290e+00 },
+ { 1.177456002620215e-09, -2.978550230079517e+00 },
+ { 1.193868489936097e-09, -3.007324910002949e+00 },
+ { 1.210236028777826e-09, -3.036055110540183e+00 },
+ { 1.226558002917232e-09, -3.064739560196251e+00 },
+ { 1.242833797841123e-09, -3.093376986616735e+00 },
+ { 1.259062800774685e-09, -3.121966116643377e+00 },
+ { 1.275244400705935e-09, -3.150505676371791e+00 },
+ { 1.291377988406056e-09, -3.178994391202159e+00 },
+ { 1.307462956454857e-09, -3.207430985899192e+00 },
+ { 1.323498699262108e-09, -3.235814184645077e+00 },
+ { 1.339484613091842e-09, -3.264142711097884e+00 },
+ { 1.355420096082785e-09, -3.292415288443373e+00 },
+ { 1.371304548273191e-09, -3.320630639454825e+00 },
+ { 1.387137371622433e-09, -3.348787486547389e+00 },
+ { 1.402917970033511e-09, -3.376884551834256e+00 },
+ { 1.418645749376393e-09, -3.404920557184582e+00 },
+ { 1.434320117508396e-09, -3.432894224276359e+00 },
+ { 1.449940484298756e-09, -3.460804274656981e+00 },
+ { 1.465506261649108e-09, -3.488649429796768e+00 },
+ { 1.481016863517580e-09, -3.516428411149154e+00 },
+ { 1.496471705937951e-09, -3.544139940202303e+00 },
+ { 1.511870207044433e-09, -3.571782738540999e+00 },
+ { 1.527211787092206e-09, -3.599355527901174e+00 },
+ { 1.542495868479076e-09, -3.626857030226671e+00 },
+ { 1.557721875768920e-09, -3.654285967729458e+00 },
+ { 1.572889235710329e-09, -3.681641062941412e+00 },
+ { 1.587997377261005e-09, -3.708921038776707e+00 },
+ { 1.603045731607830e-09, -3.736124618586623e+00 },
+ { 1.618033732189314e-09, -3.763250526218862e+00 },
+ { 1.632960814715177e-09, -3.790297486071938e+00 },
+ { 1.647826417189275e-09, -3.817264223155802e+00 },
+ { 1.662629979930247e-09, -3.844149463148589e+00 },
+ { 1.677370945591844e-09, -3.870951932452996e+00 },
+ { 1.692048759186008e-09, -3.897670358257890e+00 },
+ { 1.706662868100504e-09, -3.924303468590212e+00 },
+ { 1.721212722122685e-09, -3.950849992378278e+00 },
+ { 1.735697773458400e-09, -3.977308659506432e+00 },
+ { 1.750117476754591e-09, -4.003678200876669e+00 },
+ { 1.764471289116712e-09, -4.029957348461003e+00 },
+ { 1.778758670132079e-09, -4.056144835364877e+00 },
+ { 1.792979081888926e-09, -4.082239395882965e+00 },
+ { 1.807131988996465e-09, -4.108239765556996e+00 },
+ { 1.821216858606652e-09, -4.134144681236933e+00 },
+ { 1.835233160431175e-09, -4.159952881133585e+00 },
+ { 1.849180366764537e-09, -4.185663104882633e+00 },
+ { 1.863057952502055e-09, -4.211274093599509e+00 },
+ { 1.876865395161145e-09, -4.236784589940537e+00 },
+ { 1.890602174898734e-09, -4.262193338157148e+00 },
+ { 1.904267774533022e-09, -4.287499084158302e+00 },
+ { 1.917861679562008e-09, -4.312700575567174e+00 },
+ { 1.931383378182392e-09, -4.337796561778708e+00 },
+ { 1.944832361310856e-09, -4.362785794021793e+00 },
+ { 1.958208122599839e-09, -4.387667025411434e+00 },
+ { 1.971510158459931e-09, -4.412439011013396e+00 },
+ { 1.984737968076495e-09, -4.437100507898339e+00 },
+ { 1.997891053431005e-09, -4.461650275204912e+00 },
+ { 2.010968919316289e-09, -4.486087074191693e+00 },
+ { 2.023971073358447e-09, -4.510409668301784e+00 },
+ { 2.036897026033634e-09, -4.534616823217992e+00 },
+ { 2.049746290686799e-09, -4.558707306921882e+00 },
+ { 2.062518383551274e-09, -4.582679889754607e+00 },
+ { 2.075212823764071e-09, -4.606533344469879e+00 },
+ { 2.087829133387063e-09, -4.630266446298172e+00 },
+ { 2.100366837422912e-09, -4.653877973001258e+00 },
+ { 2.112825463835087e-09, -4.677366704934605e+00 },
+ { 2.125204543562522e-09, -4.700731425099899e+00 },
+ { 2.137503610540056e-09, -4.723970919208608e+00 },
+ { 2.149722201714786e-09, -4.747083975738060e+00 },
+ { 2.161859857063438e-09, -4.770069385989595e+00 },
+ { 2.173916119610994e-09, -4.792925944149308e+00 },
+ { 2.185890535445098e-09, -4.815652447340950e+00 },
+ { 2.197782653735957e-09, -4.838247695689436e+00 },
+ { 2.209592026751962e-09, -4.860710492376411e+00 },
+ { 2.221318209877576e-09, -4.883039643700314e+00 },
+ { 2.232960761627846e-09, -4.905233959130168e+00 },
+ { 2.244519243667616e-09, -4.927292251368517e+00 },
+ { 2.255993220826402e-09, -4.949213336406265e+00 },
+ { 2.267382261115285e-09, -4.970996033581527e+00 },
+ { 2.278685935744269e-09, -4.992639165639563e+00 },
+ { 2.289903819135414e-09, -5.014141558784778e+00 },
+ { 2.301035488942000e-09, -5.035502042744443e+00 },
+ { 2.312080526062763e-09, -5.056719450823151e+00 },
+ { 2.323038514659161e-09, -5.077792619963239e+00 },
+ { 2.333909042168180e-09, -5.098720390796817e+00 },
+ { 2.344691699320969e-09, -5.119501607709159e+00 },
+ { 2.355386080156553e-09, -5.140135118892792e+00 },
+ { 2.365991782037187e-09, -5.160619776404897e+00 },
+ { 2.376508405665132e-09, -5.180954436227641e+00 },
+ { 2.386935555094626e-09, -5.201137958319343e+00 },
+ { 2.397272837749508e-09, -5.221169206676762e+00 },
+ { 2.407519864436774e-09, -5.241047049389645e+00 },
+ { 2.417676249362563e-09, -5.260770358700167e+00 },
+ { 2.427741610143750e-09, -5.280338011053974e+00 },
+ { 2.437715567825576e-09, -5.299748887163106e+00 },
+ { 2.447597746894037e-09, -5.319001872058887e+00 },
+ { 2.457387775290440e-09, -5.338095855149190e+00 },
+ { 2.467085284426756e-09, -5.357029730277389e+00 },
+ { 2.476689909196263e-09, -5.375802395772283e+00 },
+ { 2.486201287990485e-09, -5.394412754510426e+00 },
+ { 2.495619062711154e-09, -5.412859713968929e+00 },
+ { 2.504942878785408e-09, -5.431142186284682e+00 },
+ { 2.514172385175743e-09, -5.449259088303476e+00 },
+ { 2.523307234396791e-09, -5.467209341642627e+00 },
+ { 2.532347082526785e-09, -5.484991872743321e+00 },
+ { 2.541291589219998e-09, -5.502605612925014e+00 },
+ { 2.550140417722072e-09, -5.520049498445633e+00 },
+ { 2.558893234878378e-09, -5.537322470548212e+00 },
+ { 2.567549711150773e-09, -5.554423475524196e+00 },
+ { 2.576109520627371e-09, -5.571351464763084e+00 },
+ { 2.584572341037361e-09, -5.588105394812198e+00 },
+ { 2.592937853759161e-09, -5.604684227423386e+00 },
+ { 2.601205743836355e-09, -5.621086929615246e+00 },
+ { 2.609375699987564e-09, -5.637312473723475e+00 },
+ { 2.617447414618146e-09, -5.653359837454964e+00 },
+ { 2.625420583833750e-09, -5.669228003945694e+00 },
+ { 2.633294907447937e-09, -5.684915961806963e+00 },
+ { 2.641070088997271e-09, -5.700422705186584e+00 },
+ { 2.648745835750128e-09, -5.715747233817712e+00 },
+ { 2.656321858720176e-09, -5.730888553077074e+00 },
+ { 2.663797872673252e-09, -5.745845674030161e+00 },
+ { 2.671173596142054e-09, -5.760617613492118e+00 },
+ { 2.678448751434797e-09, -5.775203394076705e+00 },
+ { 2.685623064645538e-09, -5.789602044248679e+00 },
+ { 2.692696265666640e-09, -5.803812598380606e+00 },
+ { 2.699668088194915e-09, -5.817834096797069e+00 },
+ { 2.706538269745573e-09, -5.831665585834668e+00 },
+ { 2.713306551659817e-09, -5.845306117889361e+00 },
+ { 2.719972679116734e-09, -5.858754751472542e+00 },
+ { 2.726536401139295e-09, -5.872010551255358e+00 },
+ { 2.732997470607439e-09, -5.885072588127400e+00 },
+ { 2.739355644265558e-09, -5.897939939244211e+00 },
+ { 2.745610682731633e-09, -5.910611688078208e+00 },
+ { 2.751762350508137e-09, -5.923086924473290e+00 },
+ { 2.757810415987146e-09, -5.935364744687794e+00 },
+ { 2.763754651462700e-09, -5.947444251452243e+00 },
+ { 2.769594833137415e-09, -5.959324554015538e+00 },
+ { 2.775330741132843e-09, -5.971004768198829e+00 },
+ { 2.780962159494174e-09, -5.982484016437981e+00 },
+ { 2.786488876202047e-09, -5.993761427840588e+00 },
+ { 2.791910683178690e-09, -6.004836138231525e+00 },
+ { 2.797227376295779e-09, -6.015707290202086e+00 },
+ { 2.802438755383971e-09, -6.026374033162623e+00 },
+ { 2.807544624236659e-09, -6.036835523383457e+00 },
+ { 2.812544790621093e-09, -6.047090924050914e+00 },
+ { 2.817439066283459e-09, -6.057139405311101e+00 },
+ { 2.822227266958278e-09, -6.066980144322601e+00 },
+ { 2.826909212371261e-09, -6.076612325295799e+00 },
+ { 2.831484726250221e-09, -6.086035139548830e+00 },
+ { 2.835953636329660e-09, -6.095247785550617e+00 },
+ { 2.840315774357203e-09, -6.104249468967751e+00 },
+ { 2.844570976102082e-09, -6.113039402715685e+00 },
+ { 2.848719081357095e-09, -6.121616806996519e+00 },
+ { 2.852759933948860e-09, -6.129980909353977e+00 },
+ { 2.856693381741114e-09, -6.138130944714082e+00 },
+ { 2.860519276643053e-09, -6.146066155436312e+00 },
+ { 2.864237474610633e-09, -6.153785791350256e+00 },
+ { 2.867847835656203e-09, -6.161289109809551e+00 },
+ { 2.871350223851726e-09, -6.168575375732642e+00 },
+ { 2.874744507333867e-09, -6.175643861647406e+00 },
+ { 2.878030558310989e-09, -6.182493847739853e+00 },
+ { 2.881208253063899e-09, -6.189124621889823e+00 },
+ { 2.884277471954592e-09, -6.195535479723423e+00 },
+ { 2.887238099428306e-09, -6.201725724651554e+00 },
+ { 2.890090024020323e-09, -6.207694667918394e+00 },
+ { 2.892833138356060e-09, -6.213441628635915e+00 },
+ { 2.895467339159240e-09, -6.218965933835304e+00 },
+ { 2.897992527253659e-09, -6.224266918505075e+00 },
+ { 2.900408607567016e-09, -6.229343925633495e+00 },
+ { 2.902715489136496e-09, -6.234196306254763e+00 },
+ { 2.904913085108075e-09, -6.238823419482017e+00 },
+ { 2.907001312743911e-09, -6.243224632557377e+00 },
+ { 2.908980093422997e-09, -6.247399320887848e+00 },
+ { 2.910849352646620e-09, -6.251346868091392e+00 },
+ { 2.912609020036956e-09, -6.255066666028537e+00 },
+ { 2.914259029343965e-09, -6.258558114851525e+00 },
+ { 2.915799318445710e-09, -6.261820623039620e+00 },
+ { 2.917229829350759e-09, -6.264853607438842e+00 },
+ { 2.918550508202463e-09, -6.267656493305673e+00 },
+ { 2.919761305276718e-09, -6.270228714337005e+00 },
+ { 2.920862174988150e-09, -6.272569712717951e+00 },
+ { 2.921853075889193e-09, -6.274678939154603e+00 },
+ { 2.922733970674264e-09, -6.276555852917634e+00 },
+ { 2.923504826176907e-09, -6.278199921870962e+00 },
+ { 2.924165613375264e-09, -6.279610622518139e+00 },
+ { 2.924716307391075e-09, -6.280787440034993e+00 },
+ { 2.925156887490598e-09, -6.281729868306345e+00 },
+ { 2.925487337087508e-09, -6.282437409966992e+00 },
+ { 2.925707643739298e-09, -6.282909576428774e+00 },
+ { 2.925817799151970e-09, -6.283145887925411e+00 },
diff --git a/gnuradio-runtime/lib/test_runtime.cc b/gnuradio-runtime/lib/test_runtime.cc
new file mode 100644
index 0000000000..bd5378332e
--- /dev/null
+++ b/gnuradio-runtime/lib/test_runtime.cc
@@ -0,0 +1,42 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2010,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <cppunit/TextTestRunner.h>
+#include <cppunit/XmlOutputter.h>
+
+#include <gr_unittests.h>
+#include <qa_runtime.h>
+
+int
+main (int argc, char **argv)
+{
+ CppUnit::TextTestRunner runner;
+ std::ofstream xmlfile(get_unittest_path("gnuradio_core_runtime.xml").c_str());
+ CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), xmlfile);
+
+ runner.addTest (qa_runtime::suite ());
+ runner.setOutputter(xmlout);
+
+ bool was_successful = runner.run ("", false);
+
+ return was_successful ? 0 : 1;
+}