summaryrefslogtreecommitdiff
path: root/gnuradio-runtime
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-runtime')
-rw-r--r--gnuradio-runtime/CMakeLists.txt194
-rw-r--r--gnuradio-runtime/ConfigChecks.cmake212
-rw-r--r--gnuradio-runtime/apps/CMakeLists.txt42
-rw-r--r--gnuradio-runtime/apps/gnuradio-config-info.cc72
-rw-r--r--gnuradio-runtime/ctrlport.conf.example30
-rw-r--r--gnuradio-runtime/ctrlport.conf.in6
-rw-r--r--gnuradio-runtime/examples/CMakeLists.txt22
-rw-r--r--gnuradio-runtime/examples/mp-sched/CMakeLists.txt36
-rw-r--r--gnuradio-runtime/examples/mp-sched/README2
-rwxr-xr-xgnuradio-runtime/examples/mp-sched/affinity_set.py72
-rw-r--r--gnuradio-runtime/examples/mp-sched/perf-data/core-duo.dat65
-rw-r--r--gnuradio-runtime/examples/mp-sched/perf-data/core2-duo.dat65
-rw-r--r--gnuradio-runtime/examples/mp-sched/perf-data/dual-quad-core-2.33-clovertown.dat257
-rw-r--r--gnuradio-runtime/examples/mp-sched/perf-data/dual-quad-core-3.00-penryn.dat257
-rw-r--r--gnuradio-runtime/examples/mp-sched/perf-data/js21-altivec.dat65
-rw-r--r--gnuradio-runtime/examples/mp-sched/perf-data/js21.dat65
-rw-r--r--gnuradio-runtime/examples/mp-sched/perf-data/ps3-altivec.dat65
-rw-r--r--gnuradio-runtime/examples/mp-sched/perf-data/ps3.dat65
-rw-r--r--gnuradio-runtime/examples/mp-sched/perf-data/qs21-altivec.dat65
-rw-r--r--gnuradio-runtime/examples/mp-sched/perf-data/qs21.dat65
-rwxr-xr-xgnuradio-runtime/examples/mp-sched/plot_flops.py98
-rwxr-xr-xgnuradio-runtime/examples/mp-sched/run_synthetic.py101
-rwxr-xr-xgnuradio-runtime/examples/mp-sched/synthetic.py119
-rwxr-xr-xgnuradio-runtime/examples/mp-sched/wfm_rcv_pll_to_wav.py128
-rw-r--r--gnuradio-runtime/examples/network/CMakeLists.txt30
-rwxr-xr-xgnuradio-runtime/examples/network/audio_sink.py70
-rwxr-xr-xgnuradio-runtime/examples/network/audio_source.py70
-rwxr-xr-xgnuradio-runtime/examples/network/dial_tone_sink.py63
-rwxr-xr-xgnuradio-runtime/examples/network/dial_tone_source.py82
-rwxr-xr-xgnuradio-runtime/examples/network/vector_sink.py62
-rwxr-xr-xgnuradio-runtime/examples/network/vector_source.py61
-rw-r--r--gnuradio-runtime/examples/volk_benchmark/CMakeLists.txt35
-rw-r--r--gnuradio-runtime/examples/volk_benchmark/README252
-rwxr-xr-xgnuradio-runtime/examples/volk_benchmark/volk_math.py157
-rwxr-xr-xgnuradio-runtime/examples/volk_benchmark/volk_plot.py169
-rw-r--r--gnuradio-runtime/examples/volk_benchmark/volk_test_funcs.py172
-rwxr-xr-xgnuradio-runtime/examples/volk_benchmark/volk_types.py169
-rw-r--r--gnuradio-runtime/gnuradio-runtime.conf.in39
-rw-r--r--gnuradio-runtime/gnuradio-runtime.pc.in11
-rw-r--r--gnuradio-runtime/gr_log_default.conf40
-rw-r--r--gnuradio-runtime/include/CMakeLists.txt92
-rw-r--r--gnuradio-runtime/include/IcePy_Communicator.h35
-rw-r--r--gnuradio-runtime/include/gr_basic_block.h344
-rw-r--r--gnuradio-runtime/include/gr_block.h700
-rw-r--r--gnuradio-runtime/include/gr_block_detail.h248
-rw-r--r--gnuradio-runtime/include/gr_block_registry.h44
-rw-r--r--gnuradio-runtime/include/gr_buffer.h309
-rw-r--r--gnuradio-runtime/include/gr_complex.h44
-rw-r--r--gnuradio-runtime/include/gr_constants.h53
-rw-r--r--gnuradio-runtime/include/gr_dispatcher.h69
-rw-r--r--gnuradio-runtime/include/gr_endianness.h27
-rw-r--r--gnuradio-runtime/include/gr_error_handler.h117
-rw-r--r--gnuradio-runtime/include/gr_expj.h38
-rw-r--r--gnuradio-runtime/include/gr_feval.h177
-rw-r--r--gnuradio-runtime/include/gr_flowgraph.h251
-rw-r--r--gnuradio-runtime/include/gr_fxpt.h104
-rw-r--r--gnuradio-runtime/include/gr_fxpt_nco.h153
-rw-r--r--gnuradio-runtime/include/gr_fxpt_vco.h73
-rw-r--r--gnuradio-runtime/include/gr_hier_block2.h208
-rw-r--r--gnuradio-runtime/include/gr_io_signature.h117
-rw-r--r--gnuradio-runtime/include/gr_logger.h644
-rw-r--r--gnuradio-runtime/include/gr_math.h209
-rw-r--r--gnuradio-runtime/include/gr_message.h91
-rw-r--r--gnuradio-runtime/include/gr_misc.h39
-rw-r--r--gnuradio-runtime/include/gr_msg_accepter.h43
-rw-r--r--gnuradio-runtime/include/gr_msg_handler.h43
-rw-r--r--gnuradio-runtime/include/gr_msg_queue.h92
-rw-r--r--gnuradio-runtime/include/gr_nco.h198
-rw-r--r--gnuradio-runtime/include/gr_preferences.h34
-rw-r--r--gnuradio-runtime/include/gr_prefs.h143
-rw-r--r--gnuradio-runtime/include/gr_py_feval.h51
-rw-r--r--gnuradio-runtime/include/gr_random.h65
-rw-r--r--gnuradio-runtime/include/gr_realtime.h37
-rw-r--r--gnuradio-runtime/include/gr_runtime_api.h33
-rw-r--r--gnuradio-runtime/include/gr_runtime_types.h56
-rw-r--r--gnuradio-runtime/include/gr_select_handler.h85
-rw-r--r--gnuradio-runtime/include/gr_sincos.h41
-rw-r--r--gnuradio-runtime/include/gr_single_threaded_scheduler.h62
-rw-r--r--gnuradio-runtime/include/gr_sptr_magic.h52
-rw-r--r--gnuradio-runtime/include/gr_sync_block.h66
-rw-r--r--gnuradio-runtime/include/gr_sync_decimator.h69
-rw-r--r--gnuradio-runtime/include/gr_sync_interpolator.h70
-rw-r--r--gnuradio-runtime/include/gr_sys_paths.h33
-rw-r--r--gnuradio-runtime/include/gr_tagged_stream_block.h138
-rw-r--r--gnuradio-runtime/include/gr_tags.h55
-rw-r--r--gnuradio-runtime/include/gr_timer.h84
-rw-r--r--gnuradio-runtime/include/gr_top_block.h141
-rw-r--r--gnuradio-runtime/include/gr_tpb_detail.h89
-rw-r--r--gnuradio-runtime/include/gr_types.h65
-rw-r--r--gnuradio-runtime/include/gr_unittests.h39
-rw-r--r--gnuradio-runtime/include/ice_application_base.h222
-rw-r--r--gnuradio-runtime/include/ice_server_template.h96
-rw-r--r--gnuradio-runtime/include/pycallback_object.h206
-rw-r--r--gnuradio-runtime/include/random.h38
-rw-r--r--gnuradio-runtime/include/rpccallbackregister_base.h105
-rw-r--r--gnuradio-runtime/include/rpcmanager.h59
-rw-r--r--gnuradio-runtime/include/rpcmanager_base.h46
-rw-r--r--gnuradio-runtime/include/rpcpmtconverters_ice.h35
-rw-r--r--gnuradio-runtime/include/rpcregisterhelpers.h659
-rw-r--r--gnuradio-runtime/include/rpcserver_aggregator.h100
-rw-r--r--gnuradio-runtime/include/rpcserver_base.h47
-rw-r--r--gnuradio-runtime/include/rpcserver_booter_aggregator.h56
-rw-r--r--gnuradio-runtime/include/rpcserver_booter_base.h44
-rw-r--r--gnuradio-runtime/include/rpcserver_booter_ice.h49
-rw-r--r--gnuradio-runtime/include/rpcserver_ice.h224
-rw-r--r--gnuradio-runtime/include/rpcserver_selector.h32
-rw-r--r--gnuradio-runtime/include/runtime_block_gateway.h265
-rw-r--r--gnuradio-runtime/lib/CMakeLists.txt257
-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.ice152
-rwxr-xr-xgnuradio-runtime/lib/gen_sine_table.py77
-rw-r--r--gnuradio-runtime/lib/gnuradio.ice95
-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_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.cc295
-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/runtime_block_gateway.cc185
-rw-r--r--gnuradio-runtime/lib/sine_table.h1025
-rw-r--r--gnuradio-runtime/lib/test_runtime.cc46
-rw-r--r--gnuradio-runtime/python/CMakeLists.txt23
-rw-r--r--gnuradio-runtime/python/build_utils.py226
-rw-r--r--gnuradio-runtime/python/build_utils_codes.py52
-rw-r--r--gnuradio-runtime/python/gnuradio/CMakeLists.txt38
-rw-r--r--gnuradio-runtime/python/gnuradio/__init__.py12
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/CMakeLists.txt97
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py428
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/IceRadioClient.py102
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/__init__.py30
-rwxr-xr-xgnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-curses268
-rwxr-xr-xgnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor721
-rwxr-xr-xgnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitor591
-rwxr-xr-xgnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx727
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/icon.pngbin0 -> 1532 bytes
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/monitor.py59
-rw-r--r--gnuradio-runtime/python/gnuradio/eng_notation.py74
-rw-r--r--gnuradio-runtime/python/gnuradio/eng_option.py63
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt46
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/__init__.py39
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/exceptions.py27
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/gateway.py243
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/gr_threading.py35
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/gr_threading_23.py724
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/gr_threading_24.py793
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/hier_block2.py132
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/prefs.py127
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/pubsub.py153
-rwxr-xr-xgnuradio-runtime/python/gnuradio/gr/qa_feval.py110
-rwxr-xr-xgnuradio-runtime/python/gnuradio/gr/qa_kludged_imports.py39
-rwxr-xr-xgnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py55
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/tag_utils.py57
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/top_block.py170
-rwxr-xr-xgnuradio-runtime/python/gnuradio/gr_unittest.py170
-rw-r--r--gnuradio-runtime/python/gnuradio/gr_xmlrunner.py387
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/CMakeLists.txt36
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/__init__.py13
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/daemon.py102
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/freqz.py344
-rwxr-xr-xgnuradio-runtime/python/gnuradio/gru/gnuplot_freqz.py102
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/hexint.py44
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/listmisc.py29
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/mathmisc.py33
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/msgq_runner.py82
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/os_read_exactly.py36
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/seq_with_cursor.py77
-rw-r--r--gnuradio-runtime/python/gnuradio/gru/socket_stuff.py62
-rw-r--r--gnuradio-runtime/swig/CMakeLists.txt101
-rw-r--r--gnuradio-runtime/swig/complex_vec_test.i25
-rwxr-xr-xgnuradio-runtime/swig/gen-swig-bug-fix111
-rw-r--r--gnuradio-runtime/swig/gnuradio.i87
-rw-r--r--gnuradio-runtime/swig/gnuradio_swig_bug_workaround.h45
-rw-r--r--gnuradio-runtime/swig/gr_basic_block.i62
-rw-r--r--gnuradio-runtime/swig/gr_block.i93
-rw-r--r--gnuradio-runtime/swig/gr_block_detail.i66
-rw-r--r--gnuradio-runtime/swig/gr_buffer.i63
-rw-r--r--gnuradio-runtime/swig/gr_constants.i13
-rw-r--r--gnuradio-runtime/swig/gr_dispatcher.i55
-rw-r--r--gnuradio-runtime/swig/gr_error_handler.i69
-rw-r--r--gnuradio-runtime/swig/gr_feval.i233
-rw-r--r--gnuradio-runtime/swig/gr_hier_block2.i88
-rw-r--r--gnuradio-runtime/swig/gr_io_signature.i73
-rw-r--r--gnuradio-runtime/swig/gr_logger.i79
-rw-r--r--gnuradio-runtime/swig/gr_message.i65
-rw-r--r--gnuradio-runtime/swig/gr_msg_handler.i32
-rw-r--r--gnuradio-runtime/swig/gr_msg_queue.i107
-rw-r--r--gnuradio-runtime/swig/gr_prefs.i63
-rw-r--r--gnuradio-runtime/swig/gr_realtime.i44
-rw-r--r--gnuradio-runtime/swig/gr_shared_ptr.i43
-rw-r--r--gnuradio-runtime/swig/gr_single_threaded_scheduler.i54
-rw-r--r--gnuradio-runtime/swig/gr_swig_block_magic.i58
-rw-r--r--gnuradio-runtime/swig/gr_sync_block.i29
-rw-r--r--gnuradio-runtime/swig/gr_sync_decimator.i31
-rw-r--r--gnuradio-runtime/swig/gr_sync_interpolator.i31
-rw-r--r--gnuradio-runtime/swig/gr_tagged_stream_block.i30
-rw-r--r--gnuradio-runtime/swig/gr_tags.i32
-rw-r--r--gnuradio-runtime/swig/gr_top_block.i74
-rw-r--r--gnuradio-runtime/swig/runtime_block_gateway.i46
-rw-r--r--gnuradio-runtime/swig/runtime_swig.i170
307 files changed, 38048 insertions, 0 deletions
diff --git a/gnuradio-runtime/CMakeLists.txt b/gnuradio-runtime/CMakeLists.txt
new file mode 100644
index 0000000000..96b844b193
--- /dev/null
+++ b/gnuradio-runtime/CMakeLists.txt
@@ -0,0 +1,194 @@
+# 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.
+
+########################################################################
+# Setup dependencies
+########################################################################
+include(GrBoost)
+include(GrPython)
+
+########################################################################
+# Setup compatibility checks and defines
+########################################################################
+include(${CMAKE_CURRENT_SOURCE_DIR}/ConfigChecks.cmake)
+
+########################################################################
+# Register component
+########################################################################
+include(GrComponent)
+GR_REGISTER_COMPONENT("gnuradio-runtime" ENABLE_GNURADIO_RUNTIME
+ Boost_FOUND
+ ENABLE_GRUEL
+ ENABLE_VOLK
+ PYTHONINTERP_FOUND
+)
+
+GR_SET_GLOBAL(GNURADIO_RUNTIME_INCLUDE_DIRS
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/gnuradio-runtime/include
+ ${CMAKE_BINARY_DIR}/gnuradio-runtime/include
+)
+
+GR_SET_GLOBAL(GNURADIO_RUNTIME_SWIG_INCLUDE_DIRS
+ ${GNURADIO_RUNTIME_INCLUDE_DIRS}
+ ${CMAKE_SOURCE_DIR}/gnuradio-runtime/swig
+ ${CMAKE_BINARY_DIR}/gnuradio-runtime/swig
+)
+
+get_filename_component(GNURADIO_RUNTIME_PYTHONPATH
+ ${CMAKE_SOURCE_DIR}/python ABSOLUTE
+)
+GR_SET_GLOBAL(GNURADIO_RUNTIME_PYTHONPATH ${GNURADIO_RUNTIME_PYTHONPATH})
+
+########################################################################
+# Register controlport component
+########################################################################
+
+FIND_PACKAGE(ICE)
+FIND_PACKAGE(SWIG)
+
+if(SWIG_FOUND)
+ set(SWIG_VERSION_CHECK FALSE)
+ if("${SWIG_VERSION}" VERSION_GREATER "2.0.0")
+ set(SWIG_VERSION_CHECK TRUE)
+ else("${SWIG_VERSION}" VERSION_GREATER "2.0.0")
+ message(STATUS "")
+ message(STATUS "Ctrlport requires SWIG version >= 2.0")
+ endif()
+endif(SWIG_FOUND)
+
+GR_REGISTER_COMPONENT("gr-ctrlport" ENABLE_GR_CTRLPORT
+ Boost_FOUND
+ SWIG_FOUND
+ SWIG_VERSION_CHECK
+ ICE_FOUND
+ ENABLE_GRUEL
+ ENABLE_GNURADIO_RUNTIME
+)
+
+########################################################################
+# Begin conditional configuration
+########################################################################
+if(ENABLE_GNURADIO_RUNTIME)
+
+get_filename_component(GR_RUNTIME_PYTHONPATH
+ ${CMAKE_CURRENT_SOURCE_DIR}/python ABSOLUTE
+)
+GR_SET_GLOBAL(GR_RUNTIME_PYTHONPATH ${GR_RUNTIME_PYTHONPATH})
+
+########################################################################
+# Setup CPack components
+########################################################################
+include(GrPackage)
+CPACK_SET(CPACK_COMPONENT_GROUP_RUNTIME_DESCRIPTION "GNU Radio Runtime")
+
+CPACK_COMPONENT("runtime_runtime"
+ GROUP "Runtime"
+ DISPLAY_NAME "Runtime"
+ DESCRIPTION "Dynamic link libraries"
+ DEPENDS "core_runtime"
+)
+
+CPACK_COMPONENT("runtime_devel"
+ GROUP "Runtime"
+ DISPLAY_NAME "Development"
+ DESCRIPTION "C++ headers, package config, import libraries"
+ DEPENDS "core_devel"
+)
+
+CPACK_COMPONENT("runtime_python"
+ GROUP "Runtime"
+ DISPLAY_NAME "Python"
+ DESCRIPTION "Python modules for runtime"
+ DEPENDS "core_python;runtime_runtime"
+)
+
+CPACK_COMPONENT("runtime_swig"
+ GROUP "Runtime"
+ DISPLAY_NAME "SWIG"
+ DESCRIPTION "SWIG development .i files"
+ DEPENDS "core_swig;runtime_python;runtime_devel"
+)
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/gnuradio-runtime.conf.in
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-runtime.conf
+@ONLY)
+
+install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-runtime.conf
+ ctrlport.conf.example
+ DESTINATION ${GR_PREFSDIR}
+ COMPONENT "core_runtime"
+)
+
+if(ENABLE_GR_LOG AND HAVE_LOG4CPP)
+install(FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_log_default.conf
+ DESTINATION ${GR_CONF_DIR}/gnuradio
+ COMPONENT "core_runtime"
+)
+endif(ENABLE_GR_LOG AND HAVE_LOG4CPP)
+
+########################################################################
+# Add subdirectories
+########################################################################
+add_subdirectory(include)
+add_subdirectory(lib)
+add_subdirectory(apps)
+#add_subdirectory(doc)
+if(ENABLE_PYTHON)
+ add_subdirectory(swig)
+ add_subdirectory(python)
+# add_subdirectory(grc)
+ add_subdirectory(examples)
+endif(ENABLE_PYTHON)
+
+########################################################################
+# Create Pkg Config File
+########################################################################
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/gnuradio-runtime.pc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-runtime.pc
+@ONLY)
+
+install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-runtime.pc
+ DESTINATION ${GR_LIBRARY_DIR}/pkgconfig
+ COMPONENT "runtime_devel"
+)
+
+########################################################################
+# Setup ControlPort preferences file and installation information
+########################################################################
+if(ENABLE_GR_CTRLPORT)
+
+SET(GR_PKG_CTRL_EXAMPLES_DIR ${GR_PKG_DATA_DIR}/examples/ctrlport)
+
+SET(GR_PKG_CTRL_SLICE_DIR ${GR_PKG_DATA_DIR}/ctrlport)
+file(TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/${GR_PKG_CTRL_SLICE_DIR} slicedir)
+
+install(
+ FILES ctrlport.conf.example
+ DESTINATION ${SYSCONFDIR}/${CMAKE_PROJECT_NAME}
+ COMPONENT "gnuradio_runtime"
+)
+
+endif(ENABLE_GR_CTRLPORT)
+
+endif(ENABLE_GNURADIO_RUNTIME)
diff --git a/gnuradio-runtime/ConfigChecks.cmake b/gnuradio-runtime/ConfigChecks.cmake
new file mode 100644
index 0000000000..e6c97bada4
--- /dev/null
+++ b/gnuradio-runtime/ConfigChecks.cmake
@@ -0,0 +1,212 @@
+# Copyright 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.
+
+########################################################################
+INCLUDE(GrMiscUtils)
+INCLUDE(CheckCXXSourceCompiles)
+
+IF(MSVC) #add this directory for our provided headers
+LIST(APPEND CMAKE_REQUIRED_INCLUDES ${CMAKE_SOURCE_DIR}/msvc)
+ENDIF(MSVC)
+
+GR_CHECK_HDR_N_DEF(netdb.h HAVE_NETDB_H)
+GR_CHECK_HDR_N_DEF(sys/time.h HAVE_SYS_TIME_H)
+GR_CHECK_HDR_N_DEF(sys/types.h HAVE_SYS_TYPES_H)
+GR_CHECK_HDR_N_DEF(sys/select.h HAVE_SYS_SELECT_H)
+GR_CHECK_HDR_N_DEF(sys/socket.h HAVE_SYS_SOCKET_H)
+GR_CHECK_HDR_N_DEF(io.h HAVE_IO_H)
+GR_CHECK_HDR_N_DEF(sys/mman.h HAVE_SYS_MMAN_H)
+GR_CHECK_HDR_N_DEF(sys/ipc.h HAVE_SYS_IPC_H)
+GR_CHECK_HDR_N_DEF(sys/shm.h HAVE_SYS_SHM_H)
+GR_CHECK_HDR_N_DEF(signal.h HAVE_SIGNAL_H)
+GR_CHECK_HDR_N_DEF(netinet/in.h HAVE_NETINET_IN_H)
+GR_CHECK_HDR_N_DEF(arpa/inet.h HAVE_ARPA_INET_H)
+GR_CHECK_HDR_N_DEF(byteswap.h HAVE_BYTESWAP_H)
+GR_CHECK_HDR_N_DEF(linux/ppdev.h HAVE_LINUX_PPDEV_H)
+GR_CHECK_HDR_N_DEF(dev/ppbus/ppi.h HAVE_DEV_PPBUS_PPI_H)
+GR_CHECK_HDR_N_DEF(unistd.h HAVE_UNISTD_H)
+GR_CHECK_HDR_N_DEF(malloc.h HAVE_MALLOC_H)
+
+
+########################################################################
+CHECK_CXX_SOURCE_COMPILES("
+ #include <stdio.h>
+ int main(){snprintf(0, 0, 0); return 0;}
+ " HAVE_SNPRINTF
+)
+GR_ADD_COND_DEF(HAVE_SNPRINTF)
+
+########################################################################
+CHECK_CXX_SOURCE_COMPILES("
+ #include <signal.h>
+ int main(){sigaction(0, 0, 0); return 0;}
+ " HAVE_SIGACTION
+)
+GR_ADD_COND_DEF(HAVE_SIGACTION)
+
+########################################################################
+CHECK_CXX_SOURCE_COMPILES("
+ #include <sys/select.h>
+ int main(){select(0, 0, 0, 0, 0); return 0;}
+ " HAVE_SELECT
+)
+GR_ADD_COND_DEF(HAVE_SELECT)
+
+
+########################################################################
+CHECK_CXX_SOURCE_COMPILES("
+ #include <unistd.h>
+ int main(){sysconf(0); return 0;}
+ " HAVE_SYSCONF
+)
+GR_ADD_COND_DEF(HAVE_SYSCONF)
+
+CHECK_CXX_SOURCE_COMPILES("
+ #include <unistd.h>
+ int main(){getpagesize(); return 0;}
+ " HAVE_GETPAGESIZE
+)
+GR_ADD_COND_DEF(HAVE_GETPAGESIZE)
+
+
+########################################################################
+CHECK_CXX_SOURCE_COMPILES("
+ #include <Winbase.h>
+ int main(){Sleep(0); return 0;}
+ " HAVE_SSLEEP
+)
+GR_ADD_COND_DEF(HAVE_SSLEEP)
+
+CHECK_CXX_SOURCE_COMPILES("
+ #include <time.h>
+ int main(){nanosleep(0, 0); return 0;}
+ " HAVE_NANOSLEEP
+)
+GR_ADD_COND_DEF(HAVE_NANOSLEEP)
+
+CHECK_CXX_SOURCE_COMPILES("
+ #include <sys/time.h>
+ int main(){gettimeofday(0, 0); return 0;}
+ " HAVE_GETTIMEOFDAY
+)
+GR_ADD_COND_DEF(HAVE_GETTIMEOFDAY)
+
+########################################################################
+CHECK_CXX_SOURCE_COMPILES("
+ #include <stdlib.h>
+ int main(){posix_memalign(0, 0, 0); return 0;}
+ " HAVE_POSIX_MEMALIGN
+)
+GR_ADD_COND_DEF(HAVE_POSIX_MEMALIGN)
+
+CHECK_CXX_SOURCE_COMPILES("
+ #include <malloc.h>
+ int main(){valloc(0); return 0;}
+ " HAVE_VALLOC
+)
+GR_ADD_COND_DEF(HAVE_VALLOC)
+
+ADD_DEFINITIONS(-DALIGNED_MALLOC=0)
+
+########################################################################
+SET(CMAKE_REQUIRED_LIBRARIES -lpthread)
+CHECK_CXX_SOURCE_COMPILES("
+ #include <signal.h>
+ int main(){pthread_sigmask(0, 0, 0); return 0;}
+ " HAVE_PTHREAD_SIGMASK
+)
+GR_ADD_COND_DEF(HAVE_PTHREAD_SIGMASK)
+SET(CMAKE_REQUIRED_LIBRARIES)
+
+########################################################################
+CHECK_CXX_SOURCE_COMPILES("
+ #include <windows.h>
+ int main(){
+ HANDLE handle;
+ int size;
+ LPCTSTR lpName;
+ handle = CreateFileMapping(
+ INVALID_HANDLE_VALUE, // use paging file
+ NULL, // default security
+ PAGE_READWRITE, // read/write access
+ 0, // max. object size
+ size, // buffer size
+ lpName); // name of mapping object
+ return 0;
+ } " HAVE_CREATEFILEMAPPING
+)
+GR_ADD_COND_DEF(HAVE_CREATEFILEMAPPING)
+
+########################################################################
+CHECK_INCLUDE_FILE_CXX(windows.h HAVE_WINDOWS_H)
+IF(HAVE_WINDOWS_H)
+ ADD_DEFINITIONS(-DHAVE_WINDOWS_H -DUSING_WINSOCK)
+ MESSAGE(STATUS "Adding windows libs to gnuradio core libs...")
+ LIST(APPEND gnuradio_core_libs WS2_32.lib WSock32.lib)
+ENDIF(HAVE_WINDOWS_H)
+
+########################################################################
+SET(CMAKE_REQUIRED_LIBRARIES -lrt)
+CHECK_CXX_SOURCE_COMPILES("
+ #include <sys/types.h>
+ #include <sys/mman.h>
+ int main(){shm_open(0, 0, 0); return 0;}
+ " HAVE_SHM_OPEN
+)
+GR_ADD_COND_DEF(HAVE_SHM_OPEN)
+SET(CMAKE_REQUIRED_LIBRARIES)
+
+########################################################################
+CHECK_CXX_SOURCE_COMPILES("
+ #define _GNU_SOURCE
+ #include <math.h>
+ int main(){double x, sin, cos; sincos(x, &sin, &cos); return 0;}
+ " HAVE_SINCOS
+)
+GR_ADD_COND_DEF(HAVE_SINCOS)
+
+CHECK_CXX_SOURCE_COMPILES("
+ #define _GNU_SOURCE
+ #include <math.h>
+ int main(){float x, sin, cos; sincosf(x, &sin, &cos); return 0;}
+ " HAVE_SINCOSF
+)
+GR_ADD_COND_DEF(HAVE_SINCOSF)
+
+CHECK_CXX_SOURCE_COMPILES("
+ #include <math.h>
+ int main(){sinf(0); return 0;}
+ " HAVE_SINF
+)
+GR_ADD_COND_DEF(HAVE_SINF)
+
+CHECK_CXX_SOURCE_COMPILES("
+ #include <math.h>
+ int main(){cosf(0); return 0;}
+ " HAVE_COSF
+)
+GR_ADD_COND_DEF(HAVE_COSF)
+
+########################################################################
+CHECK_CXX_SOURCE_COMPILES("
+ #include <sys/mman.h>
+ int main(){mmap(0, 0, 0, 0, 0, 0); return 0;}
+ " HAVE_MMAP
+)
+GR_ADD_COND_DEF(HAVE_MMAP)
diff --git a/gnuradio-runtime/apps/CMakeLists.txt b/gnuradio-runtime/apps/CMakeLists.txt
new file mode 100644
index 0000000000..9efd3f2b69
--- /dev/null
+++ b/gnuradio-runtime/apps/CMakeLists.txt
@@ -0,0 +1,42 @@
+# Copyright 2010-2011,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.
+
+########################################################################
+# Setup the include and linker paths
+########################################################################
+include_directories(
+ ${GNURADIO_RUNTIME_INCLUDE_DIRS}
+ ${GRUEL_INCLUDE_DIRS}
+ ${Boost_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${Boost_LIBRARY_DIRS}
+)
+
+########################################################################
+# Setup executables
+########################################################################
+add_executable(gnuradio-config-info gnuradio-config-info.cc)
+target_link_libraries(gnuradio-config-info gnuradio-runtime ${Boost_LIBRARIES})
+install(
+ TARGETS gnuradio-config-info
+ DESTINATION ${GR_RUNTIME_DIR}
+ COMPONENT "runtime_runtime"
+)
diff --git a/gnuradio-runtime/apps/gnuradio-config-info.cc b/gnuradio-runtime/apps/gnuradio-config-info.cc
new file mode 100644
index 0000000000..d3e6454fd8
--- /dev/null
+++ b/gnuradio-runtime/apps/gnuradio-config-info.cc
@@ -0,0 +1,72 @@
+/* -*- 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 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>
+#include <boost/program_options.hpp>
+#include <iostream>
+
+namespace po = boost::program_options;
+
+int
+main(int argc, char **argv)
+{
+ po::options_description desc("Program options: gnuradio [options]");
+ po::variables_map vm;
+
+ desc.add_options()
+ ("help,h", "print help message")
+ ("prefix", "print gnuradio installation prefix")
+ ("sysconfdir", "print gnuradio system configuration directory")
+ ("prefsdir", "print gnuradio preferences directory")
+ ("builddate", "print gnuradio build date (RFC2822 format)")
+ ("version,v", "print gnuradio version")
+ ;
+
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.size() == 0 || vm.count("help")) {
+ std::cout << desc << std::endl;
+ return 1;
+ }
+
+ if (vm.count("prefix"))
+ std::cout << gr_prefix() << std::endl;
+
+ if (vm.count("sysconfdir"))
+ std::cout << gr_sysconfdir() << std::endl;
+
+ if (vm.count("prefsdir"))
+ std::cout << gr_prefsdir() << std::endl;
+
+ if (vm.count("builddate"))
+ std::cout << gr_build_date() << std::endl;
+
+ if (vm.count("version"))
+ std::cout << gr_version() << std::endl;
+
+ return 0;
+}
diff --git a/gnuradio-runtime/ctrlport.conf.example b/gnuradio-runtime/ctrlport.conf.example
new file mode 100644
index 0000000000..51d9e934f2
--- /dev/null
+++ b/gnuradio-runtime/ctrlport.conf.example
@@ -0,0 +1,30 @@
+## Use this to create an endpoint used to export ControlPort.
+##
+## A typical configuation would be to specify using a particular
+## interface (determined from the IP address) and port number:
+##
+## ControlPort.Endpoints=tcp -h 192.168.1.1 -p 9000
+##
+## A similar endpoint without the port number stated will pick a
+## random, free port:
+##
+## ControlPort.Endpoints=tcp -h 192.168.1.1
+##
+## ICE has some wildcard capabilities, as well. The following tells
+## ICE to use all available interfaces:
+##
+## ControlPort.Endpoints=tcp -h *
+##
+## Using 'default' for the host will use what 'hostname' resolves to.
+##
+## For more details:
+## http://doc.zeroc.com/display/Ice/Proxy+and+Endpoint+Syntax
+## http://www.zeroc.com/doc/Ice-3.2.1/manual/ProxyEndpointRef.51.2.html
+
+# ControlPort.Endpoints = tcp -t 300 -h 127.0.0.1 -p 23456
+
+
+## Set a default hostname (or IP) if no '-h' is used in the Endpoint
+## configuration
+
+#Ice.Default.Host = myhost
diff --git a/gnuradio-runtime/ctrlport.conf.in b/gnuradio-runtime/ctrlport.conf.in
new file mode 100644
index 0000000000..5c31a04516
--- /dev/null
+++ b/gnuradio-runtime/ctrlport.conf.in
@@ -0,0 +1,6 @@
+# This file contains system wide configuration data for GNU Radio.
+# You may override any setting on a per-user basis by editing
+# ~/.gnuradio/config.conf
+
+[ctrlport]
+ice_directory=@slicedir@
diff --git a/gnuradio-runtime/examples/CMakeLists.txt b/gnuradio-runtime/examples/CMakeLists.txt
new file mode 100644
index 0000000000..b90a5542df
--- /dev/null
+++ b/gnuradio-runtime/examples/CMakeLists.txt
@@ -0,0 +1,22 @@
+# 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.
+
+add_subdirectory(mp-sched)
+add_subdirectory(network)
+add_subdirectory(volk_benchmark)
diff --git a/gnuradio-runtime/examples/mp-sched/CMakeLists.txt b/gnuradio-runtime/examples/mp-sched/CMakeLists.txt
new file mode 100644
index 0000000000..863cfa733a
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/CMakeLists.txt
@@ -0,0 +1,36 @@
+# 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(GrPython)
+
+GR_PYTHON_INSTALL(PROGRAMS
+ affinity_set.py
+ plot_flops.py
+ run_synthetic.py
+ synthetic.py
+ wfm_rcv_pll_to_wav.py
+ DESTINATION ${GR_PKG_DATA_DIR}/examples/mp-sched
+ COMPONENT "runtime_python"
+)
+
+install(
+ FILES README
+ DESTINATION ${GR_PKG_DATA_DIR}/examples/mp-sched
+ COMPONENT "runtime_python"
+)
diff --git a/gnuradio-runtime/examples/mp-sched/README b/gnuradio-runtime/examples/mp-sched/README
new file mode 100644
index 0000000000..ae575437ac
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/README
@@ -0,0 +1,2 @@
+These are pieces of code used to test and benchmark the
+multi-processor scheduler.
diff --git a/gnuradio-runtime/examples/mp-sched/affinity_set.py b/gnuradio-runtime/examples/mp-sched/affinity_set.py
new file mode 100755
index 0000000000..4d28a04174
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/affinity_set.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+##################################################
+# Gnuradio Python Flow Graph
+# Title: Affinity Set Test
+##################################################
+
+from gnuradio import eng_notation
+from gnuradio import gr
+from gnuradio import blocks
+from gnuradio import filter
+from gnuradio.eng_option import eng_option
+from gnuradio.filter import firdes
+from optparse import OptionParser
+import sys
+
+class affinity_set(gr.top_block):
+
+ def __init__(self):
+ gr.top_block.__init__(self, "Affinity Set Test")
+
+ ##################################################
+ # Variables
+ ##################################################
+ self.samp_rate = samp_rate = 32000
+
+ ##################################################
+ # Blocks
+ ##################################################
+ vec_len = 1
+ self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*vec_len, samp_rate)
+ self.blocks_null_source_0 = blocks.null_source(gr.sizeof_gr_complex*vec_len)
+ self.blocks_null_sink_0 = blocks.null_sink(gr.sizeof_gr_complex*vec_len)
+ self.filter_filt_0 = filter.fir_filter_ccc(1, 40000*[0.2+0.3j,])
+ self.filter_filt_1 = filter.fir_filter_ccc(1, 40000*[0.2+0.3j,])
+
+ self.filter_filt_0.set_processor_affinity([0,])
+ self.filter_filt_1.set_processor_affinity([0,1])
+
+ ##################################################
+ # Connections
+ ##################################################
+ self.connect((self.blocks_null_source_0, 0), (self.blocks_throttle_0, 0))
+ self.connect((self.blocks_throttle_0, 0), (self.filter_filt_0, 0))
+ self.connect((self.filter_filt_0, 0), (self.filter_filt_1, 0))
+ self.connect((self.filter_filt_1, 0), (self.blocks_null_sink_0, 0))
+
+ def get_samp_rate(self):
+ return self.samp_rate
+
+ def set_samp_rate(self, samp_rate):
+ self.samp_rate = samp_rate
+
+if __name__ == '__main__':
+ parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
+ (options, args) = parser.parse_args()
+ tb = affinity_set()
+ tb.start()
+
+ while(1):
+ ret = raw_input('Enter a new Core # or Press Enter to quit: ')
+ if(len(ret) == 0):
+ tb.stop()
+ sys.exit(0)
+ elif(ret.lower() == "none"):
+ tb.filter_filt_0.unset_processor_affinity()
+ else:
+ try:
+ n = int(ret)
+ except ValueError:
+ print "Invalid number"
+ else:
+ tb.filter_filt_0.set_processor_affinity([n,])
diff --git a/gnuradio-runtime/examples/mp-sched/perf-data/core-duo.dat b/gnuradio-runtime/examples/mp-sched/perf-data/core-duo.dat
new file mode 100644
index 0000000000..064d1e1282
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/perf-data/core-duo.dat
@@ -0,0 +1,65 @@
+#D Core Duo 1.83 GHz (T2400)
+ 1 1 5.273e+07 10.010 10.160 0.060 1.021 2.700000e+10 2.697e+09
+ 1 2 5.273e+07 10.410 20.180 0.150 1.953 5.400000e+10 5.187e+09
+ 1 3 3.516e+07 10.360 20.030 0.150 1.948 5.400000e+10 5.212e+09
+ 1 4 2.637e+07 10.100 20.030 0.100 1.993 5.400000e+10 5.347e+09
+ 1 5 2.109e+07 10.140 19.980 0.110 1.981 5.400000e+10 5.325e+09
+ 1 6 1.758e+07 10.110 20.030 0.110 1.992 5.400000e+10 5.341e+09
+ 1 7 1.507e+07 10.120 20.030 0.110 1.990 5.400000e+10 5.336e+09
+ 1 8 1.318e+07 10.060 19.980 0.090 1.995 5.400000e+10 5.368e+09
+ 2 1 5.273e+07 10.210 20.130 0.260 1.997 5.400000e+10 5.289e+09
+ 2 2 2.637e+07 10.110 20.030 0.140 1.995 5.400000e+10 5.341e+09
+ 2 3 1.758e+07 10.120 20.010 0.150 1.992 5.400000e+10 5.336e+09
+ 2 4 1.318e+07 10.080 19.990 0.110 1.994 5.400000e+10 5.357e+09
+ 2 5 1.055e+07 10.050 19.990 0.090 1.998 5.400000e+10 5.373e+09
+ 2 6 8.789e+06 10.050 19.980 0.080 1.996 5.400000e+10 5.373e+09
+ 2 7 7.533e+06 10.050 19.970 0.090 1.996 5.400000e+10 5.373e+09
+ 2 8 6.592e+06 10.040 19.970 0.090 1.998 5.399999e+10 5.378e+09
+ 3 1 3.516e+07 10.630 20.130 0.230 1.915 5.400000e+10 5.080e+09
+ 3 2 1.758e+07 10.120 20.020 0.170 1.995 5.400000e+10 5.336e+09
+ 3 3 1.172e+07 10.140 20.050 0.130 1.990 5.400000e+10 5.325e+09
+ 3 4 8.789e+06 10.070 20.010 0.100 1.997 5.400000e+10 5.362e+09
+ 3 5 7.031e+06 10.060 19.980 0.100 1.996 5.400000e+10 5.368e+09
+ 3 6 5.859e+06 10.060 20.000 0.100 1.998 5.400000e+10 5.368e+09
+ 3 7 5.022e+06 10.050 20.010 0.070 1.998 5.400000e+10 5.373e+09
+ 3 8 4.395e+06 10.050 19.990 0.070 1.996 5.400000e+10 5.373e+09
+ 4 1 2.637e+07 10.180 20.080 0.240 1.996 5.400000e+10 5.305e+09
+ 4 2 1.318e+07 10.140 20.000 0.180 1.990 5.400000e+10 5.325e+09
+ 4 3 8.789e+06 10.110 20.020 0.120 1.992 5.400000e+10 5.341e+09
+ 4 4 6.592e+06 10.080 20.020 0.090 1.995 5.399999e+10 5.357e+09
+ 4 5 5.273e+06 10.050 19.990 0.090 1.998 5.399999e+10 5.373e+09
+ 4 6 4.395e+06 10.080 20.010 0.080 1.993 5.400000e+10 5.357e+09
+ 4 7 3.767e+06 10.070 20.000 0.080 1.994 5.400000e+10 5.362e+09
+ 4 8 3.296e+06 10.050 20.000 0.080 1.998 5.399999e+10 5.373e+09
+ 5 1 2.109e+07 11.240 20.080 0.260 1.810 5.400000e+10 4.804e+09
+ 5 2 1.055e+07 10.130 19.990 0.150 1.988 5.400000e+10 5.331e+09
+ 5 3 7.031e+06 10.100 20.020 0.120 1.994 5.400000e+10 5.347e+09
+ 5 4 5.273e+06 10.070 20.000 0.090 1.995 5.399999e+10 5.362e+09
+ 5 5 4.219e+06 10.100 20.040 0.090 1.993 5.400000e+10 5.347e+09
+ 5 6 3.516e+06 10.080 20.000 0.090 1.993 5.400000e+10 5.357e+09
+ 5 7 3.013e+06 10.070 20.000 0.100 1.996 5.399998e+10 5.362e+09
+ 5 8 2.637e+06 10.070 20.000 0.090 1.995 5.399998e+10 5.362e+09
+ 6 1 1.758e+07 10.220 20.100 0.290 1.995 5.400000e+10 5.284e+09
+ 6 2 8.789e+06 10.080 20.010 0.130 1.998 5.400000e+10 5.357e+09
+ 6 3 5.859e+06 10.090 20.030 0.120 1.997 5.400000e+10 5.352e+09
+ 6 4 4.395e+06 10.100 20.030 0.080 1.991 5.400000e+10 5.347e+09
+ 6 5 3.516e+06 10.060 20.020 0.080 1.998 5.400000e+10 5.368e+09
+ 6 6 2.930e+06 10.070 20.030 0.090 1.998 5.399999e+10 5.362e+09
+ 6 7 2.511e+06 10.070 20.030 0.080 1.997 5.399998e+10 5.362e+09
+ 6 8 2.197e+06 10.070 20.010 0.090 1.996 5.399998e+10 5.362e+09
+ 7 1 1.507e+07 10.420 20.030 0.260 1.947 5.400000e+10 5.182e+09
+ 7 2 7.533e+06 10.100 20.010 0.140 1.995 5.400000e+10 5.347e+09
+ 7 3 5.022e+06 10.080 20.020 0.120 1.998 5.400000e+10 5.357e+09
+ 7 4 3.767e+06 10.080 20.010 0.100 1.995 5.400000e+10 5.357e+09
+ 7 5 3.013e+06 10.070 20.030 0.080 1.997 5.399998e+10 5.362e+09
+ 7 6 2.511e+06 10.080 20.010 0.090 1.994 5.399998e+10 5.357e+09
+ 7 7 2.152e+06 10.080 20.060 0.070 1.997 5.399999e+10 5.357e+09
+ 7 8 1.883e+06 10.070 20.040 0.070 1.997 5.399998e+10 5.362e+09
+ 8 1 1.318e+07 10.220 20.080 0.270 1.991 5.400000e+10 5.284e+09
+ 8 2 6.592e+06 10.100 20.010 0.140 1.995 5.399999e+10 5.347e+09
+ 8 3 4.395e+06 10.110 20.020 0.120 1.992 5.400000e+10 5.341e+09
+ 8 4 3.296e+06 10.090 20.040 0.090 1.995 5.399999e+10 5.352e+09
+ 8 5 2.637e+06 10.090 20.040 0.090 1.995 5.399998e+10 5.352e+09
+ 8 6 2.197e+06 10.070 20.040 0.100 2.000 5.399998e+10 5.362e+09
+ 8 7 1.883e+06 10.090 20.050 0.080 1.995 5.399998e+10 5.352e+09
+ 8 8 1.648e+06 10.090 20.040 0.090 1.995 5.399999e+10 5.352e+09
diff --git a/gnuradio-runtime/examples/mp-sched/perf-data/core2-duo.dat b/gnuradio-runtime/examples/mp-sched/perf-data/core2-duo.dat
new file mode 100644
index 0000000000..d67dee8e51
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/perf-data/core2-duo.dat
@@ -0,0 +1,65 @@
+#D Core2 Duo 2.66 GHz (6700)
+ 1 1 1.406e+08 9.890 10.100 0.230 1.044 7.200000e+10 7.280e+09
+ 1 2 1.406e+08 10.400 19.900 0.290 1.941 1.440000e+11 1.385e+10
+ 1 3 9.375e+07 11.410 19.950 0.200 1.766 1.440000e+11 1.262e+10
+ 1 4 7.031e+07 10.230 19.800 0.230 1.958 1.440000e+11 1.408e+10
+ 1 5 5.625e+07 10.640 19.800 0.180 1.878 1.440000e+11 1.353e+10
+ 1 6 4.688e+07 10.000 19.780 0.130 1.991 1.440000e+11 1.440e+10
+ 1 7 4.018e+07 10.500 19.690 0.180 1.892 1.440000e+11 1.371e+10
+ 1 8 3.516e+07 10.020 19.750 0.170 1.988 1.440000e+11 1.437e+10
+ 2 1 1.406e+08 10.330 20.000 0.460 1.981 1.440000e+11 1.394e+10
+ 2 2 7.031e+07 10.160 19.870 0.270 1.982 1.440000e+11 1.417e+10
+ 2 3 4.688e+07 10.210 19.780 0.230 1.960 1.440000e+11 1.410e+10
+ 2 4 3.516e+07 10.050 19.730 0.210 1.984 1.440000e+11 1.433e+10
+ 2 5 2.812e+07 10.060 19.760 0.170 1.981 1.440000e+11 1.431e+10
+ 2 6 2.344e+07 10.030 19.780 0.180 1.990 1.440000e+11 1.436e+10
+ 2 7 2.009e+07 10.040 19.820 0.180 1.992 1.440000e+11 1.434e+10
+ 2 8 1.758e+07 10.050 19.820 0.180 1.990 1.440000e+11 1.433e+10
+ 3 1 9.375e+07 13.140 19.950 0.450 1.553 1.440000e+11 1.096e+10
+ 3 2 4.688e+07 10.570 19.840 0.290 1.904 1.440000e+11 1.362e+10
+ 3 3 3.125e+07 10.420 19.730 0.280 1.920 1.440000e+11 1.382e+10
+ 3 4 2.344e+07 10.120 19.710 0.240 1.971 1.440000e+11 1.423e+10
+ 3 5 1.875e+07 10.140 19.750 0.190 1.966 1.440000e+11 1.420e+10
+ 3 6 1.562e+07 10.030 19.730 0.190 1.986 1.440000e+11 1.436e+10
+ 3 7 1.339e+07 10.020 19.720 0.200 1.988 1.440000e+11 1.437e+10
+ 3 8 1.172e+07 9.990 19.720 0.170 1.991 1.440000e+11 1.441e+10
+ 4 1 7.031e+07 10.310 19.980 0.460 1.983 1.440000e+11 1.397e+10
+ 4 2 3.516e+07 10.300 19.830 0.320 1.956 1.440000e+11 1.398e+10
+ 4 3 2.344e+07 10.180 19.780 0.230 1.966 1.440000e+11 1.415e+10
+ 4 4 1.758e+07 10.070 19.750 0.220 1.983 1.440000e+11 1.430e+10
+ 4 5 1.406e+07 10.090 19.750 0.190 1.976 1.440000e+11 1.427e+10
+ 4 6 1.172e+07 10.020 19.720 0.190 1.987 1.440000e+11 1.437e+10
+ 4 7 1.004e+07 10.040 19.780 0.190 1.989 1.440000e+11 1.434e+10
+ 4 8 8.789e+06 10.000 19.750 0.160 1.991 1.440000e+11 1.440e+10
+ 5 1 5.625e+07 11.580 19.930 0.500 1.764 1.440000e+11 1.244e+10
+ 5 2 2.812e+07 10.300 19.830 0.320 1.956 1.440000e+11 1.398e+10
+ 5 3 1.875e+07 10.240 19.760 0.240 1.953 1.440000e+11 1.406e+10
+ 5 4 1.406e+07 10.140 19.880 0.230 1.983 1.440000e+11 1.420e+10
+ 5 5 1.125e+07 10.040 19.730 0.200 1.985 1.440000e+11 1.434e+10
+ 5 6 9.375e+06 10.030 19.770 0.200 1.991 1.440000e+11 1.436e+10
+ 5 7 8.036e+06 10.030 19.780 0.170 1.989 1.440000e+11 1.436e+10
+ 5 8 7.031e+06 10.000 19.750 0.180 1.993 1.440000e+11 1.440e+10
+ 6 1 4.688e+07 10.340 19.910 0.560 1.980 1.440000e+11 1.393e+10
+ 6 2 2.344e+07 10.290 19.770 0.330 1.953 1.440000e+11 1.399e+10
+ 6 3 1.562e+07 10.150 19.770 0.270 1.974 1.440000e+11 1.419e+10
+ 6 4 1.172e+07 10.170 19.880 0.240 1.978 1.440000e+11 1.416e+10
+ 6 5 9.375e+06 10.080 19.780 0.240 1.986 1.440000e+11 1.429e+10
+ 6 6 7.812e+06 10.020 19.740 0.220 1.992 1.440000e+11 1.437e+10
+ 6 7 6.696e+06 10.050 19.760 0.200 1.986 1.440000e+11 1.433e+10
+ 6 8 5.859e+06 10.070 19.750 0.210 1.982 1.440000e+11 1.430e+10
+ 7 1 4.018e+07 11.220 19.880 0.530 1.819 1.440000e+11 1.283e+10
+ 7 2 2.009e+07 10.280 19.790 0.340 1.958 1.440000e+11 1.401e+10
+ 7 3 1.339e+07 10.190 19.760 0.250 1.964 1.440000e+11 1.413e+10
+ 7 4 1.004e+07 10.060 19.750 0.240 1.987 1.440000e+11 1.431e+10
+ 7 5 8.036e+06 10.070 19.750 0.240 1.985 1.440000e+11 1.430e+10
+ 7 6 6.696e+06 10.040 19.810 0.220 1.995 1.440000e+11 1.434e+10
+ 7 7 5.740e+06 10.050 19.780 0.210 1.989 1.440000e+11 1.433e+10
+ 7 8 5.022e+06 10.010 19.790 0.190 1.996 1.440000e+11 1.439e+10
+ 8 1 3.516e+07 10.320 19.900 0.470 1.974 1.440000e+11 1.395e+10
+ 8 2 1.758e+07 10.340 19.900 0.320 1.956 1.440000e+11 1.393e+10
+ 8 3 1.172e+07 10.130 19.770 0.290 1.980 1.440000e+11 1.422e+10
+ 8 4 8.789e+06 10.120 19.780 0.230 1.977 1.440000e+11 1.423e+10
+ 8 5 7.031e+06 10.040 19.790 0.200 1.991 1.440000e+11 1.434e+10
+ 8 6 5.859e+06 10.050 19.770 0.220 1.989 1.440000e+11 1.433e+10
+ 8 7 5.022e+06 10.030 19.800 0.200 1.994 1.440000e+11 1.436e+10
+ 8 8 4.395e+06 10.050 19.800 0.210 1.991 1.440000e+11 1.433e+10
diff --git a/gnuradio-runtime/examples/mp-sched/perf-data/dual-quad-core-2.33-clovertown.dat b/gnuradio-runtime/examples/mp-sched/perf-data/dual-quad-core-2.33-clovertown.dat
new file mode 100644
index 0000000000..fa182c69a7
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/perf-data/dual-quad-core-2.33-clovertown.dat
@@ -0,0 +1,257 @@
+#D Dual quad-core Xeon 2.33GHz (Clovertown E5345)
+ 1 1 1.367e+08 10.980 12.080 0.360 1.133 7.000000e+10 6.375e+09
+ 1 2 1.367e+08 12.250 24.310 0.400 2.017 1.400000e+11 1.143e+10
+ 1 3 1.367e+08 12.830 36.080 0.580 2.857 2.100000e+11 1.637e+10
+ 1 4 1.367e+08 12.600 46.820 0.770 3.777 2.800000e+11 2.222e+10
+ 1 5 1.367e+08 12.620 58.850 0.720 4.720 3.500000e+11 2.773e+10
+ 1 6 1.367e+08 12.310 69.430 0.860 5.710 4.200000e+11 3.412e+10
+ 1 7 1.367e+08 12.720 80.580 0.950 6.410 4.900000e+11 3.852e+10
+ 1 8 1.367e+08 12.440 91.530 1.010 7.439 5.600000e+11 4.502e+10
+ 1 9 1.367e+08 22.310 102.660 1.080 4.650 6.300000e+11 2.824e+10
+ 1 10 1.367e+08 22.610 113.670 1.160 5.079 7.000000e+11 3.096e+10
+ 1 11 1.367e+08 22.690 124.730 1.030 5.543 7.700000e+11 3.394e+10
+ 1 12 1.367e+08 23.260 136.520 1.030 5.914 8.400000e+11 3.611e+10
+ 1 13 1.367e+08 23.330 147.270 1.130 6.361 9.100000e+11 3.901e+10
+ 1 14 1.367e+08 24.110 158.070 1.010 6.598 9.800000e+11 4.065e+10
+ 1 15 1.367e+08 25.380 168.370 1.080 6.677 1.050000e+12 4.137e+10
+ 1 16 1.367e+08 26.660 179.130 1.250 6.766 1.120000e+12 4.201e+10
+ 2 1 1.367e+08 11.190 23.330 0.420 2.122 1.400000e+11 1.251e+10
+ 2 2 1.367e+08 12.650 46.350 0.940 3.738 2.800000e+11 2.213e+10
+ 2 3 1.367e+08 12.510 69.010 0.980 5.595 4.200000e+11 3.357e+10
+ 2 4 1.367e+08 13.250 89.330 0.890 6.809 5.600000e+11 4.226e+10
+ 2 5 1.367e+08 22.540 113.580 1.150 5.090 7.000000e+11 3.106e+10
+ 2 6 1.367e+08 22.940 135.790 1.260 5.974 8.400000e+11 3.662e+10
+ 2 7 1.367e+08 24.250 158.360 1.520 6.593 9.800000e+11 4.041e+10
+ 2 8 1.367e+08 26.610 179.840 1.490 6.814 1.120000e+12 4.209e+10
+ 2 9 1.215e+08 26.860 179.400 1.540 6.736 1.120000e+12 4.170e+10
+ 2 10 1.094e+08 26.350 178.740 1.430 6.838 1.120000e+12 4.250e+10
+ 2 11 9.943e+07 25.790 177.910 1.350 6.951 1.120000e+12 4.343e+10
+ 2 12 9.115e+07 25.200 176.980 1.460 7.081 1.120000e+12 4.444e+10
+ 2 13 8.413e+07 24.840 177.320 1.260 7.189 1.120000e+12 4.509e+10
+ 2 14 7.812e+07 24.450 176.920 1.130 7.282 1.120000e+12 4.581e+10
+ 2 15 7.292e+07 24.280 177.400 1.140 7.353 1.120000e+12 4.613e+10
+ 2 16 6.836e+07 23.830 176.290 1.100 7.444 1.120000e+12 4.700e+10
+ 3 1 1.367e+08 11.360 34.790 0.930 3.144 2.100000e+11 1.849e+10
+ 3 2 1.367e+08 12.560 68.800 1.400 5.589 4.200000e+11 3.344e+10
+ 3 3 1.367e+08 22.310 103.250 1.310 4.687 6.300000e+11 2.824e+10
+ 3 4 1.367e+08 22.940 136.120 1.500 5.999 8.400000e+11 3.662e+10
+ 3 5 1.367e+08 25.240 168.550 1.790 6.749 1.050000e+12 4.160e+10
+ 3 6 1.215e+08 26.800 178.710 1.610 6.728 1.120000e+12 4.179e+10
+ 3 7 1.042e+08 26.090 178.710 1.490 6.907 1.120000e+12 4.293e+10
+ 3 8 9.115e+07 25.420 178.140 1.360 7.061 1.120000e+12 4.406e+10
+ 3 9 8.102e+07 24.680 177.260 1.410 7.239 1.120000e+12 4.538e+10
+ 3 10 7.292e+07 24.270 176.830 1.390 7.343 1.120000e+12 4.615e+10
+ 3 11 6.629e+07 23.890 177.060 1.240 7.463 1.120000e+12 4.688e+10
+ 3 12 6.076e+07 23.620 176.290 1.300 7.519 1.120000e+12 4.742e+10
+ 3 13 5.609e+07 23.340 176.780 1.230 7.627 1.120000e+12 4.799e+10
+ 3 14 5.208e+07 23.140 176.330 1.300 7.676 1.120000e+12 4.840e+10
+ 3 15 4.861e+07 23.100 176.940 1.080 7.706 1.120000e+12 4.848e+10
+ 3 16 4.557e+07 22.850 176.120 1.060 7.754 1.120000e+12 4.902e+10
+ 4 1 1.367e+08 11.440 45.520 1.080 4.073 2.800000e+11 2.448e+10
+ 4 2 1.367e+08 12.410 90.020 1.440 7.370 5.600000e+11 4.512e+10
+ 4 3 1.367e+08 23.060 135.570 1.600 5.948 8.400000e+11 3.643e+10
+ 4 4 1.367e+08 26.720 179.780 1.880 6.799 1.120000e+12 4.192e+10
+ 4 5 1.094e+08 26.280 178.110 1.890 6.849 1.120000e+12 4.262e+10
+ 4 6 9.115e+07 25.250 177.280 1.700 7.088 1.120000e+12 4.436e+10
+ 4 7 7.812e+07 24.880 177.830 1.570 7.211 1.120000e+12 4.502e+10
+ 4 8 6.836e+07 24.150 177.240 1.350 7.395 1.120000e+12 4.638e+10
+ 4 9 6.076e+07 23.730 176.590 1.370 7.499 1.120000e+12 4.720e+10
+ 4 10 5.469e+07 23.380 176.570 1.310 7.608 1.120000e+12 4.790e+10
+ 4 11 4.972e+07 23.230 176.400 1.290 7.649 1.120000e+12 4.821e+10
+ 4 12 4.557e+07 22.950 176.100 1.250 7.728 1.120000e+12 4.880e+10
+ 4 13 4.207e+07 22.980 176.430 1.260 7.732 1.120000e+12 4.874e+10
+ 4 14 3.906e+07 22.820 176.300 1.350 7.785 1.120000e+12 4.908e+10
+ 4 15 3.646e+07 22.750 176.450 1.220 7.810 1.120000e+12 4.923e+10
+ 4 16 3.418e+07 22.620 176.350 1.080 7.844 1.120000e+12 4.951e+10
+ 5 1 1.367e+08 12.000 56.890 1.600 4.874 3.500000e+11 2.917e+10
+ 5 2 1.367e+08 22.390 112.870 1.920 5.127 7.000000e+11 3.126e+10
+ 5 3 1.367e+08 25.170 167.880 2.110 6.754 1.050000e+12 4.172e+10
+ 5 4 1.094e+08 26.380 178.010 1.900 6.820 1.120000e+12 4.246e+10
+ 5 5 8.750e+07 25.190 177.570 1.660 7.115 1.120000e+12 4.446e+10
+ 5 6 7.292e+07 24.400 176.750 1.650 7.311 1.120000e+12 4.590e+10
+ 5 7 6.250e+07 24.020 177.580 1.570 7.458 1.120000e+12 4.663e+10
+ 5 8 5.469e+07 23.470 176.650 1.350 7.584 1.120000e+12 4.772e+10
+ 5 9 4.861e+07 23.200 176.350 1.280 7.656 1.120000e+12 4.828e+10
+ 5 10 4.375e+07 23.140 176.230 1.410 7.677 1.120000e+12 4.840e+10
+ 5 11 3.977e+07 22.930 176.120 1.320 7.738 1.120000e+12 4.884e+10
+ 5 12 3.646e+07 22.740 176.060 1.330 7.801 1.120000e+12 4.925e+10
+ 5 13 3.365e+07 22.690 176.450 1.210 7.830 1.120000e+12 4.936e+10
+ 5 14 3.125e+07 22.690 176.430 1.230 7.830 1.120000e+12 4.936e+10
+ 5 15 2.917e+07 22.690 176.410 1.260 7.830 1.120000e+12 4.936e+10
+ 5 16 2.734e+07 22.560 176.150 1.110 7.857 1.120000e+12 4.965e+10
+ 6 1 1.367e+08 12.600 68.590 2.230 5.621 4.200000e+11 3.333e+10
+ 6 2 1.367e+08 22.830 135.260 2.100 6.017 8.400000e+11 3.679e+10
+ 6 3 1.215e+08 26.860 178.470 2.140 6.724 1.120000e+12 4.170e+10
+ 6 4 9.115e+07 25.450 177.110 2.060 7.040 1.120000e+12 4.401e+10
+ 6 5 7.292e+07 24.510 176.850 1.910 7.293 1.120000e+12 4.570e+10
+ 6 6 6.076e+07 23.890 176.450 1.760 7.460 1.120000e+12 4.688e+10
+ 6 7 5.208e+07 23.460 175.980 1.540 7.567 1.120000e+12 4.774e+10
+ 6 8 4.557e+07 23.150 176.480 1.370 7.683 1.120000e+12 4.838e+10
+ 6 9 4.051e+07 22.920 176.030 1.400 7.741 1.120000e+12 4.887e+10
+ 6 10 3.646e+07 22.880 176.300 1.350 7.764 1.120000e+12 4.895e+10
+ 6 11 3.314e+07 22.830 175.970 1.360 7.767 1.120000e+12 4.906e+10
+ 6 12 3.038e+07 22.710 176.040 1.190 7.804 1.120000e+12 4.932e+10
+ 6 13 2.804e+07 22.690 176.050 1.340 7.818 1.120000e+12 4.936e+10
+ 6 14 2.604e+07 22.650 176.410 1.140 7.839 1.120000e+12 4.945e+10
+ 6 15 2.431e+07 22.570 175.940 1.250 7.851 1.120000e+12 4.962e+10
+ 6 16 2.279e+07 22.500 175.980 1.170 7.873 1.120000e+12 4.978e+10
+ 7 1 1.367e+08 12.960 79.970 2.850 6.390 4.900000e+11 3.781e+10
+ 7 2 1.367e+08 24.040 156.540 2.500 6.616 9.800000e+11 4.077e+10
+ 7 3 1.042e+08 26.130 178.060 2.210 6.899 1.120000e+12 4.286e+10
+ 7 4 7.812e+07 24.860 176.880 1.810 7.188 1.120000e+12 4.505e+10
+ 7 5 6.250e+07 24.000 176.590 1.790 7.433 1.120000e+12 4.667e+10
+ 7 6 5.208e+07 23.540 176.480 1.670 7.568 1.120000e+12 4.758e+10
+ 7 7 4.464e+07 23.180 176.030 1.510 7.659 1.120000e+12 4.832e+10
+ 7 8 3.906e+07 22.980 176.500 1.340 7.739 1.120000e+12 4.874e+10
+ 7 9 3.472e+07 22.870 175.970 1.280 7.750 1.120000e+12 4.897e+10
+ 7 10 3.125e+07 22.730 176.220 1.300 7.810 1.120000e+12 4.927e+10
+ 7 11 2.841e+07 22.700 176.030 1.300 7.812 1.120000e+12 4.934e+10
+ 7 12 2.604e+07 22.650 176.300 1.210 7.837 1.120000e+12 4.945e+10
+ 7 13 2.404e+07 22.580 176.140 1.170 7.853 1.120000e+12 4.960e+10
+ 7 14 2.232e+07 22.540 176.550 1.130 7.883 1.120000e+12 4.969e+10
+ 7 15 2.083e+07 22.570 175.870 1.260 7.848 1.120000e+12 4.962e+10
+ 7 16 1.953e+07 22.520 175.980 1.310 7.873 1.120000e+12 4.973e+10
+ 8 1 1.367e+08 13.250 91.770 3.010 7.153 5.600000e+11 4.226e+10
+ 8 2 1.367e+08 26.280 178.100 2.980 6.890 1.120000e+12 4.262e+10
+ 8 3 9.115e+07 25.510 177.140 2.270 7.033 1.120000e+12 4.390e+10
+ 8 4 6.836e+07 24.330 176.850 1.870 7.346 1.120000e+12 4.603e+10
+ 8 5 5.469e+07 23.680 176.850 1.690 7.540 1.120000e+12 4.730e+10
+ 8 6 4.557e+07 23.430 176.210 1.700 7.593 1.120000e+12 4.780e+10
+ 8 7 3.906e+07 23.100 176.680 1.440 7.711 1.120000e+12 4.848e+10
+ 8 8 3.418e+07 22.890 176.270 1.430 7.763 1.120000e+12 4.893e+10
+ 8 9 3.038e+07 22.760 175.980 1.320 7.790 1.120000e+12 4.921e+10
+ 8 10 2.734e+07 22.760 176.340 1.290 7.804 1.120000e+12 4.921e+10
+ 8 11 2.486e+07 22.660 176.220 1.170 7.828 1.120000e+12 4.943e+10
+ 8 12 2.279e+07 22.660 176.050 1.280 7.826 1.120000e+12 4.943e+10
+ 8 13 2.103e+07 22.590 176.170 1.350 7.858 1.120000e+12 4.958e+10
+ 8 14 1.953e+07 22.550 176.120 1.320 7.869 1.120000e+12 4.967e+10
+ 8 15 1.823e+07 22.590 176.130 1.270 7.853 1.120000e+12 4.958e+10
+ 8 16 1.709e+07 22.500 176.090 1.230 7.881 1.120000e+12 4.978e+10
+ 9 1 1.367e+08 21.110 101.410 2.640 4.929 6.300000e+11 2.984e+10
+ 9 2 1.215e+08 27.400 178.180 2.720 6.602 1.120000e+12 4.088e+10
+ 9 3 8.102e+07 25.140 177.370 2.230 7.144 1.120000e+12 4.455e+10
+ 9 4 6.076e+07 24.110 176.810 1.910 7.413 1.120000e+12 4.645e+10
+ 9 5 4.861e+07 23.460 176.240 1.600 7.581 1.120000e+12 4.774e+10
+ 9 6 4.051e+07 23.200 176.310 1.620 7.669 1.120000e+12 4.828e+10
+ 9 7 3.472e+07 22.970 176.560 1.540 7.754 1.120000e+12 4.876e+10
+ 9 8 3.038e+07 22.920 176.300 1.440 7.755 1.120000e+12 4.887e+10
+ 9 9 2.701e+07 22.830 176.090 1.370 7.773 1.120000e+12 4.906e+10
+ 9 10 2.431e+07 22.730 175.960 1.430 7.804 1.120000e+12 4.927e+10
+ 9 11 2.210e+07 22.750 176.160 1.260 7.799 1.120000e+12 4.923e+10
+ 9 12 2.025e+07 22.660 176.100 1.380 7.832 1.120000e+12 4.943e+10
+ 9 13 1.870e+07 22.700 176.040 1.400 7.817 1.120000e+12 4.934e+10
+ 9 14 1.736e+07 22.620 175.940 1.410 7.840 1.120000e+12 4.951e+10
+ 9 15 1.620e+07 22.490 175.910 1.340 7.881 1.120000e+12 4.980e+10
+ 9 16 1.519e+07 22.540 175.990 1.330 7.867 1.120000e+12 4.969e+10
+ 10 1 1.367e+08 21.730 113.690 2.870 5.364 7.000000e+11 3.221e+10
+ 10 2 1.094e+08 26.660 177.920 3.180 6.793 1.120000e+12 4.201e+10
+ 10 3 7.292e+07 24.740 176.810 2.090 7.231 1.120000e+12 4.527e+10
+ 10 4 5.469e+07 23.880 176.280 2.020 7.466 1.120000e+12 4.690e+10
+ 10 5 4.375e+07 23.330 176.510 1.610 7.635 1.120000e+12 4.801e+10
+ 10 6 3.646e+07 23.170 176.160 1.680 7.675 1.120000e+12 4.834e+10
+ 10 7 3.125e+07 22.950 176.490 1.470 7.754 1.120000e+12 4.880e+10
+ 10 8 2.734e+07 22.830 176.260 1.360 7.780 1.120000e+12 4.906e+10
+ 10 9 2.431e+07 22.770 175.930 1.410 7.788 1.120000e+12 4.919e+10
+ 10 10 2.188e+07 22.680 175.870 1.440 7.818 1.120000e+12 4.938e+10
+ 10 11 1.989e+07 22.700 176.140 1.310 7.817 1.120000e+12 4.934e+10
+ 10 12 1.823e+07 22.630 176.040 1.430 7.842 1.120000e+12 4.949e+10
+ 10 13 1.683e+07 22.640 176.000 1.320 7.832 1.120000e+12 4.947e+10
+ 10 14 1.562e+07 22.610 176.160 1.230 7.846 1.120000e+12 4.954e+10
+ 10 15 1.458e+07 22.570 176.010 1.290 7.856 1.120000e+12 4.962e+10
+ 10 16 1.367e+07 22.640 176.060 1.270 7.833 1.120000e+12 4.947e+10
+ 11 1 1.367e+08 22.060 124.440 3.050 5.779 7.700000e+11 3.490e+10
+ 11 2 9.943e+07 26.060 178.400 3.000 6.961 1.120000e+12 4.298e+10
+ 11 3 6.629e+07 24.380 176.690 2.200 7.338 1.120000e+12 4.594e+10
+ 11 4 4.972e+07 23.650 176.730 1.830 7.550 1.120000e+12 4.736e+10
+ 11 5 3.977e+07 23.310 176.030 1.780 7.628 1.120000e+12 4.805e+10
+ 11 6 3.314e+07 23.050 176.210 1.680 7.718 1.120000e+12 4.859e+10
+ 11 7 2.841e+07 22.940 176.300 1.540 7.752 1.120000e+12 4.882e+10
+ 11 8 2.486e+07 22.830 175.990 1.530 7.776 1.120000e+12 4.906e+10
+ 11 9 2.210e+07 22.760 176.060 1.440 7.799 1.120000e+12 4.921e+10
+ 11 10 1.989e+07 22.630 176.010 1.430 7.841 1.120000e+12 4.949e+10
+ 11 11 1.808e+07 22.720 176.040 1.390 7.809 1.120000e+12 4.930e+10
+ 11 12 1.657e+07 22.640 175.890 1.400 7.831 1.120000e+12 4.947e+10
+ 11 13 1.530e+07 22.570 176.090 1.260 7.858 1.120000e+12 4.962e+10
+ 11 14 1.420e+07 22.610 176.150 1.450 7.855 1.120000e+12 4.954e+10
+ 11 15 1.326e+07 22.550 175.980 1.310 7.862 1.120000e+12 4.967e+10
+ 11 16 1.243e+07 22.610 175.920 1.400 7.843 1.120000e+12 4.954e+10
+ 12 1 1.367e+08 22.220 136.260 3.390 6.285 8.400000e+11 3.780e+10
+ 12 2 9.115e+07 25.610 178.090 2.800 7.063 1.120000e+12 4.373e+10
+ 12 3 6.076e+07 24.180 176.320 2.230 7.384 1.120000e+12 4.632e+10
+ 12 4 4.557e+07 23.570 176.570 2.010 7.577 1.120000e+12 4.752e+10
+ 12 5 3.646e+07 23.210 176.420 1.710 7.675 1.120000e+12 4.826e+10
+ 12 6 3.038e+07 23.040 175.910 1.640 7.706 1.120000e+12 4.861e+10
+ 12 7 2.604e+07 22.980 176.390 1.510 7.742 1.120000e+12 4.874e+10
+ 12 8 2.279e+07 22.840 176.110 1.640 7.782 1.120000e+12 4.904e+10
+ 12 9 2.025e+07 22.760 175.950 1.500 7.797 1.120000e+12 4.921e+10
+ 12 10 1.823e+07 22.660 175.810 1.600 7.829 1.120000e+12 4.943e+10
+ 12 11 1.657e+07 22.710 175.940 1.410 7.809 1.120000e+12 4.932e+10
+ 12 12 1.519e+07 22.650 175.870 1.400 7.826 1.120000e+12 4.945e+10
+ 12 13 1.402e+07 22.640 176.040 1.260 7.831 1.120000e+12 4.947e+10
+ 12 14 1.302e+07 22.650 176.130 1.450 7.840 1.120000e+12 4.945e+10
+ 12 15 1.215e+07 22.580 175.990 1.370 7.855 1.120000e+12 4.960e+10
+ 12 16 1.139e+07 22.640 175.870 1.440 7.832 1.120000e+12 4.947e+10
+ 13 1 1.367e+08 22.640 147.020 3.570 6.652 9.100000e+11 4.019e+10
+ 13 2 8.413e+07 25.600 177.820 2.870 7.058 1.120000e+12 4.375e+10
+ 13 3 5.609e+07 24.020 176.980 2.270 7.463 1.120000e+12 4.663e+10
+ 13 4 4.207e+07 23.440 176.430 2.030 7.613 1.120000e+12 4.778e+10
+ 13 5 3.365e+07 23.080 176.110 1.790 7.708 1.120000e+12 4.853e+10
+ 13 6 2.804e+07 22.870 176.210 1.600 7.775 1.120000e+12 4.897e+10
+ 13 7 2.404e+07 22.940 176.340 1.580 7.756 1.120000e+12 4.882e+10
+ 13 8 2.103e+07 22.880 176.050 1.520 7.761 1.120000e+12 4.895e+10
+ 13 9 1.870e+07 22.740 176.020 1.400 7.802 1.120000e+12 4.925e+10
+ 13 10 1.683e+07 22.710 175.880 1.440 7.808 1.120000e+12 4.932e+10
+ 13 11 1.530e+07 22.590 176.040 1.350 7.853 1.120000e+12 4.958e+10
+ 13 12 1.402e+07 22.600 175.930 1.380 7.846 1.120000e+12 4.956e+10
+ 13 13 1.294e+07 22.710 176.010 1.340 7.809 1.120000e+12 4.932e+10
+ 13 14 1.202e+07 22.690 176.270 1.350 7.828 1.120000e+12 4.936e+10
+ 13 15 1.122e+07 22.590 175.960 1.290 7.846 1.120000e+12 4.958e+10
+ 13 16 1.052e+07 22.610 175.960 1.370 7.843 1.120000e+12 4.954e+10
+ 14 1 1.367e+08 23.120 157.180 3.810 6.963 9.800000e+11 4.239e+10
+ 14 2 7.812e+07 25.310 177.210 3.020 7.121 1.120000e+12 4.425e+10
+ 14 3 5.208e+07 24.130 177.110 2.340 7.437 1.120000e+12 4.642e+10
+ 14 4 3.906e+07 23.390 176.660 1.800 7.630 1.120000e+12 4.788e+10
+ 14 5 3.125e+07 23.060 176.420 1.750 7.726 1.120000e+12 4.857e+10
+ 14 6 2.604e+07 22.890 176.180 1.530 7.764 1.120000e+12 4.893e+10
+ 14 7 2.232e+07 22.940 176.060 1.550 7.742 1.120000e+12 4.882e+10
+ 14 8 1.953e+07 22.810 176.110 1.500 7.786 1.120000e+12 4.910e+10
+ 14 9 1.736e+07 22.750 176.370 1.370 7.813 1.120000e+12 4.923e+10
+ 14 10 1.562e+07 22.720 176.020 1.450 7.811 1.120000e+12 4.930e+10
+ 14 11 1.420e+07 22.680 176.090 1.310 7.822 1.120000e+12 4.938e+10
+ 14 12 1.302e+07 22.710 175.950 1.510 7.814 1.120000e+12 4.932e+10
+ 14 13 1.202e+07 22.700 176.100 1.500 7.824 1.120000e+12 4.934e+10
+ 14 14 1.116e+07 22.660 176.150 1.460 7.838 1.120000e+12 4.943e+10
+ 14 15 1.042e+07 22.680 176.120 1.370 7.826 1.120000e+12 4.938e+10
+ 14 16 9.766e+06 22.710 176.110 1.430 7.818 1.120000e+12 4.932e+10
+ 15 1 1.367e+08 23.710 168.080 4.140 7.264 1.050000e+12 4.429e+10
+ 15 2 7.292e+07 25.170 176.640 2.930 7.134 1.120000e+12 4.450e+10
+ 15 3 4.861e+07 23.820 176.980 2.110 7.518 1.120000e+12 4.702e+10
+ 15 4 3.646e+07 23.250 176.190 1.970 7.663 1.120000e+12 4.817e+10
+ 15 5 2.917e+07 23.050 176.450 1.690 7.728 1.120000e+12 4.859e+10
+ 15 6 2.431e+07 22.900 175.980 1.680 7.758 1.120000e+12 4.891e+10
+ 15 7 2.083e+07 22.830 176.090 1.640 7.785 1.120000e+12 4.906e+10
+ 15 8 1.823e+07 22.850 176.160 1.530 7.776 1.120000e+12 4.902e+10
+ 15 9 1.620e+07 22.780 176.390 1.360 7.803 1.120000e+12 4.917e+10
+ 15 10 1.458e+07 22.660 176.000 1.440 7.831 1.120000e+12 4.943e+10
+ 15 11 1.326e+07 22.660 176.110 1.430 7.835 1.120000e+12 4.943e+10
+ 15 12 1.215e+07 22.660 176.150 1.380 7.835 1.120000e+12 4.943e+10
+ 15 13 1.122e+07 22.760 175.970 1.580 7.801 1.120000e+12 4.921e+10
+ 15 14 1.042e+07 22.670 176.290 1.270 7.832 1.120000e+12 4.940e+10
+ 15 15 9.722e+06 22.710 176.060 1.550 7.821 1.120000e+12 4.932e+10
+ 15 16 9.115e+06 22.800 176.020 1.490 7.786 1.120000e+12 4.912e+10
+ 16 1 1.367e+08 25.470 179.270 4.730 7.224 1.120000e+12 4.397e+10
+ 16 2 6.836e+07 24.870 176.820 2.960 7.229 1.120000e+12 4.503e+10
+ 16 3 4.557e+07 23.810 176.930 2.250 7.525 1.120000e+12 4.704e+10
+ 16 4 3.418e+07 23.240 176.650 1.950 7.685 1.120000e+12 4.819e+10
+ 16 5 2.734e+07 23.090 175.940 1.940 7.704 1.120000e+12 4.851e+10
+ 16 6 2.279e+07 22.900 176.120 1.680 7.764 1.120000e+12 4.891e+10
+ 16 7 1.953e+07 22.890 176.290 1.440 7.765 1.120000e+12 4.893e+10
+ 16 8 1.709e+07 22.820 176.040 1.610 7.785 1.120000e+12 4.908e+10
+ 16 9 1.519e+07 22.890 175.990 1.470 7.753 1.120000e+12 4.893e+10
+ 16 10 1.367e+07 22.700 175.890 1.470 7.813 1.120000e+12 4.934e+10
+ 16 11 1.243e+07 22.770 175.960 1.520 7.794 1.120000e+12 4.919e+10
+ 16 12 1.139e+07 22.730 176.000 1.430 7.806 1.120000e+12 4.927e+10
+ 16 13 1.052e+07 22.670 175.990 1.540 7.831 1.120000e+12 4.940e+10
+ 16 14 9.766e+06 22.720 176.130 1.440 7.816 1.120000e+12 4.930e+10
+ 16 15 9.115e+06 22.740 176.320 1.360 7.814 1.120000e+12 4.925e+10
+ 16 16 8.545e+06 22.680 176.170 1.320 7.826 1.120000e+12 4.938e+10
diff --git a/gnuradio-runtime/examples/mp-sched/perf-data/dual-quad-core-3.00-penryn.dat b/gnuradio-runtime/examples/mp-sched/perf-data/dual-quad-core-3.00-penryn.dat
new file mode 100644
index 0000000000..57d49ed334
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/perf-data/dual-quad-core-3.00-penryn.dat
@@ -0,0 +1,257 @@
+#D Dual quad-core Xeon 3.0 GHz (Penryn E5472, 1600 MHz FSB, 5400 chipset)
+ 1 1 5.000e+07 2.720 3.020 0.110 1.151 2.560000e+10 9.412e+09
+ 1 2 5.000e+07 2.870 5.630 0.170 2.021 5.120000e+10 1.784e+10
+ 1 3 5.000e+07 2.880 8.380 0.160 2.965 7.680000e+10 2.667e+10
+ 1 4 5.000e+07 2.990 11.080 0.200 3.773 1.024000e+11 3.425e+10
+ 1 5 5.000e+07 2.950 13.950 0.190 4.793 1.280000e+11 4.339e+10
+ 1 6 5.000e+07 3.020 16.620 0.240 5.583 1.536000e+11 5.086e+10
+ 1 7 5.000e+07 2.930 19.250 0.200 6.638 1.792000e+11 6.116e+10
+ 1 8 5.000e+07 3.170 22.240 0.290 7.107 2.048000e+11 6.461e+10
+ 1 9 5.000e+07 5.450 24.410 0.310 4.536 2.304000e+11 4.228e+10
+ 1 10 5.000e+07 5.610 27.400 0.370 4.950 2.560000e+11 4.563e+10
+ 1 11 5.000e+07 5.680 29.960 0.370 5.340 2.816000e+11 4.958e+10
+ 1 12 5.000e+07 5.440 32.490 0.350 6.037 3.072000e+11 5.647e+10
+ 1 13 5.000e+07 5.630 35.270 0.400 6.336 3.328000e+11 5.911e+10
+ 1 14 5.000e+07 6.270 38.500 0.480 6.217 3.584000e+11 5.716e+10
+ 1 15 5.000e+07 6.080 40.880 0.490 6.804 3.840000e+11 6.316e+10
+ 1 16 5.000e+07 7.740 43.390 0.600 5.683 4.096000e+11 5.292e+10
+ 2 1 5.000e+07 2.820 5.700 0.210 2.096 5.120000e+10 1.816e+10
+ 2 2 5.000e+07 2.820 11.130 0.230 4.028 1.024000e+11 3.631e+10
+ 2 3 5.000e+07 2.960 16.570 0.320 5.706 1.536000e+11 5.189e+10
+ 2 4 5.000e+07 3.110 21.920 0.390 7.174 2.048000e+11 6.585e+10
+ 2 5 5.000e+07 5.650 27.550 0.520 4.968 2.560000e+11 4.531e+10
+ 2 6 5.000e+07 5.880 32.890 0.440 5.668 3.072000e+11 5.224e+10
+ 2 7 5.000e+07 6.750 38.210 0.560 5.744 3.584000e+11 5.310e+10
+ 2 8 5.000e+07 6.360 43.480 0.580 6.928 4.096000e+11 6.440e+10
+ 2 9 5.000e+07 8.270 48.750 0.730 5.983 4.608000e+11 5.572e+10
+ 2 10 5.000e+07 8.210 54.400 0.610 6.700 5.120000e+11 6.236e+10
+ 2 11 5.000e+07 8.750 59.760 0.640 6.903 5.632000e+11 6.437e+10
+ 2 12 5.000e+07 9.300 65.050 0.700 7.070 6.144000e+11 6.606e+10
+ 2 13 5.000e+07 9.990 70.750 0.750 7.157 6.656000e+11 6.663e+10
+ 2 14 5.000e+07 10.610 75.950 0.810 7.235 7.168000e+11 6.756e+10
+ 2 15 5.000e+07 11.900 80.400 0.870 6.829 7.680000e+11 6.454e+10
+ 2 16 5.000e+07 11.820 86.790 0.900 7.419 8.192000e+11 6.931e+10
+ 3 1 5.000e+07 2.970 8.300 0.380 2.923 7.680000e+10 2.586e+10
+ 3 2 5.000e+07 2.980 16.660 0.390 5.721 1.536000e+11 5.154e+10
+ 3 3 5.000e+07 5.480 24.690 0.420 4.582 2.304000e+11 4.204e+10
+ 3 4 5.000e+07 5.620 32.820 0.560 5.940 3.072000e+11 5.466e+10
+ 3 5 5.000e+07 6.940 40.800 0.620 5.968 3.840000e+11 5.533e+10
+ 3 6 5.000e+07 7.860 49.010 0.710 6.326 4.608000e+11 5.863e+10
+ 3 7 5.000e+07 8.470 57.130 0.750 6.834 5.376000e+11 6.347e+10
+ 3 8 5.000e+07 9.420 65.310 0.820 7.020 6.144000e+11 6.522e+10
+ 3 9 5.000e+07 10.350 73.640 0.940 7.206 6.912000e+11 6.678e+10
+ 3 10 5.000e+07 11.460 82.230 1.030 7.265 7.680000e+11 6.702e+10
+ 3 11 5.000e+07 12.200 89.590 1.050 7.430 8.448000e+11 6.925e+10
+ 3 12 5.000e+07 13.040 97.520 1.140 7.566 9.216000e+11 7.067e+10
+ 3 13 5.000e+07 14.000 105.560 1.150 7.622 9.984000e+11 7.131e+10
+ 3 14 5.000e+07 14.930 113.630 1.210 7.692 1.075200e+12 7.202e+10
+ 3 15 5.000e+07 15.920 121.610 1.350 7.724 1.152000e+12 7.236e+10
+ 3 16 5.000e+07 16.870 129.770 1.390 7.775 1.228800e+12 7.284e+10
+ 4 1 5.000e+07 2.900 11.100 0.340 3.945 1.024000e+11 3.531e+10
+ 4 2 5.000e+07 4.380 21.980 0.480 5.128 2.048000e+11 4.676e+10
+ 4 3 5.000e+07 5.720 32.800 0.610 5.841 3.072000e+11 5.371e+10
+ 4 4 5.000e+07 6.820 43.880 0.700 6.537 4.096000e+11 6.006e+10
+ 4 5 5.000e+07 8.150 54.420 0.760 6.771 5.120000e+11 6.282e+10
+ 4 6 5.000e+07 9.510 65.180 0.980 6.957 6.144000e+11 6.461e+10
+ 4 7 5.000e+07 10.650 76.080 1.020 7.239 7.168000e+11 6.731e+10
+ 4 8 5.000e+07 11.880 86.720 1.110 7.393 8.192000e+11 6.896e+10
+ 4 9 5.000e+07 13.150 97.920 1.250 7.541 9.216000e+11 7.008e+10
+ 4 10 5.000e+07 14.640 109.260 1.410 7.559 1.024000e+12 6.995e+10
+ 4 11 5.000e+07 15.710 119.170 1.440 7.677 1.126400e+12 7.170e+10
+ 4 12 5.000e+07 16.950 129.960 1.420 7.751 1.228800e+12 7.250e+10
+ 4 13 5.000e+07 18.260 140.520 1.620 7.784 1.331200e+12 7.290e+10
+ 4 14 5.000e+07 19.610 151.290 1.780 7.806 1.433600e+12 7.311e+10
+ 4 15 5.000e+07 21.060 162.760 1.890 7.818 1.536000e+12 7.293e+10
+ 4 16 5.000e+07 22.280 172.870 1.980 7.848 1.638400e+12 7.354e+10
+ 5 1 5.000e+07 3.040 13.810 0.390 4.671 1.280000e+11 4.211e+10
+ 5 2 5.000e+07 5.590 27.510 0.610 5.030 2.560000e+11 4.580e+10
+ 5 3 5.000e+07 6.550 40.970 0.780 6.374 3.840000e+11 5.863e+10
+ 5 4 5.000e+07 8.520 54.470 0.940 6.504 5.120000e+11 6.009e+10
+ 5 5 5.000e+07 9.920 67.950 1.060 6.957 6.400000e+11 6.452e+10
+ 5 6 5.000e+07 11.350 81.490 1.180 7.284 7.680000e+11 6.767e+10
+ 5 7 5.000e+07 12.910 94.960 1.300 7.456 8.960000e+11 6.940e+10
+ 5 8 5.000e+07 14.520 108.510 1.400 7.570 1.024000e+12 7.052e+10
+ 5 9 5.000e+07 16.070 122.120 1.620 7.700 1.152000e+12 7.169e+10
+ 5 10 5.000e+07 17.950 136.140 1.730 7.681 1.280000e+12 7.131e+10
+ 5 11 5.000e+07 19.470 148.330 1.830 7.712 1.408000e+12 7.232e+10
+ 5 12 5.000e+07 20.980 162.100 2.030 7.823 1.536000e+12 7.321e+10
+ 5 13 5.000e+07 22.670 175.470 2.160 7.835 1.664000e+12 7.340e+10
+ 5 14 5.000e+07 24.440 189.630 2.170 7.848 1.792000e+12 7.332e+10
+ 5 15 5.000e+07 26.100 203.010 2.450 7.872 1.920000e+12 7.356e+10
+ 5 16 5.000e+07 27.720 216.000 2.550 7.884 2.048000e+12 7.388e+10
+ 6 1 5.000e+07 2.950 16.560 0.540 5.797 1.536000e+11 5.207e+10
+ 6 2 5.000e+07 5.540 32.900 0.720 6.069 3.072000e+11 5.545e+10
+ 6 3 5.000e+07 8.490 48.860 1.000 5.873 4.608000e+11 5.428e+10
+ 6 4 5.000e+07 10.000 64.670 1.100 6.577 6.144000e+11 6.144e+10
+ 6 5 5.000e+07 11.440 81.430 1.310 7.233 7.680000e+11 6.713e+10
+ 6 6 5.000e+07 13.250 97.690 1.360 7.475 9.216000e+11 6.955e+10
+ 6 7 5.000e+07 15.270 113.730 1.610 7.553 1.075200e+12 7.041e+10
+ 6 8 5.000e+07 17.180 129.780 1.820 7.660 1.228800e+12 7.153e+10
+ 6 9 5.000e+07 19.200 146.020 1.870 7.703 1.382400e+12 7.200e+10
+ 6 10 5.000e+07 21.220 162.290 2.100 7.747 1.536000e+12 7.238e+10
+ 6 11 5.000e+07 23.070 178.420 2.160 7.827 1.689600e+12 7.324e+10
+ 6 12 5.000e+07 25.120 194.590 2.450 7.844 1.843200e+12 7.338e+10
+ 6 13 5.000e+07 27.110 210.640 2.660 7.868 1.996800e+12 7.366e+10
+ 6 14 5.000e+07 29.110 226.820 2.750 7.886 2.150400e+12 7.387e+10
+ 6 15 5.000e+07 31.130 242.800 2.940 7.894 2.304000e+12 7.401e+10
+ 6 16 5.000e+07 33.100 258.790 3.210 7.915 2.457600e+12 7.425e+10
+ 7 1 5.000e+07 2.940 19.140 0.590 6.711 1.792000e+11 6.095e+10
+ 7 2 5.000e+07 5.920 37.910 1.030 6.578 3.584000e+11 6.054e+10
+ 7 3 5.000e+07 8.570 57.010 1.150 6.786 5.376000e+11 6.273e+10
+ 7 4 5.000e+07 10.840 76.060 1.320 7.138 7.168000e+11 6.613e+10
+ 7 5 5.000e+07 13.070 94.920 1.540 7.380 8.960000e+11 6.855e+10
+ 7 6 5.000e+07 15.270 113.790 1.730 7.565 1.075200e+12 7.041e+10
+ 7 7 5.000e+07 17.700 132.560 1.960 7.600 1.254400e+12 7.087e+10
+ 7 8 5.000e+07 19.930 151.500 2.130 7.708 1.433600e+12 7.193e+10
+ 7 9 5.000e+07 22.250 170.570 2.340 7.771 1.612800e+12 7.249e+10
+ 7 10 5.000e+07 24.600 189.280 2.450 7.794 1.792000e+12 7.285e+10
+ 7 11 5.000e+07 26.950 208.030 2.700 7.819 1.971200e+12 7.314e+10
+ 7 12 5.000e+07 29.280 227.070 2.850 7.852 2.150400e+12 7.344e+10
+ 7 13 5.000e+07 31.570 245.750 3.040 7.881 2.329600e+12 7.379e+10
+ 7 14 5.000e+07 33.930 264.960 3.160 7.902 2.508800e+12 7.394e+10
+ 7 15 5.000e+07 36.310 283.960 3.440 7.915 2.688000e+12 7.403e+10
+ 7 16 5.000e+07 38.560 302.120 3.630 7.929 2.867200e+12 7.436e+10
+ 8 1 5.000e+07 3.200 21.880 0.860 7.106 2.048000e+11 6.400e+10
+ 8 2 5.000e+07 5.890 43.450 0.930 7.535 4.096000e+11 6.954e+10
+ 8 3 5.000e+07 9.520 65.180 1.250 6.978 6.144000e+11 6.454e+10
+ 8 4 5.000e+07 12.200 86.780 1.480 7.234 8.192000e+11 6.715e+10
+ 8 5 5.000e+07 14.760 108.420 1.670 7.459 1.024000e+12 6.938e+10
+ 8 6 5.000e+07 17.300 129.850 1.960 7.619 1.228800e+12 7.103e+10
+ 8 7 5.000e+07 20.020 151.430 2.190 7.673 1.433600e+12 7.161e+10
+ 8 8 5.000e+07 22.750 173.550 2.420 7.735 1.638400e+12 7.202e+10
+ 8 9 5.000e+07 25.410 194.560 2.760 7.765 1.843200e+12 7.254e+10
+ 8 10 5.000e+07 28.410 217.250 2.920 7.750 2.048000e+12 7.209e+10
+ 8 11 5.000e+07 30.720 237.990 3.210 7.852 2.252800e+12 7.333e+10
+ 8 12 5.000e+07 33.310 259.340 3.280 7.884 2.457600e+12 7.378e+10
+ 8 13 5.000e+07 36.000 280.760 3.670 7.901 2.662400e+12 7.396e+10
+ 8 14 5.000e+07 38.800 302.570 3.740 7.895 2.867200e+12 7.390e+10
+ 8 15 5.000e+07 41.530 324.520 4.060 7.912 3.072000e+12 7.397e+10
+ 8 16 5.000e+07 44.060 345.420 4.250 7.936 3.276800e+12 7.437e+10
+ 9 1 5.000e+07 5.460 24.660 1.000 4.700 2.304000e+11 4.220e+10
+ 9 2 5.000e+07 8.460 49.010 1.200 5.935 4.608000e+11 5.447e+10
+ 9 3 5.000e+07 10.810 71.410 1.400 6.735 6.912000e+11 6.394e+10
+ 9 4 5.000e+07 13.470 97.570 1.710 7.370 9.216000e+11 6.842e+10
+ 9 5 5.000e+07 16.490 121.780 2.130 7.514 1.152000e+12 6.986e+10
+ 9 6 5.000e+07 19.540 146.070 2.280 7.592 1.382400e+12 7.075e+10
+ 9 7 5.000e+07 22.660 170.830 2.570 7.652 1.612800e+12 7.117e+10
+ 9 8 5.000e+07 25.520 194.720 2.760 7.738 1.843200e+12 7.223e+10
+ 9 9 5.000e+07 28.400 219.020 3.060 7.820 2.073600e+12 7.301e+10
+ 9 10 5.000e+07 31.490 243.030 3.320 7.823 2.304000e+12 7.317e+10
+ 9 11 5.000e+07 34.530 267.230 3.420 7.838 2.534400e+12 7.340e+10
+ 9 12 5.000e+07 37.520 291.720 3.860 7.878 2.764800e+12 7.369e+10
+ 9 13 5.000e+07 40.550 315.780 4.170 7.890 2.995200e+12 7.386e+10
+ 9 14 5.000e+07 43.470 339.930 4.290 7.919 3.225600e+12 7.420e+10
+ 9 15 5.000e+07 46.820 364.970 4.640 7.894 3.456000e+12 7.381e+10
+ 9 16 5.000e+07 49.660 388.630 4.890 7.924 3.686400e+12 7.423e+10
+ 10 1 5.000e+07 5.500 27.290 0.980 5.140 2.560000e+11 4.655e+10
+ 10 2 5.000e+07 8.480 54.830 1.420 6.633 5.120000e+11 6.038e+10
+ 10 3 5.000e+07 11.540 81.580 1.630 7.211 7.680000e+11 6.655e+10
+ 10 4 5.000e+07 14.950 108.480 1.860 7.381 1.024000e+12 6.849e+10
+ 10 5 5.000e+07 18.330 135.300 2.280 7.506 1.280000e+12 6.983e+10
+ 10 6 5.000e+07 21.680 162.380 2.540 7.607 1.536000e+12 7.085e+10
+ 10 7 5.000e+07 24.950 189.360 2.730 7.699 1.792000e+12 7.182e+10
+ 10 8 5.000e+07 28.280 216.090 3.110 7.751 2.048000e+12 7.242e+10
+ 10 9 5.000e+07 31.730 243.290 3.450 7.776 2.304000e+12 7.261e+10
+ 10 10 5.000e+07 35.040 270.380 3.680 7.821 2.560000e+12 7.306e+10
+ 10 11 5.000e+07 38.340 297.080 4.050 7.854 2.816000e+12 7.345e+10
+ 10 12 5.000e+07 41.770 323.840 4.330 7.857 3.072000e+12 7.355e+10
+ 10 13 5.000e+07 45.120 351.380 4.710 7.892 3.328000e+12 7.376e+10
+ 10 14 5.000e+07 48.360 377.870 4.880 7.915 3.584000e+12 7.411e+10
+ 10 15 5.000e+07 51.760 404.740 5.110 7.918 3.840000e+12 7.419e+10
+ 10 16 5.000e+07 55.130 431.760 5.430 7.930 4.096000e+12 7.430e+10
+ 11 1 5.000e+07 5.570 30.080 1.080 5.594 2.816000e+11 5.056e+10
+ 11 2 5.000e+07 9.000 60.230 1.470 6.856 5.632000e+11 6.258e+10
+ 11 3 5.000e+07 12.630 89.890 1.770 7.257 8.448000e+11 6.689e+10
+ 11 4 5.000e+07 16.290 119.110 2.140 7.443 1.126400e+12 6.915e+10
+ 11 5 5.000e+07 19.940 148.730 2.440 7.581 1.408000e+12 7.061e+10
+ 11 6 5.000e+07 23.800 178.620 2.790 7.622 1.689600e+12 7.099e+10
+ 11 7 5.000e+07 27.480 208.510 3.160 7.703 1.971200e+12 7.173e+10
+ 11 8 5.000e+07 31.140 237.820 3.490 7.749 2.252800e+12 7.234e+10
+ 11 9 5.000e+07 34.770 267.390 3.800 7.800 2.534400e+12 7.289e+10
+ 11 10 5.000e+07 38.510 297.250 4.240 7.829 2.816000e+12 7.312e+10
+ 11 11 5.000e+07 42.080 326.570 4.610 7.870 3.097600e+12 7.361e+10
+ 11 12 5.000e+07 45.860 356.540 4.590 7.875 3.379200e+12 7.369e+10
+ 11 13 5.000e+07 49.570 386.250 5.150 7.896 3.660800e+12 7.385e+10
+ 11 14 5.000e+07 53.220 415.630 5.360 7.910 3.942400e+12 7.408e+10
+ 11 15 5.000e+07 57.000 445.200 5.870 7.914 4.224000e+12 7.411e+10
+ 11 16 5.000e+07 60.800 474.810 6.250 7.912 4.505600e+12 7.411e+10
+ 12 1 5.000e+07 5.600 32.770 1.240 6.073 3.072000e+11 5.486e+10
+ 12 2 5.000e+07 10.220 65.660 1.600 6.581 6.144000e+11 6.012e+10
+ 12 3 5.000e+07 13.680 97.900 2.000 7.303 9.216000e+11 6.737e+10
+ 12 4 5.000e+07 17.790 129.710 2.330 7.422 1.228800e+12 6.907e+10
+ 12 5 5.000e+07 21.770 162.420 2.700 7.585 1.536000e+12 7.056e+10
+ 12 6 5.000e+07 25.770 194.770 3.090 7.678 1.843200e+12 7.153e+10
+ 12 7 5.000e+07 29.940 227.290 3.390 7.705 2.150400e+12 7.182e+10
+ 12 8 5.000e+07 34.030 259.370 3.860 7.735 2.457600e+12 7.222e+10
+ 12 9 5.000e+07 38.070 291.890 4.310 7.780 2.764800e+12 7.262e+10
+ 12 10 5.000e+07 42.080 324.370 4.660 7.819 3.072000e+12 7.300e+10
+ 12 11 5.000e+07 45.950 356.370 5.000 7.864 3.379200e+12 7.354e+10
+ 12 12 5.000e+07 49.960 388.790 5.250 7.887 3.686400e+12 7.379e+10
+ 12 13 5.000e+07 54.010 422.050 5.420 7.915 3.993600e+12 7.394e+10
+ 12 14 5.000e+07 58.010 453.330 6.120 7.920 4.300800e+12 7.414e+10
+ 12 15 5.000e+07 62.080 485.830 6.310 7.928 4.608000e+12 7.423e+10
+ 12 16 5.000e+07 66.200 518.060 6.780 7.928 4.915200e+12 7.425e+10
+ 13 1 5.000e+07 5.630 35.420 1.300 6.522 3.328000e+11 5.911e+10
+ 13 2 5.000e+07 10.730 71.050 1.830 6.792 6.656000e+11 6.203e+10
+ 13 3 5.000e+07 14.690 105.710 2.160 7.343 9.984000e+11 6.796e+10
+ 13 4 5.000e+07 19.120 140.630 2.510 7.486 1.331200e+12 6.962e+10
+ 13 5 5.000e+07 23.600 175.730 3.000 7.573 1.664000e+12 7.051e+10
+ 13 6 5.000e+07 27.910 211.000 3.350 7.680 1.996800e+12 7.154e+10
+ 13 7 5.000e+07 32.370 246.320 3.860 7.729 2.329600e+12 7.197e+10
+ 13 8 5.000e+07 36.790 281.150 4.260 7.758 2.662400e+12 7.237e+10
+ 13 9 5.000e+07 41.080 316.080 4.520 7.804 2.995200e+12 7.291e+10
+ 13 10 5.000e+07 45.600 352.020 5.090 7.831 3.328000e+12 7.298e+10
+ 13 11 5.000e+07 49.760 386.130 5.470 7.870 3.660800e+12 7.357e+10
+ 13 12 5.000e+07 54.080 421.160 5.780 7.895 3.993600e+12 7.385e+10
+ 13 13 5.000e+07 58.520 455.980 6.170 7.897 4.326400e+12 7.393e+10
+ 13 14 5.000e+07 63.000 491.340 6.710 7.906 4.659200e+12 7.396e+10
+ 13 15 5.000e+07 67.250 525.920 6.920 7.923 4.992000e+12 7.423e+10
+ 13 16 5.000e+07 72.090 560.640 7.160 7.876 5.324800e+12 7.386e+10
+ 14 1 5.000e+07 5.670 38.290 1.330 6.988 3.584000e+11 6.321e+10
+ 14 2 5.000e+07 10.850 75.880 1.940 7.172 7.168000e+11 6.606e+10
+ 14 3 5.000e+07 15.840 114.160 2.400 7.359 1.075200e+12 6.788e+10
+ 14 4 5.000e+07 20.610 151.540 2.710 7.484 1.433600e+12 6.956e+10
+ 14 5 5.000e+07 25.330 189.160 3.320 7.599 1.792000e+12 7.075e+10
+ 14 6 5.000e+07 30.160 227.510 3.670 7.665 2.150400e+12 7.130e+10
+ 14 7 5.000e+07 34.730 265.020 3.960 7.745 2.508800e+12 7.224e+10
+ 14 8 5.000e+07 39.530 302.550 4.640 7.771 2.867200e+12 7.253e+10
+ 14 9 5.000e+07 44.220 340.330 5.180 7.813 3.225600e+12 7.294e+10
+ 14 10 5.000e+07 48.800 378.180 5.430 7.861 3.584000e+12 7.344e+10
+ 14 11 5.000e+07 53.550 415.790 5.800 7.873 3.942400e+12 7.362e+10
+ 14 12 5.000e+07 58.250 453.340 6.430 7.893 4.300800e+12 7.383e+10
+ 14 13 5.000e+07 63.150 492.200 6.960 7.904 4.659200e+12 7.378e+10
+ 14 14 5.000e+07 67.850 528.470 6.970 7.892 5.017600e+12 7.395e+10
+ 14 15 5.000e+07 72.510 566.950 7.720 7.925 5.376000e+12 7.414e+10
+ 14 16 5.000e+07 77.230 604.250 8.170 7.930 5.734400e+12 7.425e+10
+ 15 1 5.000e+07 5.800 41.070 1.460 7.333 3.840000e+11 6.621e+10
+ 15 2 5.000e+07 11.900 80.380 2.190 6.939 7.680000e+11 6.454e+10
+ 15 3 5.000e+07 16.990 121.790 2.610 7.322 1.152000e+12 6.780e+10
+ 15 4 5.000e+07 22.040 162.330 3.030 7.503 1.536000e+12 6.969e+10
+ 15 5 5.000e+07 27.120 202.750 3.460 7.604 1.920000e+12 7.080e+10
+ 15 6 5.000e+07 32.290 243.420 3.870 7.658 2.304000e+12 7.135e+10
+ 15 7 5.000e+07 37.450 284.300 4.410 7.709 2.688000e+12 7.178e+10
+ 15 8 5.000e+07 42.560 323.740 4.890 7.722 3.072000e+12 7.218e+10
+ 15 9 5.000e+07 47.440 364.880 5.330 7.804 3.456000e+12 7.285e+10
+ 15 10 5.000e+07 52.440 405.400 5.750 7.840 3.840000e+12 7.323e+10
+ 15 11 5.000e+07 57.270 445.500 6.070 7.885 4.224000e+12 7.376e+10
+ 15 12 5.000e+07 62.450 485.920 6.770 7.889 4.608000e+12 7.379e+10
+ 15 13 5.000e+07 67.680 527.540 7.440 7.905 4.992000e+12 7.376e+10
+ 15 14 5.000e+07 72.740 566.990 7.790 7.902 5.376000e+12 7.391e+10
+ 15 15 5.000e+07 77.760 607.620 8.060 7.918 5.760000e+12 7.407e+10
+ 15 16 5.000e+07 82.750 647.630 8.640 7.931 6.144000e+12 7.425e+10
+ 16 1 5.000e+07 6.310 43.540 1.790 7.184 4.096000e+11 6.491e+10
+ 16 2 5.000e+07 12.340 87.310 2.190 7.253 8.192000e+11 6.639e+10
+ 16 3 5.000e+07 17.930 130.440 2.830 7.433 1.228800e+12 6.853e+10
+ 16 4 5.000e+07 23.530 173.540 3.140 7.509 1.638400e+12 6.963e+10
+ 16 5 5.000e+07 28.910 216.290 3.710 7.610 2.048000e+12 7.084e+10
+ 16 6 5.000e+07 34.310 259.400 4.260 7.685 2.457600e+12 7.163e+10
+ 16 7 5.000e+07 39.790 302.740 4.620 7.725 2.867200e+12 7.206e+10
+ 16 8 5.000e+07 44.970 346.250 5.340 7.818 3.276800e+12 7.287e+10
+ 16 9 5.000e+07 50.470 388.870 5.910 7.822 3.686400e+12 7.304e+10
+ 16 10 5.000e+07 55.890 432.480 6.140 7.848 4.096000e+12 7.329e+10
+ 16 11 5.000e+07 61.250 475.380 6.770 7.872 4.505600e+12 7.356e+10
+ 16 12 5.000e+07 66.670 518.940 7.160 7.891 4.915200e+12 7.372e+10
+ 16 13 5.000e+07 72.160 562.230 7.890 7.901 5.324800e+12 7.379e+10
+ 16 14 5.000e+07 77.600 604.950 8.230 7.902 5.734400e+12 7.390e+10
+ 16 15 5.000e+07 82.970 648.420 8.690 7.920 6.144000e+12 7.405e+10
+ 16 16 5.000e+07 88.370 690.730 9.460 7.923 6.553600e+12 7.416e+10
diff --git a/gnuradio-runtime/examples/mp-sched/perf-data/js21-altivec.dat b/gnuradio-runtime/examples/mp-sched/perf-data/js21-altivec.dat
new file mode 100644
index 0000000000..d0b8148f0e
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/perf-data/js21-altivec.dat
@@ -0,0 +1,65 @@
+#D JS21 4-core PPC970M 2.5 GHz (using Altivec)
+ 1 1 9.766e+07 9.820 10.210 0.360 1.076 5.000000e+10 5.092e+09
+ 1 2 9.766e+07 10.620 19.890 0.640 1.933 1.000000e+11 9.416e+09
+ 1 3 9.766e+07 10.310 29.590 0.610 2.929 1.500000e+11 1.455e+10
+ 1 4 9.766e+07 10.440 39.290 0.680 3.829 2.000000e+11 1.916e+10
+ 1 5 7.812e+07 15.730 39.150 0.590 2.526 2.000000e+11 1.271e+10
+ 1 6 6.510e+07 13.100 39.080 0.590 3.028 2.000000e+11 1.527e+10
+ 1 7 5.580e+07 11.550 39.030 0.500 3.423 2.000000e+11 1.732e+10
+ 1 8 4.883e+07 10.410 39.010 0.510 3.796 2.000000e+11 1.921e+10
+ 2 1 9.766e+07 10.080 20.070 0.700 2.061 1.000000e+11 9.921e+09
+ 2 2 9.766e+07 11.360 39.650 0.960 3.575 2.000000e+11 1.761e+10
+ 2 3 6.510e+07 13.120 39.270 0.740 3.050 2.000000e+11 1.524e+10
+ 2 4 4.883e+07 10.410 39.110 0.650 3.819 2.000000e+11 1.921e+10
+ 2 5 3.906e+07 11.030 39.080 0.610 3.598 2.000000e+11 1.813e+10
+ 2 6 3.255e+07 10.640 39.020 0.560 3.720 2.000000e+11 1.880e+10
+ 2 7 2.790e+07 10.510 38.980 0.550 3.761 2.000000e+11 1.903e+10
+ 2 8 2.441e+07 10.440 38.970 0.570 3.787 2.000000e+11 1.916e+10
+ 3 1 9.766e+07 12.130 29.970 0.920 2.547 1.500000e+11 1.237e+10
+ 3 2 6.510e+07 13.100 39.300 0.920 3.070 2.000000e+11 1.527e+10
+ 3 3 4.340e+07 11.400 39.200 0.760 3.505 2.000000e+11 1.754e+10
+ 3 4 3.255e+07 10.730 39.100 0.690 3.708 2.000000e+11 1.864e+10
+ 3 5 2.604e+07 10.470 39.010 0.620 3.785 2.000000e+11 1.910e+10
+ 3 6 2.170e+07 10.380 39.010 0.620 3.818 2.000000e+11 1.927e+10
+ 3 7 1.860e+07 10.280 39.120 0.580 3.862 2.000000e+11 1.946e+10
+ 3 8 1.628e+07 10.230 39.000 0.600 3.871 2.000000e+11 1.955e+10
+ 4 1 9.766e+07 10.700 39.990 1.540 3.881 2.000000e+11 1.869e+10
+ 4 2 4.883e+07 10.530 39.260 0.940 3.818 2.000000e+11 1.899e+10
+ 4 3 3.255e+07 10.840 39.140 0.760 3.681 2.000000e+11 1.845e+10
+ 4 4 2.441e+07 10.530 39.040 0.680 3.772 2.000000e+11 1.899e+10
+ 4 5 1.953e+07 10.380 39.030 0.650 3.823 2.000000e+11 1.927e+10
+ 4 6 1.628e+07 10.310 39.020 0.650 3.848 2.000000e+11 1.940e+10
+ 4 7 1.395e+07 10.160 38.980 0.620 3.898 2.000000e+11 1.969e+10
+ 4 8 1.221e+07 10.150 38.990 0.580 3.899 2.000000e+11 1.970e+10
+ 5 1 7.812e+07 14.750 39.780 1.470 2.797 2.000000e+11 1.356e+10
+ 5 2 3.906e+07 11.350 39.240 0.950 3.541 2.000000e+11 1.762e+10
+ 5 3 2.604e+07 10.720 39.120 0.800 3.724 2.000000e+11 1.866e+10
+ 5 4 1.953e+07 10.440 39.060 0.730 3.811 2.000000e+11 1.916e+10
+ 5 5 1.562e+07 10.410 39.060 0.690 3.818 2.000000e+11 1.921e+10
+ 5 6 1.302e+07 10.260 38.970 0.650 3.862 2.000000e+11 1.949e+10
+ 5 7 1.116e+07 10.270 39.020 0.650 3.863 2.000000e+11 1.947e+10
+ 5 8 9.766e+06 10.130 39.010 0.660 3.916 2.000000e+11 1.974e+10
+ 6 1 6.510e+07 12.850 39.730 1.450 3.205 2.000000e+11 1.556e+10
+ 6 2 3.255e+07 10.700 39.300 0.990 3.765 2.000000e+11 1.869e+10
+ 6 3 2.170e+07 10.770 39.110 0.810 3.707 2.000000e+11 1.857e+10
+ 6 4 1.628e+07 10.570 39.090 0.750 3.769 2.000000e+11 1.892e+10
+ 6 5 1.302e+07 10.310 39.040 0.690 3.854 2.000000e+11 1.940e+10
+ 6 6 1.085e+07 10.260 39.030 0.700 3.872 2.000000e+11 1.949e+10
+ 6 7 9.301e+06 10.170 39.020 0.680 3.904 2.000000e+11 1.967e+10
+ 6 8 8.138e+06 10.150 39.020 0.670 3.910 2.000000e+11 1.970e+10
+ 7 1 5.580e+07 11.440 39.730 1.500 3.604 2.000000e+11 1.748e+10
+ 7 2 2.790e+07 10.950 39.260 0.990 3.676 2.000000e+11 1.826e+10
+ 7 3 1.860e+07 10.620 39.140 0.860 3.766 2.000000e+11 1.883e+10
+ 7 4 1.395e+07 10.420 39.070 0.750 3.821 2.000000e+11 1.919e+10
+ 7 5 1.116e+07 10.290 39.040 0.710 3.863 2.000000e+11 1.944e+10
+ 7 6 9.301e+06 10.200 39.040 0.720 3.898 2.000000e+11 1.961e+10
+ 7 7 7.972e+06 10.210 39.020 0.670 3.887 2.000000e+11 1.959e+10
+ 7 8 6.975e+06 10.160 39.020 0.650 3.905 2.000000e+11 1.969e+10
+ 8 1 4.883e+07 10.870 39.950 1.520 3.815 2.000000e+11 1.840e+10
+ 8 2 2.441e+07 10.690 39.270 1.000 3.767 2.000000e+11 1.871e+10
+ 8 3 1.628e+07 10.540 39.130 0.860 3.794 2.000000e+11 1.898e+10
+ 8 4 1.221e+07 10.410 39.110 0.790 3.833 2.000000e+11 1.921e+10
+ 8 5 9.766e+06 10.230 39.040 0.710 3.886 2.000000e+11 1.955e+10
+ 8 6 8.138e+06 10.260 39.050 0.700 3.874 2.000000e+11 1.949e+10
+ 8 7 6.975e+06 10.220 39.100 0.690 3.893 2.000000e+11 1.957e+10
+ 8 8 6.104e+06 10.170 39.020 0.650 3.901 2.000000e+11 1.967e+10
diff --git a/gnuradio-runtime/examples/mp-sched/perf-data/js21.dat b/gnuradio-runtime/examples/mp-sched/perf-data/js21.dat
new file mode 100644
index 0000000000..a23bcebe77
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/perf-data/js21.dat
@@ -0,0 +1,65 @@
+#D JS21 4-core PPC970MP 2.5 GHz
+ 1 1 5.273e+07 10.050 10.180 0.290 1.042 2.700000e+10 2.687e+09
+ 1 2 5.273e+07 10.240 20.210 0.260 1.999 5.400000e+10 5.273e+09
+ 1 3 5.273e+07 10.300 30.090 0.340 2.954 8.100000e+10 7.864e+09
+ 1 4 5.273e+07 10.490 40.120 0.490 3.871 1.080000e+11 1.030e+10
+ 1 5 4.219e+07 16.010 39.900 0.380 2.516 1.080000e+11 6.746e+09
+ 1 6 3.516e+07 13.360 39.920 0.370 3.016 1.080000e+11 8.084e+09
+ 1 7 3.013e+07 11.510 39.900 0.330 3.495 1.080000e+11 9.383e+09
+ 1 8 2.637e+07 10.420 39.880 0.320 3.858 1.080000e+11 1.036e+10
+ 2 1 5.273e+07 10.370 20.340 0.470 2.007 5.400000e+10 5.207e+09
+ 2 2 5.273e+07 10.320 40.080 0.550 3.937 1.080000e+11 1.047e+10
+ 2 3 3.516e+07 13.340 39.990 0.470 3.033 1.080000e+11 8.096e+09
+ 2 4 2.637e+07 10.480 39.970 0.400 3.852 1.080000e+11 1.031e+10
+ 2 5 2.109e+07 10.910 39.920 0.390 3.695 1.080000e+11 9.899e+09
+ 2 6 1.758e+07 10.610 39.860 0.360 3.791 1.080000e+11 1.018e+10
+ 2 7 1.507e+07 10.520 39.890 0.360 3.826 1.080000e+11 1.027e+10
+ 2 8 1.318e+07 10.470 39.980 0.350 3.852 1.080000e+11 1.032e+10
+ 3 1 5.273e+07 10.230 30.320 0.600 3.022 8.100000e+10 7.918e+09
+ 3 2 3.516e+07 13.250 40.050 0.560 3.065 1.080000e+11 8.151e+09
+ 3 3 2.344e+07 11.160 40.010 0.470 3.627 1.080000e+11 9.677e+09
+ 3 4 1.758e+07 10.710 39.950 0.420 3.769 1.080000e+11 1.008e+10
+ 3 5 1.406e+07 10.520 39.920 0.400 3.833 1.080000e+11 1.027e+10
+ 3 6 1.172e+07 10.420 39.880 0.380 3.864 1.080000e+11 1.036e+10
+ 3 7 1.004e+07 10.340 39.880 0.370 3.893 1.080000e+11 1.044e+10
+ 3 8 8.789e+06 10.380 39.960 0.380 3.886 1.080000e+11 1.040e+10
+ 4 1 5.273e+07 10.570 40.390 0.890 3.905 1.080000e+11 1.022e+10
+ 4 2 2.637e+07 10.690 40.020 0.560 3.796 1.080000e+11 1.010e+10
+ 4 3 1.758e+07 10.790 39.980 0.480 3.750 1.080000e+11 1.001e+10
+ 4 4 1.318e+07 10.570 39.950 0.430 3.820 1.080000e+11 1.022e+10
+ 4 5 1.055e+07 10.440 39.950 0.420 3.867 1.080000e+11 1.034e+10
+ 4 6 8.789e+06 10.340 39.900 0.420 3.899 1.080000e+11 1.044e+10
+ 4 7 7.533e+06 10.290 39.870 0.410 3.914 1.080000e+11 1.050e+10
+ 4 8 6.592e+06 10.270 39.950 0.390 3.928 1.080000e+11 1.052e+10
+ 5 1 4.219e+07 15.110 40.290 0.830 2.721 1.080000e+11 7.148e+09
+ 5 2 2.109e+07 11.240 40.000 0.580 3.610 1.080000e+11 9.609e+09
+ 5 3 1.406e+07 10.710 39.970 0.490 3.778 1.080000e+11 1.008e+10
+ 5 4 1.055e+07 10.490 39.980 0.460 3.855 1.080000e+11 1.030e+10
+ 5 5 8.438e+06 10.430 39.940 0.440 3.872 1.080000e+11 1.035e+10
+ 5 6 7.031e+06 10.280 39.890 0.420 3.921 1.080000e+11 1.051e+10
+ 5 7 6.027e+06 10.290 39.870 0.400 3.914 1.080000e+11 1.050e+10
+ 5 8 5.273e+06 10.290 39.940 0.400 3.920 1.080000e+11 1.050e+10
+ 6 1 3.516e+07 12.880 40.250 0.850 3.191 1.080000e+11 8.385e+09
+ 6 2 1.758e+07 10.730 39.980 0.580 3.780 1.080000e+11 1.007e+10
+ 6 3 1.172e+07 10.740 39.980 0.490 3.768 1.080000e+11 1.006e+10
+ 6 4 8.789e+06 10.510 39.940 0.460 3.844 1.080000e+11 1.028e+10
+ 6 5 7.031e+06 10.430 39.920 0.450 3.871 1.080000e+11 1.035e+10
+ 6 6 5.859e+06 10.300 39.910 0.430 3.917 1.080000e+11 1.049e+10
+ 6 7 5.022e+06 10.290 39.870 0.420 3.915 1.080000e+11 1.050e+10
+ 6 8 4.395e+06 10.300 39.950 0.420 3.919 1.080000e+11 1.049e+10
+ 7 1 3.013e+07 11.240 40.270 0.860 3.659 1.080000e+11 9.609e+09
+ 7 2 1.507e+07 11.040 40.000 0.590 3.677 1.080000e+11 9.783e+09
+ 7 3 1.004e+07 10.660 39.970 0.520 3.798 1.080000e+11 1.013e+10
+ 7 4 7.533e+06 10.430 39.930 0.470 3.873 1.080000e+11 1.035e+10
+ 7 5 6.027e+06 10.390 39.920 0.470 3.887 1.080000e+11 1.039e+10
+ 7 6 5.022e+06 10.320 39.910 0.430 3.909 1.080000e+11 1.047e+10
+ 7 7 4.305e+06 10.330 39.890 0.420 3.902 1.080000e+11 1.045e+10
+ 7 8 3.767e+06 10.300 39.930 0.420 3.917 1.080000e+11 1.049e+10
+ 8 1 2.637e+07 10.530 40.290 0.910 3.913 1.080000e+11 1.026e+10
+ 8 2 1.318e+07 10.850 40.040 0.610 3.747 1.080000e+11 9.954e+09
+ 8 3 8.789e+06 10.500 39.960 0.540 3.857 1.080000e+11 1.029e+10
+ 8 4 6.592e+06 10.490 39.960 0.500 3.857 1.080000e+11 1.030e+10
+ 8 5 5.273e+06 10.330 39.930 0.480 3.912 1.080000e+11 1.045e+10
+ 8 6 4.395e+06 10.340 39.900 0.450 3.902 1.080000e+11 1.044e+10
+ 8 7 3.767e+06 10.260 39.900 0.430 3.931 1.080000e+11 1.053e+10
+ 8 8 3.296e+06 10.250 39.960 0.430 3.940 1.080000e+11 1.054e+10
diff --git a/gnuradio-runtime/examples/mp-sched/perf-data/ps3-altivec.dat b/gnuradio-runtime/examples/mp-sched/perf-data/ps3-altivec.dat
new file mode 100644
index 0000000000..dd01b31bd7
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/perf-data/ps3-altivec.dat
@@ -0,0 +1,65 @@
+#D Playstation 3 (using Altivec)
+ 1 1 3.906e+07 10.500 10.580 0.440 1.050 2.000000e+10 1.905e+09
+ 1 2 1.953e+07 7.010 13.200 0.400 1.940 2.000000e+10 2.853e+09
+ 1 3 1.302e+07 7.540 13.140 0.380 1.793 2.000000e+10 2.653e+09
+ 1 4 9.766e+06 7.200 13.620 0.370 1.943 2.000000e+10 2.778e+09
+ 1 5 7.812e+06 7.170 13.670 0.340 1.954 2.000000e+10 2.789e+09
+ 1 6 6.510e+06 7.010 13.590 0.320 1.984 2.000000e+10 2.853e+09
+ 1 7 5.580e+06 6.990 13.530 0.330 1.983 2.000000e+10 2.861e+09
+ 1 8 4.883e+06 6.980 13.490 0.320 1.979 2.000000e+10 2.865e+09
+ 2 1 1.953e+07 8.110 14.730 0.530 1.882 2.000000e+10 2.466e+09
+ 2 2 9.766e+06 7.090 13.570 0.420 1.973 2.000000e+10 2.821e+09
+ 2 3 6.510e+06 7.040 13.590 0.410 1.989 2.000000e+10 2.841e+09
+ 2 4 4.883e+06 6.990 13.490 0.370 1.983 2.000000e+10 2.861e+09
+ 2 5 3.906e+06 6.970 13.480 0.360 1.986 2.000000e+10 2.869e+09
+ 2 6 3.255e+06 6.990 13.530 0.370 1.989 2.000000e+10 2.861e+09
+ 2 7 2.790e+06 6.890 13.390 0.350 1.994 2.000000e+10 2.903e+09
+ 2 8 2.441e+06 6.880 13.380 0.350 1.996 2.000000e+10 2.907e+09
+ 3 1 1.302e+07 8.220 13.720 0.510 1.731 2.000000e+10 2.433e+09
+ 3 2 6.510e+06 7.050 13.480 0.450 1.976 2.000000e+10 2.837e+09
+ 3 3 4.340e+06 6.990 13.460 0.400 1.983 2.000000e+10 2.861e+09
+ 3 4 3.255e+06 6.990 13.550 0.380 1.993 2.000000e+10 2.861e+09
+ 3 5 2.604e+06 6.920 13.430 0.360 1.993 1.999999e+10 2.890e+09
+ 3 6 2.170e+06 6.940 13.460 0.360 1.991 1.999999e+10 2.882e+09
+ 3 7 1.860e+06 6.920 13.440 0.360 1.994 2.000000e+10 2.890e+09
+ 3 8 1.628e+06 6.890 13.380 0.350 1.993 2.000000e+10 2.903e+09
+ 4 1 9.766e+06 7.620 14.550 0.590 1.987 2.000000e+10 2.625e+09
+ 4 2 4.883e+06 7.010 13.460 0.440 1.983 2.000000e+10 2.853e+09
+ 4 3 3.255e+06 7.040 13.580 0.410 1.987 2.000000e+10 2.841e+09
+ 4 4 2.441e+06 6.960 13.470 0.390 1.991 2.000000e+10 2.874e+09
+ 4 5 1.953e+06 6.920 13.410 0.370 1.991 2.000000e+10 2.890e+09
+ 4 6 1.628e+06 6.950 13.490 0.370 1.994 2.000000e+10 2.878e+09
+ 4 7 1.395e+06 6.890 13.350 0.370 1.991 2.000000e+10 2.903e+09
+ 4 8 1.221e+06 6.940 13.490 0.360 1.996 2.000000e+10 2.882e+09
+ 5 1 7.812e+06 7.680 14.000 0.560 1.896 2.000000e+10 2.604e+09
+ 5 2 3.906e+06 7.070 13.460 0.460 1.969 2.000000e+10 2.829e+09
+ 5 3 2.604e+06 6.990 13.430 0.420 1.981 1.999999e+10 2.861e+09
+ 5 4 1.953e+06 7.010 13.550 0.390 1.989 2.000000e+10 2.853e+09
+ 5 5 1.562e+06 6.920 13.430 0.380 1.996 2.000000e+10 2.890e+09
+ 5 6 1.302e+06 6.920 13.410 0.380 1.993 1.999999e+10 2.890e+09
+ 5 7 1.116e+06 6.920 13.420 0.370 1.993 1.999999e+10 2.890e+09
+ 5 8 9.766e+05 6.910 13.360 0.370 1.987 1.999999e+10 2.894e+09
+ 6 1 6.510e+06 7.350 13.970 0.630 1.986 2.000000e+10 2.721e+09
+ 6 2 3.255e+06 7.040 13.470 0.470 1.980 2.000000e+10 2.841e+09
+ 6 3 2.170e+06 7.050 13.600 0.420 1.989 1.999999e+10 2.837e+09
+ 6 4 1.628e+06 6.970 13.480 0.400 1.991 2.000000e+10 2.869e+09
+ 6 5 1.302e+06 6.990 13.540 0.390 1.993 1.999999e+10 2.861e+09
+ 6 6 1.085e+06 6.970 13.470 0.380 1.987 1.999999e+10 2.869e+09
+ 6 7 9.301e+05 6.890 13.350 0.380 1.993 1.999999e+10 2.903e+09
+ 6 8 8.138e+05 6.920 13.420 0.370 1.993 2.000000e+10 2.890e+09
+ 7 1 5.580e+06 7.530 14.030 0.580 1.940 2.000000e+10 2.656e+09
+ 7 2 2.790e+06 7.000 13.370 0.460 1.976 2.000000e+10 2.857e+09
+ 7 3 1.860e+06 7.000 13.520 0.420 1.991 2.000000e+10 2.857e+09
+ 7 4 1.395e+06 7.060 13.590 0.410 1.983 2.000000e+10 2.833e+09
+ 7 5 1.116e+06 6.950 13.460 0.390 1.993 1.999999e+10 2.878e+09
+ 7 6 9.301e+05 6.950 13.420 0.380 1.986 1.999999e+10 2.878e+09
+ 7 7 7.972e+05 6.880 13.300 0.380 1.988 1.999998e+10 2.907e+09
+ 7 8 6.975e+05 6.920 13.390 0.380 1.990 1.999998e+10 2.890e+09
+ 8 1 4.883e+06 7.440 14.150 0.620 1.985 2.000000e+10 2.688e+09
+ 8 2 2.441e+06 6.990 13.400 0.480 1.986 2.000000e+10 2.861e+09
+ 8 3 1.628e+06 6.990 13.460 0.430 1.987 2.000000e+10 2.861e+09
+ 8 4 1.221e+06 7.020 13.550 0.410 1.989 2.000000e+10 2.849e+09
+ 8 5 9.766e+05 6.920 13.370 0.390 1.988 1.999999e+10 2.890e+09
+ 8 6 8.138e+05 6.950 13.400 0.390 1.984 2.000000e+10 2.878e+09
+ 8 7 6.975e+05 6.930 13.360 0.390 1.984 1.999998e+10 2.886e+09
+ 8 8 6.104e+05 6.920 13.390 0.380 1.990 1.999998e+10 2.890e+09
diff --git a/gnuradio-runtime/examples/mp-sched/perf-data/ps3.dat b/gnuradio-runtime/examples/mp-sched/perf-data/ps3.dat
new file mode 100644
index 0000000000..c9bac37cc1
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/perf-data/ps3.dat
@@ -0,0 +1,65 @@
+#D Playstation 3
+ 1 1 2.344e+07 9.970 9.960 0.280 1.027 1.200000e+10 1.204e+09
+ 1 2 1.172e+07 12.590 24.430 0.400 1.972 1.200000e+10 9.531e+08
+ 1 3 7.812e+06 12.200 22.790 0.360 1.898 1.200000e+10 9.836e+08
+ 1 4 5.859e+06 12.450 24.440 0.360 1.992 1.200000e+10 9.639e+08
+ 1 5 4.688e+06 12.390 24.100 0.360 1.974 1.200000e+10 9.685e+08
+ 1 6 3.906e+06 12.360 24.200 0.370 1.988 1.200000e+10 9.709e+08
+ 1 7 3.348e+06 12.460 24.390 0.360 1.986 1.200000e+10 9.631e+08
+ 1 8 2.930e+06 12.440 24.400 0.360 1.990 1.200000e+10 9.646e+08
+ 2 1 1.172e+07 12.580 24.660 0.490 1.999 1.200000e+10 9.539e+08
+ 2 2 5.859e+06 12.480 24.290 0.420 1.980 1.200000e+10 9.615e+08
+ 2 3 3.906e+06 12.500 24.500 0.400 1.992 1.200000e+10 9.600e+08
+ 2 4 2.930e+06 12.440 24.400 0.390 1.993 1.200000e+10 9.646e+08
+ 2 5 2.344e+06 12.500 24.510 0.380 1.991 1.200000e+10 9.600e+08
+ 2 6 1.953e+06 12.450 24.480 0.380 1.997 1.200000e+10 9.639e+08
+ 2 7 1.674e+06 12.450 24.430 0.380 1.993 1.200000e+10 9.639e+08
+ 2 8 1.465e+06 12.430 24.450 0.380 1.998 1.199999e+10 9.654e+08
+ 3 1 7.812e+06 12.280 23.600 0.460 1.959 1.200000e+10 9.772e+08
+ 3 2 3.906e+06 12.690 24.760 0.430 1.985 1.200000e+10 9.456e+08
+ 3 3 2.604e+06 12.610 24.700 0.410 1.991 1.200000e+10 9.516e+08
+ 3 4 1.953e+06 12.440 24.410 0.400 1.994 1.200000e+10 9.646e+08
+ 3 5 1.562e+06 12.400 24.370 0.380 1.996 1.200000e+10 9.677e+08
+ 3 6 1.302e+06 12.440 24.450 0.380 1.996 1.200000e+10 9.646e+08
+ 3 7 1.116e+06 12.470 24.470 0.380 1.993 1.200000e+10 9.623e+08
+ 3 8 9.766e+05 12.440 24.440 0.380 1.995 1.199999e+10 9.646e+08
+ 4 1 5.859e+06 12.670 24.710 0.500 1.990 1.200000e+10 9.471e+08
+ 4 2 2.930e+06 12.600 24.600 0.440 1.987 1.200000e+10 9.524e+08
+ 4 3 1.953e+06 12.490 24.480 0.410 1.993 1.200000e+10 9.608e+08
+ 4 4 1.465e+06 12.400 24.340 0.400 1.995 1.199999e+10 9.677e+08
+ 4 5 1.172e+06 12.440 24.410 0.390 1.994 1.200000e+10 9.646e+08
+ 4 6 9.766e+05 12.440 24.440 0.390 1.996 1.199999e+10 9.646e+08
+ 4 7 8.371e+05 12.450 24.420 0.390 1.993 1.199999e+10 9.639e+08
+ 4 8 7.324e+05 12.370 24.310 0.380 1.996 1.199999e+10 9.701e+08
+ 5 1 4.688e+06 12.890 24.790 0.500 1.962 1.200000e+10 9.310e+08
+ 5 2 2.344e+06 12.620 24.680 0.450 1.991 1.200000e+10 9.509e+08
+ 5 3 1.562e+06 12.430 24.360 0.410 1.993 1.200000e+10 9.654e+08
+ 5 4 1.172e+06 12.420 24.390 0.410 1.997 1.200000e+10 9.662e+08
+ 5 5 9.375e+05 12.430 24.380 0.400 1.994 1.200000e+10 9.654e+08
+ 5 6 7.812e+05 12.400 24.340 0.400 1.995 1.200000e+10 9.677e+08
+ 5 7 6.696e+05 12.360 24.290 0.390 1.997 1.199998e+10 9.709e+08
+ 5 8 5.859e+05 12.420 24.370 0.390 1.994 1.199999e+10 9.662e+08
+ 6 1 3.906e+06 12.990 25.320 0.560 1.992 1.200000e+10 9.238e+08
+ 6 2 1.953e+06 12.610 24.550 0.440 1.982 1.200000e+10 9.516e+08
+ 6 3 1.302e+06 12.520 24.310 0.420 1.975 1.200000e+10 9.585e+08
+ 6 4 9.766e+05 12.460 24.310 0.420 1.985 1.199999e+10 9.631e+08
+ 6 5 7.812e+05 12.440 24.240 0.410 1.982 1.200000e+10 9.646e+08
+ 6 6 6.510e+05 12.430 24.170 0.410 1.977 1.199999e+10 9.654e+08
+ 6 7 5.580e+05 12.450 24.230 0.410 1.979 1.199998e+10 9.639e+08
+ 6 8 4.883e+05 12.490 24.190 0.420 1.970 1.199999e+10 9.608e+08
+ 7 1 3.348e+06 13.150 24.280 0.500 1.884 1.200000e+10 9.125e+08
+ 7 2 1.674e+06 12.480 24.170 0.430 1.971 1.200000e+10 9.615e+08
+ 7 3 1.116e+06 12.480 24.430 0.440 1.993 1.200000e+10 9.615e+08
+ 7 4 8.371e+05 12.380 24.270 0.420 1.994 1.199999e+10 9.693e+08
+ 7 5 6.696e+05 12.390 24.290 0.430 1.995 1.199998e+10 9.685e+08
+ 7 6 5.580e+05 12.430 24.300 0.430 1.990 1.199998e+10 9.654e+08
+ 7 7 4.783e+05 12.460 24.360 0.430 1.990 1.199999e+10 9.631e+08
+ 7 8 4.185e+05 12.460 24.340 0.430 1.988 1.199998e+10 9.631e+08
+ 8 1 2.930e+06 12.960 24.600 0.530 1.939 1.200000e+10 9.259e+08
+ 8 2 1.465e+06 12.580 24.240 0.440 1.962 1.199999e+10 9.539e+08
+ 8 3 9.766e+05 12.520 24.060 0.430 1.956 1.199999e+10 9.585e+08
+ 8 4 7.324e+05 12.420 24.200 0.410 1.981 1.199999e+10 9.662e+08
+ 8 5 5.859e+05 12.430 24.310 0.430 1.990 1.199999e+10 9.654e+08
+ 8 6 4.883e+05 12.430 24.130 0.420 1.975 1.199999e+10 9.654e+08
+ 8 7 4.185e+05 12.800 24.220 0.490 1.930 1.199998e+10 9.375e+08
+ 8 8 3.662e+05 12.460 24.340 0.430 1.988 1.199997e+10 9.631e+08
diff --git a/gnuradio-runtime/examples/mp-sched/perf-data/qs21-altivec.dat b/gnuradio-runtime/examples/mp-sched/perf-data/qs21-altivec.dat
new file mode 100644
index 0000000000..8364be363d
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/perf-data/qs21-altivec.dat
@@ -0,0 +1,65 @@
+#D QS21 dual cell 3.2 GHz (using Altivec)
+ 1 1 3.516e+07 9.810 10.240 0.430 1.088 1.800000e+10 1.835e+09
+ 1 2 3.516e+07 11.650 22.840 0.750 2.025 3.600000e+10 3.090e+09
+ 1 3 2.344e+07 9.400 24.860 0.680 2.717 3.600000e+10 3.830e+09
+ 1 4 1.758e+07 7.800 26.820 0.740 3.533 3.600000e+10 4.615e+09
+ 1 5 1.406e+07 8.810 25.970 0.760 3.034 3.600000e+10 4.086e+09
+ 1 6 1.172e+07 8.110 25.710 0.740 3.261 3.600000e+10 4.439e+09
+ 1 7 1.004e+07 7.750 26.020 0.710 3.449 3.600000e+10 4.645e+09
+ 1 8 8.789e+06 7.290 26.600 0.690 3.743 3.600000e+10 4.938e+09
+ 2 1 3.516e+07 10.130 20.690 0.770 2.118 3.600000e+10 3.554e+09
+ 2 2 1.758e+07 7.240 26.820 0.920 3.831 3.600000e+10 4.972e+09
+ 2 3 1.172e+07 8.090 26.670 0.840 3.400 3.600000e+10 4.450e+09
+ 2 4 8.789e+06 7.480 27.010 0.790 3.717 3.600000e+10 4.813e+09
+ 2 5 7.031e+06 7.180 26.530 0.740 3.798 3.600000e+10 5.014e+09
+ 2 6 5.859e+06 7.060 26.590 0.730 3.870 3.600000e+10 5.099e+09
+ 2 7 5.022e+06 7.040 26.610 0.740 3.885 3.600000e+10 5.114e+09
+ 2 8 4.395e+06 7.090 27.020 0.730 3.914 3.600000e+10 5.078e+09
+ 3 1 2.344e+07 9.670 25.850 1.020 2.779 3.600000e+10 3.723e+09
+ 3 2 1.172e+07 7.700 25.940 0.930 3.490 3.600000e+10 4.675e+09
+ 3 3 7.812e+06 7.290 26.760 0.830 3.785 3.600000e+10 4.938e+09
+ 3 4 5.859e+06 7.210 26.900 0.800 3.842 3.600000e+10 4.993e+09
+ 3 5 4.688e+06 7.060 26.690 0.770 3.890 3.600000e+10 5.099e+09
+ 3 6 3.906e+06 7.060 26.830 0.810 3.915 3.600000e+10 5.099e+09
+ 3 7 3.348e+06 6.960 26.680 0.780 3.945 3.600000e+10 5.172e+09
+ 3 8 2.930e+06 6.960 26.600 0.770 3.932 3.599999e+10 5.172e+09
+ 4 1 1.758e+07 7.640 28.700 1.250 3.920 3.600000e+10 4.712e+09
+ 4 2 8.789e+06 7.230 26.640 0.940 3.815 3.600000e+10 4.979e+09
+ 4 3 5.859e+06 7.200 26.800 0.860 3.842 3.600000e+10 5.000e+09
+ 4 4 4.395e+06 7.110 26.900 0.840 3.902 3.600000e+10 5.063e+09
+ 4 5 3.516e+06 7.020 26.680 0.800 3.915 3.600000e+10 5.128e+09
+ 4 6 2.930e+06 6.950 26.700 0.800 3.957 3.599999e+10 5.180e+09
+ 4 7 2.511e+06 6.930 26.590 0.800 3.952 3.599999e+10 5.195e+09
+ 4 8 2.197e+06 6.960 26.570 0.790 3.931 3.599999e+10 5.172e+09
+ 5 1 1.406e+07 8.730 26.540 1.190 3.176 3.600000e+10 4.124e+09
+ 5 2 7.031e+06 7.270 26.450 0.960 3.770 3.600000e+10 4.952e+09
+ 5 3 4.688e+06 7.100 26.630 0.880 3.875 3.600000e+10 5.070e+09
+ 5 4 3.516e+06 7.050 26.700 0.850 3.908 3.600000e+10 5.106e+09
+ 5 5 2.812e+06 6.970 26.610 0.830 3.937 3.600000e+10 5.165e+09
+ 5 6 2.344e+06 6.980 26.710 0.840 3.947 3.600000e+10 5.158e+09
+ 5 7 2.009e+06 6.900 26.470 0.800 3.952 3.599999e+10 5.217e+09
+ 5 8 1.758e+06 6.940 26.580 0.820 3.948 3.599999e+10 5.187e+09
+ 6 1 1.172e+07 8.200 26.510 1.190 3.378 3.600000e+10 4.390e+09
+ 6 2 5.859e+06 7.210 26.590 0.970 3.822 3.600000e+10 4.993e+09
+ 6 3 3.906e+06 7.070 26.580 0.910 3.888 3.600000e+10 5.092e+09
+ 6 4 2.930e+06 7.090 26.750 0.860 3.894 3.599999e+10 5.078e+09
+ 6 5 2.344e+06 7.040 26.830 0.830 3.929 3.600000e+10 5.114e+09
+ 6 6 1.953e+06 6.960 26.600 0.830 3.941 3.600000e+10 5.172e+09
+ 6 7 1.674e+06 6.940 26.500 0.810 3.935 3.600000e+10 5.187e+09
+ 6 8 1.465e+06 6.940 26.540 0.830 3.944 3.599998e+10 5.187e+09
+ 7 1 1.004e+07 7.730 26.940 1.190 3.639 3.600000e+10 4.657e+09
+ 7 2 5.022e+06 7.240 26.600 0.980 3.809 3.600000e+10 4.972e+09
+ 7 3 3.348e+06 7.120 26.680 0.930 3.878 3.600000e+10 5.056e+09
+ 7 4 2.511e+06 7.070 26.840 0.890 3.922 3.599999e+10 5.092e+09
+ 7 5 2.009e+06 6.980 26.570 0.850 3.928 3.599999e+10 5.158e+09
+ 7 6 1.674e+06 6.950 26.530 0.840 3.938 3.600000e+10 5.180e+09
+ 7 7 1.435e+06 6.940 26.570 0.860 3.952 3.599998e+10 5.187e+09
+ 7 8 1.256e+06 6.980 26.590 0.840 3.930 3.599999e+10 5.158e+09
+ 8 1 8.789e+06 7.570 27.360 1.260 3.781 3.600000e+10 4.756e+09
+ 8 2 4.395e+06 7.130 26.460 0.980 3.849 3.600000e+10 5.049e+09
+ 8 3 2.930e+06 7.060 26.680 0.920 3.909 3.599999e+10 5.099e+09
+ 8 4 2.197e+06 7.040 26.670 0.880 3.913 3.599999e+10 5.114e+09
+ 8 5 1.758e+06 6.970 26.600 0.860 3.940 3.599999e+10 5.165e+09
+ 8 6 1.465e+06 6.940 26.490 0.840 3.938 3.599998e+10 5.187e+09
+ 8 7 1.256e+06 6.980 26.630 0.850 3.937 3.599999e+10 5.158e+09
+ 8 8 1.099e+06 7.010 26.820 0.860 3.949 3.599997e+10 5.136e+09
diff --git a/gnuradio-runtime/examples/mp-sched/perf-data/qs21.dat b/gnuradio-runtime/examples/mp-sched/perf-data/qs21.dat
new file mode 100644
index 0000000000..cc628740a8
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/perf-data/qs21.dat
@@ -0,0 +1,65 @@
+#D QS21 dual cell 3.2 GHz
+ 1 1 1.953e+07 8.480 8.730 0.270 1.061 1.000000e+10 1.179e+09
+ 1 2 1.953e+07 8.750 17.210 0.460 2.019 2.000000e+10 2.286e+09
+ 1 3 1.302e+07 12.390 29.530 0.540 2.427 2.000000e+10 1.614e+09
+ 1 4 9.766e+06 10.120 31.500 0.590 3.171 2.000000e+10 1.976e+09
+ 1 5 7.812e+06 10.200 31.350 0.610 3.133 2.000000e+10 1.961e+09
+ 1 6 6.510e+06 9.520 31.690 0.590 3.391 2.000000e+10 2.101e+09
+ 1 7 5.580e+06 9.430 32.610 0.600 3.522 2.000000e+10 2.121e+09
+ 1 8 4.883e+06 9.400 34.160 0.620 3.700 2.000000e+10 2.128e+09
+ 2 1 1.953e+07 8.800 17.750 0.500 2.074 2.000000e+10 2.273e+09
+ 2 2 9.766e+06 8.990 28.900 0.640 3.286 2.000000e+10 2.225e+09
+ 2 3 6.510e+06 9.390 32.450 0.660 3.526 2.000000e+10 2.130e+09
+ 2 4 4.883e+06 9.220 34.450 0.660 3.808 2.000000e+10 2.169e+09
+ 2 5 3.906e+06 9.180 34.730 0.650 3.854 2.000000e+10 2.179e+09
+ 2 6 3.255e+06 9.150 34.960 0.650 3.892 2.000000e+10 2.186e+09
+ 2 7 2.790e+06 9.140 35.290 0.650 3.932 2.000000e+10 2.188e+09
+ 2 8 2.441e+06 9.080 35.240 0.650 3.953 2.000000e+10 2.203e+09
+ 3 1 1.302e+07 11.720 28.890 0.740 2.528 2.000000e+10 1.706e+09
+ 3 2 6.510e+06 9.390 32.700 0.730 3.560 2.000000e+10 2.130e+09
+ 3 3 4.340e+06 9.150 33.930 0.690 3.784 2.000000e+10 2.186e+09
+ 3 4 3.255e+06 9.040 34.650 0.680 3.908 2.000000e+10 2.212e+09
+ 3 5 2.604e+06 9.090 34.990 0.680 3.924 1.999999e+10 2.200e+09
+ 3 6 2.170e+06 9.050 34.870 0.670 3.927 1.999999e+10 2.210e+09
+ 3 7 1.860e+06 9.010 34.850 0.660 3.941 2.000000e+10 2.220e+09
+ 3 8 1.628e+06 8.980 34.860 0.670 3.957 2.000000e+10 2.227e+09
+ 4 1 9.766e+06 9.000 34.680 0.940 3.958 2.000000e+10 2.222e+09
+ 4 2 4.883e+06 9.020 34.180 0.740 3.871 2.000000e+10 2.217e+09
+ 4 3 3.255e+06 9.150 34.640 0.710 3.863 2.000000e+10 2.186e+09
+ 4 4 2.441e+06 9.010 34.780 0.690 3.937 2.000000e+10 2.220e+09
+ 4 5 1.953e+06 8.980 34.680 0.690 3.939 2.000000e+10 2.227e+09
+ 4 6 1.628e+06 9.050 35.120 0.690 3.957 2.000000e+10 2.210e+09
+ 4 7 1.395e+06 9.010 34.900 0.670 3.948 2.000000e+10 2.220e+09
+ 4 8 1.221e+06 8.960 34.900 0.680 3.971 2.000000e+10 2.232e+09
+ 5 1 7.812e+06 10.150 31.760 0.840 3.212 2.000000e+10 1.970e+09
+ 5 2 3.906e+06 9.090 34.040 0.750 3.827 2.000000e+10 2.200e+09
+ 5 3 2.604e+06 9.030 34.650 0.720 3.917 1.999999e+10 2.215e+09
+ 5 4 1.953e+06 8.990 34.610 0.700 3.928 2.000000e+10 2.225e+09
+ 5 5 1.562e+06 9.000 34.920 0.700 3.958 2.000000e+10 2.222e+09
+ 5 6 1.302e+06 9.120 35.370 0.690 3.954 1.999999e+10 2.193e+09
+ 5 7 1.116e+06 8.910 34.680 0.690 3.970 1.999999e+10 2.245e+09
+ 5 8 9.766e+05 8.930 34.790 0.680 3.972 1.999999e+10 2.240e+09
+ 6 1 6.510e+06 9.390 31.810 0.840 3.477 2.000000e+10 2.130e+09
+ 6 2 3.255e+06 9.000 34.320 0.760 3.898 2.000000e+10 2.222e+09
+ 6 3 2.170e+06 8.960 34.310 0.740 3.912 1.999999e+10 2.232e+09
+ 6 4 1.628e+06 8.970 34.640 0.730 3.943 2.000000e+10 2.230e+09
+ 6 5 1.302e+06 9.110 35.360 0.710 3.959 1.999999e+10 2.195e+09
+ 6 6 1.085e+06 8.970 34.750 0.710 3.953 1.999999e+10 2.230e+09
+ 6 7 9.301e+05 8.950 34.710 0.700 3.956 1.999999e+10 2.235e+09
+ 6 8 8.138e+05 8.920 34.570 0.710 3.955 2.000000e+10 2.242e+09
+ 7 1 5.580e+06 9.290 32.840 0.870 3.629 2.000000e+10 2.153e+09
+ 7 2 2.790e+06 9.040 34.400 0.770 3.890 2.000000e+10 2.212e+09
+ 7 3 1.860e+06 8.940 34.380 0.740 3.928 2.000000e+10 2.237e+09
+ 7 4 1.395e+06 8.990 34.820 0.730 3.954 2.000000e+10 2.225e+09
+ 7 5 1.116e+06 8.990 34.820 0.720 3.953 1.999999e+10 2.225e+09
+ 7 6 9.301e+05 8.940 34.720 0.720 3.964 1.999999e+10 2.237e+09
+ 7 7 7.972e+05 8.930 34.700 0.710 3.965 1.999998e+10 2.240e+09
+ 7 8 6.975e+05 8.910 34.510 0.700 3.952 1.999998e+10 2.245e+09
+ 8 1 4.883e+06 9.070 33.770 0.910 3.824 2.000000e+10 2.205e+09
+ 8 2 2.441e+06 9.000 34.340 0.780 3.902 2.000000e+10 2.222e+09
+ 8 3 1.628e+06 8.990 34.510 0.740 3.921 2.000000e+10 2.225e+09
+ 8 4 1.221e+06 8.980 34.650 0.740 3.941 2.000000e+10 2.227e+09
+ 8 5 9.766e+05 8.960 34.700 0.720 3.953 1.999999e+10 2.232e+09
+ 8 6 8.138e+05 8.920 34.680 0.710 3.967 2.000000e+10 2.242e+09
+ 8 7 6.975e+05 8.900 34.580 0.720 3.966 1.999998e+10 2.247e+09
+ 8 8 6.104e+05 8.930 34.590 0.710 3.953 1.999998e+10 2.240e+09
diff --git a/gnuradio-runtime/examples/mp-sched/plot_flops.py b/gnuradio-runtime/examples/mp-sched/plot_flops.py
new file mode 100755
index 0000000000..d9d810ae2f
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/plot_flops.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+"""
+Reads output from run_synthetic.py and runs gnuplot showing
+GFLOPS as f(npipes, nstages)
+"""
+
+import re
+import sys
+import os
+import tempfile
+from optparse import OptionParser
+
+
+def parse_file(input_filename, output):
+ last = None
+ desc = ''
+ for line in open(input_filename, 'r'):
+ s = line.strip()
+ if s.startswith('>>>'): # ignore ">>> using SSE cruft"
+ continue
+
+ if s.startswith('#D'): # machine description
+ desc = s[2:].strip()
+ continue
+
+ fields = s.split()
+ npipes, nstages, flops = fields[0], fields[1], fields[8]
+
+ if last is not None and npipes != last:
+ output.write('\n')
+ last = npipes
+
+ output.write(' '.join((npipes, nstages, flops)))
+ output.write('\n')
+
+ output.flush()
+ return desc
+
+
+def handle_file(input_filename):
+ cmd_file = tempfile.NamedTemporaryFile(mode='w+', prefix='pf', suffix='.cmd')
+ cmd_file_name = cmd_file.name
+ data_file = tempfile.NamedTemporaryFile(mode='w+', prefix='pf', suffix='.dat')
+ data_file_name = data_file.name
+ desc = parse_file(input_filename, data_file)
+ if len(desc) > 0:
+ cmd_file.write("set title '%s'\n" % (desc,))
+ cmd_file.write("set xlabel 'N pipes'\n")
+ cmd_file.write("set ylabel 'N stages'\n")
+ cmd_file.write("set zlabel 'GFLOPS'\n")
+ cmd_file.write("set key off\n")
+ cmd_file.write("set view 60, 312\n")
+ cmd_file.write("set pm3d\n")
+ cmd_file.write("splot '%s' using 1:2:($3*1e-9) with pm3d at b, '%s' using 1:2:($3*1e-9) with pm3d\n" % (
+ data_file_name, data_file_name))
+
+ cmd_file.flush()
+ data_file.flush()
+
+ os.system("gnuplot " + cmd_file_name + " -")
+
+ #sys.stdout.write(open(cmd_file_name,'r').read())
+ #sys.stdout.write(open(data_file_name,'r').read())
+
+
+def main():
+ usage = "usage: %prog [options] file.dat"
+ parser = OptionParser(usage=usage)
+ (options, args) = parser.parse_args()
+ if len(args) != 1:
+ parser.print_help()
+ raise SystemExit, 1
+
+ handle_file(args[0])
+
+
+if __name__ == '__main__':
+ main()
diff --git a/gnuradio-runtime/examples/mp-sched/run_synthetic.py b/gnuradio-runtime/examples/mp-sched/run_synthetic.py
new file mode 100755
index 0000000000..4896bca462
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/run_synthetic.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+"""
+Run synthetic.py for npipes in [1,16], nstages in [1,16]
+"""
+
+import re
+import sys
+import os
+import tempfile
+from optparse import OptionParser
+
+
+def write_shell_script(f, data_filename, description, ncores, gflops, max_pipes_and_stages):
+ """
+ f is the file to write the script to
+ data_filename is the where the data ends up
+ description describes the machine
+ ncores is the number of cores (used to size the workload)
+ gflops is the estimated GFLOPS per core (used to size the workload)
+ """
+
+ f.write("#!/bin/sh\n")
+ f.write("(\n")
+ if description:
+ f.write("echo '#D %s'\n" % (description,))
+
+ for npipes in range(1, max_pipes_and_stages + 1):
+ for nstages in range(1, max_pipes_and_stages + 1):
+ # We'd like each run of synthetic to take ~10 seconds
+ desired_time_per_run = 10
+ est_gflops_avail = min(nstages * npipes, ncores) * gflops
+ nsamples = (est_gflops_avail * desired_time_per_run)/(512.0 * nstages * npipes)
+ nsamples = int(nsamples * 1e9)
+
+ cmd = "./synthetic.py -m -s %d -p %d -N %d\n" % (nstages, npipes, nsamples)
+ f.write(cmd)
+ f.write('if test $? -ge 128; then exit 128; fi\n')
+
+ f.write(") 2>&1 | grep --line-buffered -v '^>>>' | tee %s\n" % (data_filename,))
+ f.flush()
+
+
+
+def main():
+ description = """%prog gathers multiprocessor scaling data using the ./synthetic.py benchmark.
+All combinations of npipes and nstages between 1 and --max-pipes-and-stages are tried.
+The -n and -f options provides hints used to size the workload. We'd like each run
+of synthetic to take about 10 seconds. For the full 16x16 case this results in a
+total runtime of about 43 minutes, assuming that your values for -n and -f are reasonable.
+For x86 machines, assume 3 FLOPS per processor Hz. E.g., 3 GHz machine -> 9 GFLOPS.
+plot_flops.py will make pretty graphs from the output data generated by %prog.
+"""
+ usage = "usage: %prog [options] output.dat"
+ parser = OptionParser(usage=usage, description=description)
+ parser.add_option("-d", "--description", metavar="DESC",
+ help="machine description, e.g., \"Dual quad-core Xeon 3 GHz\"", default=None)
+ parser.add_option("-n", "--ncores", type="int", default=1,
+ help="number of processor cores [default=%default]")
+ parser.add_option("-g", "--gflops", metavar="GFLOPS", type="float", default=3.0,
+ help="estimated GFLOPS per core [default=%default]")
+ parser.add_option("-m", "--max-pipes-and-stages", metavar="MAX", type="int", default=16,
+ help="maximum number of pipes and stages to use [default=%default]")
+ (options, args) = parser.parse_args()
+ if len(args) != 1:
+ parser.print_help()
+ raise SystemExit, 1
+
+ output_filename = args[0]
+
+ shell = os.popen("/bin/sh", "w")
+
+ write_shell_script(shell,
+ output_filename,
+ options.description,
+ options.ncores,
+ options.gflops,
+ options.max_pipes_and_stages)
+
+if __name__ == '__main__':
+ main()
+
diff --git a/gnuradio-runtime/examples/mp-sched/synthetic.py b/gnuradio-runtime/examples/mp-sched/synthetic.py
new file mode 100755
index 0000000000..6f0bb85da8
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/synthetic.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+#
+# Copyright 2008,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 this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+from gnuradio import gr, gru, eng_notation, blks2
+from gnuradio import blocks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import os
+
+
+class pipeline(gr.hier_block2):
+ def __init__(self, nstages, ntaps=256):
+ """
+ Create a pipeline of nstages of filter.fir_filter_fff's connected in serial
+ terminating in a blocks.null_sink.
+ """
+ gr.hier_block2.__init__(self, "pipeline",
+ gr.io_signature(1, 1, gr.sizeof_float),
+ gr.io_signature(0, 0, 0))
+ taps = ntaps*[1.0/ntaps]
+ upstream = self
+ for i in range(nstages):
+ op = filter.fir_filter_fff(1, taps)
+ self.connect(upstream, op)
+ upstream = op
+
+ self.connect(upstream, blocks.null_sink(gr.sizeof_float))
+
+
+class top(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ default_nsamples = 10e6
+ parser=OptionParser(option_class=eng_option)
+ parser.add_option("-p", "--npipelines", type="intx", default=1,
+ metavar="NPIPES", help="the number of pipelines to create (default=%default)")
+ parser.add_option("-s", "--nstages", type="intx", default=1,
+ metavar="NSTAGES", help="the number of stages in each pipeline (default=%default)")
+ parser.add_option("-N", "--nsamples", type="eng_float", default=default_nsamples,
+ help=("the number of samples to run through the graph (default=%s)" %
+ (eng_notation.num_to_str(default_nsamples))))
+ parser.add_option("-m", "--machine-readable", action="store_true", default=False,
+ help="enable machine readable output")
+
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ raise SystemExit, 1
+
+ self.npipes = options.npipelines
+ self.nstages = options.nstages
+ self.nsamples = options.nsamples
+ self.machine_readable = options.machine_readable
+
+ ntaps = 256
+
+ # Something vaguely like floating point ops
+ self.flop = 2 * ntaps * options.npipelines * options.nstages * options.nsamples
+
+ src = blocks.null_source(gr.sizeof_float)
+ head = blocks.head(gr.sizeof_float, int(options.nsamples))
+ self.connect(src, head)
+
+ for n in range(options.npipelines):
+ self.connect(head, pipeline(options.nstages, ntaps))
+
+
+def time_it(tb):
+ start = os.times()
+ tb.run()
+ stop = os.times()
+ delta = map((lambda a, b: a-b), stop, start)
+ user, sys, childrens_user, childrens_sys, real = delta
+ total_user = user + childrens_user
+ total_sys = sys + childrens_sys
+ if tb.machine_readable:
+ print "%3d %3d %.3e %7.3f %7.3f %7.3f %7.3f %.6e %.3e" % (
+ tb.npipes, tb.nstages, tb.nsamples, real, total_user, total_sys, (total_user+total_sys)/real, tb.flop, tb.flop/real)
+ else:
+ print "npipes %7d" % (tb.npipes,)
+ print "nstages %7d" % (tb.nstages,)
+ print "nsamples %s" % (eng_notation.num_to_str(tb.nsamples),)
+ print "real %7.3f" % (real,)
+ print "user %7.3f" % (total_user,)
+ print "sys %7.3f" % (total_sys,)
+ print "(user+sys)/real %7.3f" % ((total_user + total_sys)/real,)
+ print "pseudo_flop %s" % (eng_notation.num_to_str(tb.flop),)
+ print "pseudo_flop/real %s" % (eng_notation.num_to_str(tb.flop/real),)
+
+
+if __name__ == "__main__":
+ try:
+ tb = top()
+ time_it(tb)
+ except KeyboardInterrupt:
+ raise SystemExit, 128
+
+
+
+
diff --git a/gnuradio-runtime/examples/mp-sched/wfm_rcv_pll_to_wav.py b/gnuradio-runtime/examples/mp-sched/wfm_rcv_pll_to_wav.py
new file mode 100755
index 0000000000..7cf3210b0e
--- /dev/null
+++ b/gnuradio-runtime/examples/mp-sched/wfm_rcv_pll_to_wav.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+#
+# Copyright 2005,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.
+#
+
+from gnuradio import gr, gru, eng_notation, optfir
+from gnuradio import audio
+from gnuradio import analog
+from gnuradio import blocks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import sys
+import math
+
+class wfm_rx_block (gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+
+ usage = "usage: %prog [options] input-samples-320kS.dat output.wav"
+ parser=OptionParser(option_class=eng_option, usage=usage)
+ parser.add_option("-V", "--volume", type="eng_float", default=None,
+ help="set volume (default is midpoint)")
+
+ (options, args) = parser.parse_args()
+ if len(args) != 2:
+ parser.print_help()
+ sys.exit(1)
+
+ input_filename = args[0]
+ output_filename = args[1]
+
+ self.vol = 0
+
+ # build graph
+
+ self.src = blocks.file_source(gr.sizeof_gr_complex, input_filename, False)
+
+ adc_rate = 64e6 # 64 MS/s
+ usrp_decim = 200
+ usrp_rate = adc_rate / usrp_decim # 320 kS/s
+ chanfilt_decim = 1
+ demod_rate = usrp_rate / chanfilt_decim
+ audio_decimation = 10
+ audio_rate = demod_rate / audio_decimation # 32 kHz
+
+
+ chan_filt_coeffs = optfir.low_pass (1, # gain
+ usrp_rate, # sampling rate
+ 80e3, # passband cutoff
+ 115e3, # stopband cutoff
+ 0.1, # passband ripple
+ 60) # stopband attenuation
+ #print len(chan_filt_coeffs)
+ chan_filt = filter.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
+
+
+ #self.guts = analog.wfm_rcv (demod_rate, audio_decimation)
+ self.guts = analog.wfm_rcv_pll (demod_rate, audio_decimation)
+
+ # FIXME rework {add,multiply}_const_* to handle multiple streams
+ self.volume_control_l = blocks.multiply_const_ff(self.vol)
+ self.volume_control_r = blocks.multiply_const_ff(self.vol)
+
+ # wave file as final sink
+ if 1:
+ sink = blocks.wavfile_sink(output_filename, 2, int(audio_rate), 16)
+ else:
+ sink = audio.sink (int (audio_rate),
+ options.audio_output,
+ False) # ok_to_block
+
+ # now wire it all together
+ self.connect (self.src, chan_filt, self.guts)
+ self.connect ((self.guts, 0), self.volume_control_l, (sink, 0))
+ self.connect ((self.guts, 1), self.volume_control_r, (sink, 1))
+ try:
+ self.guts.stereo_carrier_pll_recovery.squelch_enable(True)
+ except:
+ pass
+ #print "FYI: This implementation of the stereo_carrier_pll_recovery has no squelch implementation yet"
+
+ if options.volume is None:
+ g = self.volume_range()
+ options.volume = float(g[0]+g[1])/2
+
+ # set initial values
+
+ self.set_vol(options.volume)
+ try:
+ self.guts.stereo_carrier_pll_recovery.set_lock_threshold(options.squelch)
+ except:
+ pass
+ #print "FYI: This implementation of the stereo_carrier_pll_recovery has no squelch implementation yet"
+
+
+ def set_vol (self, vol):
+ g = self.volume_range()
+ self.vol = max(g[0], min(g[1], vol))
+ self.volume_control_l.set_k(10**(self.vol/10))
+ self.volume_control_r.set_k(10**(self.vol/10))
+
+ def volume_range(self):
+ return (-20.0, 0.0, 0.5)
+
+
+if __name__ == '__main__':
+ tb = wfm_rx_block()
+ try:
+ tb.run()
+ except KeyboardInterrupt:
+ pass
diff --git a/gnuradio-runtime/examples/network/CMakeLists.txt b/gnuradio-runtime/examples/network/CMakeLists.txt
new file mode 100644
index 0000000000..92eb734768
--- /dev/null
+++ b/gnuradio-runtime/examples/network/CMakeLists.txt
@@ -0,0 +1,30 @@
+# 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.
+
+GR_PYTHON_INSTALL(PROGRAMS
+ audio_sink.py
+ audio_source.py
+ dial_tone_sink.py
+ dial_tone_source.py
+ vector_sink.py
+ vector_source.py
+ DESTINATION ${GR_PKG_DATA_DIR}/examples/network
+ COMPONENT "runtime_python"
+)
+
diff --git a/gnuradio-runtime/examples/network/audio_sink.py b/gnuradio-runtime/examples/network/audio_sink.py
new file mode 100755
index 0000000000..0e412de5ae
--- /dev/null
+++ b/gnuradio-runtime/examples/network/audio_sink.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+#
+# Copyright 2006,2007,2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr
+from gnuradio import blocks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import sys
+
+try:
+ from gnuradio import audio
+except ImportError:
+ sys.stderr.write("Failed to import gnuradio.audio. Make sure gr-audio component is installed.\n")
+ sys.exit(1)
+
+class audio_sink(gr.top_block):
+ def __init__(self, host, port, pkt_size, sample_rate, eof, wait):
+ gr.top_block.__init__(self, "audio_sink")
+ src = blocks.udp_source(gr.sizeof_float, host, port, pkt_size, eof=eof)
+ dst = audio.sink(sample_rate)
+ self.connect(src, dst)
+
+if __name__ == '__main__':
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("", "--host", type="string", default="0.0.0.0",
+ help="local host name (domain name or IP address)")
+ parser.add_option("", "--port", type="int", default=65500,
+ help="port value to listen to for connection")
+ parser.add_option("", "--packet-size", type="int", default=1472,
+ help="packet size.")
+ parser.add_option("-r", "--sample-rate", type="int", default=32000,
+ help="audio signal sample rate [default=%default]")
+ parser.add_option("", "--no-eof", action="store_true", default=False,
+ help="don't send EOF on disconnect")
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ raise SystemExit, 1
+
+ # Create an instance of a hierarchical block
+ top_block = audio_sink(options.host, options.port,
+ options.packet_size, options.sample_rate,
+ not options.no_eof)
+
+ try:
+ # Run forever
+ top_block.run()
+ except KeyboardInterrupt:
+ # Ctrl-C exits
+ pass
+
diff --git a/gnuradio-runtime/examples/network/audio_source.py b/gnuradio-runtime/examples/network/audio_source.py
new file mode 100755
index 0000000000..577beff84c
--- /dev/null
+++ b/gnuradio-runtime/examples/network/audio_source.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+#
+# Copyright 2006,2007,2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr
+from gnuradio import blocks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import sys
+
+try:
+ from gnuradio import audio
+except ImportError:
+ sys.stderr.write("Failed to import gnuradio.audio. Make sure gr-audio component is installed.\n")
+ sys.exit(1)
+
+class audio_source(gr.top_block):
+ def __init__(self, host, port, pkt_size, sample_rate, eof):
+ gr.top_block.__init__(self, "audio_source")
+ self.audio = audio.source(sample_rate)
+ self.sink = blocks.udp_sink(gr.sizeof_float, host, port, pkt_size, eof=eof)
+ self.connect(self.audio, self.sink)
+
+if __name__ == '__main__':
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("", "--host", type="string", default="localhost",
+ help="Remote host name (domain name or IP address")
+ parser.add_option("", "--port", type="int", default=65500,
+ help="port number to connect to")
+ parser.add_option("", "--packet-size", type="int", default=1472,
+ help="packet size.")
+ parser.add_option("-r", "--sample-rate", type="int", default=32000 ,
+ help="audio signal sample rate [default=%default]")
+ parser.add_option("", "--no-eof", action="store_true", default=False,
+ help="don't send EOF on disconnect")
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ raise SystemExit, 1
+
+ # Create an instance of a hierarchical block
+ top_block = audio_source(options.host, options.port,
+ options.packet_size, options.sample_rate,
+ not options.no_eof)
+
+ try:
+ # Run forever
+ top_block.run()
+ except KeyboardInterrupt:
+ # Ctrl-C exits
+ pass
+
diff --git a/gnuradio-runtime/examples/network/dial_tone_sink.py b/gnuradio-runtime/examples/network/dial_tone_sink.py
new file mode 100755
index 0000000000..fee6ded846
--- /dev/null
+++ b/gnuradio-runtime/examples/network/dial_tone_sink.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+#
+# Copyright 2006,2007,2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, audio
+from gnuradio import blocks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+class dial_tone_sink(gr.top_block):
+ def __init__(self, host, port, pkt_size, sample_rate, eof):
+ gr.top_block.__init__(self, "dial_tone_sink")
+ udp = blokcs.udp_source(gr.sizeof_float, host, port, pkt_size, eof=eof)
+ sink = audio.sink(sample_rate)
+ self.connect(udp, sink)
+
+if __name__ == '__main__':
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("", "--host", type="string", default="0.0.0.0",
+ help="local host name (domain name or IP address)")
+ parser.add_option("", "--port", type="int", default=65500,
+ help="port value to listen to for connection")
+ parser.add_option("", "--packet-size", type="int", default=1472,
+ help="packet size.")
+ parser.add_option("-r", "--sample-rate", type="int", default=8000,
+ help="audio signal sample rate [default=%default]")
+ parser.add_option("", "--no-eof", action="store_true", default=False,
+ help="don't send EOF on disconnect")
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ raise SystemExit, 1
+
+ # Create an instance of a hierarchical block
+ top_block = dial_tone_sink(options.host, options.port,
+ options.packet_size, options.sample_rate,
+ not options.no_eof)
+
+ try:
+ # Run forever
+ top_block.run()
+ except KeyboardInterrupt:
+ # Ctrl-C exits
+ pass
+
diff --git a/gnuradio-runtime/examples/network/dial_tone_source.py b/gnuradio-runtime/examples/network/dial_tone_source.py
new file mode 100755
index 0000000000..44f05dc83c
--- /dev/null
+++ b/gnuradio-runtime/examples/network/dial_tone_source.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+#
+# Copyright 2006,2007,2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr
+from gnuradio import blocks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import sys
+
+try:
+ from gnuradio import analog
+except ImportError:
+ sys.stderr.write("This example requires gr-analog.\n")
+
+try:
+ from gnuradio import blocks
+except ImportError:
+ sys.stderr.write("This example requires gr-blocks.\n")
+
+class dial_tone_source(gr.top_block):
+ def __init__(self, host, port, pkt_size, sample_rate, eof):
+ gr.top_block.__init__(self, "dial_tone_source")
+
+ amplitude = 0.3
+ src0 = analog.sig_source_f(sample_rate, analog.GR_SIN_WAVE, 350, amplitude)
+ src1 = analog.sig_source_f(sample_rate, analog.GR_SIN_WAVE, 440, amplitude)
+ add = blocks.add_ff()
+
+ # Throttle needed here to account for the other side's audio card sampling rate
+ thr = blocks.throttle(gr.sizeof_float, sample_rate)
+ sink = blocks.udp_sink(gr.sizeof_float, host, port, pkt_size, eof=eof)
+ self.connect(src0, (add, 0))
+ self.connect(src1, (add, 1))
+ self.connect(add, thr, sink)
+
+if __name__ == '__main__':
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("", "--host", type="string", default="localhost",
+ help="Remote host name (domain name or IP address")
+ parser.add_option("", "--port", type="int", default=65500,
+ help="port number to connect to")
+ parser.add_option("", "--packet-size", type="int", default=1472,
+ help="packet size.")
+ parser.add_option("-r", "--sample-rate", type="int", default=8000,
+ help="audio signal sample rate [default=%default]")
+ parser.add_option("", "--no-eof", action="store_true", default=False,
+ help="don't send EOF on disconnect")
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ raise SystemExit, 1
+
+ # Create an instance of a hierarchical block
+ top_block = dial_tone_source(options.host, options.port,
+ options.packet_size, options.sample_rate,
+ not options.no_eof)
+
+ try:
+ # Run forever
+ top_block.run()
+ except KeyboardInterrupt:
+ # Ctrl-C exits
+ pass
diff --git a/gnuradio-runtime/examples/network/vector_sink.py b/gnuradio-runtime/examples/network/vector_sink.py
new file mode 100755
index 0000000000..c0397d1e43
--- /dev/null
+++ b/gnuradio-runtime/examples/network/vector_sink.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+#
+# Copyright 2006,2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr
+from gnuradio import blocks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+class vector_sink(gr.top_block):
+ def __init__(self, host, port, pkt_size, eof, wait):
+ gr.top_block.__init__(self, "vector_sink")
+
+ udp = blocks.udp_source(gr.sizeof_float, host, port, pkt_size, eof=eof)
+ sink = blocks.file_sink(gr.sizeof_float, "received.dat")
+ self.connect(udp, sink)
+
+if __name__ == "__main__":
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("", "--host", type="string", default="0.0.0.0",
+ help="local host name (domain name or IP address)")
+ parser.add_option("", "--port", type="int", default=65500,
+ help="port value to listen to for connection")
+ parser.add_option("", "--packet-size", type="int", default=1471,
+ help="packet size.")
+ parser.add_option("", "--no-eof", action="store_true", default=False,
+ help="don't send EOF on disconnect")
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ raise SystemExit, 1
+
+ # Create an instance of a hierarchical block
+ top_block = vector_sink(options.host, options.port,
+ options.packet_size,
+ not options.no_eof)
+
+ try:
+ # Run forever
+ top_block.run()
+ except KeyboardInterrupt:
+ # Ctrl-C exits
+ pass
+
diff --git a/gnuradio-runtime/examples/network/vector_source.py b/gnuradio-runtime/examples/network/vector_source.py
new file mode 100755
index 0000000000..568425fd50
--- /dev/null
+++ b/gnuradio-runtime/examples/network/vector_source.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+#
+# Copyright 2006,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.
+#
+
+from gnuradio import gr
+from gnuradio import blocks
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+class vector_source(gr.top_block):
+ def __init__(self, host, port, pkt_size, eof):
+ gr.top_block.__init__(self, "vector_source")
+ data = [i*0.01 for i in range(1000)]
+ vec = blocks.vector_source_f(data, True)
+ udp = blocks.udp_sink(gr.sizeof_float, host, port, pkt_size, eof=eof)
+ self.connect(vec, udp)
+
+if __name__ == '__main__':
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("", "--host", type="string", default="localhost",
+ help="Remote host name (domain name or IP address")
+ parser.add_option("", "--port", type="int", default=65500,
+ help="port number to connect to")
+ parser.add_option("", "--packet-size", type="int", default=1471,
+ help="packet size.")
+ parser.add_option("", "--no-eof", action="store_true", default=False,
+ help="don't send EOF on disconnect")
+ (options, args) = parser.parse_args()
+ if len(args) != 0:
+ parser.print_help()
+ raise SystemExit, 1
+
+# Create an instance of a hierarchical block
+ top_block = vector_source(options.host, options.port, options.packet_size,
+ not options.no_eof)
+
+ try:
+ # Run forever
+ top_block.run()
+ except KeyboardInterrupt:
+ # Ctrl-C exits
+ pass
+
diff --git a/gnuradio-runtime/examples/volk_benchmark/CMakeLists.txt b/gnuradio-runtime/examples/volk_benchmark/CMakeLists.txt
new file mode 100644
index 0000000000..f56675e556
--- /dev/null
+++ b/gnuradio-runtime/examples/volk_benchmark/CMakeLists.txt
@@ -0,0 +1,35 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+include(GrPython)
+
+GR_PYTHON_INSTALL(PROGRAMS
+ volk_math.py
+ volk_plot.py
+ volk_test_funcs.py
+ volk_types.py
+ DESTINATION ${GR_PKG_DATA_DIR}/examples/volk_benchmark
+ COMPONENT "runtime_python"
+)
+
+install(
+ FILES README
+ DESTINATION ${GR_PKG_DATA_DIR}/examples/volk_benchmark
+ COMPONENT "runtime_python"
+)
diff --git a/gnuradio-runtime/examples/volk_benchmark/README b/gnuradio-runtime/examples/volk_benchmark/README
new file mode 100644
index 0000000000..c58b40d115
--- /dev/null
+++ b/gnuradio-runtime/examples/volk_benchmark/README
@@ -0,0 +1,252 @@
+VOLK Benchmarking Scripts
+
+The Python programs in this directory are designed to help benchmark
+and compare Volk enhancements to GNU Radio. There are two kinds of
+scripts here: collecting data and displaying the data.
+
+Data collection is done by running a Volk testing script that will
+populate a SQLite database file (volk_results.db by default). The
+plotting utility provided here reads from the database files and plots
+bar graphs to compare the different installations.
+
+These benchmarks can be used to compare previous versions of GNU
+Radio to using Volk; they can be used to compare different Volk
+proto-kernels, as well, by editing the volk_config file; or they could
+be used to compare performance between different machines and/or
+processors.
+
+
+======================================================================
+Volk Profiling
+
+Before doing any kind of Volk benchmarking, it is important to run the
+volk_profile program. The profiler will build a config file for the
+best SIMD architecture for your processor. Run volk_profile that is
+installed into $PREFIX/bin. This program tests all known Volk kernels
+for each proto-kernel supported by the processor. When finished, it
+will write to $HOME/.volk/volk_config the best architecture for the
+VOLK function. This file is read when using a function to know the
+best version of the function to execute.
+
+The volk_config file contains a line for each kernel, where each line
+looks like:
+
+ volk_<KERNEL_NAME> <ARCHITECTURE>
+
+The architecture will be something like (sse, sse2, sse3, avx, neon,
+etc.), depending on your processor.
+
+
+======================================================================
+Benchmark Tests
+
+There are currently two benchmark scripts defined for collecting
+data. There is one that runs through the type conversions that have
+been converted to Volk (volk_types.py) and the other runs through the
+math operators converted to using Volk (volk_math.py).
+
+Script prototypes
+Both have the same structure for use:
+
+----------------------------------------------------------------------
+./volk_<test>.py [-h] -L LABEL [-D DATABASE] [-N NITEMS] [-I ITERATIONS]
+ [--tests [{0,1,2,3} [{0,1,2,3} ...]]] [--list]
+ [--all]
+
+optional arguments:
+ -h, --help show this help message and exit
+ -L LABEL, --label LABEL
+ Label of database table [default: None]
+ -D DATABASE, --database DATABASE
+ Database file to store data in [default:
+ volk_results.db]
+ -N NITEMS, --nitems NITEMS
+ Number of items per iterations [default: 1000000000.0]
+ -I ITERATIONS, --iterations ITERATIONS
+ Number of iterations [default: 20]
+ --tests [{0,1,2,3} [{0,1,2,3} ...]]
+ A list of tests to run; can be a single test or a
+ space-separated list.
+ --list List the available tests
+ --all Run all tests
+----------------------------------------------------------------------
+
+To run, you specify the tests to run and a label to store along with
+the results. To find out what the available tests are, use the
+'--list' option.
+
+To specify a subset of tests, use the '--tests' with space-separated
+list of tests numbers (e.g., --tests 0 2 4 9).
+
+Use the '--all' to run all tests.
+
+The label specified is used as an identifier for the benchmarking
+currently being done. This is required as it is important in
+organizing the data in the database (each label is its own
+table). Usually, the label will specify the type of run being done,
+such as "volk_aligned" or "v3_5_1". In these cases, the "volk_aligned"
+label says that this is for a benchmarking using the GNU Radio version
+that uses the aligned scheduler and Volk calls in the work
+functions. The "v3_5_1" label is if you were benchmarking an installed
+version 3.5.1 of GNU Radio, which is pre-Volk. These will then be
+plotted against each other to see the timing differences.
+
+The 'database' option will output the results to a new database
+file. This can be useful for separating the output of different runs
+or of different benchmarks, such as the types versus the math scripts,
+say, or to distinguish results from different computers.
+
+If rerun using the same database and label, the entries in the table
+will simply be replaced by the new results.
+
+It is often useful to use the 'sqlitebrowser' program to interrogate
+the database file farther, if you are interested in the structure or
+the raw data.
+
+Other parameters of this script set the number of items to process and
+number of iterations to use when computing the benchmarking
+data. These default to 1 billion samples per iteration over 20
+iterations. Expect a default run to take a long time. Using the '-N'
+and '-I' options can be used to change the runtime of the benchmarks
+but are set high to remove problems of variance between iterations.
+
+======================================================================
+Plotting Results
+
+The volk_plot.py script reads a given database file and plots the
+results. The default behavior is to read all of the labels stored in
+the database and plot them as data sets on a bar graph. This shows the
+average time taken to process the number of items given.
+
+The options for the plotting script are:
+
+usage: volk_plot.py [-h] [-D DATABASE] [-E] [-P {mean,min,max}] [-% table]
+
+Plot Volk performance results from a SQLite database. Run one of the volk
+tests first (e.g, volk_math.py)
+
+----------------------------------------------------------------------
+optional arguments:
+ -h, --help show this help message and exit
+ -D DATABASE, --database DATABASE
+ Database file to read data from [default:
+ volk_results.db]
+ -E, --errorbars Show error bars (1 standard dev.)
+ -P {mean,min,max}, --plot {mean,min,max}
+ Set the type of plot to produce [default: mean]
+ -% table, --percent table
+ Show percent difference to the given type [default:
+ None]
+----------------------------------------------------------------------
+
+This script allows you to specify the database used (-D), but will
+always read all rows from all tables from it and display them. You can
+also turn on plotting error bars (1 standard deviation the mean). Be
+careful, though, as some older versions of Matplotlib might have an
+issue with this option.
+
+The mean time is only one possible statistic that we might be
+interested in when looking at the data. It represents the average user
+experience when running a given block. On the other hand, the minimum
+runtime best represents the actual performance of a block given
+minimal OS interruptions while running. Right now, the data collected
+includes the mean, variance, min, and max over the number of
+iterations given. Using the '-P' option, you can specify the type of
+data to plot (mean, min, or max).
+
+Another useful way of looking at the data is to compare the percent
+improvement of a benchmark compared to another. This is done using the
+'-%' option with the provided table (or label) as the baseline. So if
+we were interested in comparing how much the 'volk_aligned' was over
+'v3_5_1', we would specify '-% v3_5_1' to see this. The plot would
+then only show the percent speedup observed using Volk for each of the
+blocks.
+
+
+======================================================================
+Benchmarking Walkthrough
+
+This will walk through an example of benchmarking the new Volk
+implementation versus the pre-Volk GNU Radio. It also shows how to
+look at the SIMD optimized versions versus the generic
+implementations.
+
+Since we introduced Volk in GNU Radio 3.5.2, we will use the following
+labels for our data:
+
+ 1.) volk_aligned: v3.5.2 with volk_profile results in .volk/volk_config
+ 2.) v3_5_2: v3.5.2 with the generic (non-SIMD) calls to Volk
+ 3.) v3_5_1: an installation of GNU Radio from version v3.5.1
+
+We assume that we have installed two versions of GNU Radio.
+
+ v3.5.2 installed into /opt/gr-3_5_2
+ v3.5.1 installed into /opt/gr-3_5_1
+
+To test cases 1 and 2 above, we have to run GNU Radio from the v3.5.2
+installation, so we set the following environmental variables. Note
+that this is written for Ubuntu 11.10. These commands and directories
+may have to be changed depending on your OS and versions.
+
+ export LD_LIBRARY_PATH=/opt/gr-3_5_2/lib
+ export LD_LIBRARY_PATH=/opt/gr-3_5_2/lib/python2.7/dist-packages
+
+Now we can run the benchmark tests, so we will focus on the math
+operators:
+
+ ./volk_math.py -D volk_results_math.db --all -L volk_aligned
+
+When this finishes, the 'volk_results_math.db' will contain our
+results for this run.
+
+We next want to run the generic, non-SIMD, calls. This can be done by
+changing the Volk kernel settings in $HOME/.volk/volk_config. First,
+make a backup of this file. Then edit it and change all architecture
+calls (sse, sse2, etc.) to 'generic.' Now, Volk will only call the
+generic versions of these functions. So we rerun the benchmark with:
+
+ ./volk_math.py -D volk_results_math.db --all -L v3_5_2
+
+Notice that the only thing changed here was the label to 'v3_5_2'.
+
+Next, we want to collect data for the non-Volk version of GNU
+Radio. This is important because some internals to GNU Radio were made
+when adding support for Volk, so it is nice to know what the
+differences do to our performance. First, we set the environmental
+variables to point to the v3.5.1 installation:
+
+ export LD_LIBRARY_PATH=/opt/gr-3_5_1/lib
+ export LD_LIBRARY_PATH=/opt/gr-3_5_1/lib/python2.7/dist-packages
+
+And when we run the test, we use the same command line, but the GNU
+Radio libraries and Python files used come from v3.5.1. We also change
+the label to indicate the different version to store.
+
+ ./volk_math.py -D volk_results_math.db --all -L v3_5_1
+
+We now have a database populated with three tables for the three
+different labels. We can plot them all together by simply running:
+
+ ./volk_plot.py -D volk_results_math.db
+
+This will show the average run times for each of the three
+configurations for all math functions tested. We might also be
+interested to see the difference in performance from the v3.5.1
+version, so we can run:
+
+ ./volk_plot.py -D volk_results_math.db -% v3_5_1
+
+That will plot both the 'volk_aligned' and 'v3_5_2' as a percentage
+improvement over v3_5_1. A positive value indicates that this version
+runs faster than the v3.5.1 version.
+
+
+----------------------------------------------------------------------
+
+Another interesting test case could be to compare results on different
+processors. So if you have different generation Intels, AMD, or
+whatever, you can simply pass the .db file around and run the Volk
+benchmark script to populate the database with different results. For
+this, you would specify a label like '-L i7_2620M' that indicates the
+processor type to uniquely ID the data.
+
diff --git a/gnuradio-runtime/examples/volk_benchmark/volk_math.py b/gnuradio-runtime/examples/volk_benchmark/volk_math.py
new file mode 100755
index 0000000000..753257c237
--- /dev/null
+++ b/gnuradio-runtime/examples/volk_benchmark/volk_math.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python
+
+from gnuradio import gr
+from gnuradio import blocks
+import argparse
+from volk_test_funcs import *
+
+try:
+ from gnuradio import blocks
+except ImportError:
+ sys.stderr.write("This example requires gr-blocks.\n")
+
+def multiply_const_cc(N):
+ k = 3.3
+ op = blocks.multiply_const_cc(k)
+ tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 1, 1)
+ return tb
+
+######################################################################
+
+def multiply_const_ff(N):
+ k = 3.3
+ op = blocks.multiply_const_ff(k)
+ tb = helper(N, op, gr.sizeof_float, gr.sizeof_float, 1, 1)
+ return tb
+
+######################################################################
+
+def multiply_cc(N):
+ op = blocks.multiply_cc(1)
+ tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 2, 1)
+ return tb
+
+######################################################################
+
+def multiply_ff(N):
+ op = blocks.multiply_ff()
+ tb = helper(N, op, gr.sizeof_float, gr.sizeof_float, 2, 1)
+ return tb
+
+######################################################################
+
+def add_ff(N):
+ op = blocks.add_ff()
+ tb = helper(N, op, gr.sizeof_float, gr.sizeof_float, 2, 1)
+ return tb
+
+######################################################################
+
+def conjugate_cc(N):
+ op = blocks.conjugate_cc()
+ tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 1, 1)
+ return tb
+
+######################################################################
+
+def multiply_conjugate_cc(N):
+ try:
+ op = blocks.multiply_conjugate_cc()
+ tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 2, 1)
+ return tb
+
+ except AttributeError:
+ class s(gr.hier_block2):
+ def __init__(self):
+ gr.hier_block2.__init__(self, "s",
+ gr.io_signature(2, 2, gr.sizeof_gr_complex),
+ gr.io_signature(1, 1, gr.sizeof_gr_complex))
+ conj = blocks.conjugate_cc()
+ mult = blocks.multiply_cc()
+ self.connect((self,0), (mult,0))
+ self.connect((self,1), conj, (mult,1))
+ self.connect(mult, self)
+
+ op = s()
+ tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 2, 1)
+ return tb
+
+
+######################################################################
+
+def run_tests(func, N, iters):
+ print("Running Test: {0}".format(func.__name__))
+ try:
+ tb = func(N)
+ t = timeit(tb, iters)
+ res = format_results(func.__name__, t)
+ return res
+ except AttributeError:
+ print "\tCould not run test. Skipping."
+ return None
+
+def main():
+ avail_tests = [multiply_const_cc,
+ multiply_const_ff,
+ multiply_cc,
+ multiply_ff,
+ add_ff,
+ conjugate_cc,
+ multiply_conjugate_cc]
+
+ desc='Time an operation to compare with other implementations. \
+ This program runs a simple GNU Radio flowgraph to test a \
+ particular math function, mostly to compare the \
+ Volk-optimized implementation versus a regular \
+ implementation. The results are stored to an SQLite database \
+ that can then be read by volk_plot.py to plot the differences.'
+ parser = argparse.ArgumentParser(description=desc)
+ parser.add_argument('-L', '--label', type=str,
+ required=True, default=None,
+ help='Label of database table [default: %(default)s]')
+ parser.add_argument('-D', '--database', type=str,
+ default="volk_results.db",
+ help='Database file to store data in [default: %(default)s]')
+ parser.add_argument('-N', '--nitems', type=float,
+ default=1e9,
+ help='Number of items per iterations [default: %(default)s]')
+ parser.add_argument('-I', '--iterations', type=int,
+ default=20,
+ help='Number of iterations [default: %(default)s]')
+ parser.add_argument('--tests', type=int, nargs='*',
+ choices=xrange(len(avail_tests)),
+ help='A list of tests to run; can be a single test or a \
+ space-separated list.')
+ parser.add_argument('--list', action='store_true',
+ help='List the available tests')
+ parser.add_argument('--all', action='store_true',
+ help='Run all tests')
+ args = parser.parse_args()
+
+ if(args.list):
+ print "Available Tests to Run:"
+ print "\n".join(["\t{0}: {1}".format(i,f.__name__) for i,f in enumerate(avail_tests)])
+ sys.exit(0)
+
+ N = int(args.nitems)
+ iters = args.iterations
+ label = args.label
+
+ conn = create_connection(args.database)
+ new_table(conn, label)
+
+ if args.all:
+ tests = xrange(len(avail_tests))
+ else:
+ tests = args.tests
+
+ for test in tests:
+ res = run_tests(avail_tests[test], N, iters)
+ if res is not None:
+ replace_results(conn, label, N, iters, res)
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
diff --git a/gnuradio-runtime/examples/volk_benchmark/volk_plot.py b/gnuradio-runtime/examples/volk_benchmark/volk_plot.py
new file mode 100755
index 0000000000..48f9922054
--- /dev/null
+++ b/gnuradio-runtime/examples/volk_benchmark/volk_plot.py
@@ -0,0 +1,169 @@
+#!/usr/bin/env python
+
+import sys, math
+import argparse
+from volk_test_funcs import *
+
+try:
+ import matplotlib
+ import matplotlib.pyplot as plt
+except ImportError:
+ sys.stderr.write("Could not import Matplotlib (http://matplotlib.sourceforge.net/)\n")
+ sys.exit(1)
+
+def main():
+ desc='Plot Volk performance results from a SQLite database. ' + \
+ 'Run one of the volk tests first (e.g, volk_math.py)'
+ parser = argparse.ArgumentParser(description=desc)
+ parser.add_argument('-D', '--database', type=str,
+ default='volk_results.db',
+ help='Database file to read data from [default: %(default)s]')
+ parser.add_argument('-E', '--errorbars',
+ action='store_true', default=False,
+ help='Show error bars (1 standard dev.)')
+ parser.add_argument('-P', '--plot', type=str,
+ choices=['mean', 'min', 'max'],
+ default='mean',
+ help='Set the type of plot to produce [default: %(default)s]')
+ parser.add_argument('-%', '--percent', type=str,
+ default=None, metavar="table",
+ help='Show percent difference to the given type [default: %(default)s]')
+ args = parser.parse_args()
+
+ # Set up global plotting properties
+ matplotlib.rcParams['figure.subplot.bottom'] = 0.2
+ matplotlib.rcParams['figure.subplot.top'] = 0.95
+ matplotlib.rcParams['figure.subplot.right'] = 0.98
+ matplotlib.rcParams['ytick.labelsize'] = 16
+ matplotlib.rcParams['xtick.labelsize'] = 16
+ matplotlib.rcParams['legend.fontsize'] = 18
+
+ # Get list of tables to compare
+ conn = create_connection(args.database)
+ tables = list_tables(conn)
+ M = len(tables)
+
+ # Colors to distinguish each table in the bar graph
+ # More than 5 tables will wrap around to the start.
+ colors = ['b', 'r', 'g', 'm', 'k']
+
+ # Set up figure for plotting
+ f0 = plt.figure(0, facecolor='w', figsize=(14,10))
+ s0 = f0.add_subplot(1,1,1)
+
+ # Create a register of names that exist in all tables
+ tmp_regs = []
+ for table in tables:
+ # Get results from the next table
+ res = get_results(conn, table[0])
+
+ tmp_regs.append(list())
+ for r in res:
+ try:
+ tmp_regs[-1].index(r['kernel'])
+ except ValueError:
+ tmp_regs[-1].append(r['kernel'])
+
+ # Get only those names that are common in all tables
+ name_reg = tmp_regs[0]
+ for t in tmp_regs[1:]:
+ name_reg = list(set(name_reg) & set(t))
+ name_reg.sort()
+
+ # Pull the data out for each table into a dictionary
+ # we can ref the table by it's name and the data associated
+ # with a given kernel in name_reg by it's name.
+ # This ensures there is no sorting issue with the data in the
+ # dictionary, so the kernels are plotted against each other.
+ table_data = dict()
+ for i,table in enumerate(tables):
+ # Get results from the next table
+ res = get_results(conn, table[0])
+
+ data = dict()
+ for r in res:
+ data[r['kernel']] = r
+
+ table_data[table[0]] = data
+
+ if args.percent is not None:
+ for i,t in enumerate(table_data):
+ if args.percent == t:
+ norm_data = []
+ for name in name_reg:
+ if(args.plot == 'max'):
+ norm_data.append(table_data[t][name]['max'])
+ elif(args.plot == 'min'):
+ norm_data.append(table_data[t][name]['min'])
+ elif(args.plot == 'mean'):
+ norm_data.append(table_data[t][name]['avg'])
+
+
+ # Plot the results
+ x0 = xrange(len(name_reg))
+ i = 0
+ for t in (table_data):
+ ydata = []
+ stds = []
+ for name in name_reg:
+ stds.append(math.sqrt(table_data[t][name]['var']))
+ if(args.plot == 'max'):
+ ydata.append(table_data[t][name]['max'])
+ elif(args.plot == 'min'):
+ ydata.append(table_data[t][name]['min'])
+ elif(args.plot == 'mean'):
+ ydata.append(table_data[t][name]['avg'])
+
+ if args.percent is not None:
+ ydata = [-100*(y-n)/y for y,n in zip(ydata,norm_data)]
+ if(args.percent != t):
+ # makes x values for this data set placement
+ # width of bars depends on number of comparisons
+ wdth = 0.80/(M-1)
+ x1 = [x + i*wdth for x in x0]
+ i += 1
+
+ s0.bar(x1, ydata, width=wdth,
+ color=colors[(i-1)%M], label=t,
+ edgecolor='k', linewidth=2)
+
+ else:
+ # makes x values for this data set placement
+ # width of bars depends on number of comparisons
+ wdth = 0.80/M
+ x1 = [x + i*wdth for x in x0]
+ i += 1
+
+ if(args.errorbars is False):
+ s0.bar(x1, ydata, width=wdth,
+ color=colors[(i-1)%M], label=t,
+ edgecolor='k', linewidth=2)
+ else:
+ s0.bar(x1, ydata, width=wdth,
+ yerr=stds,
+ color=colors[i%M], label=t,
+ edgecolor='k', linewidth=2,
+ error_kw={"ecolor": 'k', "capsize":5,
+ "linewidth":2})
+
+ nitems = res[0]['nitems']
+ if args.percent is None:
+ s0.set_ylabel("Processing time (sec) [{0:G} items]".format(nitems),
+ fontsize=22, fontweight='bold',
+ horizontalalignment='center')
+ else:
+ s0.set_ylabel("% Improvement over {0} [{1:G} items]".format(
+ args.percent, nitems),
+ fontsize=22, fontweight='bold')
+
+ s0.legend()
+ s0.set_xticks(x0)
+ s0.set_xticklabels(name_reg)
+ for label in s0.xaxis.get_ticklabels():
+ label.set_rotation(45)
+ label.set_fontsize(16)
+
+ plt.show()
+
+if __name__ == "__main__":
+ main()
diff --git a/gnuradio-runtime/examples/volk_benchmark/volk_test_funcs.py b/gnuradio-runtime/examples/volk_benchmark/volk_test_funcs.py
new file mode 100644
index 0000000000..0f2c84100a
--- /dev/null
+++ b/gnuradio-runtime/examples/volk_benchmark/volk_test_funcs.py
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+
+from gnuradio import gr
+from gnuradio import blocks
+import math, sys, os, time
+
+try:
+ import scipy
+except ImportError:
+ sys.stderr.write("Unable to import Scipy (www.scipy.org)\n")
+ sys.exit(1)
+
+try:
+ import sqlite3
+except ImportError:
+ sys.stderr.write("Unable to import sqlite3: requires Python 2.5\n")
+ sys.exit(1)
+
+def execute(conn, cmd):
+ '''
+ Executes the command cmd to the database opened in connection conn.
+ '''
+ c = conn.cursor()
+ c.execute(cmd)
+ conn.commit()
+ c.close()
+
+def create_connection(database):
+ '''
+ Returns a connection object to the SQLite database.
+ '''
+ return sqlite3.connect(database)
+
+def new_table(conn, tablename):
+ '''
+ Create a new table for results.
+ All results are in the form: [kernel | nitems | iters | avg. time | variance | max time | min time ]
+ Each table is meant as a different setting (e.g., volk_aligned, volk_unaligned, etc.)
+ '''
+ cols = "kernel text, nitems int, iters int, avg real, var real, max real, min real"
+ cmd = "create table if not exists {0} ({1})".format(
+ tablename, cols)
+ execute(conn, cmd)
+
+def replace_results(conn, tablename, nitems, iters, res):
+ '''
+ Inserts or replaces the results 'res' dictionary values into the table.
+ This deletes all old entries of the kernel in this table.
+ '''
+ cmd = "DELETE FROM {0} where kernel='{1}'".format(tablename, res["kernel"])
+ execute(conn, cmd)
+ insert_results(conn, tablename, nitems, iters, res)
+
+def insert_results(conn, tablename, nitems, iters, res):
+ '''
+ Inserts the results dictionary values into the table.
+ '''
+ cols = "kernel, nitems, iters, avg, var, max, min"
+ cmd = "INSERT INTO {0} ({1}) VALUES ('{2}', {3}, {4}, {5}, {6}, {7}, {8})".format(
+ tablename, cols, res["kernel"], nitems, iters,
+ res["avg"], res["var"], res["max"], res["min"])
+ execute(conn, cmd)
+
+def list_tables(conn):
+ '''
+ Returns a list of all tables in the database.
+ '''
+ cmd = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"
+ c = conn.cursor()
+ c.execute(cmd)
+ t = c.fetchall()
+ c.close()
+
+ return t
+
+def get_results(conn, tablename):
+ '''
+ Gets all results in tablename.
+ '''
+ cmd = "SELECT * FROM {0}".format(tablename)
+ c = conn.cursor()
+ c.execute(cmd)
+ fetched = c.fetchall()
+ c.close()
+
+ res = list()
+ for f in fetched:
+ r = dict()
+ r['kernel'] = f[0]
+ r['nitems'] = f[1]
+ r['iters'] = f[2]
+ r['avg'] = f[3]
+ r['var'] = f[4]
+ r['min'] = f[5]
+ r['max'] = f[6]
+ res.append(r)
+
+ return res
+
+
+class helper(gr.top_block):
+ '''
+ Helper function to run the tests. The parameters are:
+ N: number of items to process (int)
+ op: The GR block/hier_block to test
+ isizeof: the sizeof the input type
+ osizeof: the sizeof the output type
+ nsrcs: number of inputs to the op
+ nsnks: number of outputs of the op
+
+ This function can only handle blocks where all inputs are the same
+ datatype and all outputs are the same data type
+ '''
+ def __init__(self, N, op,
+ isizeof=gr.sizeof_gr_complex,
+ osizeof=gr.sizeof_gr_complex,
+ nsrcs=1, nsnks=1):
+ gr.top_block.__init__(self, "helper")
+
+ self.op = op
+ self.srcs = []
+ self.snks = []
+ self.head = blocks.head(isizeof, N)
+
+ for n in xrange(nsrcs):
+ self.srcs.append(blocks.null_source(isizeof))
+
+ for n in xrange(nsnks):
+ self.snks.append(blocks.null_sink(osizeof))
+
+ self.connect(self.srcs[0], self.head, (self.op,0))
+
+ for n in xrange(1, nsrcs):
+ self.connect(self.srcs[n], (self.op,n))
+
+ for n in xrange(nsnks):
+ self.connect((self.op,n), self.snks[n])
+
+def timeit(tb, iterations):
+ '''
+ Given a top block, this function times it for a number of
+ iterations and stores the time in a list that is returned.
+ '''
+ r = gr.enable_realtime_scheduling()
+ if r != gr.RT_OK:
+ print "Warning: failed to enable realtime scheduling"
+
+ times = []
+ for i in xrange(iterations):
+ start_time = time.time()
+ tb.run()
+ end_time = time.time()
+ tb.head.reset()
+
+ times.append(end_time - start_time)
+
+ return times
+
+def format_results(kernel, times):
+ '''
+ Convinience function to convert the results of the timeit function
+ into a dictionary.
+ '''
+ res = dict()
+ res["kernel"] = kernel
+ res["avg"] = scipy.mean(times)
+ res["var"] = scipy.var(times)
+ res["max"] = max(times)
+ res["min"] = min(times)
+ return res
+
+
diff --git a/gnuradio-runtime/examples/volk_benchmark/volk_types.py b/gnuradio-runtime/examples/volk_benchmark/volk_types.py
new file mode 100755
index 0000000000..e8db14aff7
--- /dev/null
+++ b/gnuradio-runtime/examples/volk_benchmark/volk_types.py
@@ -0,0 +1,169 @@
+#!/usr/bin/env python
+
+from gnuradio import gr
+from gnuradio import blocks
+import argparse
+from volk_test_funcs import *
+
+######################################################################
+
+def float_to_char(N):
+ op = blocks.float_to_char()
+ tb = helper(N, op, gr.sizeof_float, gr.sizeof_char, 1, 1)
+ return tb
+
+######################################################################
+
+def float_to_int(N):
+ op = blocks.float_to_int()
+ tb = helper(N, op, gr.sizeof_float, gr.sizeof_int, 1, 1)
+ return tb
+
+######################################################################
+
+def float_to_short(N):
+ op = blocks.float_to_short()
+ tb = helper(N, op, gr.sizeof_float, gr.sizeof_short, 1, 1)
+ return tb
+
+######################################################################
+
+def short_to_float(N):
+ op = blocks.short_to_float()
+ tb = helper(N, op, gr.sizeof_short, gr.sizeof_float, 1, 1)
+ return tb
+
+######################################################################
+
+def short_to_char(N):
+ op = blocks.short_to_char()
+ tb = helper(N, op, gr.sizeof_short, gr.sizeof_char, 1, 1)
+ return tb
+
+######################################################################
+
+def int_to_float(N):
+ op = blocks.int_to_float()
+ tb = helper(N, op, gr.sizeof_int, gr.sizeof_float, 1, 1)
+ return tb
+
+######################################################################
+
+def complex_to_float(N):
+ op = blocks.complex_to_float()
+ tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 2)
+ return tb
+
+######################################################################
+
+def complex_to_real(N):
+ op = blocks.complex_to_real()
+ tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1)
+ return tb
+
+######################################################################
+
+def complex_to_imag(N):
+ op = blocks.complex_to_imag()
+ tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1)
+ return tb
+
+######################################################################
+
+def complex_to_mag(N):
+ op = blocks.complex_to_mag()
+ tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1)
+ return tb
+
+######################################################################
+
+def complex_to_mag_squared(N):
+ op = blocks.complex_to_mag_squared()
+ tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1)
+ return tb
+
+######################################################################
+
+
+def run_tests(func, N, iters):
+ print("Running Test: {0}".format(func.__name__))
+ try:
+ tb = func(N)
+ t = timeit(tb, iters)
+ res = format_results(func.__name__, t)
+ return res
+ except AttributeError:
+ print "\tCould not run test. Skipping."
+ return None
+
+def main():
+ avail_tests = [float_to_char,
+ float_to_int,
+ float_to_short,
+ short_to_float,
+ short_to_char,
+ char_to_short,
+ char_to_float,
+ int_to_float,
+ complex_to_float,
+ complex_to_real,
+ complex_to_imag,
+ complex_to_mag,
+ complex_to_mag_squared]
+
+ desc='Time an operation to compare with other implementations. \
+ This program runs a simple GNU Radio flowgraph to test a \
+ particular math function, mostly to compare the \
+ Volk-optimized implementation versus a regular \
+ implementation. The results are stored to an SQLite database \
+ that can then be read by volk_plot.py to plot the differences.'
+ parser = argparse.ArgumentParser(description=desc)
+ parser.add_argument('-L', '--label', type=str,
+ required=True, default=None,
+ help='Label of database table [default: %(default)s]')
+ parser.add_argument('-D', '--database', type=str,
+ default="volk_results.db",
+ help='Database file to store data in [default: %(default)s]')
+ parser.add_argument('-N', '--nitems', type=float,
+ default=1e9,
+ help='Number of items per iterations [default: %(default)s]')
+ parser.add_argument('-I', '--iterations', type=int,
+ default=20,
+ help='Number of iterations [default: %(default)s]')
+ parser.add_argument('--tests', type=int, nargs='*',
+ choices=xrange(len(avail_tests)),
+ help='A list of tests to run; can be a single test or a \
+ space-separated list.')
+ parser.add_argument('--list', action='store_true',
+ help='List the available tests')
+ parser.add_argument('--all', action='store_true',
+ help='Run all tests')
+ args = parser.parse_args()
+
+ if(args.list):
+ print "Available Tests to Run:"
+ print "\n".join(["\t{0}: {1}".format(i,f.__name__) for i,f in enumerate(avail_tests)])
+ sys.exit(0)
+
+ N = int(args.nitems)
+ iters = args.iterations
+ label = args.label
+
+ conn = create_connection(args.database)
+ new_table(conn, label)
+
+ if args.all:
+ tests = xrange(len(avail_tests))
+ else:
+ tests = args.tests
+
+ for test in tests:
+ res = run_tests(avail_tests[test], N, iters)
+ if res is not None:
+ replace_results(conn, label, N, iters, res)
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
diff --git a/gnuradio-runtime/gnuradio-runtime.conf.in b/gnuradio-runtime/gnuradio-runtime.conf.in
new file mode 100644
index 0000000000..d41801aa23
--- /dev/null
+++ b/gnuradio-runtime/gnuradio-runtime.conf.in
@@ -0,0 +1,39 @@
+# This file contains system wide configuration data for GNU Radio.
+# You may override any setting on a per-user basis by editing
+# ~/.gnuradio/config.conf
+
+[DEFAULT]
+verbose = False
+
+# The maximum number of messages a block will store up before pruning
+# the queue by popping messages from the front.
+max_messages = 100
+
+
+[LOG]
+# Levels can be (case insensitive):
+# DEBUG, INFO, WARN, TRACE, ERROR, ALERT, CRIT, FATAL, EMERG
+log_level = debug
+debug_level = emerg
+
+# These file names can either be 'stdout' to output to standard output
+# or 'stderr' to output to standard error. Any other string will
+# create a file in which to output the logging information. An empty
+# string or no value here will ignore this level of configuration
+# completely.
+log_file = stdout
+debug_file = stderr
+
+# Used for advanced configuration of the logger
+#log_config = @CMAKE_INSTALL_PREFIX@/etc/gnuradio/gr_log_default.xml
+
+
+[PerfCounters]
+on = False
+export = True
+
+
+[ControlPort]
+on = False
+edges_list = False
+config = # @CMAKE_INSTALL_PREFIX@/etc/gnuradio/ctrlport.conf
diff --git a/gnuradio-runtime/gnuradio-runtime.pc.in b/gnuradio-runtime/gnuradio-runtime.pc.in
new file mode 100644
index 0000000000..ede19cbba4
--- /dev/null
+++ b/gnuradio-runtime/gnuradio-runtime.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: gnuradio-runtime
+Description: GNU Radio core runtime infrastructure
+Requires:
+Version: @LIBVER@
+Libs: -L${libdir} -lgnuradio-runtime
+Cflags: -I${includedir}
diff --git a/gnuradio-runtime/gr_log_default.conf b/gnuradio-runtime/gr_log_default.conf
new file mode 100644
index 0000000000..79c2d91e94
--- /dev/null
+++ b/gnuradio-runtime/gr_log_default.conf
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2006,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.
+ */
+
+log4j.rootCategory=EMERG,A1
+log4j.category.gr_log=DEBUG,A2
+log4j.category.gr_log_debug=NOTSET,A3
+
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+log4j.appender.A1.target=System.out
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=Root :%p: %c{1} - %m%n
+
+log4j.appender.A2=org.apache.log4j.ConsoleAppender
+log4j.appender.A2.target=System.out
+log4j.appender.A2.layout=org.apache.log4j.PatternLayout
+log4j.appender.A2.layout.ConversionPattern=gr::log :%p: %c{1} - %m%n
+
+log4j.appender.A3=org.apache.log4j.ConsoleAppender
+log4j.appender.A3.target=System.out
+log4j.appender.A3.layout=org.apache.log4j.PatternLayout
+log4j.appender.A3.layout.ConversionPattern=gr::debug :%p: %c{1} - %m%n
+
diff --git a/gnuradio-runtime/include/CMakeLists.txt b/gnuradio-runtime/include/CMakeLists.txt
new file mode 100644
index 0000000000..77b284705a
--- /dev/null
+++ b/gnuradio-runtime/include/CMakeLists.txt
@@ -0,0 +1,92 @@
+# 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.
+
+########################################################################
+# Install header files
+########################################################################
+install(FILES
+ gr_basic_block.h
+ gr_block_detail.h
+ gr_block.h
+ gr_block_registry.h
+ gr_buffer.h
+ gr_complex.h
+ gr_constants.h
+ gr_dispatcher.h
+ gr_endianness.h
+ gr_error_handler.h
+ gr_expj.h
+ gr_feval.h
+ gr_flowgraph.h
+ gr_fxpt.h
+ gr_fxpt_nco.h
+ gr_fxpt_vco.h
+ gr_hier_block2.h
+ gr_io_signature.h
+ gr_logger.h
+ gr_math.h
+ gr_message.h
+ gr_misc.h
+ gr_msg_accepter.h
+ gr_msg_handler.h
+ gr_msg_queue.h
+ gr_nco.h
+ gr_preferences.h
+ gr_prefs.h
+ gr_py_feval.h
+ gr_random.h
+ gr_realtime.h
+ gr_runtime_api.h
+ gr_runtime_types.h
+ gr_select_handler.h
+ gr_sincos.h
+ gr_single_threaded_scheduler.h
+ gr_sptr_magic.h
+ gr_sync_block.h
+ gr_sync_decimator.h
+ gr_sync_interpolator.h
+ gr_sys_paths.h
+ gr_tagged_stream_block.h
+ gr_tags.h
+ gr_timer.h
+ gr_top_block.h
+ gr_tpb_detail.h
+ gr_types.h
+ gr_unittests.h
+ ice_application_base.h
+ IcePy_Communicator.h
+ ice_server_template.h
+ pycallback_object.h
+ random.h
+ rpccallbackregister_base.h
+ rpcmanager_base.h
+ rpcmanager.h
+ rpcpmtconverters_ice.h
+ rpcregisterhelpers.h
+ rpcserver_aggregator.h
+ rpcserver_base.h
+ rpcserver_booter_aggregator.h
+ rpcserver_booter_base.h
+ rpcserver_booter_ice.h
+ rpcserver_ice.h
+ rpcserver_selector.h
+ runtime_block_gateway.h
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio
+ COMPONENT "runtime_devel"
+)
diff --git a/gnuradio-runtime/include/IcePy_Communicator.h b/gnuradio-runtime/include/IcePy_Communicator.h
new file mode 100644
index 0000000000..aae4378229
--- /dev/null
+++ b/gnuradio-runtime/include/IcePy_Communicator.h
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#ifndef ICEPY_COMMUNICATOR_H
+#define ICEPY_COMMUNICATOR_H
+
+#include <Ice/CommunicatorF.h>
+#include <gr_runtime_api.h>
+
+namespace IcePy
+{
+
+extern PyTypeObject CommunicatorType;
+
+GR_RUNTIME_API bool initCommunicator(PyObject*);
+
+GR_RUNTIME_API Ice::CommunicatorPtr getCommunicator(PyObject*);
+
+GR_RUNTIME_API PyObject* createCommunicator(const Ice::CommunicatorPtr&);
+GR_RUNTIME_API PyObject* getCommunicatorWrapper(const Ice::CommunicatorPtr&);
+
+}
+
+extern "C" PyObject* IcePy_initialize(PyObject*, PyObject*);
+extern "C" PyObject* IcePy_initializeWithProperties(PyObject*, PyObject*);
+extern "C" PyObject* IcePy_initializeWithLogger(PyObject*, PyObject*);
+extern "C" PyObject* IcePy_initializeWithPropertiesAndLogger(PyObject*, PyObject*);
+
+#endif
diff --git a/gnuradio-runtime/include/gr_basic_block.h b/gnuradio-runtime/include/gr_basic_block.h
new file mode 100644
index 0000000000..1fa8bb9d7a
--- /dev/null
+++ b/gnuradio-runtime/include/gr_basic_block.h
@@ -0,0 +1,344 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,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 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_BASIC_BLOCK_H
+#define INCLUDED_GR_BASIC_BLOCK_H
+
+#include <gr_runtime_api.h>
+#include <gr_runtime_types.h>
+#include <gr_sptr_magic.h>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/function.hpp>
+#include <gr_msg_accepter.h>
+#include <string>
+#include <deque>
+#include <map>
+#include <gr_io_signature.h>
+#include <gruel/thread.h>
+#include <boost/foreach.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <iostream>
+
+#ifdef GR_CTRLPORT
+#include <rpcregisterhelpers.h>
+#endif
+
+/*!
+ * \brief The abstract base class for all signal processing blocks.
+ * \ingroup internal
+ *
+ * Basic blocks are the bare abstraction of an entity that has a name,
+ * a set of inputs and outputs, and a message queue. These are never instantiated
+ * directly; rather, this is the abstract parent class of both gr_hier_block,
+ * which is a recursive container, and gr_block, which implements actual
+ * signal processing functions.
+ */
+
+class GR_RUNTIME_API gr_basic_block : public gr_msg_accepter, public boost::enable_shared_from_this<gr_basic_block>
+{
+ typedef boost::function<void(pmt::pmt_t)> msg_handler_t;
+
+ private:
+
+ //msg_handler_t d_msg_handler;
+ typedef std::map<pmt::pmt_t , msg_handler_t, pmt::comperator> d_msg_handlers_t;
+ d_msg_handlers_t d_msg_handlers;
+
+ typedef std::deque<pmt::pmt_t> msg_queue_t;
+ typedef std::map<pmt::pmt_t, msg_queue_t, pmt::comperator> msg_queue_map_t;
+ typedef std::map<pmt::pmt_t, msg_queue_t, pmt::comperator>::iterator msg_queue_map_itr;
+ std::map<pmt::pmt_t, boost::shared_ptr<boost::condition_variable>, pmt::comperator> msg_queue_ready;
+
+ gruel::mutex mutex; //< protects all vars
+
+ protected:
+ friend class gr_flowgraph;
+ friend class gr_flat_flowgraph; // TODO: will be redundant
+ friend class gr_tpb_thread_body;
+
+ enum vcolor { WHITE, GREY, BLACK };
+
+ std::string d_name;
+ gr_io_signature_sptr d_input_signature;
+ gr_io_signature_sptr d_output_signature;
+ long d_unique_id;
+ long d_symbolic_id;
+ std::string d_symbol_name;
+ std::string d_symbol_alias;
+ vcolor d_color;
+ bool d_rpc_set;
+
+ msg_queue_map_t msg_queue;
+ std::vector<boost::any> d_rpc_vars; // container for all RPC variables
+
+ gr_basic_block(void){} //allows pure virtual interface sub-classes
+
+ //! Protected constructor prevents instantiation by non-derived classes
+ gr_basic_block(const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature);
+
+ //! may only be called during constructor
+ void set_input_signature(gr_io_signature_sptr iosig) {
+ d_input_signature = iosig;
+ }
+
+ //! may only be called during constructor
+ void set_output_signature(gr_io_signature_sptr iosig) {
+ d_output_signature = iosig;
+ }
+
+ /*!
+ * \brief Allow the flowgraph to set for sorting and partitioning
+ */
+ void set_color(vcolor color) { d_color = color; }
+ vcolor color() const { return d_color; }
+
+ /*!
+ * \brief Tests if there is a handler attached to port \p which_port
+ */
+ bool has_msg_handler(pmt::pmt_t which_port) {
+ return (d_msg_handlers.find(which_port) != d_msg_handlers.end());
+ }
+
+ /*
+ * This function is called by the runtime system to dispatch messages.
+ *
+ * The thread-safety guarantees mentioned in set_msg_handler are implemented
+ * by the callers of this method.
+ */
+ virtual void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg)
+ {
+ // AA Update this
+ if(has_msg_handler(which_port)) { // Is there a handler?
+ d_msg_handlers[which_port](msg); // Yes, invoke it.
+ }
+ }
+
+ // Message passing interface
+ pmt::pmt_t message_subscribers;
+
+ public:
+ virtual ~gr_basic_block();
+ long unique_id() const { return d_unique_id; }
+ long symbolic_id() const { return d_symbolic_id; }
+ std::string name() const { return d_name; }
+ std::string symbol_name() const { return d_symbol_name; }
+ gr_io_signature_sptr input_signature() const { return d_input_signature; }
+ gr_io_signature_sptr output_signature() const { return d_output_signature; }
+ gr_basic_block_sptr to_basic_block(); // Needed for Python type coercion
+ bool alias_set() { return !d_symbol_alias.empty(); }
+ std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); }
+ pmt::pmt_t alias_pmt(){ return pmt::intern(alias()); }
+ void set_block_alias(std::string name);
+
+ // ** Message passing interface **
+ void message_port_register_in(pmt::pmt_t port_id);
+ void message_port_register_out(pmt::pmt_t port_id);
+ void message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg);
+ void message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target);
+ void message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target);
+
+ virtual bool message_port_is_hier(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier\n"; return false; }
+ virtual bool message_port_is_hier_in(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier_in\n"; return false; }
+ virtual bool message_port_is_hier_out(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier_out\n"; return false; }
+
+ /*!
+ * \brief Get input message port names.
+ *
+ * Returns the available input message ports for a block. The
+ * return object is a PMT vector that is filled with PMT symbols.
+ */
+ pmt::pmt_t message_ports_in();
+
+ /*!
+ * \brief Get output message port names.
+ *
+ * Returns the available output message ports for a block. The
+ * return object is a PMT vector that is filled with PMT symbols.
+ */
+ pmt::pmt_t message_ports_out();
+
+ /*!
+ * Accept msg, place in queue, arrange for thread to be awakened if it's not already.
+ */
+ void _post(pmt::pmt_t which_port, pmt::pmt_t msg);
+
+ //! is the queue empty?
+ //bool empty_p(const pmt::pmt_t &which_port) const { return msg_queue[which_port].empty(); }
+ bool empty_p(pmt::pmt_t which_port) {
+ if(msg_queue.find(which_port) == msg_queue.end())
+ throw std::runtime_error("port does not exist!");
+ return msg_queue[which_port].empty();
+ }
+ bool empty_p() {
+ bool rv = true;
+ BOOST_FOREACH(msg_queue_map_t::value_type &i, msg_queue) {
+ rv &= msg_queue[i.first].empty();
+ }
+ return rv;
+ }
+
+ //! How many messages in the queue?
+ size_t nmsgs(pmt::pmt_t which_port) {
+ if(msg_queue.find(which_port) == msg_queue.end())
+ throw std::runtime_error("port does not exist!");
+ return msg_queue[which_port].size();
+ }
+
+ //| Acquires and release the mutex
+ void insert_tail( pmt::pmt_t which_port, pmt::pmt_t msg);
+ /*!
+ * \returns returns pmt at head of queue or pmt_t() if empty.
+ */
+ pmt::pmt_t delete_head_nowait( pmt::pmt_t which_port);
+
+ /*!
+ * \returns returns pmt at head of queue or pmt_t() if empty.
+ */
+ pmt::pmt_t delete_head_blocking( pmt::pmt_t which_port);
+
+ msg_queue_t::iterator get_iterator(pmt::pmt_t which_port){
+ return msg_queue[which_port].begin();
+ }
+
+ void erase_msg(pmt::pmt_t which_port, msg_queue_t::iterator it){
+ msg_queue[which_port].erase(it);
+ }
+
+ virtual bool has_msg_port(pmt::pmt_t which_port){
+ if(msg_queue.find(which_port) != msg_queue.end()){
+ return true;
+ }
+ if(pmt::dict_has_key(message_subscribers, which_port)){
+ return true;
+ }
+ return false;
+ }
+
+#ifdef GR_CTRLPORT
+ /*!
+ * \brief Add an RPC variable (get or set).
+ *
+ * Using controlport, we create new getters/setters and need to
+ * store them. Each block has a vector to do this, and these never
+ * need to be accessed again once they are registered with the RPC
+ * backend. This function takes a
+ * boost::shared_sptr<rpcbasic_base> so that when the block is
+ * deleted, all RPC registered variables are cleaned up.
+ *
+ * \param s an rpcbasic_sptr of the new RPC variable register to store.
+ */
+ void add_rpc_variable(rpcbasic_sptr s)
+ {
+ d_rpc_vars.push_back(s);
+ }
+#endif /* GR_CTRLPORT */
+
+ /*!
+ * \brief Set up the RPC registered variables.
+ *
+ * This must be overloaded by a block that wants to use
+ * controlport. This is where rpcbasic_register_{get,set} pointers
+ * are created, which then get wrapped as shared pointers
+ * (rpcbasic_sptr(...)) and stored using add_rpc_variable.
+ */
+ virtual void setup_rpc() {};
+
+ /*!
+ * \brief Ask if this block has been registered to the RPC.
+ *
+ * We can only register a block once, so we use this to protect us
+ * from calling it multiple times.
+ */
+ bool is_rpc_set() { return d_rpc_set; }
+
+ /*!
+ * \brief When the block is registered with the RPC, set this.
+ */
+ void rpc_set() { d_rpc_set = true; }
+
+ /*!
+ * \brief Confirm that ninputs and noutputs is an acceptable combination.
+ *
+ * \param ninputs number of input streams connected
+ * \param noutputs number of output streams connected
+ *
+ * \returns true if this is a valid configuration for this block.
+ *
+ * This function is called by the runtime system whenever the
+ * topology changes. Most classes do not need to override this.
+ * This check is in addition to the constraints specified by the input
+ * and output gr_io_signatures.
+ */
+ virtual bool check_topology(int ninputs, int noutputs) { (void) ninputs; (void) noutputs; return true; }
+
+ /*!
+ * \brief Set the callback that is fired when messages are available.
+ *
+ * \p msg_handler can be any kind of function pointer or function object
+ * that has the signature:
+ * <pre>
+ * void msg_handler(pmt::pmt msg);
+ * </pre>
+ *
+ * (You may want to use boost::bind to massage your callable into
+ * the correct form. See gr::blocks::nop for an example that sets
+ * up a class method as the callback.)
+ *
+ * Blocks that desire to handle messages must call this method in their
+ * constructors to register the handler that will be invoked when messages
+ * are available.
+ *
+ * If the block inherits from gr_block, the runtime system will ensure that
+ * msg_handler is called in a thread-safe manner, such that work and
+ * msg_handler will never be called concurrently. This allows msg_handler
+ * to update state variables without having to worry about thread-safety
+ * issues with work, general_work or another invocation of msg_handler.
+ *
+ * If the block inherits from gr_hier_block2, the runtime system will
+ * ensure that no reentrant calls are made to msg_handler.
+ */
+ template <typename T> void set_msg_handler(pmt::pmt_t which_port, T msg_handler){
+ if(msg_queue.find(which_port) == msg_queue.end()){
+ throw std::runtime_error("attempt to set_msg_handler() on bad input message port!"); }
+ d_msg_handlers[which_port] = msg_handler_t(msg_handler);
+ }
+};
+
+inline bool operator<(gr_basic_block_sptr lhs, gr_basic_block_sptr rhs)
+{
+ return lhs->unique_id() < rhs->unique_id();
+}
+
+typedef std::vector<gr_basic_block_sptr> gr_basic_block_vector_t;
+typedef std::vector<gr_basic_block_sptr>::iterator gr_basic_block_viter_t;
+
+GR_RUNTIME_API long gr_basic_block_ncurrently_allocated();
+
+inline std::ostream &operator << (std::ostream &os, gr_basic_block_sptr basic_block)
+{
+ os << basic_block->name() << "(" << basic_block->unique_id() << ")";
+ return os;
+}
+
+#endif /* INCLUDED_GR_BASIC_BLOCK_H */
diff --git a/gnuradio-runtime/include/gr_block.h b/gnuradio-runtime/include/gr_block.h
new file mode 100644
index 0000000000..a25bb4a528
--- /dev/null
+++ b/gnuradio-runtime/include/gr_block.h
@@ -0,0 +1,700 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,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.
+ */
+
+#ifndef INCLUDED_GR_BLOCK_H
+#define INCLUDED_GR_BLOCK_H
+
+#include <gr_runtime_api.h>
+#include <gr_basic_block.h>
+#include <gr_tags.h>
+#include <gr_logger.h>
+
+/*!
+ * \brief The abstract base class for all 'terminal' processing blocks.
+ * \ingroup base_blk
+ *
+ * A signal processing flow is constructed by creating a tree of
+ * hierarchical blocks, which at any level may also contain terminal nodes
+ * that actually implement signal processing functions. This is the base
+ * class for all such leaf nodes.
+
+ * Blocks have a set of input streams and output streams. The
+ * input_signature and output_signature define the number of input
+ * streams and output streams respectively, and the type of the data
+ * items in each stream.
+ *
+ * Although blocks may consume data on each input stream at a
+ * different rate, all outputs streams must produce data at the same
+ * rate. That rate may be different from any of the input rates.
+ *
+ * User derived blocks override two methods, forecast and general_work,
+ * to implement their signal processing behavior. forecast is called
+ * by the system scheduler to determine how many items are required on
+ * each input stream in order to produce a given number of output
+ * items.
+ *
+ * general_work is called to perform the signal processing in the block.
+ * It reads the input items and writes the output items.
+ */
+
+class GR_RUNTIME_API gr_block : public gr_basic_block {
+
+ public:
+
+ //! Magic return values from general_work
+ enum {
+ WORK_CALLED_PRODUCE = -2,
+ WORK_DONE = -1
+ };
+
+ enum tag_propagation_policy_t {
+ TPP_DONT = 0,
+ TPP_ALL_TO_ALL = 1,
+ TPP_ONE_TO_ONE = 2
+ };
+
+ virtual ~gr_block ();
+
+ /*!
+ * Assume block computes y_i = f(x_i, x_i-1, x_i-2, x_i-3...)
+ * History is the number of x_i's that are examined to produce one y_i.
+ * This comes in handy for FIR filters, where we use history to
+ * ensure that our input contains the appropriate "history" for the
+ * filter. History should be equal to the number of filter taps.
+ */
+ unsigned history () const { return d_history; }
+ void set_history (unsigned history) { d_history = history; }
+
+ /*!
+ * \brief Return true if this block has a fixed input to output rate.
+ *
+ * If true, then fixed_rate_in_to_out and fixed_rate_out_to_in may be called.
+ */
+ bool fixed_rate() const { return d_fixed_rate; }
+
+ // ----------------------------------------------------------------
+ // 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.
+ */
+ virtual void forecast (int noutput_items,
+ gr_vector_int &ninput_items_required);
+
+ /*!
+ * \brief compute output items from input items
+ *
+ * \param noutput_items number of output items to write on each output stream
+ * \param ninput_items number of input items available on each input stream
+ * \param input_items vector of pointers to the input items, one entry per input stream
+ * \param output_items vector of pointers to the output items, one entry per output stream
+ *
+ * \returns number of items actually written to each output stream, or -1 on EOF.
+ * It is OK to return a value less than noutput_items. -1 <= return value <= noutput_items
+ *
+ * general_work must call consume or consume_each to indicate how many items
+ * were consumed on each input stream.
+ */
+ virtual int general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ /*!
+ * \brief Called to enable drivers, etc for i/o devices.
+ *
+ * This allows a block to enable an associated driver to begin
+ * transfering data just before we start to execute the scheduler.
+ * The end result is that this reduces latency in the pipeline when
+ * dealing with audio devices, usrps, etc.
+ */
+ virtual bool start();
+
+ /*!
+ * \brief Called to disable drivers, etc for i/o devices.
+ */
+ virtual bool stop();
+
+ // ----------------------------------------------------------------
+
+ /*!
+ * \brief Constrain the noutput_items argument passed to forecast and general_work
+ *
+ * set_output_multiple causes the scheduler to ensure that the noutput_items
+ * argument passed to forecast and general_work will be an integer multiple
+ * of \param multiple The default value of output multiple is 1.
+ */
+ void set_output_multiple (int multiple);
+ int output_multiple () const { return d_output_multiple; }
+ bool output_multiple_set () const { return d_output_multiple_set; }
+
+ /*!
+ * \brief Constrains buffers to work on a set item alignment (for SIMD)
+ *
+ * set_alignment_multiple causes the scheduler to ensure that the noutput_items
+ * argument passed to forecast and general_work will be an integer multiple
+ * of \param multiple The default value is 1.
+ *
+ * This control is similar to the output_multiple setting, except
+ * that if the number of items passed to the block is less than the
+ * output_multiple, this value is ignored and the block can produce
+ * like normal. The d_unaligned value is set to the number of items
+ * the block is off by. In the next call to general_work, the
+ * noutput_items is set to d_unaligned or less until
+ * d_unaligned==0. The buffers are now aligned again and the aligned
+ * calls can be performed again.
+ */
+ void set_alignment (int multiple);
+ int alignment () const { return d_output_multiple; }
+
+ void set_unaligned (int na);
+ int unaligned () const { return d_unaligned; }
+ void set_is_unaligned (bool u);
+ bool is_unaligned () const { return d_is_unaligned; }
+
+ /*!
+ * \brief Tell the scheduler \p how_many_items of input stream \p which_input were consumed.
+ */
+ void consume (int which_input, int how_many_items);
+
+ /*!
+ * \brief Tell the scheduler \p how_many_items were consumed on each input stream.
+ */
+ void consume_each (int how_many_items);
+
+ /*!
+ * \brief Tell the scheduler \p how_many_items were produced on output stream \p which_output.
+ *
+ * If the block's general_work method calls produce, \p general_work must return WORK_CALLED_PRODUCE.
+ */
+ void produce (int which_output, int how_many_items);
+
+ /*!
+ * \brief Set the approximate output rate / input rate
+ *
+ * Provide a hint to the buffer allocator and scheduler.
+ * The default relative_rate is 1.0
+ *
+ * decimators have relative_rates < 1.0
+ * interpolators have relative_rates > 1.0
+ */
+ void set_relative_rate (double relative_rate);
+
+ /*!
+ * \brief return the approximate output rate / input rate
+ */
+ double relative_rate () const { return d_relative_rate; }
+
+ /*
+ * 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.
+ */
+ virtual int fixed_rate_ninput_to_noutput(int ninput);
+
+ /*!
+ * \brief Given noutput samples, return number of input samples required to produce noutput.
+ * N.B. this is only defined if fixed_rate returns true.
+ * Generally speaking, you don't need to override this.
+ */
+ virtual int fixed_rate_noutput_to_ninput(int noutput);
+
+ /*!
+ * \brief Return the number of items read on input stream which_input
+ */
+ uint64_t nitems_read(unsigned int which_input);
+
+ /*!
+ * \brief Return the number of items written on output stream which_output
+ */
+ uint64_t nitems_written(unsigned int which_output);
+
+ /*!
+ * \brief Asks for the policy used by the scheduler to moved tags downstream.
+ */
+ tag_propagation_policy_t tag_propagation_policy();
+
+ /*!
+ * \brief Set the policy by the scheduler to determine how tags are moved downstream.
+ */
+ void set_tag_propagation_policy(tag_propagation_policy_t p);
+
+ /*!
+ * \brief Return the minimum number of output items this block can
+ * produce during a call to work.
+ *
+ * Should be 0 for most blocks. Useful if we're dealing with packets and
+ * the block produces one packet per call to work.
+ */
+ int min_noutput_items() const { return d_min_noutput_items; }
+
+ /*!
+ * \brief Set the minimum number of output items this block can
+ * produce during a call to work.
+ *
+ * \param m the minimum noutput_items this block can produce.
+ */
+ void set_min_noutput_items(int m) { d_min_noutput_items = m; }
+
+ /*!
+ * \brief Return the maximum number of output items this block will
+ * handle during a call to work.
+ */
+ int max_noutput_items();
+
+ /*!
+ * \brief Set the maximum number of output items this block will
+ * handle during a call to work.
+ *
+ * \param m the maximum noutput_items this block will handle.
+ */
+ void set_max_noutput_items(int m);
+
+ /*!
+ * \brief Clear the switch for using the max_noutput_items value of this block.
+ *
+ * When is_set_max_noutput_items() returns 'true', the scheduler
+ * will use the value returned by max_noutput_items() to limit the
+ * size of the number of items possible for this block's work
+ * function. If is_set_max_notput_items() returns 'false', then the
+ * scheduler ignores the internal value and uses the value set
+ * globally in the top_block.
+ *
+ * Use this value to clear the 'is_set' flag so the scheduler will
+ * ignore this. Use the set_max_noutput_items(m) call to both set a
+ * new value for max_noutput_items and to reenable its use in the
+ * scheduler.
+ */
+ void unset_max_noutput_items();
+
+ /*!
+ * \brief Ask the block if the flag is or is not set to use the
+ * internal value of max_noutput_items during a call to work.
+ */
+ bool is_set_max_noutput_items();
+
+ /*
+ * Used to expand the vectors that hold the min/max buffer sizes.
+ *
+ * Specifically, when -1 is used, the vectors are just initialized
+ * with 1 value; this is used by the flat_flowgraph to expand when
+ * required to add a new value for new ports on these blocks.
+ */
+ void expand_minmax_buffer(int port) {
+ if((size_t)port >= d_max_output_buffer.size())
+ set_max_output_buffer(port, -1);
+ if((size_t)port >= d_min_output_buffer.size())
+ set_min_output_buffer(port, -1);
+ }
+
+ /*!
+ * \brief Returns max buffer size on output port \p i.
+ */
+ long max_output_buffer(size_t i) {
+ if(i >= d_max_output_buffer.size())
+ throw std::invalid_argument("gr_basic_block::max_output_buffer: port out of range.");
+ return d_max_output_buffer[i];
+ }
+
+ /*!
+ * \brief Sets max buffer size on all output ports.
+ */
+ void set_max_output_buffer(long max_output_buffer) {
+ for(int i = 0; i < output_signature()->max_streams(); i++) {
+ set_max_output_buffer(i, max_output_buffer);
+ }
+ }
+
+ /*!
+ * \brief Sets max buffer size on output port \p port.
+ */
+ void set_max_output_buffer(int port, long max_output_buffer) {
+ if((size_t)port >= d_max_output_buffer.size())
+ d_max_output_buffer.push_back(max_output_buffer);
+ else
+ d_max_output_buffer[port] = max_output_buffer;
+ }
+
+ /*!
+ * \brief Returns min buffer size on output port \p i.
+ */
+ long min_output_buffer(size_t i) {
+ if(i >= d_min_output_buffer.size())
+ throw std::invalid_argument("gr_basic_block::min_output_buffer: port out of range.");
+ return d_min_output_buffer[i];
+ }
+
+ /*!
+ * \brief Sets min buffer size on all output ports.
+ */
+ void set_min_output_buffer(long min_output_buffer) {
+ for(int i=0; i<output_signature()->max_streams(); i++) {
+ set_min_output_buffer(i, min_output_buffer);
+ }
+ }
+
+ /*!
+ * \brief Sets min buffer size on output port \p port.
+ */
+ void set_min_output_buffer(int port, long min_output_buffer) {
+ if((size_t)port >= d_min_output_buffer.size())
+ d_min_output_buffer.push_back(min_output_buffer);
+ else
+ d_min_output_buffer[port] = min_output_buffer;
+ }
+
+ // --------------- Performance counter functions -------------
+
+ /*!
+ * \brief Gets instantaneous noutput_items performance counter.
+ */
+ float pc_noutput_items();
+
+ /*!
+ * \brief Gets average noutput_items performance counter.
+ */
+ float pc_noutput_items_avg();
+
+ /*!
+ * \brief Gets variance of noutput_items performance counter.
+ */
+ float pc_noutput_items_var();
+
+ /*!
+ * \brief Gets instantaneous num items produced performance counter.
+ */
+ float pc_nproduced();
+
+ /*!
+ * \brief Gets average num items produced performance counter.
+ */
+ float pc_nproduced_avg();
+
+ /*!
+ * \brief Gets variance of num items produced performance counter.
+ */
+ float pc_nproduced_var();
+
+ /*!
+ * \brief Gets instantaneous fullness of \p which input buffer.
+ */
+ float pc_input_buffers_full(int which);
+
+ /*!
+ * \brief Gets average fullness of \p which input buffer.
+ */
+ float pc_input_buffers_full_avg(int which);
+
+ /*!
+ * \brief Gets variance of fullness of \p which input buffer.
+ */
+ float pc_input_buffers_full_var(int which);
+
+ /*!
+ * \brief Gets instantaneous fullness of all input buffers.
+ */
+ std::vector<float> pc_input_buffers_full();
+
+ /*!
+ * \brief Gets average fullness of all input buffers.
+ */
+ std::vector<float> pc_input_buffers_full_avg();
+
+ /*!
+ * \brief Gets variance of fullness of all input buffers.
+ */
+ std::vector<float> pc_input_buffers_full_var();
+
+ /*!
+ * \brief Gets instantaneous fullness of \p which input buffer.
+ */
+ float pc_output_buffers_full(int which);
+
+ /*!
+ * \brief Gets average fullness of \p which input buffer.
+ */
+ float pc_output_buffers_full_avg(int which);
+
+ /*!
+ * \brief Gets variance of fullness of \p which input buffer.
+ */
+ float pc_output_buffers_full_var(int which);
+
+ /*!
+ * \brief Gets instantaneous fullness of all output buffers.
+ */
+ std::vector<float> pc_output_buffers_full();
+
+ /*!
+ * \brief Gets average fullness of all output buffers.
+ */
+ std::vector<float> pc_output_buffers_full_avg();
+
+ /*!
+ * \brief Gets variance of fullness of all output buffers.
+ */
+ std::vector<float> pc_output_buffers_full_var();
+
+ /*!
+ * \brief Gets instantaneous clock cycles spent in work.
+ */
+ float pc_work_time();
+
+ /*!
+ * \brief Gets average clock cycles spent in work.
+ */
+ float pc_work_time_avg();
+
+ /*!
+ * \brief Gets average clock cycles spent in work.
+ */
+ float pc_work_time_var();
+
+ /*!
+ * \brief Resets the performance counters
+ */
+ void reset_perf_counters();
+
+ /*!
+ * \brief Sets up export of perf. counters to ControlPort. Only
+ * called by the scheduler.
+ */
+ void setup_pc_rpc();
+
+ /*!
+ * \brief Checks if this block is already exporting perf. counters
+ * to ControlPort.
+ */
+ bool is_pc_rpc_set() { return d_pc_rpc_set; }
+
+ /*!
+ * \brief If the block calls this in its constructor, it's
+ * perf. counters will not be exported.
+ */
+ void no_pc_rpc() { d_pc_rpc_set = true; }
+
+
+ // ----------------------------------------------------------------------------
+ // Functions to handle thread affinity
+
+ /*!
+ * \brief Set the thread's affinity to processor core \p n.
+ *
+ * \param mask a vector of ints of the core numbers available to this block.
+ */
+ void set_processor_affinity(const std::vector<int> &mask);
+
+ /*!
+ * \brief Remove processor affinity to a specific core.
+ */
+ void unset_processor_affinity();
+
+ /*!
+ * \brief Get the current processor affinity.
+ */
+ std::vector<int> processor_affinity() { return d_affinity; }
+
+ // ----------------------------------------------------------------------------
+
+ private:
+
+ int d_output_multiple;
+ bool d_output_multiple_set;
+ int d_unaligned;
+ bool d_is_unaligned;
+ double d_relative_rate; // approx output_rate / input_rate
+ gr_block_detail_sptr d_detail; // implementation details
+ unsigned d_history;
+ bool d_fixed_rate;
+ bool d_max_noutput_items_set; // if d_max_noutput_items is valid
+ int d_max_noutput_items; // value of max_noutput_items for this block
+ int d_min_noutput_items;
+ tag_propagation_policy_t d_tag_propagation_policy; // policy for moving tags downstream
+ std::vector<int> d_affinity; // thread affinity proc. mask
+ bool d_pc_rpc_set;
+
+ protected:
+ gr_block (void){} //allows pure virtual interface sub-classes
+ gr_block (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature);
+
+ void set_fixed_rate(bool fixed_rate){ d_fixed_rate = fixed_rate; }
+
+
+ /*!
+ * \brief Adds a new tag onto the given output buffer.
+ *
+ * \param which_output an integer of which output stream to attach the tag
+ * \param abs_offset a uint64 number of the absolute item number
+ * assicated with the tag. Can get from nitems_written.
+ * \param key the tag key as a PMT symbol
+ * \param value any PMT holding any value for the given key
+ * \param srcid optional source ID specifier; defaults to PMT_F
+ */
+ inline void add_item_tag(unsigned int which_output,
+ uint64_t abs_offset,
+ const pmt::pmt_t &key,
+ const pmt::pmt_t &value,
+ const pmt::pmt_t &srcid=pmt::PMT_F)
+ {
+ gr_tag_t tag;
+ tag.offset = abs_offset;
+ tag.key = key;
+ tag.value = value;
+ tag.srcid = srcid;
+ this->add_item_tag(which_output, tag);
+ }
+
+ /*!
+ * \brief Adds a new tag onto the given output buffer.
+ *
+ * \param which_output an integer of which output stream to attach the tag
+ * \param tag the tag object to add
+ */
+ void add_item_tag(unsigned int which_output, const gr_tag_t &tag);
+
+ /*!
+ * \brief Removes a tag from the given input buffer.
+ *
+ * \param which_input an integer of which input stream to remove the tag from
+ * \param abs_offset a uint64 number of the absolute item number
+ * assicated with the tag. Can get from nitems_written.
+ * \param key the tag key as a PMT symbol
+ * \param value any PMT holding any value for the given key
+ * \param srcid optional source ID specifier; defaults to PMT_F
+ *
+ * If no such tag is found, does nothing.
+ */
+ inline void remove_item_tag(unsigned int which_input,
+ uint64_t abs_offset,
+ const pmt::pmt_t &key,
+ const pmt::pmt_t &value,
+ const pmt::pmt_t &srcid=pmt::PMT_F)
+ {
+ gr_tag_t tag;
+ tag.offset = abs_offset;
+ tag.key = key;
+ tag.value = value;
+ tag.srcid = srcid;
+ this->remove_item_tag(which_input, tag);
+ }
+
+ /*!
+ * \brief Removes a tag from the given input buffer.
+ *
+ * If no such tag is found, does nothing.
+ *
+ * \param which_input an integer of which input stream to remove the tag from
+ * \param tag the tag object to remove
+ */
+ void remove_item_tag(unsigned int which_input, const gr_tag_t &tag);
+
+ /*!
+ * \brief Given a [start,end), returns a vector of all tags in the range.
+ *
+ * Range of counts is from start to end-1.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param which_input an integer of which input stream to pull from
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ */
+ void get_tags_in_range(std::vector<gr_tag_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end);
+
+ /*!
+ * \brief Given a [start,end), returns a vector of all tags in the range
+ * with a given key.
+ *
+ * Range of counts is from start to end-1.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param which_input an integer of which input stream to pull from
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ * \param key a PMT symbol key to filter only tags of this key
+ */
+ void 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<long> d_max_output_buffer;
+ std::vector<long> d_min_output_buffer;
+
+ /*! Used by block's setters and work functions to make
+ * setting/resetting of parameters thread-safe.
+ *
+ * Used by calling gruel::scoped_lock l(d_setlock);
+ */
+ gruel::mutex d_setlock;
+
+ /*! Used by blocks to access the logger system.
+ */
+ gr_logger_ptr d_logger;
+ gr_logger_ptr d_debug_logger;
+
+ // These are really only for internal use, but leaving them public avoids
+ // having to work up an ever-varying list of friend GR_RUNTIME_APIs
+
+ public:
+ gr_block_detail_sptr detail () const { return d_detail; }
+ void set_detail (gr_block_detail_sptr detail) { d_detail = detail; }
+};
+
+typedef std::vector<gr_block_sptr> gr_block_vector_t;
+typedef std::vector<gr_block_sptr>::iterator gr_block_viter_t;
+
+inline gr_block_sptr cast_to_block_sptr(gr_basic_block_sptr p)
+{
+ return boost::dynamic_pointer_cast<gr_block, gr_basic_block>(p);
+}
+
+
+std::ostream&
+operator << (std::ostream& os, const gr_block *m);
+
+#endif /* INCLUDED_GR_BLOCK_H */
diff --git a/gnuradio-runtime/include/gr_block_detail.h b/gnuradio-runtime/include/gr_block_detail.h
new file mode 100644
index 0000000000..d24148f951
--- /dev/null
+++ b/gnuradio-runtime/include/gr_block_detail.h
@@ -0,0 +1,248 @@
+/* -*- 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 detail.
+ *
+ * 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_DETAIL_H
+#define INCLUDED_GR_BLOCK_DETAIL_H
+
+#include <gr_runtime_api.h>
+#include <gr_runtime_types.h>
+#include <gr_tpb_detail.h>
+#include <gr_tags.h>
+#include <gruel/high_res_timer.h>
+#include <stdexcept>
+
+/*!
+ * \brief Implementation details to support the signal processing abstraction
+ * \ingroup internal
+ *
+ * This class contains implementation detail that should be "out of sight"
+ * of almost all users of GNU Radio. This decoupling also means that
+ * we can make changes to the guts without having to recompile everything.
+ */
+class GR_RUNTIME_API gr_block_detail {
+ public:
+ ~gr_block_detail ();
+
+ int ninputs () const { return d_ninputs; }
+ int noutputs () const { return d_noutputs; }
+ bool sink_p () const { return d_noutputs == 0; }
+ bool source_p () const { return d_ninputs == 0; }
+
+ void set_done (bool done);
+ bool done () const { return d_done; }
+
+ void set_input (unsigned int which, gr_buffer_reader_sptr reader);
+ gr_buffer_reader_sptr input (unsigned int which)
+ {
+ if (which >= d_ninputs)
+ throw std::invalid_argument ("gr_block_detail::input");
+ return d_input[which];
+ }
+
+ void set_output (unsigned int which, gr_buffer_sptr buffer);
+ gr_buffer_sptr output (unsigned int which)
+ {
+ if (which >= d_noutputs)
+ throw std::invalid_argument ("gr_block_detail::output");
+ return d_output[which];
+ }
+
+ /*!
+ * \brief Tell the scheduler \p how_many_items of input stream \p which_input were consumed.
+ */
+ void consume (int which_input, int how_many_items);
+
+ /*!
+ * \brief Tell the scheduler \p how_many_items were consumed on each input stream.
+ */
+ void consume_each (int how_many_items);
+
+ /*!
+ * \brief Tell the scheduler \p how_many_items were produced on output stream \p which_output.
+ */
+ void produce (int which_output, int how_many_items);
+
+ /*!
+ * \brief Tell the scheduler \p how_many_items were produced on each output stream.
+ */
+ void produce_each (int how_many_items);
+
+ // Return the number of items read on input stream which_input
+ uint64_t nitems_read(unsigned int which_input);
+
+ // Return the number of items written on output stream which_output
+ uint64_t nitems_written(unsigned int which_output);
+
+
+ /*!
+ * \brief Adds a new tag to the given output stream.
+ *
+ * Calls gr_buffer::add_item_tag(),
+ * which appends the tag onto its deque.
+ *
+ * \param which_output an integer of which output stream to attach the tag
+ * \param tag the tag object to add
+ */
+ void add_item_tag(unsigned int which_output, const gr_tag_t &tag);
+
+ /*!
+ * \brief Removes a tag from the given input stream.
+ *
+ * Calls gr_buffer::remove_item_tag(), which removes the tag from its deque.
+ *
+ * \param which_input an integer of which input stream to remove the tag from
+ * \param tag the tag object to add
+ */
+ void remove_item_tag(unsigned int which_input, const gr_tag_t &tag);
+
+ /*!
+ * \brief Given a [start,end), returns a vector of all tags in the range.
+ *
+ * Pass-through function to gr_buffer_reader to get a vector of tags
+ * in given range. Range of counts is from start to end-1.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param which_input an integer of which input stream to pull from
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ */
+ void get_tags_in_range(std::vector<gr_tag_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end);
+
+ /*!
+ * \brief Given a [start,end), returns a vector of all tags in the range
+ * with a given key.
+ *
+ * Calls get_tags_in_range(which_input, abs_start, abs_end) to get a vector of
+ * tags from the buffers. This function then provides a secondary filter to
+ * the tags to extract only tags with the given 'key'.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param which_input an integer of which input stream to pull from
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ * \param key a PMT symbol to select only tags of this key
+ */
+ void 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);
+
+ /*!
+ * \brief Set core affinity of block to the cores in the vector mask.
+ *
+ * \param mask a vector of ints of the core numbers available to this block.
+ */
+ void set_processor_affinity(const std::vector<int> &mask);
+
+ /*!
+ * \brief Unset core affinity.
+ */
+ void unset_processor_affinity();
+
+ bool threaded; // set if thread is currently running.
+ gruel::gr_thread_t thread; // portable thread handle
+
+ void start_perf_counters();
+ void stop_perf_counters(int noutput_items, int nproduced);
+ void reset_perf_counters();
+
+ // Calls to get performance counter items
+ float pc_noutput_items();
+ float pc_nproduced();
+ float pc_input_buffers_full(size_t which);
+ std::vector<float> pc_input_buffers_full();
+ float pc_output_buffers_full(size_t which);
+ std::vector<float> pc_output_buffers_full();
+ float pc_work_time();
+
+ float pc_noutput_items_avg();
+ float pc_nproduced_avg();
+ float pc_input_buffers_full_avg(size_t which);
+ std::vector<float> pc_input_buffers_full_avg();
+ float pc_output_buffers_full_avg(size_t which);
+ std::vector<float> pc_output_buffers_full_avg();
+ float pc_work_time_avg();
+
+ float pc_noutput_items_var();
+ float pc_nproduced_var();
+ float pc_input_buffers_full_var(size_t which);
+ std::vector<float> pc_input_buffers_full_var();
+ float pc_output_buffers_full_var(size_t which);
+ std::vector<float> pc_output_buffers_full_var();
+ float pc_work_time_var();
+
+ gr_tpb_detail d_tpb; // used by thread-per-block scheduler
+ int d_produce_or;
+
+ // ----------------------------------------------------------------------------
+
+ private:
+ unsigned int d_ninputs;
+ unsigned int d_noutputs;
+ std::vector<gr_buffer_reader_sptr> d_input;
+ std::vector<gr_buffer_sptr> d_output;
+ bool d_done;
+
+ // Performance counters
+ float d_ins_noutput_items;
+ float d_avg_noutput_items;
+ float d_var_noutput_items;
+ float d_ins_nproduced;
+ float d_avg_nproduced;
+ float d_var_nproduced;
+ std::vector<float> d_ins_input_buffers_full;
+ std::vector<float> d_avg_input_buffers_full;
+ std::vector<float> d_var_input_buffers_full;
+ std::vector<float> d_ins_output_buffers_full;
+ std::vector<float> d_avg_output_buffers_full;
+ std::vector<float> d_var_output_buffers_full;
+ gruel::high_res_timer_type d_start_of_work, d_end_of_work;
+ float d_ins_work_time;
+ float d_avg_work_time;
+ float d_var_work_time;
+ float d_pc_counter;
+
+ gr_block_detail (unsigned int ninputs, unsigned int noutputs);
+
+ friend struct gr_tpb_detail;
+
+ friend GR_RUNTIME_API gr_block_detail_sptr
+ gr_make_block_detail (unsigned int ninputs, unsigned int noutputs);
+};
+
+GR_RUNTIME_API gr_block_detail_sptr
+gr_make_block_detail (unsigned int ninputs, unsigned int noutputs);
+
+GR_RUNTIME_API long
+gr_block_detail_ncurrently_allocated ();
+
+#endif /* INCLUDED_GR_BLOCK_DETAIL_H */
diff --git a/gnuradio-runtime/include/gr_block_registry.h b/gnuradio-runtime/include/gr_block_registry.h
new file mode 100644
index 0000000000..9b038287bc
--- /dev/null
+++ b/gnuradio-runtime/include/gr_block_registry.h
@@ -0,0 +1,44 @@
+#ifndef GR_BLOCK_REGISTRY_H
+#define GR_BLOCK_REGISTRY_H
+
+#include <gr_runtime_api.h>
+#include <map>
+#include <gr_basic_block.h>
+
+#ifndef GR_BASIC_BLOCK_H
+class gr_basic_block;
+class gr_block;
+#endif
+
+class GR_RUNTIME_API gr_block_registry {
+ public:
+ gr_block_registry();
+
+ long block_register(gr_basic_block* block);
+ void block_unregister(gr_basic_block* block);
+
+ std::string register_symbolic_name(gr_basic_block* block);
+ void register_symbolic_name(gr_basic_block* block, std::string name);
+
+ gr_basic_block_sptr block_lookup(pmt::pmt_t symbol);
+
+ void register_primitive(std::string blk, gr_block* ref);
+ void unregister_primitive(std::string blk);
+ void notify_blk(std::string blk);
+
+ private:
+
+ //typedef std::map< long, gr_basic_block_sptr > blocksubmap_t;
+ typedef std::map< long, gr_basic_block* > blocksubmap_t;
+ typedef std::map< std::string, blocksubmap_t > blockmap_t;
+
+ blockmap_t d_map;
+ pmt::pmt_t d_ref_map;
+ std::map< std::string, gr_block*> primitive_map;
+
+};
+
+GR_RUNTIME_API extern gr_block_registry global_block_registry;
+
+#endif
+
diff --git a/gnuradio-runtime/include/gr_buffer.h b/gnuradio-runtime/include/gr_buffer.h
new file mode 100644
index 0000000000..1a10ba6d8d
--- /dev/null
+++ b/gnuradio-runtime/include/gr_buffer.h
@@ -0,0 +1,309 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2009,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.
+ */
+
+#ifndef INCLUDED_GR_BUFFER_H
+#define INCLUDED_GR_BUFFER_H
+
+#include <gr_runtime_api.h>
+#include <gr_runtime_types.h>
+#include <boost/weak_ptr.hpp>
+#include <gruel/thread.h>
+#include <gr_tags.h>
+#include <deque>
+
+class gr_vmcircbuf;
+
+/*!
+ * \brief Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
+ *
+ * The total size of the buffer will be rounded up to a system
+ * dependent boundary. This is typically the system page size, but
+ * under MS windows is 64KB.
+ *
+ * \param nitems is the minimum number of items the buffer will hold.
+ * \param sizeof_item is the size of an item in bytes.
+ * \param link is the block that writes to this buffer.
+ */
+GR_RUNTIME_API gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link=gr_block_sptr());
+
+
+/*!
+ * \brief Single writer, multiple reader fifo.
+ * \ingroup internal
+ */
+class GR_RUNTIME_API gr_buffer {
+ public:
+
+ virtual ~gr_buffer ();
+
+ /*!
+ * \brief return number of items worth of space available for writing
+ */
+ int space_available ();
+
+ /*!
+ * \brief return size of this buffer in items
+ */
+ int bufsize() const { return d_bufsize; }
+
+ /*!
+ * \brief return pointer to write buffer.
+ *
+ * The return value points at space that can hold at least
+ * space_available() items.
+ */
+ void *write_pointer ();
+
+ /*!
+ * \brief tell buffer that we wrote \p nitems into it
+ */
+ void update_write_pointer (int nitems);
+
+ void set_done (bool done);
+ bool done () const { return d_done; }
+
+ /*!
+ * \brief Return the block that writes to this buffer.
+ */
+ gr_block_sptr link() { return gr_block_sptr(d_link); }
+
+ size_t nreaders() const { return d_readers.size(); }
+ gr_buffer_reader* reader(size_t index) { return d_readers[index]; }
+
+ gruel::mutex *mutex() { return &d_mutex; }
+
+ uint64_t nitems_written() { return d_abs_write_offset; }
+
+ size_t get_sizeof_item() { return d_sizeof_item; }
+
+ /*!
+ * \brief Adds a new tag to the buffer.
+ *
+ * \param tag the new tag
+ */
+ void add_item_tag(const gr_tag_t &tag);
+
+ /*!
+ * \brief Removes an existing tag from the buffer.
+ *
+ * If no such tag is found, does nothing.
+ *
+ * \param tag the tag that needs to be removed
+ */
+ void remove_item_tag(const gr_tag_t &tag);
+
+ /*!
+ * \brief Removes all tags before \p max_time from buffer
+ *
+ * \param max_time the time (item number) to trim up until.
+ */
+ void prune_tags(uint64_t max_time);
+
+ std::deque<gr_tag_t>::iterator get_tags_begin() { return d_item_tags.begin(); }
+ std::deque<gr_tag_t>::iterator get_tags_end() { return d_item_tags.end(); }
+
+ // -------------------------------------------------------------------------
+
+ private:
+
+ friend class gr_buffer_reader;
+ friend GR_RUNTIME_API gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link);
+ friend GR_RUNTIME_API gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link);
+
+ protected:
+ char *d_base; // base address of buffer
+ unsigned int d_bufsize; // in items
+ private:
+ gr_vmcircbuf *d_vmcircbuf;
+ size_t d_sizeof_item; // in bytes
+ std::vector<gr_buffer_reader *> d_readers;
+ boost::weak_ptr<gr_block> d_link; // block that writes to this buffer
+
+ //
+ // The mutex protects d_write_index, d_abs_write_offset, d_done, d_item_tags
+ // and the d_read_index's and d_abs_read_offset's in the buffer readers.
+ //
+ gruel::mutex d_mutex;
+ unsigned int d_write_index; // in items [0,d_bufsize)
+ uint64_t d_abs_write_offset; // num items written since the start
+ bool d_done;
+ std::deque<gr_tag_t> d_item_tags;
+ uint64_t d_last_min_items_read;
+
+ unsigned
+ index_add (unsigned a, unsigned b)
+ {
+ unsigned s = a + b;
+
+ if (s >= d_bufsize)
+ s -= d_bufsize;
+
+ assert (s < d_bufsize);
+ return s;
+ }
+
+ unsigned
+ index_sub (unsigned a, unsigned b)
+ {
+ int s = a - b;
+
+ if (s < 0)
+ s += d_bufsize;
+
+ assert ((unsigned) s < d_bufsize);
+ return s;
+ }
+
+ virtual bool allocate_buffer (int nitems, size_t sizeof_item);
+
+ /*!
+ * \brief constructor is private. Use gr_make_buffer to create instances.
+ *
+ * Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
+ *
+ * \param nitems is the minimum number of items the buffer will hold.
+ * \param sizeof_item is the size of an item in bytes.
+ * \param link is the block that writes to this buffer.
+ *
+ * The total size of the buffer will be rounded up to a system
+ * dependent boundary. This is typically the system page size, but
+ * under MS windows is 64KB.
+ */
+ gr_buffer (int nitems, size_t sizeof_item, gr_block_sptr link);
+
+ /*!
+ * \brief disassociate \p reader from this buffer
+ */
+ void drop_reader (gr_buffer_reader *reader);
+
+};
+
+/*!
+ * \brief Create a new gr_buffer_reader and attach it to buffer \p buf
+ * \param buf is the buffer the \p gr_buffer_reader reads from.
+ * \param nzero_preload -- number of zero items to "preload" into buffer.
+ * \param link is the block that reads from the buffer using this gr_buffer_reader.
+ */
+GR_RUNTIME_API gr_buffer_reader_sptr
+gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link=gr_block_sptr());
+
+//! returns # of gr_buffers currently allocated
+GR_RUNTIME_API long gr_buffer_ncurrently_allocated ();
+
+
+// ---------------------------------------------------------------------------
+
+/*!
+ * \brief How we keep track of the readers of a gr_buffer.
+ * \ingroup internal
+ */
+
+class GR_RUNTIME_API gr_buffer_reader {
+ public:
+
+ ~gr_buffer_reader ();
+
+ /*!
+ * \brief Return number of items available for reading.
+ */
+ int items_available () const;
+
+ /*!
+ * \brief Return buffer this reader reads from.
+ */
+ gr_buffer_sptr buffer () const { return d_buffer; }
+
+
+ /*!
+ * \brief Return maximum number of items that could ever be available for reading.
+ * This is used as a sanity check in the scheduler to avoid looping forever.
+ */
+ int max_possible_items_available () const { return d_buffer->d_bufsize - 1; }
+
+ /*!
+ * \brief return pointer to read buffer.
+ *
+ * The return value points to items_available() number of items
+ */
+ const void *read_pointer ();
+
+ /*
+ * \brief tell buffer we read \p items from it
+ */
+ void update_read_pointer (int nitems);
+
+ void set_done (bool done) { d_buffer->set_done (done); }
+ bool done () const { return d_buffer->done (); }
+
+ gruel::mutex *mutex() { return d_buffer->mutex(); }
+
+
+ uint64_t nitems_read() { return d_abs_read_offset; }
+
+ size_t get_sizeof_item() { return d_buffer->get_sizeof_item(); }
+
+ /*!
+ * \brief Return the block that reads via this reader.
+ *
+ */
+ gr_block_sptr link() { return gr_block_sptr(d_link); }
+
+
+ /*!
+ * \brief Given a [start,end), returns a vector all tags in the range.
+ *
+ * Get a vector of tags in given range. Range of counts is from start to end-1.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ */
+ void get_tags_in_range(std::vector<gr_tag_t> &v,
+ uint64_t abs_start,
+ uint64_t abs_end);
+
+ // -------------------------------------------------------------------------
+
+ private:
+
+ friend class gr_buffer;
+ friend GR_RUNTIME_API gr_buffer_reader_sptr
+ gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link);
+
+
+ gr_buffer_sptr d_buffer;
+ unsigned int d_read_index; // in items [0,d->buffer.d_bufsize)
+ uint64_t d_abs_read_offset; // num items seen since the start
+ boost::weak_ptr<gr_block> d_link; // block that reads via this buffer reader
+
+ //! constructor is private. Use gr_buffer::add_reader to create instances
+ gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index, gr_block_sptr link);
+};
+
+//! returns # of gr_buffer_readers currently allocated
+GR_RUNTIME_API long gr_buffer_reader_ncurrently_allocated ();
+
+
+#endif /* INCLUDED_GR_BUFFER_H */
diff --git a/gnuradio-runtime/include/gr_complex.h b/gnuradio-runtime/include/gr_complex.h
new file mode 100644
index 0000000000..6166c0b142
--- /dev/null
+++ b/gnuradio-runtime/include/gr_complex.h
@@ -0,0 +1,44 @@
+/* -*- 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_COMPLEX_H
+#define INCLUDED_GR_COMPLEX_H
+
+#include <complex>
+typedef std::complex<float> gr_complex;
+typedef std::complex<double> gr_complexd;
+
+inline bool is_complex (gr_complex x) { (void) x; return true;}
+inline bool is_complex (gr_complexd x) { (void) x; return true;}
+inline bool is_complex (float x) { (void) x; return false;}
+inline bool is_complex (double x) { (void) x; return false;}
+inline bool is_complex (int x) { (void) x; return false;}
+inline bool is_complex (char x) { (void) x; return false;}
+inline bool is_complex (short x) { (void) x; return false;}
+
+// this doesn't really belong here, but there are worse places for it...
+
+#define CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected,actual,delta) \
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (expected.real(), actual.real(), delta); \
+ CPPUNIT_ASSERT_DOUBLES_EQUAL (expected.imag(), actual.imag(), delta);
+
+#endif /* INCLUDED_GR_COMPLEX_H */
+
diff --git a/gnuradio-runtime/include/gr_constants.h b/gnuradio-runtime/include/gr_constants.h
new file mode 100644
index 0000000000..3534166bc0
--- /dev/null
+++ b/gnuradio-runtime/include/gr_constants.h
@@ -0,0 +1,53 @@
+/* -*- 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.
+ */
+#ifndef INCLUDED_GR_CONSTANTS_H
+#define INCLUDED_GR_CONSTANTS_H
+
+#include <gr_runtime_api.h>
+#include <string>
+
+/*!
+ * \brief return ./configure --prefix argument. Typically /usr/local
+ */
+GR_RUNTIME_API const std::string gr_prefix();
+
+/*!
+ * \brief return ./configure --sysconfdir argument. Typically $prefix/etc or /etc
+ */
+GR_RUNTIME_API const std::string gr_sysconfdir();
+
+/*!
+ * \brief return preferences file directory. Typically $sysconfdir/etc/conf.d
+ */
+GR_RUNTIME_API const std::string gr_prefsdir();
+
+/*!
+ * \brief return date/time of build, as set when 'bootstrap' is run
+ */
+GR_RUNTIME_API const std::string gr_build_date();
+
+/*!
+ * \brief return version string defined in configure.ac
+ */
+GR_RUNTIME_API const std::string gr_version();
+
+#endif /* INCLUDED_GR_CONSTANTS_H */
diff --git a/gnuradio-runtime/include/gr_dispatcher.h b/gnuradio-runtime/include/gr_dispatcher.h
new file mode 100644
index 0000000000..7a9e80c9fe
--- /dev/null
+++ b/gnuradio-runtime/include/gr_dispatcher.h
@@ -0,0 +1,69 @@
+/* -*- 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_DISPATCHER_H
+#define INCLUDED_GR_DISPATCHER_H
+
+#include <gr_runtime_api.h>
+#include <gr_select_handler.h>
+#include <vector>
+
+class gr_dispatcher;
+typedef boost::shared_ptr<gr_dispatcher> gr_dispatcher_sptr;
+
+GR_RUNTIME_API gr_dispatcher_sptr gr_dispatcher_singleton();
+GR_RUNTIME_API gr_dispatcher_sptr gr_make_dispatcher();
+
+/*!
+ * \brief invoke callbacks based on select.
+ * \ingroup internal
+ *
+ * \sa gr_select_handler
+ */
+class GR_RUNTIME_API gr_dispatcher
+{
+ gr_dispatcher();
+ friend GR_RUNTIME_API gr_dispatcher_sptr gr_make_dispatcher();
+
+ std::vector<gr_select_handler_sptr> d_handler;
+ int d_max_index;
+
+public:
+ ~gr_dispatcher();
+
+ bool add_handler(gr_select_handler_sptr handler);
+ bool del_handler(gr_select_handler_sptr handler);
+ bool del_handler(gr_select_handler *handler);
+
+ /*!
+ * \brief Event dispatching loop.
+ *
+ * Enter a polling loop that only terminates after all gr_select_handlers
+ * have been removed. \p timeout sets the timeout parameter to the select()
+ * call, measured in seconds.
+ *
+ * \param timeout maximum number of seconds to block in select.
+ */
+ void loop(double timeout=10);
+};
+
+#endif /* INCLUDED_GR_DISPATCHER_H */
diff --git a/gnuradio-runtime/include/gr_endianness.h b/gnuradio-runtime/include/gr_endianness.h
new file mode 100644
index 0000000000..c4ecb1383e
--- /dev/null
+++ b/gnuradio-runtime/include/gr_endianness.h
@@ -0,0 +1,27 @@
+/* -*- 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_ENDIANNESS_H
+#define INCLUDED_GR_ENDIANNESS_H
+
+typedef enum {GR_MSB_FIRST, GR_LSB_FIRST} gr_endianness_t;
+
+#endif /* INCLUDED_GR_ENDIANNESS_H */
diff --git a/gnuradio-runtime/include/gr_error_handler.h b/gnuradio-runtime/include/gr_error_handler.h
new file mode 100644
index 0000000000..4d326a6ba1
--- /dev/null
+++ b/gnuradio-runtime/include/gr_error_handler.h
@@ -0,0 +1,117 @@
+/* -*- 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.hh 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.
+ */
+
+#ifndef INCLUDED_GR_ERROR_HANDLER_H
+#define INCLUDED_GR_ERROR_HANDLER_H
+
+#include <gr_runtime_api.h>
+#include <stdarg.h>
+#include <string>
+#include <cstdio> // for FILE
+
+/*!
+ * \brief abstract error handler
+ * \ingroup base
+ */
+class GR_RUNTIME_API gr_error_handler {
+public:
+ enum seriousness {
+ ERR_DEBUG = 0x00000000,
+ ERR_MESSAGE = 0x00010000,
+ ERR_WARNING = 0x00020000,
+ ERR_ERROR = 0x00030000,
+ ERR_FATAL = 0x00040000
+ };
+
+ gr_error_handler() {}
+ virtual ~gr_error_handler();
+
+ static gr_error_handler *default_handler();
+ static gr_error_handler *silent_handler();
+
+ static bool has_default_handler();
+ static void set_default_handler(gr_error_handler *errh);
+
+ void debug(const char *format, ...);
+ void message(const char *format, ...);
+ void warning(const char *format, ...);
+ void error(const char *format, ...);
+ void fatal(const char *format, ...);
+
+ virtual int nwarnings() const = 0;
+ virtual int nerrors() const = 0;
+ virtual void reset_counts() = 0;
+
+ void verror(seriousness s, const char *format, va_list);
+ void verror_text(seriousness s, const std::string &text);
+
+protected:
+ virtual void count_error(seriousness s) = 0;
+ virtual void handle_text(seriousness s, const std::string &str) = 0;
+ std::string make_text(seriousness s, const char *format, va_list);
+};
+
+
+class GR_RUNTIME_API gr_base_error_handler : public gr_error_handler {
+ int d_nwarnings;
+ int d_nerrors;
+
+public:
+ gr_base_error_handler() : d_nwarnings(0), d_nerrors(0) {}
+ int nwarnings() const { return d_nwarnings; }
+ int nerrors() const { return d_nerrors; }
+ void reset_counts() { d_nwarnings = d_nerrors = 0; }
+ void count_error(seriousness s);
+};
+
+class GR_RUNTIME_API gr_file_error_handler : public gr_base_error_handler {
+ FILE *d_file;
+ int d_fd;
+public:
+ gr_file_error_handler(FILE *file);
+ gr_file_error_handler(int file_descriptor);
+ ~gr_file_error_handler();
+
+ void handle_text(seriousness s, const std::string &str);
+};
+
+#endif /* INCLUDED_GR_ERROR_HANDLER_H */
diff --git a/gnuradio-runtime/include/gr_expj.h b/gnuradio-runtime/include/gr_expj.h
new file mode 100644
index 0000000000..56291a0a6a
--- /dev/null
+++ b/gnuradio-runtime/include/gr_expj.h
@@ -0,0 +1,38 @@
+/* -*- 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_EXPJ_H
+#define INCLUDED_GR_EXPJ_H
+
+#include <gr_runtime_api.h>
+#include <gr_sincos.h>
+#include <gr_types.h>
+
+static inline gr_complex
+gr_expj(float phase)
+{
+ float t_imag, t_real;
+ gr_sincosf(phase, &t_imag, &t_real);
+ return gr_complex(t_real, t_imag);
+}
+
+
+#endif /* INCLUDED_GR_EXPJ_H */
diff --git a/gnuradio-runtime/include/gr_feval.h b/gnuradio-runtime/include/gr_feval.h
new file mode 100644
index 0000000000..af11ca2a2a
--- /dev/null
+++ b/gnuradio-runtime/include/gr_feval.h
@@ -0,0 +1,177 @@
+/* -*- 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_FEVAL_H
+#define INCLUDED_GR_FEVAL_H
+
+#include <gr_runtime_api.h>
+#include <gr_complex.h>
+#include <gruel/pmt.h>
+
+/*!
+ * \brief base class for evaluating a function: double -> double
+ * \ingroup misc
+ *
+ * This class is designed to be subclassed in Python or C++
+ * and is callable from both places. It uses SWIG's
+ * "director" feature to implement the magic.
+ * It's slow. Don't use it in a performance critical path.
+ *
+ * Override eval to define the behavior.
+ * Use calleval to invoke eval (this kludge is required to allow a
+ * python specific "shim" to be inserted.
+ */
+class GR_RUNTIME_API gr_feval_dd
+{
+protected:
+ /*!
+ * \brief override this to define the function
+ */
+ virtual double eval(double x);
+
+public:
+ gr_feval_dd() {}
+ virtual ~gr_feval_dd();
+
+ virtual double calleval(double x); // invoke "eval"
+};
+
+/*!
+ * \brief base class for evaluating a function: complex -> complex
+ * \ingroup misc
+ *
+ * This class is designed to be subclassed in Python or C++
+ * and is callable from both places. It uses SWIG's
+ * "director" feature to implement the magic.
+ * It's slow. Don't use it in a performance critical path.
+ *
+ * Override eval to define the behavior.
+ * Use calleval to invoke eval (this kludge is required to allow a
+ * python specific "shim" to be inserted.
+ */
+class GR_RUNTIME_API gr_feval_cc
+{
+protected:
+ /*!
+ * \brief override this to define the function
+ */
+ virtual gr_complex eval(gr_complex x);
+
+public:
+ gr_feval_cc() {}
+ virtual ~gr_feval_cc();
+
+ virtual gr_complex calleval(gr_complex x); // invoke "eval"
+};
+
+/*!
+ * \brief base class for evaluating a function: long -> long
+ * \ingroup misc
+ *
+ * This class is designed to be subclassed in Python or C++
+ * and is callable from both places. It uses SWIG's
+ * "director" feature to implement the magic.
+ * It's slow. Don't use it in a performance critical path.
+ *
+ * Override eval to define the behavior.
+ * Use calleval to invoke eval (this kludge is required to allow a
+ * python specific "shim" to be inserted.
+ */
+class GR_RUNTIME_API gr_feval_ll
+{
+protected:
+ /*!
+ * \brief override this to define the function
+ */
+ virtual long eval(long x);
+
+public:
+ gr_feval_ll() {}
+ virtual ~gr_feval_ll();
+
+ virtual long calleval(long x); // invoke "eval"
+};
+
+/*!
+ * \brief base class for evaluating a function: void -> void
+ * \ingroup misc
+ *
+ * This class is designed to be subclassed in Python or C++
+ * and is callable from both places. It uses SWIG's
+ * "director" feature to implement the magic.
+ * It's slow. Don't use it in a performance critical path.
+ *
+ * Override eval to define the behavior.
+ * Use calleval to invoke eval (this kludge is required to allow a
+ * python specific "shim" to be inserted.
+ */
+class GR_RUNTIME_API gr_feval
+{
+protected:
+ /*!
+ * \brief override this to define the function
+ */
+ virtual void eval();
+
+public:
+ gr_feval() {}
+ virtual ~gr_feval();
+
+ virtual void calleval(); // invoke "eval"
+};
+
+/*!
+ * \brief base class for evaluating a function: pmt -> void
+ * \ingroup misc
+ *
+ * This class is designed to be subclassed in Python or C++
+ * and is callable from both places. It uses SWIG's
+ * "director" feature to implement the magic.
+ * It's slow. Don't use it in a performance critical path.
+ *
+ * Override eval to define the behavior.
+ * Use calleval to invoke eval (this kludge is required to allow a
+ * python specific "shim" to be inserted.
+ */
+class GR_RUNTIME_API gr_feval_p
+{
+protected:
+ /*!
+ * \brief override this to define the function
+ */
+ virtual void eval(pmt::pmt_t x);
+
+public:
+ gr_feval_p() {}
+ virtual ~gr_feval_p();
+
+ virtual void calleval(pmt::pmt_t x); // invoke "eval"
+};
+
+/*!
+ * \brief trivial examples / test cases showing C++ calling Python code
+ */
+GR_RUNTIME_API double gr_feval_dd_example(gr_feval_dd *f, double x);
+GR_RUNTIME_API gr_complex gr_feval_cc_example(gr_feval_cc *f, gr_complex x);
+GR_RUNTIME_API long gr_feval_ll_example(gr_feval_ll *f, long x);
+GR_RUNTIME_API void gr_feval_example(gr_feval *f);
+
+#endif /* INCLUDED_GR_FEVAL_H */
diff --git a/gnuradio-runtime/include/gr_flowgraph.h b/gnuradio-runtime/include/gr_flowgraph.h
new file mode 100644
index 0000000000..107c50b7b6
--- /dev/null
+++ b/gnuradio-runtime/include/gr_flowgraph.h
@@ -0,0 +1,251 @@
+/* -*- 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_FLOWGRAPH_H
+#define INCLUDED_GR_FLOWGRAPH_H
+
+#include <gr_runtime_api.h>
+#include <gr_basic_block.h>
+#include <iostream>
+
+/*!
+ * \brief Class representing a specific input or output graph endpoint
+ * \ingroup internal
+ */
+class GR_RUNTIME_API gr_endpoint
+{
+private:
+ gr_basic_block_sptr d_basic_block;
+ int d_port;
+
+public:
+ gr_endpoint() : d_basic_block(), d_port(0) { }
+ gr_endpoint(gr_basic_block_sptr block, int port) { d_basic_block = block; d_port = port; }
+ gr_basic_block_sptr block() const { return d_basic_block; }
+ int port() const { return d_port; }
+
+ bool operator==(const gr_endpoint &other) const;
+};
+
+inline bool gr_endpoint::operator==(const gr_endpoint &other) const
+{
+ return (d_basic_block == other.d_basic_block &&
+ d_port == other.d_port);
+}
+
+class GR_RUNTIME_API gr_msg_endpoint
+{
+private:
+ gr_basic_block_sptr d_basic_block;
+ pmt::pmt_t d_port;
+ bool d_is_hier;
+public:
+ gr_msg_endpoint() : d_basic_block(), d_port(pmt::PMT_NIL) { }
+ gr_msg_endpoint(gr_basic_block_sptr block, pmt::pmt_t port, bool is_hier=false){ d_basic_block = block; d_port = port; d_is_hier = is_hier;}
+ gr_basic_block_sptr block() const { return d_basic_block; }
+ pmt::pmt_t port() const { return d_port; }
+ bool is_hier() const { return d_is_hier; }
+ void set_hier(bool h) { d_is_hier = h; }
+
+ bool operator==(const gr_msg_endpoint &other) const;
+
+};
+
+inline bool gr_msg_endpoint::operator==(const gr_msg_endpoint &other) const
+{
+ return (d_basic_block == other.d_basic_block &&
+ pmt::equal(d_port, other.d_port));
+}
+
+
+// Hold vectors of gr_endpoint objects
+typedef std::vector<gr_endpoint> gr_endpoint_vector_t;
+typedef std::vector<gr_endpoint>::iterator gr_endpoint_viter_t;
+
+/*!
+ *\brief Class representing a connection between to graph endpoints
+ *
+ */
+class GR_RUNTIME_API gr_edge
+{
+public:
+ gr_edge() : d_src(), d_dst() { };
+ gr_edge(const gr_endpoint &src, const gr_endpoint &dst) : d_src(src), d_dst(dst) { }
+ ~gr_edge();
+
+ const gr_endpoint &src() const { return d_src; }
+ const gr_endpoint &dst() const { return d_dst; }
+
+private:
+ gr_endpoint d_src;
+ gr_endpoint d_dst;
+};
+
+
+// Hold vectors of gr_edge objects
+typedef std::vector<gr_edge> gr_edge_vector_t;
+typedef std::vector<gr_edge>::iterator gr_edge_viter_t;
+
+
+/*!
+ *\brief Class representing a msg connection between to graph msg endpoints
+ *
+ */
+class GR_RUNTIME_API gr_msg_edge
+{
+public:
+ gr_msg_edge() : d_src(), d_dst() { };
+ gr_msg_edge(const gr_msg_endpoint &src, const gr_msg_endpoint &dst) : d_src(src), d_dst(dst) { }
+ ~gr_msg_edge() {}
+
+ const gr_msg_endpoint &src() const { return d_src; }
+ const gr_msg_endpoint &dst() const { return d_dst; }
+
+private:
+ gr_msg_endpoint d_src;
+ gr_msg_endpoint d_dst;
+};
+
+// Hold vectors of gr_edge objects
+typedef std::vector<gr_msg_edge> gr_msg_edge_vector_t;
+typedef std::vector<gr_msg_edge>::iterator gr_msg_edge_viter_t;
+
+// Create a shared pointer to a heap allocated flowgraph
+// (types defined in gr_runtime_types.h)
+GR_RUNTIME_API gr_flowgraph_sptr gr_make_flowgraph();
+
+/*!
+ * \brief Class representing a directed, acyclic graph of basic blocks
+ * \ingroup internal
+ */
+class GR_RUNTIME_API gr_flowgraph
+{
+public:
+ friend GR_RUNTIME_API gr_flowgraph_sptr gr_make_flowgraph();
+
+ // Destruct an arbitrary flowgraph
+ ~gr_flowgraph();
+
+ // Connect two endpoints
+ void connect(const gr_endpoint &src, const gr_endpoint &dst);
+
+ // Disconnect two endpoints
+ void disconnect(const gr_endpoint &src, const gr_endpoint &dst);
+
+ // Connect an output port to an input port (convenience)
+ void connect(gr_basic_block_sptr src_block, int src_port,
+ gr_basic_block_sptr dst_block, int dst_port);
+
+ // Disconnect an input port from an output port (convenience)
+ void disconnect(gr_basic_block_sptr src_block, int src_port,
+ gr_basic_block_sptr dst_block, int dst_port);
+
+ // Connect two msg endpoints
+ void connect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst);
+
+ // Disconnect two msg endpoints
+ void disconnect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst);
+
+ // Validate connectivity, raise exception if invalid
+ void validate();
+
+ // Clear existing flowgraph
+ void clear();
+
+ // Return vector of edges
+ const gr_edge_vector_t &edges() const { return d_edges; }
+
+ // Return vector of msg edges
+ const gr_msg_edge_vector_t &msg_edges() const { return d_msg_edges; }
+
+ // Return vector of connected blocks
+ gr_basic_block_vector_t calc_used_blocks();
+
+ // Return toplogically sorted vector of blocks. All the sources come first.
+ gr_basic_block_vector_t topological_sort(gr_basic_block_vector_t &blocks);
+
+ // Return vector of vectors of disjointly connected blocks, topologically
+ // sorted.
+ std::vector<gr_basic_block_vector_t> partition();
+
+protected:
+ gr_basic_block_vector_t d_blocks;
+ gr_edge_vector_t d_edges;
+ gr_msg_edge_vector_t d_msg_edges;
+
+ gr_flowgraph();
+ std::vector<int> calc_used_ports(gr_basic_block_sptr block, bool check_inputs);
+ gr_basic_block_vector_t calc_downstream_blocks(gr_basic_block_sptr block, int port);
+ gr_edge_vector_t calc_upstream_edges(gr_basic_block_sptr block);
+ bool has_block_p(gr_basic_block_sptr block);
+ gr_edge calc_upstream_edge(gr_basic_block_sptr block, int port);
+
+private:
+
+ void check_valid_port(gr_io_signature_sptr sig, int port);
+ void check_valid_port(const gr_msg_endpoint &e);
+ void check_dst_not_used(const gr_endpoint &dst);
+ void check_type_match(const gr_endpoint &src, const gr_endpoint &dst);
+ gr_edge_vector_t calc_connections(gr_basic_block_sptr block, bool check_inputs); // false=use outputs
+ void check_contiguity(gr_basic_block_sptr block, const std::vector<int> &used_ports, bool check_inputs);
+
+ gr_basic_block_vector_t calc_downstream_blocks(gr_basic_block_sptr block);
+ gr_basic_block_vector_t calc_reachable_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks);
+ void reachable_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks);
+ gr_basic_block_vector_t calc_adjacent_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks);
+ gr_basic_block_vector_t sort_sources_first(gr_basic_block_vector_t &blocks);
+ bool source_p(gr_basic_block_sptr block);
+ void topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &output);
+};
+
+// Convenience functions
+inline
+void gr_flowgraph::connect(gr_basic_block_sptr src_block, int src_port,
+ gr_basic_block_sptr dst_block, int dst_port)
+{
+ connect(gr_endpoint(src_block, src_port),
+ gr_endpoint(dst_block, dst_port));
+}
+
+inline
+void gr_flowgraph::disconnect(gr_basic_block_sptr src_block, int src_port,
+ gr_basic_block_sptr dst_block, int dst_port)
+{
+ disconnect(gr_endpoint(src_block, src_port),
+ gr_endpoint(dst_block, dst_port));
+}
+
+inline std::ostream&
+operator <<(std::ostream &os, const gr_endpoint endp)
+{
+ os << endp.block()->alias() << ":" << endp.port();
+ return os;
+}
+
+inline std::ostream&
+operator <<(std::ostream &os, const gr_edge edge)
+{
+ os << edge.src() << "->" << edge.dst();
+ return os;
+}
+
+#endif /* INCLUDED_GR_FLOWGRAPH_H */
diff --git a/gnuradio-runtime/include/gr_fxpt.h b/gnuradio-runtime/include/gr_fxpt.h
new file mode 100644
index 0000000000..b7e3518ffb
--- /dev/null
+++ b/gnuradio-runtime/include/gr_fxpt.h
@@ -0,0 +1,104 @@
+/* -*- 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_FXPT_H
+#define INCLUDED_GR_FXPT_H
+
+#include <gr_runtime_api.h>
+#include <gr_types.h>
+
+/*!
+ * \brief fixed point sine and cosine and friends.
+ * \ingroup misc
+ *
+ * fixed pt radians
+ * --------- --------
+ * -2**31 -pi
+ * 0 0
+ * 2**31-1 pi - epsilon
+ *
+ */
+class GR_RUNTIME_API gr_fxpt
+{
+ static const int WORDBITS = 32;
+ static const int NBITS = 10;
+ static const float s_sine_table[1 << NBITS][2];
+ static const float PI;
+ static const float TWO_TO_THE_31;
+public:
+
+ static gr_int32
+ float_to_fixed (float x)
+ {
+ // Fold x into -PI to PI.
+ int d = (int)floor(x/2/PI+0.5);
+ x -= d*2*PI;
+ // And convert to an integer.
+ return (gr_int32) ((float) x * TWO_TO_THE_31 / PI);
+ }
+
+ static float
+ fixed_to_float (gr_int32 x)
+ {
+ return x * (PI / TWO_TO_THE_31);
+ }
+
+ /*!
+ * \brief Given a fixed point angle x, return float sine (x)
+ */
+ static float
+ sin (gr_int32 x)
+ {
+ gr_uint32 ux = x;
+ int index = ux >> (WORDBITS - NBITS);
+ return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1];
+ }
+
+ /*
+ * \brief Given a fixed point angle x, return float cosine (x)
+ */
+ static float
+ cos (gr_int32 x)
+ {
+ gr_uint32 ux = x + 0x40000000;
+ int index = ux >> (WORDBITS - NBITS);
+ return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1];
+ }
+
+ /*
+ * \brief Given a fixedpoint angle x, return float cos(x) and sin (x)
+ */
+ static void sincos(gr_int32 x, float *s, float *c)
+ {
+ gr_uint32 ux = x;
+ int sin_index = ux >> (WORDBITS - NBITS);
+ *s = s_sine_table[sin_index][0] * (ux >> 1) + s_sine_table[sin_index][1];
+
+ ux = x + 0x40000000;
+ int cos_index = ux >> (WORDBITS - NBITS);
+ *c = s_sine_table[cos_index][0] * (ux >> 1) + s_sine_table[cos_index][1];
+
+ return;
+ }
+
+};
+
+#endif /* INCLUDED_GR_FXPT_H */
diff --git a/gnuradio-runtime/include/gr_fxpt_nco.h b/gnuradio-runtime/include/gr_fxpt_nco.h
new file mode 100644
index 0000000000..36b99ee132
--- /dev/null
+++ b/gnuradio-runtime/include/gr_fxpt_nco.h
@@ -0,0 +1,153 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,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_FXPT_NCO_H
+#define INCLUDED_GR_FXPT_NCO_H
+
+#include <gr_runtime_api.h>
+#include <gr_fxpt.h>
+#include <gr_complex.h>
+
+/*!
+ * \brief Numerically Controlled Oscillator (NCO)
+ * \ingroup misc
+ */
+class /*GR_RUNTIME_API*/ gr_fxpt_nco {
+ gr_uint32 d_phase;
+ gr_int32 d_phase_inc;
+
+public:
+ gr_fxpt_nco () : d_phase (0), d_phase_inc (0) {}
+
+ ~gr_fxpt_nco () {}
+
+ // radians
+ void set_phase (float angle) {
+ d_phase = gr_fxpt::float_to_fixed (angle);
+ }
+
+ void adjust_phase (float delta_phase) {
+ d_phase += gr_fxpt::float_to_fixed (delta_phase);
+ }
+
+ // angle_rate is in radians / step
+ void set_freq (float angle_rate){
+ d_phase_inc = gr_fxpt::float_to_fixed (angle_rate);
+ }
+
+ // angle_rate is a delta in radians / step
+ void adjust_freq (float delta_angle_rate)
+ {
+ d_phase_inc += gr_fxpt::float_to_fixed (delta_angle_rate);
+ }
+
+ // increment current phase angle
+
+ void step ()
+ {
+ d_phase += d_phase_inc;
+ }
+
+ void step (int n)
+ {
+ d_phase += d_phase_inc * n;
+ }
+
+ // units are radians / step
+ float get_phase () const { return gr_fxpt::fixed_to_float (d_phase); }
+ float get_freq () const { return gr_fxpt::fixed_to_float (d_phase_inc); }
+
+ // compute sin and cos for current phase angle
+ void sincos (float *sinx, float *cosx) const
+ {
+ *sinx = gr_fxpt::sin (d_phase);
+ *cosx = gr_fxpt::cos (d_phase);
+ }
+
+ // compute cos and sin for a block of phase angles
+ void sincos (gr_complex *output, int noutput_items, double ampl=1.0)
+ {
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = gr_complex(gr_fxpt::cos (d_phase) * ampl, gr_fxpt::sin (d_phase) * ampl);
+ step ();
+ }
+ }
+
+ // compute sin for a block of phase angles
+ void sin (float *output, int noutput_items, double ampl=1.0)
+ {
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (float)(gr_fxpt::sin (d_phase) * ampl);
+ step ();
+ }
+ }
+
+ // compute cos for a block of phase angles
+ void cos (float *output, int noutput_items, double ampl=1.0)
+ {
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (float)(gr_fxpt::cos (d_phase) * ampl);
+ step ();
+ }
+ }
+
+ // compute sin for a block of phase angles
+ void sin (short *output, int noutput_items, double ampl=1.0)
+ {
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (short)(gr_fxpt::sin (d_phase) * ampl);
+ step ();
+ }
+ }
+
+ // compute cos for a block of phase angles
+ void cos (short *output, int noutput_items, double ampl=1.0)
+ {
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (short)(gr_fxpt::cos (d_phase) * ampl);
+ step ();
+ }
+ }
+
+ // compute sin for a block of phase angles
+ void sin (int *output, int noutput_items, double ampl=1.0)
+ {
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (int)(gr_fxpt::sin (d_phase) * ampl);
+ step ();
+ }
+ }
+
+ // compute cos for a block of phase angles
+ void cos (int *output, int noutput_items, double ampl=1.0)
+ {
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (int)(gr_fxpt::cos (d_phase) * ampl);
+ step ();
+ }
+ }
+
+ // compute cos or sin for current phase angle
+ float cos () const { return gr_fxpt::cos (d_phase); }
+ float sin () const { return gr_fxpt::sin (d_phase); }
+};
+
+#endif /* INCLUDED_GR_FXPT_NCO_H */
diff --git a/gnuradio-runtime/include/gr_fxpt_vco.h b/gnuradio-runtime/include/gr_fxpt_vco.h
new file mode 100644
index 0000000000..15e7327f79
--- /dev/null
+++ b/gnuradio-runtime/include/gr_fxpt_vco.h
@@ -0,0 +1,73 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,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_GR_FXPT_VCO_H
+#define INCLUDED_GR_FXPT_VCO_H
+
+#include <gr_runtime_api.h>
+#include <gr_fxpt.h>
+#include <gr_complex.h>
+
+/*!
+ * \brief Voltage Controlled Oscillator (VCO)
+ * \ingroup misc
+ */
+class /*GR_RUNTIME_API*/ gr_fxpt_vco {
+ gr_int32 d_phase;
+
+public:
+ gr_fxpt_vco () : d_phase (0) {}
+
+ ~gr_fxpt_vco () {}
+
+ // radians
+ void set_phase (float angle) {
+ d_phase = gr_fxpt::float_to_fixed (angle);
+ }
+
+ void adjust_phase (float delta_phase) {
+ d_phase += gr_fxpt::float_to_fixed (delta_phase);
+ }
+
+ float get_phase () const { return gr_fxpt::fixed_to_float (d_phase); }
+
+ // compute sin and cos for current phase angle
+ void sincos (float *sinx, float *cosx) const
+ {
+ *sinx = gr_fxpt::sin (d_phase);
+ *cosx = gr_fxpt::cos (d_phase);
+ }
+
+ // compute a block at a time
+ void cos (float *output, const float *input, int noutput_items, float k, float ampl = 1.0)
+ {
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (float)(gr_fxpt::cos (d_phase) * ampl);
+ adjust_phase(input[i] * k);
+ }
+ }
+
+ // compute cos or sin for current phase angle
+ float cos () const { return gr_fxpt::cos (d_phase); }
+ float sin () const { return gr_fxpt::sin (d_phase); }
+};
+
+#endif /* INCLUDED_GR_FXPT_VCO_H */
diff --git a/gnuradio-runtime/include/gr_hier_block2.h b/gnuradio-runtime/include/gr_hier_block2.h
new file mode 100644
index 0000000000..c39a98f6d7
--- /dev/null
+++ b/gnuradio-runtime/include/gr_hier_block2.h
@@ -0,0 +1,208 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2007,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.
+ */
+#ifndef INCLUDED_GR_HIER_BLOCK2_H
+#define INCLUDED_GR_HIER_BLOCK2_H
+
+#include <gr_runtime_api.h>
+#include <gr_basic_block.h>
+
+/*!
+ * \brief public constructor for gr_hier_block2
+
+ */
+GR_RUNTIME_API gr_hier_block2_sptr gr_make_hier_block2(const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature);
+
+class gr_hier_block2_detail;
+
+/*!
+ * \brief Hierarchical container class for gr_block's and gr_hier_block2's
+ * \ingroup container_blk
+ * \ingroup base_blk
+ *
+ */
+class GR_RUNTIME_API gr_hier_block2 : public gr_basic_block
+{
+private:
+ friend class gr_hier_block2_detail;
+ friend GR_RUNTIME_API gr_hier_block2_sptr gr_make_hier_block2(const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature);
+
+ /*!
+ * \brief Private implementation details of gr_hier_block2
+ */
+ gr_hier_block2_detail *d_detail;
+
+protected:
+ gr_hier_block2 (void){} //allows pure virtual interface sub-classes
+ gr_hier_block2(const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature);
+
+public:
+ virtual ~gr_hier_block2();
+
+ /*!
+ * \brief typedef for object returned from self().
+ *
+ * This type is only guaranteed to be passable to connect and disconnect.
+ * No other assumptions should be made about it.
+ */
+ typedef gr_basic_block_sptr opaque_self;
+
+ /*!
+ * \brief Return an object, representing the current block, which can be passed to connect.
+ *
+ * The returned object may only be used as an argument to connect or disconnect.
+ * Any other use of self() results in unspecified (erroneous) behavior.
+ */
+ opaque_self self();
+
+ /*!
+ * \brief Add a stand-alone (possibly hierarchical) block to internal graph
+ *
+ * This adds a gr-block or hierarchical block to the internal graph
+ * without wiring it to anything else.
+ */
+ void connect(gr_basic_block_sptr block);
+
+ /*!
+ * \brief Add gr-blocks or hierarchical blocks to internal graph and wire together
+ *
+ * This adds (if not done earlier by another connect) a pair of gr-blocks or
+ * hierarchical blocks to the internal flowgraph, and wires the specified output
+ * port to the specified input port.
+ */
+ void connect(gr_basic_block_sptr src, int src_port,
+ gr_basic_block_sptr dst, int dst_port);
+
+ /*!
+ * \brief Add gr-blocks or hierarchical blocks to internal graph and wire together
+ *
+ * This adds (if not done earlier by another connect) a pair of gr-blocks or
+ * hierarchical blocks to the internal message port subscription
+ */
+ void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport);
+ void msg_connect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport);
+ void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport);
+ void msg_disconnect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport);
+
+ /*!
+ * \brief Remove a gr-block or hierarchical block from the internal flowgraph.
+ *
+ * This removes a gr-block or hierarchical block from the internal flowgraph,
+ * disconnecting it from other blocks as needed.
+ *
+ */
+ void disconnect(gr_basic_block_sptr block);
+
+ /*!
+ * \brief Disconnect a pair of gr-blocks or hierarchical blocks in internal
+ * flowgraph.
+ *
+ * This disconnects the specified input port from the specified output port
+ * of a pair of gr-blocks or hierarchical blocks.
+ */
+ void disconnect(gr_basic_block_sptr src, int src_port,
+ gr_basic_block_sptr dst, int dst_port);
+
+ /*!
+ * \brief Disconnect all connections in the internal flowgraph.
+ *
+ * This call removes all output port to input port connections in the internal
+ * flowgraph.
+ */
+ void disconnect_all();
+
+ /*!
+ * Lock a flowgraph in preparation for reconfiguration. When an equal
+ * number of calls to lock() and unlock() have occurred, the flowgraph
+ * will be reconfigured.
+ *
+ * N.B. lock() and unlock() may not be called from a flowgraph thread
+ * (E.g., gr_block::work method) or deadlock will occur when
+ * reconfiguration happens.
+ */
+ virtual void lock();
+
+ /*!
+ * Unlock a flowgraph in preparation for reconfiguration. When an equal
+ * number of calls to lock() and unlock() have occurred, the flowgraph
+ * will be reconfigured.
+ *
+ * N.B. lock() and unlock() may not be called from a flowgraph thread
+ * (E.g., gr_block::work method) or deadlock will occur when
+ * reconfiguration happens.
+ */
+ virtual void unlock();
+
+ // This is a public method for ease of code organization, but should be
+ // ignored by the user.
+ gr_flat_flowgraph_sptr flatten() const;
+
+ gr_hier_block2_sptr to_hier_block2(); // Needed for Python type coercion
+
+ bool has_msg_port(pmt::pmt_t which_port){
+ return message_port_is_hier(which_port) || gr_basic_block::has_msg_port(which_port);
+ }
+
+ bool message_port_is_hier(pmt::pmt_t port_id){
+ return message_port_is_hier_in(port_id) || message_port_is_hier_out(port_id);
+ }
+ bool message_port_is_hier_in(pmt::pmt_t port_id){
+ return pmt::list_has(hier_message_ports_in, port_id);
+ }
+ bool message_port_is_hier_out(pmt::pmt_t port_id){
+ return pmt::list_has(hier_message_ports_out, port_id);
+ }
+
+ pmt::pmt_t hier_message_ports_in;
+ pmt::pmt_t hier_message_ports_out;
+
+ void message_port_register_hier_in(pmt::pmt_t port_id){
+ if(pmt::list_has(hier_message_ports_in, port_id))
+ throw std::invalid_argument("hier msg in port by this name already registered");
+ if(msg_queue.find(port_id) != msg_queue.end())
+ throw std::invalid_argument("block already has a primitive input port by this name");
+ hier_message_ports_in = pmt::list_add(hier_message_ports_in, port_id);
+ }
+ void message_port_register_hier_out(pmt::pmt_t port_id){
+ if(pmt::list_has(hier_message_ports_out, port_id))
+ throw std::invalid_argument("hier msg out port by this name already registered");
+ if(pmt::dict_has_key(message_subscribers, port_id))
+ throw std::invalid_argument("block already has a primitive output port by this name");
+ hier_message_ports_out = pmt::list_add(hier_message_ports_out, port_id);
+ }
+
+};
+
+inline gr_hier_block2_sptr cast_to_hier_block2_sptr(gr_basic_block_sptr block) {
+ return boost::dynamic_pointer_cast<gr_hier_block2, gr_basic_block>(block);
+}
+
+#endif /* INCLUDED_GR_HIER_BLOCK2_H */
diff --git a/gnuradio-runtime/include/gr_io_signature.h b/gnuradio-runtime/include/gr_io_signature.h
new file mode 100644
index 0000000000..345cd6b9d2
--- /dev/null
+++ b/gnuradio-runtime/include/gr_io_signature.h
@@ -0,0 +1,117 @@
+/* -*- 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.
+ */
+
+#ifndef INCLUDED_IO_SIGNATURE_H
+#define INCLUDED_IO_SIGNATURE_H
+
+#include <gr_runtime_api.h>
+#include <gr_runtime_types.h>
+
+/*!
+ * \brief Create an i/o signature
+ *
+ * \ingroup internal
+ * \param min_streams specify minimum number of streams (>= 0)
+ * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite)
+ * \param sizeof_stream_item specify the size of the items in each stream
+ */
+GR_RUNTIME_API gr_io_signature_sptr
+gr_make_io_signature(int min_streams, int max_streams,
+ int sizeof_stream_item);
+
+/*!
+ * \brief Create an i/o signature
+ *
+ * \param min_streams specify minimum number of streams (>= 0)
+ * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite)
+ * \param sizeof_stream_item1 specify the size of the items in the first stream
+ * \param sizeof_stream_item2 specify the size of the items in the second and subsequent streams
+ */
+GR_RUNTIME_API gr_io_signature_sptr
+gr_make_io_signature2(int min_streams, int max_streams,
+ int sizeof_stream_item1,
+ int sizeof_stream_item2
+ );
+
+/*!
+ * \brief Create an i/o signature
+ *
+ * \param min_streams specify minimum number of streams (>= 0)
+ * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite)
+ * \param sizeof_stream_item1 specify the size of the items in the first stream
+ * \param sizeof_stream_item2 specify the size of the items in the second stream
+ * \param sizeof_stream_item3 specify the size of the items in the third and subsequent streams
+ */
+GR_RUNTIME_API 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
+ );
+
+/*!
+ * \brief Create an i/o signature
+ *
+ * \param min_streams specify minimum number of streams (>= 0)
+ * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite)
+ * \param sizeof_stream_items specify the size of the items in the streams
+ *
+ * If there are more streams than there are entries in sizeof_stream_items, the
+ * value of the last entry in sizeof_stream_items is used for the missing values.
+ * sizeof_stream_items must contain at least 1 entry.
+ */
+GR_RUNTIME_API gr_io_signature_sptr
+gr_make_io_signaturev(int min_streams, int max_streams,
+ const std::vector<int> &sizeof_stream_items);
+
+
+/*!
+ * \brief i/o signature for input and output ports.
+ * \brief misc
+ */
+class GR_RUNTIME_API gr_io_signature {
+ int d_min_streams;
+ int d_max_streams;
+ std::vector<int> d_sizeof_stream_item;
+
+ gr_io_signature(int min_streams, int max_streams,
+ const std::vector<int> &sizeof_stream_items);
+
+ friend GR_RUNTIME_API gr_io_signature_sptr
+ gr_make_io_signaturev(int min_streams,
+ int max_streams,
+ const std::vector<int> &sizeof_stream_items);
+
+ public:
+
+ static const int IO_INFINITE = -1;
+
+ ~gr_io_signature ();
+
+ int min_streams () const { return d_min_streams; }
+ int max_streams () const { return d_max_streams; }
+ int sizeof_stream_item (int index) const;
+ std::vector<int> sizeof_stream_items() const;
+};
+
+
+#endif /* INCLUDED_IO_SIGNATURE_H */
diff --git a/gnuradio-runtime/include/gr_logger.h b/gnuradio-runtime/include/gr_logger.h
new file mode 100644
index 0000000000..5898d0bfad
--- /dev/null
+++ b/gnuradio-runtime/include/gr_logger.h
@@ -0,0 +1,644 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012-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.
+ */
+
+/*******************************************************************************
+* Author: Mark Plett
+* Description:
+* The gr_logger module wraps the log4cpp library for logging in gnuradio
+*******************************************************************************/
+
+#ifndef INCLUDED_GR_LOGGER_H
+#define INCLUDED_GR_LOGGER_H
+
+/*!
+* \file gr_logger.h
+* \ingroup logging
+* \brief GNURADIO logging wrapper for log4cpp library (C++ port of log4j)
+*
+*/
+
+#include <gr_runtime_api.h>
+#include <assert.h>
+#include <iostream>
+#include <time.h>
+#include <boost/filesystem.hpp>
+#include <boost/thread.hpp>
+
+#ifdef ENABLE_GR_LOG
+
+// We have three configurations... first logging to stdout/stderr
+#ifndef HAVE_LOG4CPP
+//#warning GR logging Enabled and using std::cout
+
+typedef std::string gr_logger_ptr;
+
+#define GR_LOG_DECLARE_LOGPTR(logger)
+#define GR_LOG_ASSIGN_LOGPTR(logger,name)
+#define GR_CONFIG_LOGGER(config)
+#define GR_CONFIG_AND_WATCH_LOGGER(config,period)
+#define GR_LOG_GETLOGGER(logger, name)
+#define GR_SET_LEVEL(name, level)
+#define GR_LOG_SET_LEVEL(logger, level)
+#define GR_GET_LEVEL(name, level)
+#define GR_LOG_GET_LEVEL(logger, level)
+#define GR_ADD_CONSOLE_APPENDER(logger,target,pattern)
+#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern)
+#define GR_ADD_FILE_APPENDER(name,filename,append,pattern)
+#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern)
+#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern)
+#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern)
+#define GR_GET_LOGGER_NAMES(names)
+#define GR_RESET_CONFIGURATION()
+#define GR_DEBUG(name, msg) std::cout<<"DEBUG: "<<msg<<std::endl
+#define GR_INFO(name, msg) std::cout<<"INFO: "<<msg<<std::endl
+#define GR_NOTICE(name, msg) std::cout<<"NOTICE: "<<msg<<std::endl
+#define GR_WARN(name, msg) std::cerr<<"WARN: "<<msg<<std::endl
+#define GR_ERROR(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
+#define GR_ALERT(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
+#define GR_CRIT(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl
+#define GR_FATAL(name, msg) std::cerr<<"FATAL: "<<msg<<std::endl
+#define GR_EMERG(name, msg) std::cerr<<"EMERG: "<<msg<<std::endl
+#define GR_ERRORIF(name, cond, msg) {if((cond)) std::cerr<<"ERROR: "<<msg<<std::endl;}
+#define GR_ASSERT(name, cond, msg) {if(!(cond)) std::cerr<<"FATAL: "<<msg<<std::endl; assert(cond);}
+#define GR_LOG_DEBUG(logger, msg) std::cout<<"DEBUG: "<<msg<<std::endl
+#define GR_LOG_INFO(logger, msg) std::cout<<"INFO: "<<msg<<std::endl
+#define GR_LOG_NOTICE(logger, msg) std::cout<<"NOTICE: "<<msg<<std::endl
+#define GR_LOG_WARN(logger, msg) std::cerr<<"WARN: "<<msg<<std::endl
+#define GR_LOG_ERROR(logger, msg) std::cerr<<"ERROR: "<<msg<<std::endl
+#define GR_LOG_ALERT(logger, msg) std::cerr<<"ALERT: "<<msg<<std::endl
+#define GR_LOG_CRIT(logger, msg) std::cerr<<"CRIT: "<<msg<<std::endl
+#define GR_LOG_FATAL(logger, msg) std::cerr<<"FATAL: "<<msg<<std::endl
+#define GR_LOG_EMERG(logger, msg) std::cerr<<"EMERG: "<<msg<<std::endl
+#define GR_LOG_ERRORIF(logger, cond, msg) {\
+ if((cond)) std::cerr<<"ERROR: "<<msg<<std::endl;}
+#define GR_LOG_ASSERT(logger, cond, msg) {\
+ if(!(cond)) {std::cerr<<"FATAL: "<<msg<<std::endl; assert(cond);};}
+
+#else /* HAVE_LOG4CPP */
+// Second configuration...logging to log4cpp
+
+#include <log4cpp/Category.hh>
+#include <log4cpp/PropertyConfigurator.hh>
+#include <log4cpp/FileAppender.hh>
+#include <log4cpp/RollingFileAppender.hh>
+#include <log4cpp/OstreamAppender.hh>
+#include <log4cpp/PatternLayout.hh>
+
+/*!
+ * \brief GR_LOG macros
+ * \ingroup logging
+ *
+ * These macros wrap the standard LOG4CPP_LEVEL macros. The availablie macros
+ * are:
+ * GR_LOG_DEBUG
+ * GR_LOG_INFO
+ * GR_LOG_WARN
+ * GR_LOG_TRACE
+ * GR_LOG_ERROR
+ * GR_LOG_ALERT
+ * GR_LOG_CRIT
+ * GR_LOG_FATAL
+ * GR_LOG_EMERG
+ */
+typedef log4cpp::Category* gr_logger_ptr;
+
+/* Macros for Programmatic Configuration */
+#define GR_LOG_DECLARE_LOGPTR(logger) \
+ gr_logger_ptr logger;
+
+#define GR_LOG_ASSIGN_LOGPTR(logger,name) \
+ logger = logger_get_logger(name);
+
+#define GR_CONFIG_LOGGER(config) \
+ logger_config::load_config(config)
+
+#define GR_CONFIG_AND_WATCH_LOGGER(config,period) \
+ logger_config::load_config(config,period)
+
+#define GR_LOG_GETLOGGER(logger, name) \
+ gr_logger_ptr logger = logger_get_logger(name);
+
+#define GR_SET_LEVEL(name, level){ \
+ gr_logger_ptr logger = logger_get_logger(name);\
+ logger_set_level(logger,level);}
+
+#define GR_LOG_SET_LEVEL(logger, level) \
+ logger_set_level(logger, level);
+
+#define GR_GET_LEVEL(name, level){ \
+ gr_logger_ptr logger = logger_get_logger(name);\
+ logger_get_level(logger,level);}
+
+#define GR_LOG_GET_LEVEL(logger, level) \
+ logger_get_level(logger,level);
+
+#define GR_ADD_CONSOLE_APPENDER(name,target,pattern){\
+ gr_logger_ptr logger = logger_get_logger(name);\
+ logger_add_console_appender(logger,target,pattern);}
+
+#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern){\
+ logger_add_console_appender(logger,target,pattern);}
+
+#define GR_ADD_FILE_APPENDER(name,filename,append,pattern){\
+ gr_logger_ptr logger = logger_get_logger(name);\
+ logger_add_file_appender(logger,filename,append,pattern);}
+
+#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern){\
+ logger_add_file_appender(logger,filename,append,pattern);}
+
+#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern){\
+ gr_logger_ptr logger = logger_get_logger(name);\
+ logger_add_rollingfile_appender(logger,filename,filesize,bkup_index,append,mode,pattern);}
+
+#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern){\
+ logger_add_rollingfile_appender(logger,filename,filesize,bkup_index,append,mode,pattern);}
+
+#define GR_GET_LOGGER_NAMES(names){ \
+ names = logger_get_logger_names();}
+
+#define GR_RESET_CONFIGURATION(){ \
+ logger_config::reset_config();}
+
+/* Logger name referenced macros */
+#define GR_DEBUG(name, msg) { \
+ gr_logger_ptr logger = logger_get_logger(name);\
+ *logger<< log4cpp::Priority::DEBUG << msg << log4cpp::eol;}
+
+#define GR_INFO(name, msg) { \
+ gr_logger_ptr logger = logger_get_logger(name);\
+ *logger<< log4cpp::Priority::INFO << msg << log4cpp::eol;}
+
+#define GR_NOTICE(name, msg) { \
+ gr_logger_ptr logger = logger_get_logger(name);\
+ *logger << log4cpp::Priority::NOTICE << msg;}
+
+#define GR_WARN(name, msg) { \
+ gr_logger_ptr logger = logger_get_logger(name);\
+ *logger<< log4cpp::Priority::WARN << msg << log4cpp::eol;}
+
+#define GR_ERROR(name, msg) { \
+ gr_logger_ptr logger = logger_get_logger(name);\
+ *logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;}
+
+#define GR_CRIT(name, msg) { \
+ gr_logger_ptr logger = logger_get_logger(name);\
+ *logger<< log4cpp::Priority::CRIT << msg << log4cpp::eol;}
+
+#define GR_ALERT(name, msg) { \
+ gr_logger_ptr logger = logger_get_logger(name);\
+ *logger<< log4cpp::Priority::ALERT << msg << log4cpp::eol;}
+
+#define GR_FATAL(name, msg) { \
+ gr_logger_ptr logger = logger_get_logger(name);\
+ *logger<< log4cpp::Priority::FATAL << msg << log4cpp::eol;}
+
+#define GR_EMERG(name, msg) { \
+ gr_logger_ptr logger = logger_get_logger(name);\
+ *logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;}
+
+#define GR_ERRORIF(name, cond, msg) { \
+if((cond)){\
+ gr_logger_ptr logger = logger_get_logger(name);\
+ *logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;};\
+};
+
+#define GR_ASSERT(name, cond, msg) { \
+if(!(cond)){\
+ gr_logger_ptr logger = logger_get_logger(name);\
+ *logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;};\
+ assert(0);\
+};
+
+/* LoggerPtr Referenced Macros */
+#define GR_LOG_DEBUG(logger, msg) { \
+ *logger << log4cpp::Priority::DEBUG << msg << log4cpp::eol;}
+
+#define GR_LOG_INFO(logger, msg) { \
+ *logger << log4cpp::Priority::INFO << msg << log4cpp::eol;}
+
+#define GR_LOG_NOTICE(logger, msg) { \
+ *logger << log4cpp::Priority::NOTICE << msg << log4cpp::eol;}
+
+#define GR_LOG_WARN(logger, msg) { \
+ *logger << log4cpp::Priority::WARN << msg << log4cpp::eol;}
+
+#define GR_LOG_ERROR(logger, msg) { \
+ *logger << log4cpp::Priority::ERROR << msg << log4cpp::eol;}
+
+#define GR_LOG_CRIT(logger, msg) { \
+ *logger << log4cpp::Priority::CRIT << msg << log4cpp::eol;}
+
+#define GR_LOG_ALERT(logger, msg) { \
+ *logger << log4cpp::Priority::ALERT << msg << log4cpp::eol;}
+
+#define GR_LOG_FATAL(logger, msg) { \
+ *logger << log4cpp::Priority::FATAL << msg << log4cpp::eol;}
+
+#define GR_LOG_EMERG(logger, msg) { \
+ *logger << log4cpp::Priority::EMERG << msg << log4cpp::eol;}
+
+#define GR_LOG_ERRORIF(logger,cond, msg) { \
+if((cond)){\
+ *logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;};\
+};
+
+#define GR_LOG_ASSERT(logger, cond, msg) { \
+if(!(cond)){\
+ *logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;\
+ assert(0);};\
+};
+
+/*!
+ * \brief Class to control configuration of logger.
+ * This is a singleton that cna launch a thread to wathc a config file for changes
+ * \ingroup logging
+ */
+class logger_config {
+private:
+ /*! \brief filename of logger config file */
+ std::string filename;
+ /*! \brief Period (seconds) over which watcher thread checks config file for changes */
+ unsigned int watch_period;
+ /*! \brief Pointer to watch thread for config file changes */
+ boost::thread *watch_thread;
+
+ /*! \brief Watcher thread method
+ * /param filename Name of configuration file
+ * /param watch_period Seconds between checks for changes in config file
+ */
+ static void watch_file(std::string filename,unsigned int watch_period);
+
+ logger_config(){}; //!< Constructor
+ logger_config(logger_config const&); //!<Copy constructor
+ void operator=(logger_config const&); //!<Assignment Operator
+
+ /*! \brief destrcutor stops watch thread before exits */
+ ~logger_config(){
+ stop_watch();
+ };
+
+ /*! \brief Instance getter for singleton. Only used by class. */
+ static logger_config& get_instance(void);
+
+public:
+ /*! \brief Getter for config filename */
+ static std::string get_filename();
+ /*! \brief Getter for watch period */
+ static unsigned int get_watch_period();
+ /*! \brief Method to load configuration
+ * /param filename Name of configuration file
+ * /param watch_period Seconds between checks for changes in config file
+ */
+ static void load_config(std::string filename,unsigned int watch_period=0);
+ /*! \brief Method to stop watcher thread */
+ static void stop_watch();
+ /*! \brief method to reset logger configuration */
+ static void reset_config(void);
+};
+
+/*!
+ * \brief Retrieve a pointer to a logger by name
+ *
+ * Retrives a logger pointer
+ * \p name.
+ *
+ * \param name Name of the logger for which a pointer is requested
+ */
+GR_RUNTIME_API gr_logger_ptr logger_get_logger(std::string name);
+
+/*!
+ * \brief Load logger's configuration file.
+ *
+ * Initialize the GNU Radio logger by loading the configuration file
+ * \p config_filename.
+ *
+ * \param config_filename The configuration file. Set to "" for the
+ * basic logger that outputs to the console.
+ */
+GR_RUNTIME_API void logger_load_config(const std::string &config_filename="");
+
+/*!
+ * \brief Reset logger's configuration file.
+ *
+ * Remove all appenders from loggers
+ */
+GR_RUNTIME_API void logger_reset_config(void);
+
+GR_RUNTIME_API void logger_load_config_and_watch(const std::string &config_filename,
+ unsigned int watch_period);
+
+
+/*!
+ * \brief Set the logger's output level.
+ *
+ * Sets the level of the logger. This takes a string that is
+ * translated to the standard levels and can be (case insensitive):
+ *
+ * \li off , notset
+ * \li debug
+ * \li info
+ * \li notice
+ * \li warn
+ * \li error
+ * \li crit
+ * \li alert
+ * \li fatal
+ * \li emerg
+ *
+ * \param logger the logger to set the level of.
+ * \param level string to set the level to.
+ */
+GR_RUNTIME_API void logger_set_level(gr_logger_ptr logger, const std::string &level);
+
+/*!
+ * \brief Set the logger's output level.
+ *
+ * Sets the level of the logger. This takes the actual Log4cpp::Priority
+ * data type, which can be:
+ *
+ * \li log4cpp::Priority::NOTSET
+ * \li log4cpp::Priority::DEBUG
+ * \li log4cpp::Priority::INFO
+ * \li log4cpp::Priority::NOTICE
+ * \li log4cpp::Priority::WARN
+ * \li log4cpp::Priority::ERROR
+ * \li log4cpp::Priority::CRIT
+ * \li log4cpp::Priority::ALERT
+ * \li log4cpp::Priority::FATAL
+ * \li log4cpp::Priority::EMERG
+ *
+ * \param logger the logger to set the level of.
+ * \param level new logger level of type Log4cpp::Priority
+ */
+GR_RUNTIME_API void logger_set_level(gr_logger_ptr logger, log4cpp::Priority::Value level);
+
+
+/*!
+ * \brief Get the logger's output level.
+ *
+ * Gets the level of the logger. This returns a string that
+ * corresponds to the standard levels and can be (case insensitive):
+ *
+ * \li notset
+ * \li debug
+ * \li info
+ * \li notice
+ * \li warn
+ * \li error
+ * \li crit
+ * \li alert
+ * \li fatal
+ * \li emerg
+ *
+ * \param logger the logger to get the level of.
+ * \param level string to get the level into.
+ */
+GR_RUNTIME_API void logger_get_level(gr_logger_ptr logger, std::string &level);
+
+/*!
+ * \brief Get the logger's output level.
+ *
+ * Gets the level of the logger. This returns the actual Log4cpp::Level
+ * data type, which can be:
+ *
+ * \li log4cpp::Priority::NOTSET
+ * \li log4cpp::Priority::DEBUG
+ * \li log4cpp::Priority::INFO
+ * \li log4cpp::Priority::NOTICE
+ * \li log4cpp::Priority::WARN
+ * \li log4cpp::Priority::ERROR
+ * \li log4cpp::Priority::CRIT
+ * \li log4cpp::Priority::ALERT
+ * \li log4cpp::Priority::FATAL
+ * \li log4cpp::Priority::EMERG
+ *
+ * \param logger the logger to get the level of.
+ * \param level of the logger.
+ */
+GR_RUNTIME_API void logger_get_level(gr_logger_ptr logger, log4cpp::Priority::Value &level);
+
+/*!
+ * \brief Add console appender to a given logger
+ *
+ * Add console appender to a given logger
+ *
+ * \param logger Logger to which appender will be added
+ * \param target Std target to write 'cout' or 'cerr' (default is cout)
+ * \param pattern Formating pattern for log messages
+ */
+GR_RUNTIME_API void logger_add_console_appender(gr_logger_ptr logger,std::string target,std::string pattern);
+
+/*!
+ * \brief Add file appender to a given logger
+ *
+ * Add file appender to a given logger
+ *
+ * \param logger Logger to which appender will be added
+ * \param filename File to which log will be written
+ * \param append Overwrite or append to log file
+ * \param pattern Formating pattern for log messages
+ */
+GR_RUNTIME_API void logger_add_file_appender(gr_logger_ptr logger,std::string filename,bool append,std::string pattern);
+
+/*!
+ * \brief Add rolling file appender to a given logger
+ *
+ * Add rolling file appender to a given logger
+ *
+ * \param logger Logger to which appender will be added
+ * \param filename File to which log will be written
+ * \param filesize Sizez of files to write
+ * \param bkup_index Number of files to write
+ * \param append Overwrite or append to log file
+ * \param mode Permissions to set on log file
+ * \param pattern Formating pattern for log messages
+ */
+GR_RUNTIME_API 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);
+
+
+/*!
+ * \brief Add rolling file appender to a given logger
+ *
+ * Add rolling file appender to a given logger
+ *
+ * \return vector of string names of loggers
+ */
+GR_RUNTIME_API std::vector<std::string> logger_get_logger_names(void);
+
+#endif /* HAVE_LOG4CPP */
+
+
+// If Logger disable do nothing
+#else /* ENABLE_GR_LOG */
+
+typedef void* gr_logger_ptr;
+
+#define GR_LOG_DECLARE_LOGPTR(logger)
+#define GR_LOG_ASSIGN_LOGPTR(logger,name)
+#define GR_CONFIG_LOGGER(config)
+#define GR_CONFIG_AND_WATCH_LOGGER(config,period)
+#define GR_LOG_GETLOGGER(logger, name)
+#define GR_SET_LEVEL(name, level)
+#define GR_LOG_SET_LEVEL(logger, level)
+#define GR_GET_LEVEL(name, level)
+#define GR_LOG_GET_LEVEL(logger, level)
+#define GR_ADD_CONSOLE_APPENDER(logger,target,pattern)
+#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern)
+#define GR_ADD_FILE_APPENDER(name,filename,append,pattern)
+#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern)
+#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern)
+#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern)
+#define GR_GET_LOGGER_NAMES(names)
+#define GR_RESET_CONFIGURATION()
+#define GR_DEBUG(name, msg)
+#define GR_INFO(name, msg)
+#define GR_NOTICE(name, msg)
+#define GR_WARN(name, msg)
+#define GR_ERROR(name, msg)
+#define GR_ALERT(name, msg)
+#define GR_CRIT(name, msg)
+#define GR_FATAL(name, msg)
+#define GR_EMERG(name, msg)
+#define GR_ERRORIF(name, cond, msg)
+#define GR_ASSERT(name, cond, msg)
+#define GR_LOG_DEBUG(logger, msg)
+#define GR_LOG_INFO(logger, msg)
+#define GR_LOG_NOTICE(logger, msg)
+#define GR_LOG_WARN(logger, msg)
+#define GR_LOG_ERROR(logger, msg)
+#define GR_LOG_ALERT(logger, msg)
+#define GR_LOG_CRIT(logger, msg)
+#define GR_LOG_FATAL(logger, msg)
+#define GR_LOG_EMERG(logger, msg)
+#define GR_LOG_ERRORIF(logger, cond, msg)
+#define GR_LOG_ASSERT(logger, cond, msg)
+
+#endif /* ENABLE_GR_LOG */
+
+// Even if logger is disabled we'll need for methods below to exist in python.
+// The macros these call will be disabled if ENABLE_GR_LOG is undefined
+
+/********************* Start Classes and Methods for Python ******************/
+/*!
+ * \brief Logger class for referencing loggers in python. Not needed in C++ (use macros)
+ * Wraps and manipulates loggers for python as python has no macros
+ * \ingroup logging
+ *
+ */
+class gr_logger
+{
+ private:
+ /*! \brief logger pointer to logger associated wiith this wrapper class */
+ gr_logger_ptr d_logger;
+ public:
+ /*!
+ * \brief contructor Provide name of logger to associate with this class
+ * \param logger_name Name of logger associated with class
+ */
+ gr_logger(std::string logger_name) {
+ GR_LOG_ASSIGN_LOGPTR(d_logger,logger_name);
+ };
+
+ /*! \brief Destructor */
+ ~gr_logger(){;};
+
+ // Wrappers for logging macros
+ /*! \brief inline function, wrapper to set the logger level */
+ void set_level(std::string level){GR_LOG_SET_LEVEL(d_logger,level);}
+
+ /*! \brief inline function, wrapper to get the logger level */
+ void get_level(std::string &level){GR_LOG_GET_LEVEL(d_logger,level);}
+
+ /*! \brief inline function, wrapper for LOG4CPP_DEBUG for DEBUG message */
+ void debug(std::string msg){GR_LOG_DEBUG(d_logger,msg);};
+
+ /*! \brief inline function, wrapper for LOG4CPP_INFO for INFO message */
+ void info(std::string msg){GR_LOG_INFO(d_logger,msg);};
+
+ /*! \brief inline function, wrapper for NOTICE message */
+ void notice(std::string msg){GR_LOG_NOTICE(d_logger,msg);};
+
+ /*! \brief inline function, wrapper for LOG4CPP_WARN for WARN message */
+ void warn(std::string msg){GR_LOG_WARN(d_logger,msg);};
+
+ /*! \brief inline function, wrapper for LOG4CPP_ERROR for ERROR message */
+ void error(std::string msg){GR_LOG_ERROR(d_logger,msg);};
+
+ /*! \brief inline function, wrapper for NOTICE message */
+ void crit(std::string msg){GR_LOG_CRIT(d_logger,msg);};
+
+ /*! \brief inline function, wrapper for ALERT message */
+ void alert(std::string msg){GR_LOG_ALERT(d_logger,msg);};
+
+ /*! \brief inline function, wrapper for FATAL message */
+ void fatal(std::string msg){GR_LOG_FATAL(d_logger,msg);};
+
+ /*! \brief inline function, wrapper for EMERG message */
+ void emerg(std::string msg){GR_LOG_EMERG(d_logger,msg);};
+
+ /*! \brief inline function, wrapper for LOG4CPP_ASSERT for conditional ERROR message */
+ void errorIF(bool cond,std::string msg){GR_LOG_ERRORIF(d_logger,cond,msg);};
+
+ /*! \brief inline function, wrapper for LOG4CPP_ASSERT for conditional ERROR message */
+ void log_assert(bool cond,std::string msg){GR_LOG_ASSERT(d_logger,cond,msg);};
+
+ /*! \brief inline function, Method to add console appender to logger */
+ void add_console_appender(std::string target,std::string pattern){
+ GR_LOG_ADD_CONSOLE_APPENDER(d_logger,target,pattern);
+ };
+
+ /*! \brief inline function, Method to add file appender to logger */
+ void add_file_appender(std::string filename,bool append,std::string pattern){
+ GR_LOG_ADD_FILE_APPENDER(d_logger,filename,append,pattern);
+ };
+
+ /*! \brief inline function, Method to add rolling file appender to logger */
+ void add_rollingfile_appender(std::string filename,size_t filesize,
+ int bkup_index,bool append,mode_t mode,std::string pattern){
+ GR_LOG_ADD_ROLLINGFILE_APPENDER(d_logger,filename,filesize,
+ bkup_index,append,mode,pattern);
+ };
+};
+
+/**************** Start Configuration Class and Methods for Python ************/
+/*!
+ * \brief Function to call configuration macro from python.
+ * Note: Configuration is only updated if filename or watch_period has changed.
+ * \param config_filename Name of configuration file
+ * \param watch_period Seconds to wait between checking for changes in conf file.
+ * Watch_period defaults to 0 in which case the file is not watched for changes
+ */
+GR_RUNTIME_API void gr_logger_config(const std::string config_filename, unsigned int watch_period = 0);
+/*!
+ * \brief Function to return logger names to python
+ * \return Vector of name strings
+ *
+ */
+GR_RUNTIME_API std::vector<std::string> gr_logger_get_logger_names(void);
+/*!
+ * \brief Function to reset logger configuration from python
+ *
+ */
+GR_RUNTIME_API void gr_logger_reset_config(void);
+
+#endif /* INCLUDED_GR_LOGGER_H */
diff --git a/gnuradio-runtime/include/gr_math.h b/gnuradio-runtime/include/gr_math.h
new file mode 100644
index 0000000000..c7efe8facb
--- /dev/null
+++ b/gnuradio-runtime/include/gr_math.h
@@ -0,0 +1,209 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2005,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.
+ */
+
+/*
+ * mathematical odds and ends.
+ */
+
+#ifndef _GR_MATH_H_
+#define _GR_MATH_H_
+
+#include <gr_runtime_api.h>
+#include <gr_complex.h>
+
+static inline bool
+gr_is_power_of_2(long x)
+{
+ return x != 0 && (x & (x-1)) == 0;
+}
+
+/*!
+ * \brief Fast arc tangent using table lookup and linear interpolation
+ * \ingroup misc
+ *
+ * \param y component of input vector
+ * \param x component of input vector
+ * \returns float angle angle of vector (x, y) in radians
+ *
+ * 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.
+ */
+GR_RUNTIME_API float gr_fast_atan2f(float y, float x);
+
+static inline float gr_fast_atan2f(gr_complex z)
+{
+ return gr_fast_atan2f(z.imag(), z.real());
+}
+
+/* This bounds x by +/- clip without a branch */
+static inline float gr_branchless_clip(float x, float clip)
+{
+ float x1 = fabsf(x+clip);
+ float x2 = fabsf(x-clip);
+ x1 -= x2;
+ return 0.5*x1;
+}
+
+static inline float gr_clip(float x, float clip)
+{
+ float y = x;
+ if(x > clip)
+ y = clip;
+ else if(x < -clip)
+ y = -clip;
+ return y;
+}
+
+// Slicer Functions
+static inline unsigned int gr_binary_slicer(float x)
+{
+ if(x >= 0)
+ return 1;
+ else
+ return 0;
+}
+
+static inline unsigned int gr_quad_45deg_slicer(float r, float i)
+{
+ unsigned int ret = 0;
+ if((r >= 0) && (i >= 0))
+ ret = 0;
+ else if((r < 0) && (i >= 0))
+ ret = 1;
+ else if((r < 0) && (i < 0))
+ ret = 2;
+ else
+ ret = 3;
+ return ret;
+}
+
+static inline unsigned int gr_quad_0deg_slicer(float r, float i)
+{
+ unsigned int ret = 0;
+ if(fabsf(r) > fabsf(i)) {
+ if(r > 0)
+ ret = 0;
+ else
+ ret = 2;
+ }
+ else {
+ if(i > 0)
+ ret = 1;
+ else
+ ret = 3;
+ }
+
+ return ret;
+}
+
+static inline unsigned int gr_quad_45deg_slicer(gr_complex x)
+{
+ return gr_quad_45deg_slicer(x.real(), x.imag());
+}
+
+static inline unsigned int gr_quad_0deg_slicer(gr_complex x)
+{
+ return gr_quad_0deg_slicer(x.real(), x.imag());
+}
+
+// Branchless Slicer Functions
+static inline unsigned int gr_branchless_binary_slicer(float x)
+{
+ return (x >= 0);
+}
+
+static inline unsigned int gr_branchless_quad_0deg_slicer(float r, float i)
+{
+ unsigned int ret = 0;
+ ret = (fabsf(r) > fabsf(i)) * (((r < 0) << 0x1)); // either 0 (00) or 2 (10)
+ ret |= (fabsf(i) > fabsf(r)) * (((i < 0) << 0x1) | 0x1); // either 1 (01) or 3 (11)
+
+ return ret;
+}
+
+static inline unsigned int gr_branchless_quad_0deg_slicer(gr_complex x)
+{
+ return gr_branchless_quad_0deg_slicer(x.real(), x.imag());
+}
+
+static inline unsigned int gr_branchless_quad_45deg_slicer(float r, float i)
+{
+ char ret = (r <= 0);
+ ret |= ((i <= 0) << 1);
+ return (ret ^ ((ret & 0x2) >> 0x1));
+}
+
+static inline unsigned int gr_branchless_quad_45deg_slicer(gr_complex x)
+{
+ return gr_branchless_quad_45deg_slicer(x.real(), x.imag());
+}
+
+/*!
+ * \param x any value
+ * \param pow2 must be a power of 2
+ * \returns \p x rounded down to a multiple of \p pow2.
+ */
+static inline size_t
+gr_p2_round_down(size_t x, size_t pow2)
+{
+ return x & -pow2;
+}
+
+/*!
+ * \param x any value
+ * \param pow2 must be a power of 2
+ * \returns \p x rounded up to a multiple of \p pow2.
+ */
+static inline size_t
+gr_p2_round_up(size_t x, size_t pow2)
+{
+ return gr_p2_round_down(x + pow2 - 1, pow2);
+}
+
+/*!
+ * \param x any value
+ * \param pow2 must be a power of 2
+ * \returns \p x modulo \p pow2.
+ */
+static inline size_t
+gr_p2_modulo(size_t x, size_t pow2)
+{
+ return x & (pow2 - 1);
+}
+
+/*!
+ * \param x any value
+ * \param pow2 must be a power of 2
+ * \returns \p pow2 - (\p x modulo \p pow2).
+ */
+static inline size_t
+gr_p2_modulo_neg(size_t x, size_t pow2)
+{
+ return pow2 - gr_p2_modulo(x, pow2);
+}
+
+#endif /* _GR_MATH_H_ */
diff --git a/gnuradio-runtime/include/gr_message.h b/gnuradio-runtime/include/gr_message.h
new file mode 100644
index 0000000000..941821617b
--- /dev/null
+++ b/gnuradio-runtime/include/gr_message.h
@@ -0,0 +1,91 @@
+/* -*- 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_MESSAGE_H
+#define INCLUDED_GR_MESSAGE_H
+
+#include <gr_runtime_api.h>
+#include <gr_types.h>
+#include <string>
+
+class gr_message;
+typedef boost::shared_ptr<gr_message> gr_message_sptr;
+
+/*!
+ * \brief public constructor for gr_message
+ */
+GR_RUNTIME_API gr_message_sptr
+gr_make_message(long type = 0, double arg1 = 0, double arg2 = 0, size_t length = 0);
+
+GR_RUNTIME_API gr_message_sptr
+gr_make_message_from_string(const std::string s, long type = 0, double arg1 = 0, double arg2 = 0);
+
+/*!
+ * \brief Message class.
+ *
+ * \ingroup misc
+ * The ideas and method names for adjustable message length were
+ * lifted from the click modular router "Packet" class.
+ */
+class GR_RUNTIME_API gr_message {
+ gr_message_sptr d_next; // link field for msg queue
+ long d_type; // type of the message
+ double d_arg1; // optional arg1
+ double d_arg2; // optional arg2
+
+ unsigned char *d_buf_start; // start of allocated buffer
+ unsigned char *d_msg_start; // where the msg starts
+ unsigned char *d_msg_end; // one beyond end of msg
+ unsigned char *d_buf_end; // one beyond end of allocated buffer
+
+ gr_message (long type, double arg1, double arg2, size_t length);
+
+ friend GR_RUNTIME_API gr_message_sptr
+ gr_make_message (long type, double arg1, double arg2, size_t length);
+
+ friend GR_RUNTIME_API gr_message_sptr
+ gr_make_message_from_string (const std::string s, long type, double arg1, double arg2);
+
+ friend class gr_msg_queue;
+
+ unsigned char *buf_data() const { return d_buf_start; }
+ size_t buf_len() const { return d_buf_end - d_buf_start; }
+
+public:
+ ~gr_message ();
+
+ long type() const { return d_type; }
+ double arg1() const { return d_arg1; }
+ double arg2() const { return d_arg2; }
+
+ void set_type(long type) { d_type = type; }
+ void set_arg1(double arg1) { d_arg1 = arg1; }
+ void set_arg2(double arg2) { d_arg2 = arg2; }
+
+ unsigned char *msg() const { return d_msg_start; }
+ size_t length() const { return d_msg_end - d_msg_start; }
+ std::string to_string() const;
+
+};
+
+GR_RUNTIME_API long gr_message_ncurrently_allocated ();
+
+#endif /* INCLUDED_GR_MESSAGE_H */
diff --git a/gnuradio-runtime/include/gr_misc.h b/gnuradio-runtime/include/gr_misc.h
new file mode 100644
index 0000000000..182ae87de6
--- /dev/null
+++ b/gnuradio-runtime/include/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/include/gr_msg_accepter.h b/gnuradio-runtime/include/gr_msg_accepter.h
new file mode 100644
index 0000000000..8db28bb747
--- /dev/null
+++ b/gnuradio-runtime/include/gr_msg_accepter.h
@@ -0,0 +1,43 @@
+/* -*- 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.
+ */
+
+#ifndef INCLUDED_GR_MSG_ACCEPTER_H
+#define INCLUDED_GR_MSG_ACCEPTER_H
+
+#include <gr_runtime_api.h>
+#include <gruel/msg_accepter.h>
+#include <gruel/pmt.h>
+
+/*!
+ * \brief Accepts messages and inserts them into a message queue, then notifies
+ * subclass gr_basic_block there is a message pending.
+ */
+class GR_RUNTIME_API gr_msg_accepter : public gruel::msg_accepter
+{
+public:
+ gr_msg_accepter();
+ ~gr_msg_accepter();
+
+ void post(pmt::pmt_t which_port, pmt::pmt_t msg);
+
+};
+
+#endif /* INCLUDED_GR_MSG_ACCEPTER_H */
diff --git a/gnuradio-runtime/include/gr_msg_handler.h b/gnuradio-runtime/include/gr_msg_handler.h
new file mode 100644
index 0000000000..06d583a38b
--- /dev/null
+++ b/gnuradio-runtime/include/gr_msg_handler.h
@@ -0,0 +1,43 @@
+/* -*- 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_MSG_HANDLER_H
+#define INCLUDED_GR_MSG_HANDLER_H
+
+#include <gr_runtime_api.h>
+#include <gr_message.h>
+
+class gr_msg_handler;
+typedef boost::shared_ptr<gr_msg_handler> gr_msg_handler_sptr;
+
+/*!
+ * \brief abstract class of message handlers
+ * \ingroup base
+ */
+class GR_RUNTIME_API gr_msg_handler {
+public:
+ virtual ~gr_msg_handler ();
+
+ //! handle \p msg
+ virtual void handle (gr_message_sptr msg) = 0;
+};
+
+#endif /* INCLUDED_GR_MSG_HANDLER_H */
diff --git a/gnuradio-runtime/include/gr_msg_queue.h b/gnuradio-runtime/include/gr_msg_queue.h
new file mode 100644
index 0000000000..127186ec51
--- /dev/null
+++ b/gnuradio-runtime/include/gr_msg_queue.h
@@ -0,0 +1,92 @@
+/* -*- 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.
+ */
+#ifndef INCLUDED_GR_MSG_QUEUE_H
+#define INCLUDED_GR_MSG_QUEUE_H
+
+#include <gr_runtime_api.h>
+#include <gr_msg_handler.h>
+#include <gruel/thread.h>
+
+class gr_msg_queue;
+typedef boost::shared_ptr<gr_msg_queue> gr_msg_queue_sptr;
+
+GR_RUNTIME_API gr_msg_queue_sptr gr_make_msg_queue(unsigned int limit=0);
+
+/*!
+ * \brief thread-safe message queue
+ * \ingroup misc
+ */
+class GR_RUNTIME_API gr_msg_queue : public gr_msg_handler {
+
+ gruel::mutex d_mutex;
+ gruel::condition_variable d_not_empty;
+ gruel::condition_variable d_not_full;
+ gr_message_sptr d_head;
+ gr_message_sptr d_tail;
+ unsigned int d_count; // # of messages in queue.
+ unsigned int d_limit; // max # of messages in queue. 0 -> unbounded
+
+public:
+ gr_msg_queue(unsigned int limit);
+ ~gr_msg_queue();
+
+ //! Generic msg_handler method: insert the message.
+ void handle(gr_message_sptr msg) { insert_tail (msg); }
+
+ /*!
+ * \brief Insert message at tail of queue.
+ * \param msg message
+ *
+ * Block if queue if full.
+ */
+ void insert_tail(gr_message_sptr msg);
+
+ /*!
+ * \brief Delete message from head of queue and return it.
+ * Block if no message is available.
+ */
+ gr_message_sptr delete_head();
+
+ /*!
+ * \brief If there's a message in the q, delete it and return it.
+ * If no message is available, return 0.
+ */
+ gr_message_sptr delete_head_nowait();
+
+ //! Delete all messages from the queue
+ void flush();
+
+ //! is the queue empty?
+ bool empty_p() const { return d_count == 0; }
+
+ //! is the queue full?
+ bool full_p() const { return d_limit != 0 && d_count >= d_limit; }
+
+ //! return number of messages in queue
+ unsigned int count() const { return d_count; }
+
+ //! return limit on number of message in queue. 0 -> unbounded
+ unsigned int limit() const { return d_limit; }
+
+};
+
+#endif /* INCLUDED_GR_MSG_QUEUE_H */
diff --git a/gnuradio-runtime/include/gr_nco.h b/gnuradio-runtime/include/gr_nco.h
new file mode 100644
index 0000000000..fb51106aab
--- /dev/null
+++ b/gnuradio-runtime/include/gr_nco.h
@@ -0,0 +1,198 @@
+/* -*- 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_NCO_H_
+#define _GR_NCO_H_
+
+
+#include <vector>
+#include <gr_sincos.h>
+#include <cmath>
+#include <gr_complex.h>
+
+/*!
+ * \brief base class template for Numerically Controlled Oscillator (NCO)
+ * \ingroup misc
+ */
+
+
+//FIXME Eventually generalize this to fixed point
+
+template<class o_type, class i_type>
+class gr_nco {
+public:
+ gr_nco () : phase (0), phase_inc(0) {}
+
+ virtual ~gr_nco () {}
+
+ // radians
+ void set_phase (double angle) {
+ phase = angle;
+ }
+
+ void adjust_phase (double delta_phase) {
+ phase += delta_phase;
+ }
+
+
+ // angle_rate is in radians / step
+ void set_freq (double angle_rate){
+ phase_inc = angle_rate;
+ }
+
+ // angle_rate is a delta in radians / step
+ void adjust_freq (double delta_angle_rate)
+ {
+ phase_inc += delta_angle_rate;
+ }
+
+ // increment current phase angle
+
+ void step ()
+ {
+ phase += phase_inc;
+ if (fabs (phase) > M_PI){
+
+ while (phase > M_PI)
+ phase -= 2*M_PI;
+
+ while (phase < -M_PI)
+ phase += 2*M_PI;
+ }
+ }
+
+ void step (int n)
+ {
+ phase += phase_inc * n;
+ if (fabs (phase) > M_PI){
+
+ while (phase > M_PI)
+ phase -= 2*M_PI;
+
+ while (phase < -M_PI)
+ phase += 2*M_PI;
+ }
+ }
+
+ // units are radians / step
+ double get_phase () const { return phase; }
+ double get_freq () const { return phase_inc; }
+
+ // 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 (phase); }
+ float sin () const { return std::sin (phase); }
+
+ // compute a block at a time
+ void sin (float *output, int noutput_items, double ampl = 1.0);
+ void cos (float *output, int noutput_items, double ampl = 1.0);
+ void sincos (gr_complex *output, int noutput_items, double ampl = 1.0);
+ void sin (short *output, int noutput_items, double ampl = 1.0);
+ void cos (short *output, int noutput_items, double ampl = 1.0);
+ void sin (int *output, int noutput_items, double ampl = 1.0);
+ void cos (int *output, int noutput_items, double ampl = 1.0);
+
+protected:
+ double phase;
+ double phase_inc;
+};
+
+template<class o_type, class i_type>
+void
+gr_nco<o_type,i_type>::sincos (float *sinx, float *cosx) const
+{
+ gr_sincosf (phase, sinx, cosx);
+}
+
+template<class o_type, class i_type>
+void
+gr_nco<o_type,i_type>::sin (float *output, int noutput_items, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (float)(sin () * ampl);
+ step ();
+ }
+}
+
+template<class o_type, class i_type>
+void
+gr_nco<o_type,i_type>::cos (float *output, int noutput_items, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (float)(cos () * ampl);
+ step ();
+ }
+}
+
+template<class o_type, class i_type>
+void
+gr_nco<o_type,i_type>::sin (short *output, int noutput_items, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (short)(sin() * ampl);
+ step ();
+ }
+}
+
+template<class o_type, class i_type>
+void
+gr_nco<o_type,i_type>::cos (short *output, int noutput_items, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (short)(cos () * ampl);
+ step ();
+ }
+}
+
+template<class o_type, class i_type>
+void
+gr_nco<o_type,i_type>::sin (int *output, int noutput_items, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (int)(sin () * ampl);
+ step ();
+ }
+}
+
+template<class o_type, class i_type>
+void
+gr_nco<o_type,i_type>::cos (int *output, int noutput_items, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (int)(cos () * ampl);
+ step ();
+ }
+}
+
+template<class o_type, class i_type>
+void
+gr_nco<o_type,i_type>::sincos (gr_complex *output, int noutput_items, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ float cosx, sinx;
+ sincos (&sinx, &cosx);
+ output[i] = gr_complex(cosx * ampl, sinx * ampl);
+ step ();
+ }
+}
+#endif /* _NCO_H_ */
diff --git a/gnuradio-runtime/include/gr_preferences.h b/gnuradio-runtime/include/gr_preferences.h
new file mode 100644
index 0000000000..df5aecacba
--- /dev/null
+++ b/gnuradio-runtime/include/gr_preferences.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_PREFERENCES_H_
+#define _GR_PREFERENCES_H_
+
+#include <gr_runtime_api.h>
+
+class GR_RUNTIME_API gr_preferences {
+ public:
+ static const char *get (const char *key);
+ static void set (const char *key, const char *value);
+};
+
+#endif /* _GR_PREFERENCES_H_ */ \ No newline at end of file
diff --git a/gnuradio-runtime/include/gr_prefs.h b/gnuradio-runtime/include/gr_prefs.h
new file mode 100644
index 0000000000..7ca0991ca8
--- /dev/null
+++ b/gnuradio-runtime/include/gr_prefs.h
@@ -0,0 +1,143 @@
+/* -*- 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.
+ */
+
+#ifndef INCLUDED_GR_PREFS_H
+#define INCLUDED_GR_PREFS_H
+
+#include <gr_runtime_api.h>
+#include <string>
+#include <map>
+#include <gruel/thread.h>
+
+typedef std::map< std::string, std::map<std::string, std::string> > gr_config_map_t;
+typedef std::map< std::string, std::map<std::string, std::string> >::iterator gr_config_map_itr;
+typedef std::map<std::string, std::string> gr_config_map_elem_t;
+typedef std::map<std::string, std::string>::iterator gr_config_map_elem_itr;
+
+/*!
+ * \brief Base class for representing user preferences a la windows INI files.
+ * \ingroup misc
+ *
+ * The real implementation is in Python, and is accessable from C++
+ * via the magic of SWIG directors.
+ */
+
+class GR_RUNTIME_API gr_prefs
+{
+public:
+ static gr_prefs *singleton();
+ static void set_singleton(gr_prefs *p);
+
+ gr_prefs();
+ virtual ~gr_prefs();
+
+ /*!
+ * \brief Returns the configuration options as a string.
+ */
+ std::string to_string();
+
+ /*!
+ * \brief Saves the configuration settings to ${HOME}/.gnuradio/config.conf.
+ *
+ * WARNING: this will overwrite your current config.conf file.
+ */
+ void save();
+
+ /*!
+ * \brief Does \p section exist?
+ */
+ virtual bool has_section(const std::string &section);
+
+ /*!
+ * \brief Does \p option exist?
+ */
+ virtual bool has_option(const std::string &section, const std::string &option);
+
+ /*!
+ * \brief If option exists return associated value; else default_val.
+ */
+ virtual const std::string get_string(const std::string &section,
+ const std::string &option,
+ const std::string &default_val);
+
+ /*!
+ * \brief Set or add a string \p option to \p section with value \p val.
+ */
+ virtual void set_string(const std::string &section,
+ const std::string &option,
+ const std::string &val);
+
+ /*!
+ * \brief If option exists and value can be converted to bool, return it; else default_val.
+ */
+ virtual bool get_bool(const std::string &section,
+ const std::string &option,
+ bool default_val);
+
+ /*!
+ * \brief Set or add a bool \p option to \p section with value \p val.
+ */
+ virtual void set_bool(const std::string &section,
+ const std::string &option,
+ bool val);
+
+ /*!
+ * \brief If option exists and value can be converted to long, return it; else default_val.
+ */
+ virtual long get_long(const std::string &section,
+ const std::string &option,
+ long default_val);
+
+ /*!
+ * \brief Set or add a long \p option to \p section with value \p val.
+ */
+ virtual void set_long(const std::string &section,
+ const std::string &option,
+ long val);
+
+ /*!
+ * \brief If option exists and value can be converted to double, return it; else default_val.
+ */
+ virtual double get_double(const std::string &section,
+ const std::string &option,
+ double default_val);
+
+ /*!
+ * \brief Set or add a double \p option to \p section with value \p val.
+ */
+ virtual void set_double(const std::string &section,
+ const std::string &option,
+ double val);
+
+ protected:
+ virtual std::vector<std::string> _sys_prefs_filenames();
+ virtual void _read_files();
+ virtual void _convert_to_map(const std::string &conf);
+ virtual char * option_to_env(std::string section, std::string option);
+
+ private:
+ gruel::mutex d_mutex;
+ gr_config_map_t d_config_map;
+};
+
+
+#endif /* INCLUDED_GR_PREFS_H */
diff --git a/gnuradio-runtime/include/gr_py_feval.h b/gnuradio-runtime/include/gr_py_feval.h
new file mode 100644
index 0000000000..cf7c7bfbe5
--- /dev/null
+++ b/gnuradio-runtime/include/gr_py_feval.h
@@ -0,0 +1,51 @@
+#include <gruel/pmt.h>
+
+class gr_py_feval_dd : public gr_feval_dd
+{
+ public:
+ double calleval(double x)
+ {
+ ensure_py_gil_state _lock;
+ return eval(x);
+ }
+};
+
+class gr_py_feval_cc : public gr_feval_cc
+{
+ public:
+ gr_complex calleval(gr_complex x)
+ {
+ ensure_py_gil_state _lock;
+ return eval(x);
+ }
+};
+
+class gr_py_feval_ll : public gr_feval_ll
+{
+ public:
+ long calleval(long x)
+ {
+ ensure_py_gil_state _lock;
+ return eval(x);
+ }
+};
+
+class gr_py_feval : public gr_feval
+{
+ public:
+ void calleval()
+ {
+ ensure_py_gil_state _lock;
+ eval();
+ }
+};
+
+class gr_py_feval_p : public gr_feval_p
+{
+ public:
+ void calleval(pmt::pmt_t x)
+ {
+ ensure_py_gil_state _lock;
+ eval(x);
+ }
+};
diff --git a/gnuradio-runtime/include/gr_random.h b/gnuradio-runtime/include/gr_random.h
new file mode 100644
index 0000000000..783c05f920
--- /dev/null
+++ b/gnuradio-runtime/include/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/include/gr_realtime.h b/gnuradio-runtime/include/gr_realtime.h
new file mode 100644
index 0000000000..fcdb5222cc
--- /dev/null
+++ b/gnuradio-runtime/include/gr_realtime.h
@@ -0,0 +1,37 @@
+/* -*- 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_REALTIME_H
+#define INCLUDED_GR_REALTIME_H
+
+#include <gr_runtime_api.h>
+#include <gruel/realtime.h>
+
+typedef gruel::rt_status_t gr_rt_status_t;
+
+/*!
+ * \brief If possible, enable high-priority "real time" scheduling.
+ * \ingroup misc
+ */
+GR_RUNTIME_API gr_rt_status_t gr_enable_realtime_scheduling();
+
+#endif /* INCLUDED_GR_REALTIME_H */
diff --git a/gnuradio-runtime/include/gr_runtime_api.h b/gnuradio-runtime/include/gr_runtime_api.h
new file mode 100644
index 0000000000..32c53bd723
--- /dev/null
+++ b/gnuradio-runtime/include/gr_runtime_api.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010-2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_RUNTIME_API_H
+#define INCLUDED_GR_RUNTIME_API_H
+
+#include <gruel/attributes.h>
+
+#ifdef gnuradio_core_EXPORTS
+# define GR_RUNTIME_API __GR_ATTR_EXPORT
+#else
+# define GR_RUNTIME_API __GR_ATTR_IMPORT
+#endif
+
+#endif /* INCLUDED_GR_RUNTIME_API_H */
diff --git a/gnuradio-runtime/include/gr_runtime_types.h b/gnuradio-runtime/include/gr_runtime_types.h
new file mode 100644
index 0000000000..9af745b3fa
--- /dev/null
+++ b/gnuradio-runtime/include/gr_runtime_types.h
@@ -0,0 +1,56 @@
+/* -*- 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.
+ */
+
+#ifndef INCLUDED_GR_RUNTIME_TYPES_H
+#define INCLUDED_GR_RUNTIME_TYPES_H
+
+#include <gr_runtime_api.h>
+#include <gr_types.h>
+
+/*
+ * typedefs for smart pointers we use throughout the runtime system
+ */
+
+class gr_basic_block;
+class gr_block;
+class gr_block_detail;
+class gr_hier_block2;
+class gr_io_signature;
+class gr_buffer;
+class gr_buffer_reader;
+class gr_flowgraph;
+class gr_flat_flowgraph;
+class gr_top_block;
+class gr_top_block_detail;
+
+typedef boost::shared_ptr<gr_basic_block> gr_basic_block_sptr;
+typedef boost::shared_ptr<gr_block> gr_block_sptr;
+typedef boost::shared_ptr<gr_block_detail> gr_block_detail_sptr;
+typedef boost::shared_ptr<gr_hier_block2> gr_hier_block2_sptr;
+typedef boost::shared_ptr<gr_io_signature> gr_io_signature_sptr;
+typedef boost::shared_ptr<gr_buffer> gr_buffer_sptr;
+typedef boost::shared_ptr<gr_buffer_reader> gr_buffer_reader_sptr;
+typedef boost::shared_ptr<gr_flowgraph> gr_flowgraph_sptr;
+typedef boost::shared_ptr<gr_flat_flowgraph> gr_flat_flowgraph_sptr;
+typedef boost::shared_ptr<gr_top_block> gr_top_block_sptr;
+
+#endif /* INCLUDED_GR_RUNTIME_TYPES_H */
diff --git a/gnuradio-runtime/include/gr_select_handler.h b/gnuradio-runtime/include/gr_select_handler.h
new file mode 100644
index 0000000000..ae4b9dfdb1
--- /dev/null
+++ b/gnuradio-runtime/include/gr_select_handler.h
@@ -0,0 +1,85 @@
+/* -*- 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_SELECT_HANDLER_H
+#define INCLUDED_GR_SELECT_HANDLER_H
+
+#include <gr_runtime_api.h>
+#include <boost/shared_ptr.hpp>
+
+class gr_select_handler;
+typedef boost::shared_ptr<gr_select_handler> gr_select_handler_sptr;
+
+
+/*!
+ * \brief Abstract handler for select based notification.
+ * \ingroup base
+ *
+ * \sa gr_dispatcher
+ */
+class GR_RUNTIME_API gr_select_handler
+{
+ int d_fd;
+
+protected:
+ gr_select_handler(int file_descriptor);
+
+public:
+ virtual ~gr_select_handler();
+
+ int fd() const { return d_fd; }
+ int file_descriptor() const { return d_fd; }
+
+ /*!
+ * \brief Called when file_descriptor is readable.
+ *
+ * Called when the dispatcher detects that file_descriptor can
+ * be read without blocking.
+ */
+ virtual void handle_read() = 0;
+
+ /*!
+ * \brief Called when file_descriptor is writable.
+ *
+ * Called when dispatcher detects that file descriptor can be
+ * written without blocking.
+ */
+ virtual void handle_write() = 0;
+
+ /*!
+ * Called each time around the dispatcher loop to determine whether
+ * this handler's file descriptor should be added to the list on which
+ * read events can occur. The default method returns true, indicating
+ * that by default, all handlers are interested in read events.
+ */
+ virtual bool readable() { return true; }
+
+ /*!
+ * Called each time around the dispatcher loop to determine whether
+ * this handler's file descriptor should be added to the list on which
+ * write events can occur. The default method returns true, indicating
+ * that by default, all handlers are interested in write events.
+ */
+ virtual bool writable() { return true; }
+};
+
+#endif /* INCLUDED_GR_SELECT_HANDLER_H */
diff --git a/gnuradio-runtime/include/gr_sincos.h b/gnuradio-runtime/include/gr_sincos.h
new file mode 100644
index 0000000000..5a182081de
--- /dev/null
+++ b/gnuradio-runtime/include/gr_sincos.h
@@ -0,0 +1,41 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,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_SINCOS_H
+#define INCLUDED_GR_SINCOS_H
+
+#include <gr_runtime_api.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// compute sine and cosine at the same time
+
+GR_RUNTIME_API void gr_sincos (double x, double *sin, double *cos);
+GR_RUNTIME_API void gr_sincosf (float x, float *sin, float *cos);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* INCLUDED_GR_SINCOS_H */
diff --git a/gnuradio-runtime/include/gr_single_threaded_scheduler.h b/gnuradio-runtime/include/gr_single_threaded_scheduler.h
new file mode 100644
index 0000000000..d538fa3921
--- /dev/null
+++ b/gnuradio-runtime/include/gr_single_threaded_scheduler.h
@@ -0,0 +1,62 @@
+/* -*- 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_SINGLE_THREADED_SCHEDULER_H
+#define INCLUDED_GR_SINGLE_THREADED_SCHEDULER_H
+
+#include <gr_runtime_api.h>
+#include <gr_runtime_types.h>
+#include <fstream>
+
+class gr_single_threaded_scheduler;
+typedef boost::shared_ptr<gr_single_threaded_scheduler> gr_single_threaded_scheduler_sptr;
+
+
+/*!
+ * \brief Simple scheduler for stream computations.
+ * \ingroup internal
+ */
+
+class GR_RUNTIME_API gr_single_threaded_scheduler {
+ public:
+ ~gr_single_threaded_scheduler ();
+
+ void run ();
+ void stop ();
+
+ private:
+ const std::vector<gr_block_sptr> d_blocks;
+ volatile bool d_enabled;
+ std::ofstream *d_log;
+
+ gr_single_threaded_scheduler (const std::vector<gr_block_sptr> &blocks);
+
+ void main_loop ();
+
+ friend GR_RUNTIME_API gr_single_threaded_scheduler_sptr
+ gr_make_single_threaded_scheduler (const std::vector<gr_block_sptr> &blocks);
+};
+
+GR_RUNTIME_API gr_single_threaded_scheduler_sptr
+gr_make_single_threaded_scheduler (const std::vector<gr_block_sptr> &blocks);
+
+#endif /* INCLUDED_GR_SINGLE_THREADED_SCHEDULER_H */
diff --git a/gnuradio-runtime/include/gr_sptr_magic.h b/gnuradio-runtime/include/gr_sptr_magic.h
new file mode 100644
index 0000000000..2a94806d18
--- /dev/null
+++ b/gnuradio-runtime/include/gr_sptr_magic.h
@@ -0,0 +1,52 @@
+/* -*- 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_SPTR_MAGIC_H
+#define INCLUDED_GR_SPTR_MAGIC_H
+
+#include <gr_runtime_api.h>
+#include <boost/shared_ptr.hpp>
+
+class gr_basic_block;
+class gr_hier_block2;
+
+namespace gnuradio {
+
+ namespace detail {
+
+ class GR_RUNTIME_API sptr_magic {
+ public:
+ static boost::shared_ptr<gr_basic_block> fetch_initial_sptr(gr_basic_block *p);
+ static void create_and_stash_initial_sptr(gr_hier_block2 *p);
+ };
+ };
+
+ /*
+ * \brief New! Improved! Standard method to get/create the boost::shared_ptr for a block.
+ */
+ template<class T>
+ boost::shared_ptr<T>
+ get_initial_sptr(T *p)
+ {
+ return boost::dynamic_pointer_cast<T, gr_basic_block>(detail::sptr_magic::fetch_initial_sptr(p));
+ }
+};
+
+#endif /* INCLUDED_GR_SPTR_MAGIC_H */
diff --git a/gnuradio-runtime/include/gr_sync_block.h b/gnuradio-runtime/include/gr_sync_block.h
new file mode 100644
index 0000000000..01eb646143
--- /dev/null
+++ b/gnuradio-runtime/include/gr_sync_block.h
@@ -0,0 +1,66 @@
+/* -*- 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_SYNC_BLOCK_H
+#define INCLUDED_GR_SYNC_BLOCK_H
+
+#include <gr_runtime_api.h>
+#include <gr_block.h>
+
+/*!
+ * \brief synchronous 1:1 input to output with history
+ * \ingroup base_blk
+ *
+ * Override work to provide the signal processing implementation.
+ */
+class GR_RUNTIME_API gr_sync_block : public gr_block
+{
+ protected:
+ gr_sync_block (void){} //allows pure virtual interface sub-classes
+ gr_sync_block (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature);
+
+ public:
+
+ /*!
+ * \brief just like gr_block::general_work, only this arranges to call consume_each for you
+ *
+ * The user must override work to define the signal processing code
+ */
+ virtual int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items) = 0;
+
+
+ // gr_sync_block overrides these to assist work
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+ int general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ int fixed_rate_ninput_to_noutput(int ninput);
+ int fixed_rate_noutput_to_ninput(int noutput);
+};
+
+#endif /* INCLUDED_GR_SYNC_BLOCK_H */
diff --git a/gnuradio-runtime/include/gr_sync_decimator.h b/gnuradio-runtime/include/gr_sync_decimator.h
new file mode 100644
index 0000000000..c799ee0f7c
--- /dev/null
+++ b/gnuradio-runtime/include/gr_sync_decimator.h
@@ -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.
+ */
+
+#ifndef INCLUDED_GR_SYNC_DECIMATOR_H
+#define INCLUDED_GR_SYNC_DECIMATOR_H
+
+#include <gr_runtime_api.h>
+#include <gr_sync_block.h>
+
+/*!
+ * \brief synchronous N:1 input to output with history
+ * \ingroup base_blk
+ *
+ * Override work to provide the signal processing implementation.
+ */
+class GR_RUNTIME_API gr_sync_decimator : public gr_sync_block
+{
+ private:
+ unsigned d_decimation;
+
+ protected:
+ gr_sync_decimator (void){} //allows pure virtual interface sub-classes
+ gr_sync_decimator (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature,
+ unsigned decimation);
+ public:
+
+ unsigned decimation () const { return d_decimation; }
+ void set_decimation (unsigned decimation)
+ {
+ d_decimation = decimation;
+ set_relative_rate (1.0 / decimation);
+ }
+
+ // gr_sync_decimator overrides these to assist work
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+ int general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ // derived classes should override work
+
+ int fixed_rate_ninput_to_noutput(int ninput);
+ int fixed_rate_noutput_to_ninput(int noutput);
+};
+
+
+#endif /* INCLUDED_GR_SYNC_DECIMATOR_H */
diff --git a/gnuradio-runtime/include/gr_sync_interpolator.h b/gnuradio-runtime/include/gr_sync_interpolator.h
new file mode 100644
index 0000000000..f219916743
--- /dev/null
+++ b/gnuradio-runtime/include/gr_sync_interpolator.h
@@ -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.
+ */
+
+#ifndef INCLUDED_GR_SYNC_INTERPOLATOR_H
+#define INCLUDED_GR_SYNC_INTERPOLATOR_H
+
+#include <gr_runtime_api.h>
+#include <gr_sync_block.h>
+
+/*!
+ * \brief synchronous 1:N input to output with history
+ * \ingroup base_blk
+ *
+ * Override work to provide the signal processing implementation.
+ */
+class GR_RUNTIME_API gr_sync_interpolator : public gr_sync_block
+{
+ private:
+ unsigned d_interpolation;
+
+ protected:
+ gr_sync_interpolator (void){} //allows pure virtual interface sub-classes
+ gr_sync_interpolator (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature,
+ unsigned interpolation);
+ public:
+
+ unsigned interpolation () const { return d_interpolation; }
+ void set_interpolation (unsigned interpolation)
+ {
+ d_interpolation = interpolation;
+ set_relative_rate (1.0 * interpolation);
+ set_output_multiple (interpolation);
+ }
+
+ // gr_sync_interpolator overrides these to assist work
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+ int general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ // derived classes should override work
+
+ int fixed_rate_ninput_to_noutput(int ninput);
+ int fixed_rate_noutput_to_ninput(int noutput);
+};
+
+
+#endif /* INCLUDED_GR_SYNC_INTERPOLATOR_H */
diff --git a/gnuradio-runtime/include/gr_sys_paths.h b/gnuradio-runtime/include/gr_sys_paths.h
new file mode 100644
index 0000000000..6235e0e78f
--- /dev/null
+++ b/gnuradio-runtime/include/gr_sys_paths.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#ifndef _GR_SYS_PATHS_H_
+#define _GR_SYS_PATHS_H_
+
+#include <gr_runtime_api.h>
+
+//! directory to create temporary files
+GR_RUNTIME_API const char *gr_tmp_path();
+
+//! directory to store application data
+GR_RUNTIME_API const char *gr_appdata_path();
+
+#endif /* _GR_SYS_PATHS_H_ */
diff --git a/gnuradio-runtime/include/gr_tagged_stream_block.h b/gnuradio-runtime/include/gr_tagged_stream_block.h
new file mode 100644
index 0000000000..797845f8e2
--- /dev/null
+++ b/gnuradio-runtime/include/gr_tagged_stream_block.h
@@ -0,0 +1,138 @@
+/* -*- 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.
+ */
+
+#ifndef INCLUDED_GR_TAGGED_STREAM_BLOCK_H
+#define INCLUDED_GR_TAGGED_STREAM_BLOCK_H
+
+#include <gr_runtime_api.h>
+#include <gr_block.h>
+
+/*!
+ * \brief Block that operates on PDUs in form of tagged streams
+ * \ingroup base_blk
+ *
+ * Override work to provide the signal processing implementation.
+ */
+class GR_RUNTIME_API gr_tagged_stream_block : public gr_block
+{
+ private:
+ pmt::pmt_t d_length_tag_key; //! This is the key for the tag that stores the PDU length
+ gr_vector_int d_n_input_items_reqd; //! How many input items do I need to process the next PDU?
+
+ protected:
+ std::string d_length_tag_key_str;
+ gr_tagged_stream_block (void){} //allows pure virtual interface sub-classes
+ 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);
+
+ /* \brief Parse all tags on the first sample of a PDU, return the number of items per input
+ * and prune the length tags.
+ *
+ * In most cases, you don't need to override this, unless the number of items read
+ * is not directly coded in one single tag.
+ *
+ * Default behaviour:
+ * - Go through all input ports
+ * - On every input port, search for the tag with the key specified in \p length_tag_key
+ * - Copy that value as an int to the corresponding position in \p n_input_items_reqd
+ * - Remove the length tag.
+ *
+ * \param[in] tags All the tags found on the first item of every input port.
+ * \param[out] n_input_items_reqd Number of items which will be read from every input
+ */
+ virtual void parse_length_tags(
+ const std::vector<std::vector<gr_tag_t> > &tags,
+ gr_vector_int &n_input_items_reqd
+ );
+
+ /* \brief Calculate the number of output items.
+ *
+ * This is basically the inverse function to forecast(): Given a number of input
+ * items, it returns the maximum number of output items.
+ *
+ * You most likely need to override this function, unless your block is a sync
+ * block or integer interpolator/decimator.
+ *
+ */
+ virtual int calculate_output_stream_length(const gr_vector_int &ninput_items);
+
+ /* \brief Set the new length tags on the output stream
+ *
+ * Default behaviour: Set a tag with key \p length_tag_key and
+ * the number of produced items on every output port.
+ *
+ * For anything else, override this.
+ *
+ * \param n_produced Length of the new PDU
+ * \param n_ports Number of output ports
+ */
+ virtual void update_length_tags(int n_produced, int n_ports);
+
+ public:
+
+ /* \brief Don't override this.
+ */
+ void /* final */ forecast (int noutput_items, gr_vector_int &ninput_items_required);
+
+ /* - Reads the number of input items from the tags using parse_length_tags()
+ * - Checks there's enough data on the input and output buffers
+ * - If not, inform the scheduler and do nothing
+ * - Calls work() with the exact number of items per PDU
+ * - Updates the tags using update_length_tags()
+ */
+ int general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ /*!
+ * \brief Just like gr_block::general_work, but makes sure the input is valid
+ *
+ * The user must override work to define the signal processing code.
+ * Check the documentation for general_work() to see what happens here.
+ *
+ * Like gr_sync_block, this calls consume() for you (it consumes ninput_items[i]
+ * items from the i-th port).
+ *
+ * A note on tag propagation: The PDU length tags are handled by other functions,
+ * but all other tags are handled just as in any other \p gr_block. So, most likely,
+ * you either set the tag propagation policy to TPP_DONT and handle the tag
+ * propagation manually, or you propagate tags through the scheduler and don't
+ * do anything here.
+ *
+ * \param noutput_items The size of the writable output buffer
+ * \param ninput_items The exact size of the items on every input for this particular PDU.
+ * These will be consumed if a length tag key is provided!
+ * \param input_items See gr_block
+ * \param output_items See gr_block
+ */
+ virtual int work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items) = 0;
+
+};
+
+#endif /* INCLUDED_GR_TAGGED_STREAM_BLOCK_H */
+
diff --git a/gnuradio-runtime/include/gr_tags.h b/gnuradio-runtime/include/gr_tags.h
new file mode 100644
index 0000000000..278a5a53ae
--- /dev/null
+++ b/gnuradio-runtime/include/gr_tags.h
@@ -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.
+ */
+
+#ifndef INCLUDED_GR_TAGS_H
+#define INCLUDED_GR_TAGS_H
+
+#include <gr_runtime_api.h>
+#include <gruel/pmt.h>
+
+struct GR_RUNTIME_API gr_tag_t{
+
+ //! the item \p tag occurred at (as a uint64_t)
+ uint64_t offset;
+
+ //! the key of \p tag (as a PMT symbol)
+ pmt::pmt_t key;
+
+ //! the value of \p tag (as a PMT)
+ pmt::pmt_t value;
+
+ //! the source ID of \p tag (as a PMT)
+ pmt::pmt_t srcid;
+
+ //! Comparison function to test which tag, \p x or \p y, came first in time
+ static inline bool offset_compare(
+ const gr_tag_t &x, const gr_tag_t &y
+ ){
+ return x.offset < y.offset;
+ }
+
+ inline bool operator == (const gr_tag_t &t) const
+ {
+ return (t.key == key) && (t.value == value) && (t.srcid == srcid) && (t.offset == offset);
+ }
+};
+
+#endif /*INCLUDED_GR_TAGS_H*/
diff --git a/gnuradio-runtime/include/gr_timer.h b/gnuradio-runtime/include/gr_timer.h
new file mode 100644
index 0000000000..45b663b368
--- /dev/null
+++ b/gnuradio-runtime/include/gr_timer.h
@@ -0,0 +1,84 @@
+/* -*- 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_TIMER_H
+#define INCLUDED_GR_TIMER_H
+
+#include <gr_runtime_api.h>
+#include <gr_types.h>
+
+class gr_timer;
+
+typedef boost::shared_ptr<gr_timer> gr_timer_sptr;
+
+GR_RUNTIME_API typedef void (*gr_timer_hook)(gr_timer *, void *);
+
+/*!
+ * \brief create a timeout.
+ *
+ * \ingroup misc
+ * gr_timer_hook is called when timer fires.
+ */
+GR_RUNTIME_API gr_timer_sptr gr_make_timer (gr_timer_hook, void *);
+
+/*!
+ * \brief implement timeouts
+ */
+class GR_RUNTIME_API gr_timer {
+ double d_expiry;
+ double d_period;
+ gr_timer_hook d_hook;
+ void *d_hook_arg;
+
+ friend GR_RUNTIME_API gr_timer_sptr gr_make_timer (gr_timer_hook, void *);
+
+ gr_timer (...);
+
+public:
+ ~gr_timer ();
+
+ //! return absolute current time (seconds since the epoc).
+ static double now ();
+
+ /*!
+ * \brief schedule timer to fire at abs_when
+ * \param abs_when absolute time in seconds since the epoc.
+ */
+ void schedule_at (double abs_when);
+
+ /*!
+ * \brief schedule timer to fire rel_when seconds from now.
+ * \param rel_when relative time in seconds from now.
+ */
+ void schedule_after (double rel_when); // relative time in seconds
+
+ /*!
+ * \brief schedule a periodic timeout.
+ * \param abs_when absolute time to fire first time
+ * \param period time between firings
+ */
+ void schedule_periodic (double abs_when, double period);
+
+ //! cancel timer
+ void unschedule ();
+};
+
+#endif /* INCLUDED_GR_TIMER_H */
diff --git a/gnuradio-runtime/include/gr_top_block.h b/gnuradio-runtime/include/gr_top_block.h
new file mode 100644
index 0000000000..f523442cd0
--- /dev/null
+++ b/gnuradio-runtime/include/gr_top_block.h
@@ -0,0 +1,141 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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_TOP_BLOCK_H
+#define INCLUDED_GR_TOP_BLOCK_H
+
+#include <gr_runtime_api.h>
+#include <gr_hier_block2.h>
+
+class gr_top_block_impl;
+
+GR_RUNTIME_API gr_top_block_sptr gr_make_top_block(const std::string &name);
+
+/*!
+ *\brief Top-level hierarchical block representing a flowgraph
+ * \ingroup container_blk
+ *
+ */
+class GR_RUNTIME_API gr_top_block : public gr_hier_block2
+{
+private:
+ friend GR_RUNTIME_API gr_top_block_sptr gr_make_top_block(const std::string &name);
+
+ gr_top_block_impl *d_impl;
+
+protected:
+ gr_top_block(const std::string &name);
+
+public:
+ ~gr_top_block();
+
+ /*!
+ * \brief The simple interface to running a flowgraph.
+ *
+ * Calls start() then wait(). Used to run a flowgraph that will stop
+ * on its own, or when another thread will call stop().
+ *
+ * \param max_noutput_items the maximum number of output items
+ * allowed for any block in the flowgraph. This passes through to
+ * the start function; see that function for more details.
+ */
+ void run(int max_noutput_items=100000000);
+
+ /*!
+ * Start the contained flowgraph. Creates one or more threads to
+ * execute the flow graph. Returns to the caller once the threads
+ * are created. Calling start() on a top_block that is already
+ * started IS an error.
+ *
+ * \param max_noutput_items the maximum number of output items
+ * allowed for any block in the flowgraph; the noutput_items can
+ * always be less than this, but this will cap it as a maximum. Use
+ * this to adjust the maximum latency a flowgraph can exhibit.
+ */
+ void start(int max_noutput_items=100000000);
+
+ /*!
+ * Stop the running flowgraph. Notifies each thread created by the
+ * scheduler to shutdown, then returns to caller. Calling stop() on
+ * a top_block that is already stopped IS NOT an error.
+ */
+ void stop();
+
+ /*!
+ * Wait for a flowgraph to complete. Flowgraphs complete when
+ * either (1) all blocks indicate that they are done (typically only
+ * when using blocks.file_source, or blocks.head, or (2) after stop() has been
+ * called to request shutdown. Calling wait on a top_block that is
+ * not running IS NOT an error (wait returns w/o blocking).
+ */
+ void wait();
+
+ /*!
+ * Lock a flowgraph in preparation for reconfiguration. When an equal
+ * number of calls to lock() and unlock() have occurred, the flowgraph
+ * will be reconfigured.
+ *
+ * N.B. lock() and unlock() may not be called from a flowgraph thread
+ * (E.g., gr_block::work method) or deadlock will occur when
+ * reconfiguration happens.
+ */
+ virtual void lock();
+
+ /*!
+ * Unlock a flowgraph in preparation for reconfiguration. When an equal
+ * number of calls to lock() and unlock() have occurred, the flowgraph
+ * will be reconfigured.
+ *
+ * N.B. lock() and unlock() may not be called from a flowgraph thread
+ * (E.g., gr_block::work method) or deadlock will occur when
+ * reconfiguration happens.
+ */
+ virtual void unlock();
+
+ /*!
+ * Returns a string that lists the edge connections in the flattened
+ * flowgraph.
+ */
+ std::string edge_list();
+
+ /*!
+ * Displays flattened flowgraph edges and block connectivity
+ */
+ 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);
+
+ gr_top_block_sptr to_top_block(); // Needed for Python type coercion
+
+ void setup_rpc();
+};
+
+inline gr_top_block_sptr cast_to_top_block_sptr(gr_basic_block_sptr block) {
+ return boost::dynamic_pointer_cast<gr_top_block, gr_basic_block>(block);
+}
+
+
+#endif /* INCLUDED_GR_TOP_BLOCK_H */
diff --git a/gnuradio-runtime/include/gr_tpb_detail.h b/gnuradio-runtime/include/gr_tpb_detail.h
new file mode 100644
index 0000000000..398e18cdc8
--- /dev/null
+++ b/gnuradio-runtime/include/gr_tpb_detail.h
@@ -0,0 +1,89 @@
+/* -*- 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.
+ */
+#ifndef INCLUDED_GR_TPB_DETAIL_H
+#define INCLUDED_GR_TPB_DETAIL_H
+
+#include <gr_runtime_api.h>
+#include <gruel/thread.h>
+#include <deque>
+#include <gruel/pmt.h>
+
+class gr_block_detail;
+
+/*!
+ * \brief used by thread-per-block scheduler
+ */
+struct GR_RUNTIME_API gr_tpb_detail {
+
+ gruel::mutex mutex; //< protects all vars
+ bool input_changed;
+ gruel::condition_variable input_cond;
+ bool output_changed;
+ gruel::condition_variable output_cond;
+
+public:
+ gr_tpb_detail()
+ : input_changed(false), output_changed(false) { }
+
+ //! Called by us to tell all our upstream blocks that their output may have changed.
+ void notify_upstream(gr_block_detail *d);
+
+ //! Called by us to tell all our downstream blocks that their input may have changed.
+ void notify_downstream(gr_block_detail *d);
+
+ //! Called by us to notify both upstream and downstream
+ void notify_neighbors(gr_block_detail *d);
+
+ //! Called by pmt msg posters
+ void notify_msg(){
+ input_cond.notify_one();
+ output_cond.notify_one();
+ }
+
+ //! Called by us
+ void clear_changed()
+ {
+ gruel::scoped_lock guard(mutex);
+ input_changed = false;
+ output_changed = false;
+ }
+
+private:
+
+ //! Used by notify_downstream
+ void set_input_changed()
+ {
+ gruel::scoped_lock guard(mutex);
+ input_changed = true;
+ input_cond.notify_one();
+ }
+
+ //! Used by notify_upstream
+ void set_output_changed()
+ {
+ gruel::scoped_lock guard(mutex);
+ output_changed = true;
+ output_cond.notify_one();
+ }
+
+};
+
+#endif /* INCLUDED_GR_TPB_DETAIL_H */
diff --git a/gnuradio-runtime/include/gr_types.h b/gnuradio-runtime/include/gr_types.h
new file mode 100644
index 0000000000..47e22469b0
--- /dev/null
+++ b/gnuradio-runtime/include/gr_types.h
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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.
+ */
+
+#ifndef INCLUDED_GR_TYPES_H
+#define INCLUDED_GR_TYPES_H
+
+#include <gr_runtime_api.h>
+#include <boost/shared_ptr.hpp>
+#include <vector>
+#include <stddef.h> // size_t
+
+#include <gr_complex.h>
+
+typedef std::vector<int> gr_vector_int;
+typedef std::vector<unsigned int> gr_vector_uint;
+typedef std::vector<float> gr_vector_float;
+typedef std::vector<double> gr_vector_double;
+typedef std::vector<void *> gr_vector_void_star;
+typedef std::vector<const void *> gr_vector_const_void_star;
+
+/*
+ * #include <config.h> must be placed beforehand
+ * in the source file including gr_types.h for
+ * the following to work correctly
+ */
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+typedef int16_t gr_int16;
+typedef int32_t gr_int32;
+typedef int64_t gr_int64;
+typedef uint16_t gr_uint16;
+typedef uint32_t gr_uint32;
+typedef uint64_t gr_uint64;
+#else
+/*
+ * Note: these defaults may be wrong on 64-bit systems
+ */
+typedef short gr_int16;
+typedef int gr_int32;
+typedef long long gr_int64;
+typedef unsigned short gr_uint16;
+typedef unsigned int gr_uint32;
+typedef unsigned long long gr_uint64;
+#endif /* HAVE_STDINT_H */
+
+#endif /* INCLUDED_GR_TYPES_H */
diff --git a/gnuradio-runtime/include/gr_unittests.h b/gnuradio-runtime/include/gr_unittests.h
new file mode 100644
index 0000000000..d160ba3354
--- /dev/null
+++ b/gnuradio-runtime/include/gr_unittests.h
@@ -0,0 +1,39 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gr_runtime_api.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string>
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+
+static std::string get_unittest_path(const std::string &filename){
+ boost::filesystem::path path = boost::filesystem::current_path() / ".unittests";
+ if (!boost::filesystem::is_directory(path)) boost::filesystem::create_directory(path);
+ return (path / filename).string();
+}
diff --git a/gnuradio-runtime/include/ice_application_base.h b/gnuradio-runtime/include/ice_application_base.h
new file mode 100644
index 0000000000..f25c7272fc
--- /dev/null
+++ b/gnuradio-runtime/include/ice_application_base.h
@@ -0,0 +1,222 @@
+/* -*- 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 ICE_APPLICATION_BASE_H
+#define ICE_APPLICATION_BASE_H
+
+#include <gr_runtime_api.h>
+#include <gr_prefs.h>
+#include <Ice/Ice.h>
+#include <boost/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <stdio.h>
+#include <iostream>
+#include <set>
+#include <string>
+#include <stdio.h>
+
+namespace {
+ static const unsigned int ICEAPPLICATION_ACTIVATION_TIMEOUT_MS(600);
+};
+
+
+class GR_RUNTIME_API ice_application_common : public Ice::Application
+{
+ public:
+ template<typename TserverBase, typename TserverClass> friend class ice_application_base;
+ static boost::shared_ptr<ice_application_common> Instance();
+ ~ice_application_common() {;}
+ static int d_reacquire_attributes;
+
+ protected:
+ static bool d_main_called, d_have_ice_config;
+ static std::string d_endpointStr;
+ static boost::shared_ptr<boost::thread> d_thread;
+ ice_application_common() {;}
+ int run(int, char*[]);
+};
+
+template<typename TserverBase, typename TserverClass>
+class ice_application_base
+{
+public:
+ boost::shared_ptr<ice_application_common> d_application;
+ ice_application_base(TserverClass* _this);
+ ~ice_application_base() {;}
+
+ static TserverBase* i();
+ static const std::vector<std::string> endpoints();
+
+protected:
+ bool have_ice_config() { return d_application->d_have_ice_config; }
+ void set_endpoint(const std::string& endpoint) { d_application->d_endpointStr = endpoint;}
+
+ //this one is the key... overwrite in templated/inherited variants
+ virtual TserverBase* i_impl() = 0;
+
+ //tools for the i_impl...
+ //tell it when it has to resync with the communicator
+ virtual bool reacquire_sync();
+ virtual void sync_reacquire();
+
+ static TserverClass* d_this;
+
+ int d_reacquire;
+ //static int d_reacquire_attributes;
+
+private:
+ void starticeexample();
+
+ bool application_started();
+
+ int run(int, char*[]);
+
+ static void kickoff();
+};
+
+template<typename TserverBase, typename TserverClass>
+TserverClass* ice_application_base<TserverBase, TserverClass>::d_this(0);
+
+//template<typename TserverBase, typename TserverClass>
+//int ice_application_base<TserverBase, TserverClass>::d_reacquire_attributes(0);
+
+template<typename TserverBase, typename TserverClass>
+ice_application_base<TserverBase, TserverClass>::ice_application_base(TserverClass* _this)
+ : d_reacquire(0)
+{
+ //d_reacquire_attributes = 0;
+ d_this = _this;
+ d_application = ice_application_common::Instance();
+}
+
+template<typename TserverBase, typename TserverClass>
+void ice_application_base<TserverBase, TserverClass>::starticeexample()
+{
+ char* argv[2];
+ argv[0] = (char*)"";
+
+ std::string conffile = gr_prefs::singleton()->get_string("ControlPort", "config", "");
+
+ if(conffile.size() > 0) {
+ std::stringstream iceconf;
+ ice_application_common::d_have_ice_config = true;
+ ice_application_common::d_main_called = true;
+ iceconf << conffile;
+ d_application->main(0, argv, iceconf.str().c_str());
+ }
+ else {
+ ice_application_common::d_have_ice_config = false;
+ ice_application_common::d_main_called = true;
+ d_application->main(0, argv);
+ }
+}
+
+template<typename TserverBase, typename TserverClass>
+void ice_application_base<TserverBase, TserverClass>::kickoff()
+{
+ static bool run_once = false;
+
+ //if(!d_this->application_started()) {
+ if(!run_once) {
+ ++d_this->d_application->d_reacquire_attributes;
+
+ ice_application_common::d_thread = boost::shared_ptr<boost::thread>
+ (new boost::thread(boost::bind(&ice_application_base::starticeexample, d_this)));
+
+ ::timespec timer_ts, rem_ts;
+ timer_ts.tv_sec = 0; timer_ts.tv_nsec = ICEAPPLICATION_ACTIVATION_TIMEOUT_MS*1000;
+
+ int iter = 0;
+ while(!d_this->application_started()) {
+ ::nanosleep(&timer_ts, &rem_ts);
+ if(!d_this->application_started())
+ std::cout << "@";
+ if(iter++ > 100) {
+ std::cout << "ice_application_base::kickoff(), timeout waiting to get communicator() d_application->main() might have failed?!" << std::endl;;
+ break;
+ }
+ }
+
+ run_once = true;
+ }
+
+ return;
+}
+
+
+template<typename TserverBase, typename TserverClass>
+bool ice_application_base<TserverBase, TserverClass>::reacquire_sync()
+{
+ return (d_this->d_reacquire != d_application->d_reacquire_attributes);
+}
+
+template<typename TserverBase, typename TserverClass>
+void ice_application_base<TserverBase, TserverClass>::sync_reacquire()
+{
+ d_this->d_reacquire = d_application->d_reacquire_attributes;
+}
+
+
+template<typename TserverBase, typename TserverClass>
+const std::vector<std::string> ice_application_base<TserverBase, TserverClass>::endpoints()
+{
+ std::vector<std::string> ep; ep.push_back(d_this->d_application->d_endpointStr); return ep;
+}
+
+template<typename TserverBase, typename TserverClass>
+TserverBase* ice_application_base<TserverBase, TserverClass>::i()
+{
+ //printf("indacall\n");
+
+ assert(d_this != 0);
+ if(!d_this->application_started()) {
+ //printf("anotherkickoff\n");
+ kickoff();
+ }
+ //printf("donekickedoff\n");
+
+ /*else if(!d_proxy) {
+ d_proxy = d_this->i_impl();
+ assert(d_proxy != 0);
+ }*/
+
+ return d_this->i_impl();
+}
+
+/*template<typename TserverBase, typename TserverClass>
+ int ice_application_base<TserverBase, TserverClass>::run(int argc, char* argv[]) {
+ int implreturn(run_impl(argc, argv));
+ ice_application_base<TserverBase, TserverClass>::communicator()->waitForShutdown();
+ return implreturn;
+ }*/
+
+template<typename TserverBase, typename TImplClass>
+bool ice_application_base<TserverBase, TImplClass>::application_started()
+{
+ return ice_application_base<TserverBase, TImplClass>::d_this->d_application->communicator();
+}
+
+/*template<typename TserverBase, typename TImplClass>
+int ice_application_base<TserverBase, TImplClass>::run_impl(int argc, char* argv[]) { return EXIT_SUCCESS; }
+*/
+
+#endif
diff --git a/gnuradio-runtime/include/ice_server_template.h b/gnuradio-runtime/include/ice_server_template.h
new file mode 100644
index 0000000000..8ddb03cc8e
--- /dev/null
+++ b/gnuradio-runtime/include/ice_server_template.h
@@ -0,0 +1,96 @@
+/* -*- 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 ICE_SERVER_TEMPLATE_H
+#define ICE_SERVER_TEMPLATE_H
+
+#include <ice_application_base.h>
+#include <iostream>
+
+template<typename TserverBase, typename TserverClass, typename TImplClass, typename TIceClass>
+class ice_server_template : public ice_application_base<TserverBase, TImplClass>
+{
+public:
+ ice_server_template(TImplClass* _this,
+ const std::string& contolPortName,
+ const std::string& endpointName);
+ ~ice_server_template();
+
+protected:
+ //virtual bool application_started();
+ TserverBase* i_impl();
+ friend class ice_application_base<TserverBase, TImplClass>;
+
+private:
+ //virtual int run_impl(int, char*[]);
+ Ice::ObjectAdapterPtr d_adapter;
+ TserverBase* d_iceserver;
+ const std::string d_contolPortName, d_endpointName;
+};
+
+template<typename TserverBase, typename TserverClass, typename TImplClass, typename TIceClass>
+ice_server_template<TserverBase, TserverClass, TImplClass, TIceClass>::ice_server_template
+ (TImplClass* _this, const std::string& controlPortName, const std::string& endpointName)
+ : ice_application_base<TserverBase, TImplClass>(_this),
+ d_iceserver(0),
+ d_contolPortName(controlPortName),
+ d_endpointName(endpointName)
+{;}
+
+template<typename TserverBase, typename TserverClass, typename TImplClass, typename TIceClass>
+ice_server_template<TserverBase, TserverClass,TImplClass, TIceClass>::~ice_server_template()
+{
+ if(d_adapter) {
+ d_adapter->deactivate();
+ delete(d_iceserver);
+ d_adapter = 0;
+ }
+}
+
+template<typename TserverBase, typename TserverClass, typename TImplClass, typename TIceClass>
+TserverBase* ice_server_template<TserverBase, TserverClass, TImplClass, TIceClass>::i_impl()
+{
+ if(ice_application_base<TserverBase, TImplClass>::d_this->reacquire_sync()) {
+ d_adapter = (ice_application_base<TserverBase, TImplClass>::d_this->have_ice_config()) ?
+ ice_application_base<TserverBase, TImplClass>::d_this->d_this->d_application->communicator()->createObjectAdapter(d_contolPortName) :
+ ice_application_base<TserverBase, TImplClass>::d_this->d_this->d_application->communicator()->createObjectAdapterWithEndpoints(d_contolPortName,"tcp -h *");
+
+ TserverClass* server_ice(new TserverClass());
+ TIceClass obj(server_ice);
+
+ Ice::Identity id(ice_application_base<TserverBase, TImplClass>::d_this->d_this->d_application->communicator()->stringToIdentity(d_endpointName));
+ d_adapter->add(obj, id);
+ d_adapter->activate();
+ ice_application_base<TserverBase, TImplClass>::d_this->set_endpoint(ice_application_common::communicator()->proxyToString(d_adapter->createDirectProxy(id)));
+
+ std::cout << std::endl << "Ice Radio Endpoint: "
+ << ice_server_template<TserverBase, TserverClass, TImplClass, TIceClass>::endpoints()[0]
+ << std::endl;
+
+ d_iceserver = (TserverBase*) server_ice;
+ ice_application_base<TserverBase, TImplClass>::d_this->sync_reacquire();
+ }
+
+ return d_iceserver;
+}
+
+#endif /* ICE_SERVER_TEMPLATE_H */
diff --git a/gnuradio-runtime/include/pycallback_object.h b/gnuradio-runtime/include/pycallback_object.h
new file mode 100644
index 0000000000..23782a42be
--- /dev/null
+++ b/gnuradio-runtime/include/pycallback_object.h
@@ -0,0 +1,206 @@
+/* -*- 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 <iostream>
+#include <rpcregisterhelpers.h>
+#include <ice_application_base.h>
+#include <IcePy_Communicator.h>
+#include <pythread.h>
+#include <boost/format.hpp>
+
+enum pyport_t {
+ PYPORT_STRING,
+ PYPORT_FLOAT
+};
+
+class Instance
+{
+public:
+ static boost::shared_ptr<ice_application_common> get_application()
+ {
+ return ice_application_common::Instance();
+ }
+ static Ice::CommunicatorPtr get_swig_communicator()
+ {
+ return get_application()->communicator();
+ }
+};
+
+int pycallback_object_count = 500;
+
+// a simple to-PMT converter template class-function
+template <class myType> class pmt_assist
+{
+public:
+ static pmt::pmt_t make(myType _val)
+ {
+ return pmt::mp(_val);
+ }
+};
+
+/* template specializations for vectors that cant use pmt::mp() */
+template<>
+pmt::pmt_t pmt_assist<std::vector<float> >::make(std::vector<float> _val)
+{
+ return pmt::init_f32vector(_val.size(), &_val[0]);
+}
+
+template<>
+pmt::pmt_t pmt_assist<std::vector<gr_complex> >::make(std::vector<gr_complex> _val)
+{
+ return pmt::init_c32vector(_val.size(), &_val[0]);
+}
+
+template <class myType> class pycallback_object
+{
+public:
+ pycallback_object(std::string name, std::string functionbase,
+ std::string units, std::string desc,
+ myType min, myType max, myType deflt,
+ DisplayType dtype) :
+ d_callback(NULL),
+ d_functionbase(functionbase), d_units(units), d_desc(desc),
+ d_min(min), d_max(max), d_deflt(deflt), d_dtype(dtype),
+ d_name(name), d_id(pycallback_object_count++)
+ {
+ d_callback = NULL;
+ setup_rpc();
+ }
+
+ void add_rpc_variable(rpcbasic_sptr s)
+ {
+ d_rpc_vars.push_back(s);
+ }
+
+ myType get() {
+ myType rVal;
+ if(d_callback == NULL) {
+ printf("WARNING: pycallback_object get() called without py callback set!\n");
+ return rVal;
+ }
+ else {
+ // obtain PyGIL
+ PyGILState_STATE state = PyGILState_Ensure();
+
+ PyObject *func;
+ //PyObject *arglist;
+ PyObject *result;
+
+ func = (PyObject *) d_callback; // Get Python function
+ //arglist = Py_BuildValue(""); // Build argument list
+ result = PyEval_CallObject(func,NULL); // Call Python
+ //result = PyEval_CallObject(func,arglist); // Call Python
+ //Py_DECREF(arglist); // Trash arglist
+ if(result) { // If no errors, return double
+ rVal = pyCast(result);
+ }
+ Py_XDECREF(result);
+
+ // release PyGIL
+ PyGILState_Release(state);
+ return rVal;
+ }
+ }
+
+ void set_callback(PyObject *cb)
+ {
+ d_callback = cb;
+ }
+
+ void setup_rpc()
+ {
+#ifdef GR_CTRLPORT
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<pycallback_object, myType>(
+ (boost::format("%s%d") % d_name % d_id).str() , d_functionbase.c_str(),
+ this, &pycallback_object::get, pmt_assist<myType>::make(d_min),
+ pmt_assist<myType>::make(d_max), pmt_assist<myType>::make(d_deflt),
+ d_units.c_str(), d_desc.c_str(), RPC_PRIVLVL_MIN, d_dtype)));
+#endif /* GR_CTRLPORT */
+ }
+
+private:
+ PyObject* d_callback;
+ std::string d_functionbase, d_units, d_desc;
+ myType d_min, d_max, d_deflt;
+ DisplayType d_dtype;
+
+ myType pyCast(PyObject* obj) {
+ printf("TYPE NOT IMPLEMENTED!\n");
+ assert(0);
+ };
+ std::vector<boost::any> d_rpc_vars; // container for all RPC variables
+ std::string d_name;
+ int d_id;
+
+};
+
+
+// template specialization conversion functions
+// get data out of the PyObject and into the real world
+template<>
+std::string pycallback_object<std::string>::pyCast(PyObject* obj)
+{
+ return std::string(PyString_AsString(obj));
+}
+
+template<>
+double pycallback_object<double>::pyCast(PyObject* obj)
+{
+ return PyFloat_AsDouble(obj);
+}
+
+template<>
+float pycallback_object<float>::pyCast(PyObject* obj)
+{
+ return (float)PyFloat_AsDouble(obj);
+}
+
+template<>
+int pycallback_object<int>::pyCast(PyObject* obj)
+{
+ return PyInt_AsLong(obj);
+}
+
+template<>
+std::vector<float> pycallback_object<std::vector<float> >::pyCast(PyObject* obj)
+{
+ int size = PyObject_Size(obj);
+ std::vector<float> rval(size);
+ for(int i=0; i<size; i++) {
+ rval[i] = (float)PyFloat_AsDouble(PyList_GetItem(obj, i));
+ }
+ return rval;
+}
+
+template<>
+std::vector<gr_complex> pycallback_object<std::vector<gr_complex> >::pyCast(PyObject* obj)
+{
+ int size = PyObject_Size(obj);
+ std::vector<gr_complex> rval(size);
+ for(int i=0; i<size; i++){ rval[i] = \
+ gr_complex((float)PyComplex_RealAsDouble(PyList_GetItem(obj, i)),
+ (float)PyComplex_ImagAsDouble(PyList_GetItem(obj, i)));
+ }
+ return rval;
+}
+// TODO: add more template specializations as needed!
diff --git a/gnuradio-runtime/include/random.h b/gnuradio-runtime/include/random.h
new file mode 100644
index 0000000000..c643c3e422
--- /dev/null
+++ b/gnuradio-runtime/include/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/include/rpccallbackregister_base.h b/gnuradio-runtime/include/rpccallbackregister_base.h
new file mode 100644
index 0000000000..dbfda4ed47
--- /dev/null
+++ b/gnuradio-runtime/include/rpccallbackregister_base.h
@@ -0,0 +1,105 @@
+/* -*- 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 RPCCALLBACKREGISTER_BASE_H
+#define RPCCALLBACKREGISTER_BASE_H
+
+#include <gruel/msg_accepter.h>
+#include <gruel/msg_producer.h>
+
+typedef uint32_t DisplayType;
+
+// DisplayType Plotting types
+const uint32_t DISPNULL = 0x0000;
+const uint32_t DISPTIME = 0x0001;
+const uint32_t DISPXY = 0x0002;
+const uint32_t DISPPSD = 0x0004;
+const uint32_t DISPSPEC = 0x0008;
+const uint32_t DISPRAST = 0x0010;
+
+// DisplayType Options
+const uint32_t DISPOPTCPLX = 0x0100;
+const uint32_t DISPOPTLOG = 0x0200;
+const uint32_t DISPOPTSTEM = 0x0400;
+const uint32_t DISPOPTSTRIP = 0x0800;
+const uint32_t DISPOPTSCATTER = 0x1000;
+
+enum priv_lvl_t {
+ RPC_PRIVLVL_ALL = 0,
+ RPC_PRIVLVL_MIN = 9,
+ RPC_PRIVLVL_NONE = 10
+};
+
+enum KnobType {
+ KNOBBOOL, KNOBCHAR, KNOBINT, KNOBFLOAT,
+ KNOBDOUBLE, KNOBSTRING, KNOBLONG, KNOBVECBOOL,
+ KNOBVECCHAR, KNOBVECINT, KNOBVECFLOAT, KNOBVECDOUBLE,
+ KNOBVECSTRING, KNOBVECLONG
+};
+
+struct callbackregister_base
+{
+ struct callback_base_t
+ {
+ public:
+ callback_base_t(const priv_lvl_t priv_, const std::string& units_,
+ const DisplayType display_, const std::string& desc_,
+ const pmt::pmt_t min_, const pmt::pmt_t max_, const pmt::pmt_t def)
+ : priv(priv_), units(units_), description(desc_),
+ min(min_), max(max_), defaultvalue(def), display(display_)
+ {
+ }
+
+ priv_lvl_t priv;
+ std::string units, description;
+ pmt::pmt_t min, max, defaultvalue;
+ DisplayType display;
+ };
+
+ template<typename T, typename Tsptr>
+ class callback_t : public callback_base_t
+ {
+ public:
+ callback_t(T* callback_, priv_lvl_t priv_,
+ const std::string& units_, const DisplayType display_, const:: std::string& desc_,
+ const pmt::pmt_t& min_, const pmt::pmt_t& max_, const pmt::pmt_t& def_) :
+ callback_base_t(priv_, units_, display_, desc_, min_, max_, def_),
+ callback(callback_)
+ {
+ }
+
+ Tsptr callback;
+ };
+
+ typedef callback_t<gruel::msg_accepter, gruel::msg_accepter_sptr> configureCallback_t;
+ typedef callback_t<gruel::msg_producer, gruel::msg_producer_sptr> queryCallback_t;
+
+ callbackregister_base() {;}
+ virtual ~callbackregister_base() {;}
+
+ virtual void registerConfigureCallback(const std::string &id, const configureCallback_t callback) = 0;
+ virtual void unregisterConfigureCallback(const std::string &id) = 0;
+ virtual void registerQueryCallback(const std::string &id, const queryCallback_t callback) = 0;
+ virtual void unregisterQueryCallback(const std::string &id) = 0;
+};
+
+#endif /* RPCCALLBACKREGISTER_BASE_H */
diff --git a/gnuradio-runtime/include/rpcmanager.h b/gnuradio-runtime/include/rpcmanager.h
new file mode 100644
index 0000000000..6e1e181c3c
--- /dev/null
+++ b/gnuradio-runtime/include/rpcmanager.h
@@ -0,0 +1,59 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef RPCMANAGER_H
+#define RPCMANAGER_H
+
+#include <gr_runtime_api.h>
+#include <rpcmanager_base.h>
+#include <rpcserver_booter_aggregator.h>
+#include <memory>
+#include <iostream>
+
+class GR_RUNTIME_API rpcmanager : public virtual rpcmanager_base
+{
+ public:
+ rpcmanager();
+ ~rpcmanager();
+
+ static rpcserver_booter_base* get();
+
+ static void register_booter(rpcserver_booter_base* booter);
+
+ template<typename T> class rpcserver_booter_register_helper
+ {
+ public:
+ rpcserver_booter_register_helper() {
+ rpcmanager::register_booter(new T());
+ }
+
+ //TODO: unregister
+ };
+
+ private:
+ static bool make_aggregator, booter_registered, aggregator_registered;
+ static void rpcserver_booter_base_sptr_dest( rpcserver_booter_base* b) {;}
+ static rpcserver_booter_base* boot;
+ static std::auto_ptr<rpcserver_booter_aggregator> aggregator;
+};
+
+#endif /* RPCMANAGER_H */
diff --git a/gnuradio-runtime/include/rpcmanager_base.h b/gnuradio-runtime/include/rpcmanager_base.h
new file mode 100644
index 0000000000..60425c4a15
--- /dev/null
+++ b/gnuradio-runtime/include/rpcmanager_base.h
@@ -0,0 +1,46 @@
+/* -*- 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 RPCMANAGER_BASE_H
+#define RPCMANAGER_BASE_H
+
+#include <boost/shared_ptr.hpp>
+
+class rpcserver_booter_base;
+//class rpcserver_booter_aggregator;
+
+class rpcmanager_base
+{
+ public:
+ typedef boost::shared_ptr<rpcserver_booter_base> rpcserver_booter_base_sptr;
+
+ rpcmanager_base() {;}
+ ~rpcmanager_base() {;}
+
+ //static rpcserver_booter_base* get();
+
+ //static void register_booter(rpcserver_booter_base_sptr booter);
+
+private:
+};
+
+#endif /* RPCMANAGER_BASE_H */
diff --git a/gnuradio-runtime/include/rpcpmtconverters_ice.h b/gnuradio-runtime/include/rpcpmtconverters_ice.h
new file mode 100644
index 0000000000..4403b96a2a
--- /dev/null
+++ b/gnuradio-runtime/include/rpcpmtconverters_ice.h
@@ -0,0 +1,35 @@
+/* -*- 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 RPCPMTCONVERTERS_ICE_H
+#define RPCPMTCONVERTERS_ICE_H
+
+#include <gruel/pmt.h>
+#include <gnuradio.h>
+
+namespace rpcpmtconverter
+{
+ pmt::pmt_t to_pmt(const GNURadio::KnobPtr& knob, const Ice::Current& c);
+ GNURadio::KnobPtr from_pmt(const pmt::pmt_t& knob, const Ice::Current& c);
+}
+
+#endif /* RPCPMTCONVERTERS_ICE_H */
diff --git a/gnuradio-runtime/include/rpcregisterhelpers.h b/gnuradio-runtime/include/rpcregisterhelpers.h
new file mode 100644
index 0000000000..1be3769ac8
--- /dev/null
+++ b/gnuradio-runtime/include/rpcregisterhelpers.h
@@ -0,0 +1,659 @@
+/* -*- 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 RPCREGISTERHELPERS_H
+#define RPCREGISTERHELPERS_H
+
+#include <stdio.h>
+#include <sstream>
+#include <iostream>
+#include <rpcserver_booter_base.h>
+#include <rpcmanager.h>
+#include <rpcserver_selector.h>
+#include <rpcserver_base.h>
+#include <gr_block_registry.h>
+
+// Base classes
+template<typename T, typename Tto> class rpcextractor_base
+ : public virtual gruel::msg_accepter
+{
+public:
+ rpcextractor_base(T* source, void (T::*func)(Tto)) :
+ _source(source), _func(func) {;}
+ ~rpcextractor_base() {;}
+
+ void post(pmt::pmt_t which_port, pmt::pmt_t msg) {
+ throw std::runtime_error("rpcextractor_base: no post defined for this data type.\n");
+ }
+
+protected:
+ T* _source;
+ void (T::*_func)(Tto);
+};
+
+template<typename T, typename Tto>
+class rpcbasic_extractor : public virtual rpcextractor_base<T,Tto>
+{
+public:
+ rpcbasic_extractor(T* source, void (T::*func)(Tto)) :
+ rpcextractor_base<T,Tto>(source, func)
+ {;}
+};
+
+template<typename T, typename Tfrom>
+class rpcinserter_base : public virtual gruel::msg_producer
+{
+public:
+ rpcinserter_base(T* source, Tfrom (T::*func)()) : _source(source), _func(func) {;}
+ rpcinserter_base() {;}
+
+ pmt::pmt_t retrieve() { assert(0); return pmt::pmt_t(); }
+
+protected:
+ T* _source;
+ Tfrom (T::*_func)();
+};
+
+template<typename T, typename Tfrom>
+class rpcbasic_inserter :
+ public virtual rpcinserter_base<T,Tfrom>
+{
+public:
+ rpcbasic_inserter(T* source, Tfrom (T::*func)()const)
+ : rpcinserter_base<T,Tfrom>(source, func)
+ {;}
+
+ rpcbasic_inserter(T* source, Tfrom (T::*func)())
+ : rpcinserter_base<T,Tfrom>(source, func)
+ {;}
+
+ pmt::pmt_t retrieve()
+ {
+ return pmt::mp((rpcinserter_base<T,Tfrom>::
+ _source->*rpcinserter_base<T,Tfrom>::_func)());
+ }
+};
+
+// Specialized Extractor Templates
+template<typename T>
+class rpcbasic_extractor<T,double> : public virtual rpcextractor_base<T,double>
+{
+public:
+ rpcbasic_extractor(T* source, void (T::*func)(double))
+ : rpcextractor_base<T,double>(source, func)
+ {;}
+
+ void post(pmt::pmt_t which_port, pmt::pmt_t msg)
+ {
+ (rpcextractor_base<T,double>::_source->*rpcextractor_base<T,double>::_func)
+ (pmt::to_double(msg));
+ }
+};
+
+template<typename T>
+class rpcbasic_extractor<T,float> : public virtual rpcextractor_base<T,float>
+{
+public:
+ rpcbasic_extractor(T* source, void (T::*func)(float))
+ : rpcextractor_base<T,float>(source, func)
+ {;}
+
+ void post(pmt::pmt_t which_port, pmt::pmt_t msg)
+ {
+ (rpcextractor_base<T,float>::_source->*rpcextractor_base<T,float>::_func)
+ (pmt::to_double(msg));
+ }
+};
+
+template<typename T>
+class rpcbasic_extractor<T,long> : public virtual rpcextractor_base<T,long>
+{
+public:
+ rpcbasic_extractor(T* source, void (T::*func)(long))
+ : rpcextractor_base<T,long>(source, func)
+ {;}
+
+ void post(pmt::pmt_t which_port, pmt::pmt_t msg)
+ {
+ (rpcextractor_base<T,long>::_source->*rpcextractor_base<T,long>::_func)
+ (pmt::to_long(msg));
+ }
+};
+
+template<typename T>
+class rpcbasic_extractor<T,int> : public virtual rpcextractor_base<T,int>
+{
+public:
+ rpcbasic_extractor(T* source, void (T::*func)(int))
+ : rpcextractor_base<T,int>(source, func)
+ {;}
+
+ void post(pmt::pmt_t which_port, pmt::pmt_t msg)
+ {
+ (rpcextractor_base<T,int>::_source->*rpcextractor_base<T,int>::_func)
+ (pmt::to_long(msg));
+ }
+};
+
+template<typename T>
+class rpcbasic_extractor<T,bool> : public virtual rpcextractor_base<T,bool>
+{
+public:
+ rpcbasic_extractor(T* source, void (T::*func)(bool))
+ : rpcextractor_base<T,bool>(source, func)
+ {;}
+
+ void post(pmt::pmt_t which_port, pmt::pmt_t msg)
+ {
+ (rpcextractor_base<T,bool>::_source->*rpcextractor_base<T,bool>::_func)
+ (pmt::to_bool(msg));
+ }
+};
+
+template<typename T>
+class rpcbasic_extractor<T,std::complex<double> >
+ : public virtual rpcextractor_base<T,std::complex<double> >
+{
+public:
+ rpcbasic_extractor(T* source, void (T::*func)(std::complex<double>))
+ : rpcextractor_base<T,std::complex<double> >(source, func)
+ {;}
+
+ void post(pmt::pmt_t which_port, pmt::pmt_t msg)
+ {
+ (rpcextractor_base<T,std::complex<double> >::
+ _source->*rpcextractor_base<T,std::complex<double> >::_func)(pmt::to_complex(msg));
+ }
+};
+
+template<typename T>
+class rpcbasic_extractor<T,std::string>
+ : public virtual rpcextractor_base<T,std::string>
+{
+public:
+ rpcbasic_extractor(T* source, void (T::*func)(std::string))
+ : rpcextractor_base<T,std::string>(source, func)
+ {;}
+
+ void post(pmt::pmt_t which_port, pmt::pmt_t msg)
+ {
+ (rpcextractor_base<T,std::string>::
+ _source->*rpcextractor_base<T,std::string>::_func)(pmt::symbol_to_string(msg));
+ }
+};
+
+template<typename T>
+class rpcbasic_inserter<T,uint64_t> : public virtual rpcinserter_base<T,uint64_t>
+{
+public:
+ rpcbasic_inserter(T* source, uint64_t (T::*func)() const)
+ : rpcinserter_base<T,uint64_t>(source, func)
+ {;}
+
+ rpcbasic_inserter(T* source, uint64_t (T::*func)())
+ : rpcinserter_base<T,uint64_t>(source, func)
+ {;}
+
+ pmt::pmt_t retrieve()
+ {
+ return pmt::from_uint64((rpcinserter_base<T,uint64_t>::
+ _source->*rpcinserter_base<T,uint64_t>::_func)());
+ }
+};
+
+template<typename T>
+class rpcbasic_inserter<T,std::vector< int > >
+ : public virtual rpcinserter_base<T,std::vector< int > >
+{
+public:
+ rpcbasic_inserter(T* source, std::vector<int > (T::*func)() const)
+ : rpcinserter_base<T,std::vector<int > >(source, func)
+ {;}
+
+ rpcbasic_inserter(T* source, std::vector<int > (T::*func)())
+ : rpcinserter_base<T,std::vector<int > >(source, func)
+ {;}
+
+ pmt::pmt_t retrieve()
+ {
+ std::vector< int >
+ vec((rpcinserter_base<T,std::vector<int > >::
+ _source->*rpcinserter_base<T,std::vector< int > >::_func)());
+ return pmt::init_s32vector(vec.size(), &vec[0]);
+ }
+};
+
+template<typename T>
+class rpcbasic_inserter<T,std::vector< std::complex<float> > >
+ : public virtual rpcinserter_base<T,std::vector< std::complex<float> > >
+{
+public:
+ rpcbasic_inserter(T* source, std::vector<std::complex<float> > (T::*func)() const)
+ : rpcinserter_base<T,std::vector<std::complex<float> > >(source, func)
+ {;}
+
+ rpcbasic_inserter(T* source, std::vector<std::complex<float> > (T::*func)())
+ : rpcinserter_base<T,std::vector<std::complex<float> > >(source, func)
+ {;}
+
+ pmt::pmt_t retrieve()
+ {
+ std::vector< std::complex<float> >
+ vec((rpcinserter_base<T,std::vector<std::complex<float> > >::
+ _source->*rpcinserter_base<T,std::vector< std::complex<float> > >::_func)());
+ return pmt::init_c32vector(vec.size(), &vec[0]);
+ }
+};
+
+template<typename T>
+class rpcbasic_inserter<T,std::vector< float> >
+ : public virtual rpcinserter_base<T,std::vector< float > >
+{
+public:
+ rpcbasic_inserter(T* source, std::vector<float> (T::*func)() const)
+ : rpcinserter_base<T,std::vector<float > >(source, func)
+ {;}
+
+ rpcbasic_inserter(T* source, std::vector<float> (T::*func)())
+ : rpcinserter_base<T,std::vector<float> >(source, func)
+ {;}
+
+ pmt::pmt_t retrieve()
+ {
+ std::vector< float > vec((rpcinserter_base<T,std::vector<float> >::
+ _source->*rpcinserter_base<T,std::vector< float> >::_func)());
+ return pmt::init_f32vector(vec.size(), &vec[0]);
+ }
+};
+
+template<typename T>
+class rpcbasic_inserter<T,std::vector< uint8_t> >
+ : public virtual rpcinserter_base<T,std::vector< uint8_t > > {
+public:
+ rpcbasic_inserter(T* source, std::vector<uint8_t> (T::*func)() const)
+ : rpcinserter_base<T,std::vector<uint8_t > >(source, func)
+ {;}
+
+ rpcbasic_inserter(T* source, std::vector<uint8_t> (T::*func)())
+ : rpcinserter_base<T,std::vector<uint8_t> >(source, func)
+ {;}
+
+ pmt::pmt_t retrieve()
+ {
+ std::vector< uint8_t > vec((rpcinserter_base<T,std::vector<uint8_t> >::
+ _source->*rpcinserter_base<T,std::vector< uint8_t> >::_func)());
+ return pmt::init_u8vector(vec.size(), &vec[0]);
+ }
+};
+
+template <typename T>
+struct rpc_register_base
+{
+ rpc_register_base() {count++;}
+protected: static int count;
+};
+
+// Base class to inherit from and create universal shared pointers.
+class rpcbasic_base
+{
+public:
+ rpcbasic_base() {}
+ virtual ~rpcbasic_base() {};
+};
+
+typedef boost::shared_ptr<rpcbasic_base> rpcbasic_sptr;
+
+template<typename T, typename Tto>
+struct rpcbasic_register_set : public rpcbasic_base
+{
+ // Function used to add a 'set' RPC call using a gr_basic_block's alias.
+ rpcbasic_register_set(const std::string& block_alias,
+ const char* functionbase,
+ void (T::*function)(Tto),
+ const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def,
+ const char* units_ = "",
+ const char* desc_ = "",
+ priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
+ DisplayType display_ = DISPNULL)
+ {
+ d_min = min;
+ d_max = max;
+ d_def = def;
+ d_units = units_;
+ d_desc = desc_;
+ d_minpriv = minpriv_;
+ d_display = display_;
+ d_object = dynamic_cast<T*>(global_block_registry.block_lookup(pmt::intern(block_alias)).get());
+#ifdef RPCSERVER_ENABLED
+ callbackregister_base::configureCallback_t
+ extractor(new rpcbasic_extractor<T,Tto>(d_object, function),
+ minpriv_, std::string(units_),
+ display_, std::string(desc_), min, max, def);
+ std::ostringstream oss(std::ostringstream::out);
+ oss << block_alias << "::" << functionbase;
+ d_id = oss.str();
+ //std::cerr << "REGISTERING SET: " << d_id << " " << desc_ << std::endl;
+ rpcmanager::get()->i()->registerConfigureCallback(d_id, extractor);
+#endif
+ }
+
+ // Function used to add a 'set' RPC call using a name and the object
+ rpcbasic_register_set(const std::string& name,
+ const char* functionbase,
+ T* obj,
+ void (T::*function)(Tto),
+ const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def,
+ const char* units_ = "",
+ const char* desc_ = "",
+ priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
+ DisplayType display_ = DISPNULL)
+ {
+ d_min = min;
+ d_max = max;
+ d_def = def;
+ d_units = units_;
+ d_desc = desc_;
+ d_minpriv = minpriv_;
+ d_display = display_;
+ d_object = obj;
+#ifdef RPCSERVER_ENABLED
+ callbackregister_base::configureCallback_t
+ extractor(new rpcbasic_extractor<T,Tto>(d_object, function),
+ minpriv_, std::string(units_),
+ display_, std::string(desc_), min, max, def);
+ std::ostringstream oss(std::ostringstream::out);
+ oss << name << "::" << functionbase;
+ d_id = oss.str();
+ //std::cerr << "REGISTERING SET: " << d_id << " " << desc_ << std::endl;
+ rpcmanager::get()->i()->registerConfigureCallback(d_id, extractor);
+#endif
+ }
+
+ ~rpcbasic_register_set()
+ {
+#ifdef RPCSERVER_ENABLED
+ rpcmanager::get()->i()->unregisterConfigureCallback(d_id);
+#endif
+ }
+
+
+ pmt::pmt_t min() const { return d_min; }
+ pmt::pmt_t max() const { return d_max; }
+ pmt::pmt_t def() const { return d_def; }
+ std::string units() const { return d_units; }
+ std::string description() const { return d_desc; }
+ priv_lvl_t privilege_level() const { return d_minpriv; }
+ DisplayType default_display() const { return d_display; }
+
+ void set_min(pmt::pmt_t p) { d_min = p; }
+ void set_max(pmt::pmt_t p) { d_max = p; }
+ void set_def(pmt::pmt_t p) { d_def = p; }
+ void units(std::string u) { d_units = u; }
+ void description(std::string d) { d_desc = d; }
+ void privilege_level(priv_lvl_t p) { d_minpriv = p; }
+ void default_display(DisplayType d) { d_display = d; }
+
+private:
+ std::string d_id;
+ pmt::pmt_t d_min, d_max, d_def;
+ std::string d_units, d_desc;
+ priv_lvl_t d_minpriv;
+ DisplayType d_display;
+ T *d_object;
+};
+
+
+template<typename T, typename Tfrom>
+class rpcbasic_register_get : public rpcbasic_base
+{
+public:
+ // Function used to add a 'set' RPC call using a gr_basic_block's alias.
+ // primary constructor to allow for T get() functions
+ rpcbasic_register_get(const std::string& block_alias,
+ const char* functionbase,
+ Tfrom (T::*function)(),
+ const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def,
+ const char* units_ = "",
+ const char* desc_ = "",
+ priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
+ DisplayType display_ = DISPNULL)
+ {
+ d_min = min;
+ d_max = max;
+ d_def = def;
+ d_units = units_;
+ d_desc = desc_;
+ d_minpriv = minpriv_;
+ d_display = display_;
+ d_object = dynamic_cast<T*>(global_block_registry.block_lookup(pmt::intern(block_alias)).get());
+#ifdef RPCSERVER_ENABLED
+ callbackregister_base::queryCallback_t
+ inserter(new rpcbasic_inserter<T,Tfrom>(d_object, function),
+ minpriv_, std::string(units_), display_, std::string(desc_), min, max, def);
+ std::ostringstream oss(std::ostringstream::out);
+ oss << block_alias << "::" << functionbase;
+ d_id = oss.str();
+ //std::cerr << "REGISTERING GET: " << d_id << " " << desc_ << std::endl;
+ rpcmanager::get()->i()->registerQueryCallback(d_id, inserter);
+#endif
+ }
+
+
+ // alternate constructor to allow for T get() const functions
+ rpcbasic_register_get(const std::string& block_alias,
+ const char* functionbase,
+ Tfrom (T::*function)() const,
+ const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def,
+ const char* units_ = "",
+ const char* desc_ = "",
+ priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
+ DisplayType display_ = DISPNULL)
+ {
+ d_min = min;
+ d_max = max;
+ d_def = def;
+ d_units = units_;
+ d_desc = desc_;
+ d_minpriv = minpriv_;
+ d_display = display_;
+ d_object = dynamic_cast<T*>(global_block_registry.block_lookup(pmt::intern(block_alias)).get());
+#ifdef RPCSERVER_ENABLED
+ callbackregister_base::queryCallback_t
+ inserter(new rpcbasic_inserter<T,Tfrom>(d_object, (Tfrom (T::*)())function),
+ minpriv_, std::string(units_), display_, std::string(desc_), min, max, def);
+ std::ostringstream oss(std::ostringstream::out);
+ oss << block_alias << "::" << functionbase;
+ d_id = oss.str();
+ //std::cerr << "REGISTERING GET CONST: " << d_id << " " << desc_ << " " << display_ << std::endl;
+ rpcmanager::get()->i()->registerQueryCallback(d_id, inserter);
+#endif
+ }
+
+ // Function used to add a 'set' RPC call using a name and the object
+ // primary constructor to allow for T get() functions
+ rpcbasic_register_get(const std::string& name,
+ const char* functionbase,
+ T* obj,
+ Tfrom (T::*function)(),
+ const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def,
+ const char* units_ = "",
+ const char* desc_ = "",
+ priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
+ DisplayType display_ = DISPNULL)
+ {
+ d_min = min;
+ d_max = max;
+ d_def = def;
+ d_units = units_;
+ d_desc = desc_;
+ d_minpriv = minpriv_;
+ d_display = display_;
+ d_object = obj;
+#ifdef RPCSERVER_ENABLED
+ callbackregister_base::queryCallback_t
+ inserter(new rpcbasic_inserter<T,Tfrom>(d_object, function),
+ minpriv_, std::string(units_), display_, std::string(desc_), min, max, def);
+ std::ostringstream oss(std::ostringstream::out);
+ oss << name << "::" << functionbase;
+ d_id = oss.str();
+ //std::cerr << "REGISTERING GET: " << d_id << " " << desc_ << std::endl;
+ rpcmanager::get()->i()->registerQueryCallback(d_id, inserter);
+#endif
+ }
+
+
+ // alternate constructor to allow for T get() const functions
+ rpcbasic_register_get(const std::string& name,
+ const char* functionbase,
+ T* obj,
+ Tfrom (T::*function)() const,
+ const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def,
+ const char* units_ = "",
+ const char* desc_ = "",
+ priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
+ DisplayType display_ = DISPNULL)
+ {
+ d_min = min;
+ d_max = max;
+ d_def = def;
+ d_units = units_;
+ d_desc = desc_;
+ d_minpriv = minpriv_;
+ d_display = display_;
+ d_object = obj;
+#ifdef RPCSERVER_ENABLED
+ callbackregister_base::queryCallback_t
+ inserter(new rpcbasic_inserter<T,Tfrom>(d_object, (Tfrom (T::*)())function),
+ minpriv_, std::string(units_), display_, std::string(desc_), min, max, def);
+ std::ostringstream oss(std::ostringstream::out);
+ oss << name << "::" << functionbase;
+ d_id = oss.str();
+ //std::cerr << "REGISTERING GET CONST: " << d_id << " " << desc_ << " " << display_ << std::endl;
+ rpcmanager::get()->i()->registerQueryCallback(d_id, inserter);
+#endif
+ }
+
+ ~rpcbasic_register_get()
+ {
+#ifdef RPCSERVER_ENABLED
+ rpcmanager::get()->i()->unregisterQueryCallback(d_id);
+#endif
+ }
+
+ pmt::pmt_t min() const { return d_min; }
+ pmt::pmt_t max() const { return d_max; }
+ pmt::pmt_t def() const { return d_def; }
+ std::string units() const { return d_units; }
+ std::string description() const { return d_desc; }
+ priv_lvl_t privilege_level() const { return d_minpriv; }
+ DisplayType default_display() const { return d_display; }
+
+ void set_min(pmt::pmt_t p) { d_min = p; }
+ void set_max(pmt::pmt_t p) { d_max = p; }
+ void set_def(pmt::pmt_t p) { d_def = p; }
+ void units(std::string u) { d_units = u; }
+ void description(std::string d) { d_desc = d; }
+ void privilege_level(priv_lvl_t p) { d_minpriv = p; }
+ void default_display(DisplayType d) { d_display = d; }
+
+private:
+ std::string d_id;
+ pmt::pmt_t d_min, d_max, d_def;
+ std::string d_units, d_desc;
+ priv_lvl_t d_minpriv;
+ DisplayType d_display;
+ T *d_object;
+};
+
+/*
+ * This class can wrap a pre-existing variable type for you
+ * it will define the getter and rpcregister call for you.
+ *
+ * It should be used for read-only getters.
+ *
+ */
+template<typename Tfrom>
+class rpcbasic_register_variable : public rpcbasic_base
+{
+protected:
+ rpcbasic_register_get< rpcbasic_register_variable<Tfrom>, Tfrom > d_rpc_reg;
+ Tfrom *d_variable;
+ Tfrom get() { return *d_variable; }
+public:
+ // empty constructor which should never be called but needs to exist for ues in varous STL data structures
+ void setptr(Tfrom* _variable){ rpcbasic_register_variable<Tfrom>::d_variable = _variable; }
+ rpcbasic_register_variable() :
+ d_rpc_reg("FAIL", "FAIL", this, &rpcbasic_register_variable::get,
+ pmt::PMT_NIL, pmt::PMT_NIL, pmt::PMT_NIL, DISPNULL,
+ "FAIL", "FAIL", RPC_PRIVLVL_MIN),
+ d_variable(NULL)
+ {
+ throw std::runtime_error("ERROR: rpcbasic_register_variable called with no args. If this happens, someone has tried to use rpcbasic_register_variable incorrectly.");
+ };
+
+ rpcbasic_register_variable(const std::string& namebase,
+ const char* functionbase,
+ Tfrom *variable,
+ const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def,
+ const char* units_ = "",
+ const char* desc_ = "",
+ priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
+ DisplayType display_=DISPNULL) :
+ d_rpc_reg(namebase, functionbase, this, &rpcbasic_register_variable::get,
+ min, max, def, units_, desc_, minpriv_, display_),
+ d_variable(variable)
+ {
+ //std::cerr << "REGISTERING VAR: " << " " << desc_ << std::endl;
+ }
+};
+
+template<typename Tfrom> class rpcbasic_register_variable_rw : public rpcbasic_register_variable<Tfrom> {
+ private:
+ rpcbasic_register_set< rpcbasic_register_variable_rw<Tfrom>, Tfrom > d_rpc_regset;
+ public:
+ // empty constructor which should never be called but needs to exist for ues in varous STL data structures
+ rpcbasic_register_variable_rw() :
+ d_rpc_regset("FAIL","FAIL",this,&rpcbasic_register_variable<Tfrom>::get,pmt::PMT_NIL,pmt::PMT_NIL,pmt::PMT_NIL,DISPNULL,"FAIL","FAIL",RPC_PRIVLVL_MIN)
+ {
+ throw std::runtime_error("ERROR: rpcbasic_register_variable_rw called with no args. if this happens someone used rpcbasic_register_variable_rw incorrectly.\n");
+ };
+ void set(Tfrom _variable){ *(rpcbasic_register_variable<Tfrom>::d_variable) = _variable; }
+ rpcbasic_register_variable_rw(
+ const std::string& namebase,
+ const char* functionbase,
+ Tfrom *variable,
+ const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def,
+ const char* units_ = "",
+ const char* desc_ = "",
+ priv_lvl_t minpriv = RPC_PRIVLVL_MIN,
+ DisplayType display_=DISPNULL) :
+ rpcbasic_register_variable<Tfrom>(namebase,functionbase,variable,min,max,def,units_,desc_),
+ d_rpc_regset(namebase,functionbase,this,&rpcbasic_register_variable_rw::set,min,max,def,units_,desc_,minpriv,display_)
+ {
+ // no action
+ }
+};
+
+
+
+
+#endif
diff --git a/gnuradio-runtime/include/rpcserver_aggregator.h b/gnuradio-runtime/include/rpcserver_aggregator.h
new file mode 100644
index 0000000000..050d9bb1e5
--- /dev/null
+++ b/gnuradio-runtime/include/rpcserver_aggregator.h
@@ -0,0 +1,100 @@
+/* -*- 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 RPCSERVER_AGGREGATOR_H
+#define RPCSERVER_AGGREGATOR_H
+
+#include <vector>
+#include <string>
+#include <rpcserver_base.h>
+#include <rpcmanager_base.h>
+
+class rpcserver_aggregator : public virtual rpcserver_base
+{
+public:
+ rpcserver_aggregator();
+ virtual ~rpcserver_aggregator();
+
+ void registerConfigureCallback(const std::string &id, const configureCallback_t callback);
+ void unregisterConfigureCallback(const std::string &id);
+
+ void registerQueryCallback(const std::string &id, const queryCallback_t callback);
+ void unregisterQueryCallback(const std::string &id);
+
+ void registerServer(rpcmanager_base::rpcserver_booter_base_sptr server);
+
+ const std::string& type();
+
+ const std::vector<std::string>& registeredServers();
+
+private:
+ template<class T, typename Tcallback>
+ struct registerConfigureCallback_f: public std::unary_function<T,void>
+ {
+ registerConfigureCallback_f(const std::string &_id, const Tcallback _callback)
+ : id(_id), callback(_callback)
+ {;}
+
+ void operator()(T& x) { x->i()->registerConfigureCallback(id, callback); }
+ const std::string& id; const Tcallback& callback;
+ };
+
+ template<class T, typename Tcallback>
+ struct unregisterConfigureCallback_f: public std::unary_function<T,void>
+ {
+ unregisterConfigureCallback_f(const std::string &_id)
+ : id(_id)
+ {;}
+
+ void operator()(T& x) { x->i()->unregisterConfigureCallback(id); }
+ const std::string& id;
+ };
+
+ template<class T, typename Tcallback>
+ struct registerQueryCallback_f: public std::unary_function<T,void>
+ {
+ registerQueryCallback_f(const std::string &_id, const Tcallback _callback)
+ : id(_id), callback(_callback)
+ {;}
+
+ void operator()(T& x) { x->i()->registerQueryCallback(id, callback); }
+ const std::string& id; const Tcallback& callback;
+ };
+
+ template<class T, typename Tcallback>
+ struct unregisterQueryCallback_f: public std::unary_function<T,void>
+ {
+ unregisterQueryCallback_f(const std::string &_id)
+ : id(_id)
+ {;}
+
+ void operator()(T& x) { x->i()->unregisterQueryCallback(id); }
+ const std::string& id;
+ };
+
+ const std::string d_type;
+ typedef std::vector<rpcmanager_base::rpcserver_booter_base_sptr> rpcServerMap_t;
+ std::vector<std::string> d_registeredServers;
+ rpcServerMap_t d_serverlist;
+};
+
+#endif /* RPCSERVER_AGGREGATOR_H */
diff --git a/gnuradio-runtime/include/rpcserver_base.h b/gnuradio-runtime/include/rpcserver_base.h
new file mode 100644
index 0000000000..bc985c8d53
--- /dev/null
+++ b/gnuradio-runtime/include/rpcserver_base.h
@@ -0,0 +1,47 @@
+/* -*- 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 RPCSERVER_BASE_H
+#define RPCSERVER_BASE_H
+
+#include <rpccallbackregister_base.h>
+
+class rpcserver_base : public virtual callbackregister_base
+{
+public:
+ rpcserver_base() : cur_priv(RPC_PRIVLVL_ALL) {;}
+ virtual ~rpcserver_base() {;}
+
+ virtual void registerConfigureCallback(const std::string &id, const configureCallback_t callback) = 0;
+ virtual void unregisterConfigureCallback(const std::string &id) = 0;
+ virtual void registerQueryCallback(const std::string &id, const queryCallback_t callback) = 0;
+ virtual void unregisterQueryCallback(const std::string &id) = 0;
+ virtual void setCurPrivLevel(const priv_lvl_t priv) { cur_priv = priv; }
+
+ typedef boost::shared_ptr<rpcserver_base> rpcserver_base_sptr;
+protected:
+ priv_lvl_t cur_priv;
+
+private:
+};
+
+#endif /* RPCSERVER_BASE_H */
diff --git a/gnuradio-runtime/include/rpcserver_booter_aggregator.h b/gnuradio-runtime/include/rpcserver_booter_aggregator.h
new file mode 100644
index 0000000000..38739a1b50
--- /dev/null
+++ b/gnuradio-runtime/include/rpcserver_booter_aggregator.h
@@ -0,0 +1,56 @@
+/* -*- 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 RPCSERVER_BOOTER_AGGREGATOR
+#define RPCSERVER_BOOTER_AGGREGATOR
+
+#include <gr_runtime_api.h>
+#include <rpcserver_booter_base.h>
+#include <rpcserver_aggregator.h>
+#include <boost/shared_ptr.hpp>
+#include <string>
+
+class rpcserver_server;
+
+class GR_RUNTIME_API rpcserver_booter_aggregator :
+ public virtual rpcserver_booter_base
+{
+ public:
+ rpcserver_booter_aggregator();
+ ~rpcserver_booter_aggregator();
+
+ rpcserver_base* i();
+ const std::string& type();
+ const std::vector<std::string> endpoints();
+
+ const std::vector<std::string>& registeredServers();
+
+ protected:
+ friend class rpcmanager;
+ rpcserver_aggregator* agg();
+
+private:
+ std::string d_type;
+ boost::shared_ptr<rpcserver_aggregator> server;
+};
+
+#endif /* RPCSERVER_BOOTER_AGGREGATOR */
diff --git a/gnuradio-runtime/include/rpcserver_booter_base.h b/gnuradio-runtime/include/rpcserver_booter_base.h
new file mode 100644
index 0000000000..682944dada
--- /dev/null
+++ b/gnuradio-runtime/include/rpcserver_booter_base.h
@@ -0,0 +1,44 @@
+/* -*- 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 RPCSERVER_BOOTER_BASE
+#define RPCSERVER_BOOTER_BASE
+
+#include <string>
+#include <vector>
+
+class rpcserver_base;
+
+class rpcserver_booter_base
+{
+public:
+ rpcserver_booter_base() {;}
+ virtual ~rpcserver_booter_base() {;}
+
+ virtual rpcserver_base* i()=0;
+ virtual const std::vector<std::string> endpoints()=0;
+ virtual const std::string& type()=0;
+
+private:
+};
+
+#endif /* RPCSERVER_BOOTER_BASE */
diff --git a/gnuradio-runtime/include/rpcserver_booter_ice.h b/gnuradio-runtime/include/rpcserver_booter_ice.h
new file mode 100644
index 0000000000..69dfcc7602
--- /dev/null
+++ b/gnuradio-runtime/include/rpcserver_booter_ice.h
@@ -0,0 +1,49 @@
+/* -*- 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 RPCSERVER_BOOTER_ICE_H
+#define RPCSERVER_BOOTER_ICE_H
+
+#include <rpcserver_booter_base.h>
+#include <ice_server_template.h>
+#include <gnuradio.h>
+
+class rpcserver_base;
+class rpcserver_ice;
+
+class rpcserver_booter_ice : public virtual rpcserver_booter_base,
+ public virtual ice_server_template<rpcserver_base, rpcserver_ice,
+ rpcserver_booter_ice, GNURadio::ControlPortPtr>
+{
+public:
+ rpcserver_booter_ice();
+ ~rpcserver_booter_ice();
+
+ rpcserver_base* i();
+ const std::string & type() {return d_type;}
+ const std::vector<std::string> endpoints();
+
+private:
+ std::string d_type;
+};
+
+#endif /* RPCSERVER_BOOTER_ICE_H */
diff --git a/gnuradio-runtime/include/rpcserver_ice.h b/gnuradio-runtime/include/rpcserver_ice.h
new file mode 100644
index 0000000000..198e565978
--- /dev/null
+++ b/gnuradio-runtime/include/rpcserver_ice.h
@@ -0,0 +1,224 @@
+/* -*- 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 RPCSERVER_ICE_H
+#define RPCSERVER_ICE_H
+
+#include <rpcserver_base.h>
+#include <rpcpmtconverters_ice.h>
+#include <string>
+#include <map>
+#include <gnuradio.h>
+#include <Ice/Exception.h>
+#include <boost/format.hpp>
+
+class rpcserver_ice : public virtual rpcserver_base, public GNURadio::ControlPort
+{
+public:
+ rpcserver_ice();
+ virtual ~rpcserver_ice();
+
+ void registerConfigureCallback(const std::string &id, const configureCallback_t callback);
+ void unregisterConfigureCallback(const std::string &id);
+
+ void registerQueryCallback(const std::string &id, const queryCallback_t callback);
+ void unregisterQueryCallback(const std::string &id);
+
+ virtual void set(const GNURadio::KnobMap&, const Ice::Current&);
+
+ GNURadio::KnobMap get(const GNURadio::KnobIDList&, const Ice::Current&);
+
+ GNURadio::KnobPropMap properties(const GNURadio::KnobIDList&, const Ice::Current&);
+
+ virtual void shutdown(const Ice::Current&);
+
+private:
+ typedef std::map<std::string, configureCallback_t> ConfigureCallbackMap_t;
+ ConfigureCallbackMap_t d_setcallbackmap;
+
+ typedef std::map<std::string, queryCallback_t> QueryCallbackMap_t;
+ QueryCallbackMap_t d_getcallbackmap;
+
+ template<typename T, typename TMap> struct set_f
+ : public std::unary_function<T,void>
+ {
+ set_f(const Ice::Current& _c, TMap& _setcallbackmap, const priv_lvl_t& _cur_priv) :
+ c(_c), d_setcallbackmap(_setcallbackmap), cur_priv(_cur_priv)
+ {;}
+
+ void operator()(const T& p)
+ {
+ ConfigureCallbackMap_t::const_iterator iter(d_setcallbackmap.find(p.first));
+ if(iter != d_setcallbackmap.end()) {
+ if(cur_priv <= iter->second.priv) {
+ (*iter->second.callback).post(pmt::PMT_NIL, rpcpmtconverter::to_pmt(p.second,c));
+ }
+ else {
+ std::cout << "Key " << p.first << " requires PRIVLVL <= "
+ << iter->second.priv << " to set, currently at: "
+ << cur_priv << std::endl;
+ }
+ }
+ else {
+ throw IceUtil::NullHandleException(__FILE__, __LINE__);
+ }
+ }
+
+ const Ice::Current& c;
+ TMap& d_setcallbackmap;
+ const priv_lvl_t& cur_priv;
+ };
+
+ template<typename T, typename TMap>
+ struct get_f : public std::unary_function<T,void>
+ {
+ get_f(const Ice::Current& _c, TMap& _getcallbackmap,
+ const priv_lvl_t& _cur_priv, GNURadio::KnobMap& _outknobs) :
+ c(_c), d_getcallbackmap(_getcallbackmap), cur_priv(_cur_priv), outknobs(_outknobs)
+ {}
+
+ void operator()(const T& p)
+ {
+ QueryCallbackMap_t::const_iterator iter(d_getcallbackmap.find(p));
+ if(iter != d_getcallbackmap.end()) {
+ if(cur_priv <= iter->second.priv) {
+ outknobs[p] = rpcpmtconverter::from_pmt((*iter->second.callback).retrieve(), c);
+ }
+ else {
+ std::cout << "Key " << iter->first << " requires PRIVLVL: <= "
+ << iter->second.priv << " to get, currently at: "
+ << cur_priv << std::endl;
+ }
+ }
+ else {
+ std::cout << "Ctrlport Key called with unregistered key (" << p << ")\n";
+ std::string tmpkey(p);
+ throw IceUtil::NullHandleException((boost::format("%s Ctrlport Key called with unregistered key = %s")%__FILE__%p).str().c_str(), __LINE__);
+ }
+ }
+
+ const Ice::Current& c;
+ TMap& d_getcallbackmap;
+ const priv_lvl_t& cur_priv;
+ GNURadio::KnobMap& outknobs;
+ };
+
+ template<typename T, typename TMap, typename TKnobMap>
+ struct get_all_f : public std::unary_function<T,void>
+ {
+ get_all_f(const Ice::Current& _c, TMap& _getcallbackmap,
+ const priv_lvl_t& _cur_priv, TKnobMap& _outknobs) :
+ c(_c), d_getcallbackmap(_getcallbackmap), cur_priv(_cur_priv), outknobs(_outknobs)
+ {;}
+
+ void operator()(const T& p)
+ {
+ if(cur_priv <= p.second.priv) {
+ outknobs[p.first] = rpcpmtconverter::from_pmt(p.second.callback->retrieve(), c);
+ }
+ else {
+ std::cout << "Key " << p.first << " requires PRIVLVL <= "
+ << p.second.priv << " to get, currently at: "
+ << cur_priv << std::endl;
+ }
+ }
+
+ const Ice::Current& c;
+ TMap& d_getcallbackmap;
+ const priv_lvl_t& cur_priv;
+ TKnobMap& outknobs;
+ };
+
+ template<typename T, typename TMap, typename TKnobMap>
+ struct properties_all_f : public std::unary_function<T,void>
+ {
+ properties_all_f(const Ice::Current& _c, QueryCallbackMap_t& _getcallbackmap,
+ const priv_lvl_t& _cur_priv, GNURadio::KnobPropMap& _outknobs) :
+ c(_c), d_getcallbackmap(_getcallbackmap), cur_priv(_cur_priv), outknobs(_outknobs)
+ {;}
+
+ void operator()(const T& p)
+ {
+ if(cur_priv <= p.second.priv) {
+ GNURadio::KnobProp prop;//(new GNURadio::KnobProp());
+ prop.type = GNURadio::KNOBDOUBLE;
+ prop.units = p.second.units;
+ prop.description = p.second.description;
+ prop.min = rpcpmtconverter::from_pmt(p.second.min, c);
+ prop.max = rpcpmtconverter::from_pmt(p.second.max, c);
+ prop.display = static_cast<uint32_t>(p.second.display);
+ outknobs[p.first] = prop;
+ }
+ else {
+ std::cout << "Key " << p.first << " requires PRIVLVL <= "
+ << p.second.priv << " to get, currently at: "
+ << cur_priv << std::endl;
+ }
+ }
+
+ const Ice::Current& c;
+ TMap& d_getcallbackmap;
+ const priv_lvl_t& cur_priv;
+ TKnobMap& outknobs;
+ };
+
+ template<class T, typename TMap, typename TKnobMap>
+ struct properties_f : public std::unary_function<T,void>
+ {
+ properties_f(const Ice::Current& _c, TMap& _getcallbackmap,
+ const priv_lvl_t& _cur_priv, TKnobMap& _outknobs) :
+ c(_c), d_getcallbackmap(_getcallbackmap), cur_priv(_cur_priv), outknobs(_outknobs)
+ {;}
+
+ void operator()(const T& p)
+ {
+ typename TMap::const_iterator iter(d_getcallbackmap.find(p));
+ if(iter != d_getcallbackmap.end()) {
+ if(cur_priv <= iter->second.priv) {
+ GNURadio::KnobProp prop;
+ prop.type = GNURadio::KNOBDOUBLE;
+ prop.units = iter->second.units;
+ prop.description = iter->second.description;
+ prop.min = rpcpmtconverter::from_pmt(iter->second.min, c);
+ prop.max = rpcpmtconverter::from_pmt(iter->second.max, c);
+ prop.display = static_cast<uint32_t>(iter->second.display);
+ //outknobs[iter->first] = prop;
+ outknobs[p] = prop;
+ }
+ else {
+ std::cout << "Key " << iter->first << " requires PRIVLVL: <= " <<
+ iter->second.priv << " to get, currently at: " << cur_priv << std::endl;
+ }
+ }
+ else {
+ throw IceUtil::NullHandleException(__FILE__, __LINE__);
+ }
+ }
+
+ const Ice::Current& c;
+ TMap& d_getcallbackmap;
+ const priv_lvl_t& cur_priv;
+ TKnobMap& outknobs;
+ };
+};
+
+#endif /* RPCSERVER_ICE_H */
diff --git a/gnuradio-runtime/include/rpcserver_selector.h b/gnuradio-runtime/include/rpcserver_selector.h
new file mode 100644
index 0000000000..fa63c9a2dc
--- /dev/null
+++ b/gnuradio-runtime/include/rpcserver_selector.h
@@ -0,0 +1,32 @@
+/* -*- 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 RPCSERVER_SELECTOR
+#define RPCSERVER_SELECTOR
+
+#define RPCSERVER_ENABLED
+
+#define RPCSERVER_ICE
+//#define RPCSERVER_ERLANG
+//#define RPCSERVER_XMLRPC
+
+#endif
diff --git a/gnuradio-runtime/include/runtime_block_gateway.h b/gnuradio-runtime/include/runtime_block_gateway.h
new file mode 100644
index 0000000000..390864376f
--- /dev/null
+++ b/gnuradio-runtime/include/runtime_block_gateway.h
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2011-2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_RUNTIME_BLOCK_GATEWAY_H
+#define INCLUDED_RUNTIME_BLOCK_GATEWAY_H
+
+#include <gr_runtime_api.h>
+#include <gr_block.h>
+#include <gr_feval.h>
+
+/*!
+ * The work type enum tells the gateway what kind of block to implement.
+ * The choices are familiar gnuradio block overloads (sync, decim, interp).
+ */
+enum gr_block_gw_work_type{
+ GR_BLOCK_GW_WORK_GENERAL,
+ GR_BLOCK_GW_WORK_SYNC,
+ GR_BLOCK_GW_WORK_DECIM,
+ GR_BLOCK_GW_WORK_INTERP,
+};
+
+/*!
+ * Shared message structure between python and gateway.
+ * Each action type represents a scheduler-called function.
+ */
+struct gr_block_gw_message_type{
+ enum action_type{
+ ACTION_GENERAL_WORK, //dispatch work
+ ACTION_WORK, //dispatch work
+ ACTION_FORECAST, //dispatch forecast
+ ACTION_START, //dispatch start
+ ACTION_STOP, //dispatch stop
+ };
+
+ action_type action;
+
+ int general_work_args_noutput_items;
+ std::vector<int> general_work_args_ninput_items;
+ std::vector<void *> general_work_args_input_items; //TODO this should be const void*, but swig cant int cast it right
+ std::vector<void *> general_work_args_output_items;
+ int general_work_args_return_value;
+
+ int work_args_ninput_items;
+ int work_args_noutput_items;
+ std::vector<void *> work_args_input_items; //TODO this should be const void*, but swig cant int cast it right
+ std::vector<void *> work_args_output_items;
+ int work_args_return_value;
+
+ int forecast_args_noutput_items;
+ std::vector<int> forecast_args_ninput_items_required;
+
+ bool start_args_return_value;
+
+ bool stop_args_return_value;
+};
+
+/*!
+ * The gateway block which performs all the magic.
+ *
+ * The gateway provides access to all the gr_block routines.
+ * The methods prefixed with gr_block__ are renamed
+ * to class methods without the prefix in python.
+ */
+class GR_RUNTIME_API runtime_block_gateway : virtual public gr_block{
+public:
+ //! Provide access to the shared message object
+ virtual gr_block_gw_message_type &gr_block_message(void) = 0;
+
+ long gr_block__unique_id(void) const{
+ return gr_block::unique_id();
+ }
+
+ std::string gr_block__name(void) const{
+ return gr_block::name();
+ }
+
+ unsigned gr_block__history(void) const{
+ return gr_block::history();
+ }
+
+ void gr_block__set_history(unsigned history){
+ return gr_block::set_history(history);
+ }
+
+ void gr_block__set_fixed_rate(bool fixed_rate){
+ return gr_block::set_fixed_rate(fixed_rate);
+ }
+
+ bool gr_block__fixed_rate(void) const{
+ return gr_block::fixed_rate();
+ }
+
+ void gr_block__set_output_multiple(int multiple){
+ return gr_block::set_output_multiple(multiple);
+ }
+
+ int gr_block__output_multiple(void) const{
+ return gr_block::output_multiple();
+ }
+
+ void gr_block__consume(int which_input, int how_many_items){
+ return gr_block::consume(which_input, how_many_items);
+ }
+
+ void gr_block__consume_each(int how_many_items){
+ return gr_block::consume_each(how_many_items);
+ }
+
+ void gr_block__produce(int which_output, int how_many_items){
+ return gr_block::produce(which_output, how_many_items);
+ }
+
+ void gr_block__set_relative_rate(double relative_rate){
+ return gr_block::set_relative_rate(relative_rate);
+ }
+
+ double gr_block__relative_rate(void) const{
+ return gr_block::relative_rate();
+ }
+
+ uint64_t gr_block__nitems_read(unsigned int which_input){
+ return gr_block::nitems_read(which_input);
+ }
+
+ uint64_t gr_block__nitems_written(unsigned int which_output){
+ return gr_block::nitems_written(which_output);
+ }
+
+ gr_block::tag_propagation_policy_t gr_block__tag_propagation_policy(void){
+ return gr_block::tag_propagation_policy();
+ }
+
+ void gr_block__set_tag_propagation_policy(gr_block::tag_propagation_policy_t p){
+ return gr_block::set_tag_propagation_policy(p);
+ }
+
+ void gr_block__add_item_tag(
+ unsigned int which_output, const gr_tag_t &tag
+ ){
+ return gr_block::add_item_tag(which_output, tag);
+ }
+
+ void gr_block__add_item_tag(
+ unsigned int which_output,
+ uint64_t abs_offset,
+ const pmt::pmt_t &key,
+ const pmt::pmt_t &value,
+ const pmt::pmt_t &srcid=pmt::PMT_F
+ ){
+ return gr_block::add_item_tag(which_output, abs_offset, key, value, srcid);
+ }
+
+ std::vector<gr_tag_t> gr_block__get_tags_in_range(
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end
+ ){
+ std::vector<gr_tag_t> tags;
+ gr_block::get_tags_in_range(tags, which_input, abs_start, abs_end);
+ return tags;
+ }
+
+ std::vector<gr_tag_t> gr_block__get_tags_in_range(
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end,
+ const pmt::pmt_t &key
+ ){
+ std::vector<gr_tag_t> tags;
+ gr_block::get_tags_in_range(tags, which_input, abs_start, abs_end, key);
+ return tags;
+ }
+
+ /* Message passing interface */
+ void gr_block__message_port_register_in(pmt::pmt_t port_id){
+ gr_basic_block::message_port_register_in(port_id);
+ }
+
+ void gr_block__message_port_register_out(pmt::pmt_t port_id){
+ gr_basic_block::message_port_register_out(port_id);
+ }
+
+ void gr_block__message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg){
+ gr_basic_block::message_port_pub(port_id, msg);
+ }
+
+ void gr_block__message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target){
+ gr_basic_block::message_port_sub(port_id, target);
+ }
+
+ void gr_block__message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target){
+ gr_basic_block::message_port_unsub(port_id, target);
+ }
+
+ pmt::pmt_t gr_block__message_ports_in(){
+ return gr_basic_block::message_ports_in();
+ }
+
+ pmt::pmt_t gr_block__message_ports_out(){
+ return gr_basic_block::message_ports_out();
+ }
+
+ void set_msg_handler_feval(pmt::pmt_t which_port, gr_feval_p *msg_handler)
+ {
+ if(msg_queue.find(which_port) == msg_queue.end()){
+ throw std::runtime_error("attempt to set_msg_handler_feval() on bad input message port!");
+ }
+ d_msg_handlers_feval[which_port] = msg_handler;
+ }
+
+protected:
+ typedef std::map<pmt::pmt_t, gr_feval_p *, pmt::comperator> msg_handlers_feval_t;
+ msg_handlers_feval_t d_msg_handlers_feval;
+
+ void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg){
+ // Is there a handler?
+ if (d_msg_handlers_feval.find(which_port) != d_msg_handlers_feval.end()){
+ d_msg_handlers_feval[which_port]->calleval(msg); // Yes, invoke it.
+ }
+ else {
+ // Pass to generic dispatcher if not found
+ gr_basic_block::dispatch_msg(which_port, msg);
+ }
+ }
+};
+
+/*!
+ * Make a new gateway block.
+ * \param handler the swig director object with callback
+ * \param name the name of the block (Ex: "Shirley")
+ * \param in_sig the input signature for this block
+ * \param out_sig the output signature for this block
+ * \param work_type the type of block overload to implement
+ * \param factor the decimation or interpolation factor
+ * \return a new gateway block
+ */
+GR_RUNTIME_API boost::shared_ptr<runtime_block_gateway>
+runtime_make_block_gateway(
+ gr_feval_ll *handler,
+ const std::string &name,
+ gr_io_signature_sptr in_sig,
+ gr_io_signature_sptr out_sig,
+ const gr_block_gw_work_type work_type,
+ const unsigned factor
+);
+
+#endif /* INCLUDED_RUNTIME_BLOCK_GATEWAY_H */
diff --git a/gnuradio-runtime/lib/CMakeLists.txt b/gnuradio-runtime/lib/CMakeLists.txt
new file mode 100644
index 0000000000..01b9b172b0
--- /dev/null
+++ b/gnuradio-runtime/lib/CMakeLists.txt
@@ -0,0 +1,257 @@
+# 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_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
+ runtime_block_gateway.cc
+)
+
+# 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}
+ ${LOG4CPP_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..87ffe55085
--- /dev/null
+++ b/gnuradio-runtime/lib/frontend.ice
@@ -0,0 +1,152 @@
+/*
+ * 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 <gnuradio.ice>
+
+[["python:package:gnuradio.ctrlport"]]
+module GNURadio {
+ module Frontend {
+
+ // primitive types
+ dictionary<string, string> StrStrDict;
+ dictionary<string, string> TunerArgs;
+ struct F32Range
+ {
+ float min;
+ float max;
+ };
+
+ // exception types
+ exception NotSupported {};
+ exception InvalidSetting { string msg; };
+ exception ReceiverFailure { string msg; };
+ exception NotExist {};
+
+
+ // Status Types
+ struct TunerStatus {
+ float freq;
+ float rate;
+ int a2dbits;
+ float gain;
+ F32Range gainrange;
+ bool isInverted;
+ StrStrDict info;
+ };
+
+ struct StreamInfo {
+ string uri;
+ StrStrDict info;
+ };
+
+ struct ReceiverInfo {
+ string uid;
+ string name;
+ StrStrDict info;
+ };
+
+ struct ChannelStatus {
+ string uid;
+ string name;
+ bool active;
+ float freq;
+ float bandwidth;
+ bool isComplex;
+ StrStrDict info;
+ };
+
+ struct ChannelizerStatus {
+ string uid;
+ string name;
+ StrStrDict info;
+ };
+
+ // Interfaces
+ interface Component {
+ void setName(string newName);
+ };
+
+ interface AbstractReceiver extends Component {
+ idempotent ReceiverInfo getReceiverInfo();
+ };
+
+ interface Tuner {
+ TunerStatus configureTuner(TunerArgs args) throws ReceiverFailure, InvalidSetting;
+ idempotent TunerStatus status();
+ idempotent float setGain(float gain) throws ReceiverFailure, NotSupported, InvalidSetting;
+ idempotent bool setInversion(bool inverted) throws ReceiverFailure, NotSupported, InvalidSetting;
+ idempotent float setCenterFreq(float freq) throws ReceiverFailure, NotSupported, InvalidSetting;
+ idempotent float setBandwidth(float bw) throws ReceiverFailure, NotSupported, InvalidSetting;
+ idempotent void setInfo(string k, string v) throws ReceiverFailure, NotSupported, InvalidSetting;
+ };
+
+ interface Channel {
+ void start();
+ void stop();
+ void destroyChannel() throws NotSupported;
+ idempotent bool active();
+ idempotent ChannelStatus status();
+ idempotent StreamInfo stream();
+ idempotent bool setComplex(bool complex) throws ReceiverFailure, NotSupported, InvalidSetting;
+ idempotent void setInfo(string k, string v) throws ReceiverFailure, NotSupported, InvalidSetting;
+ idempotent void setStreamInfo(string k, string v) throws ReceiverFailure, NotSupported, InvalidSetting;
+ };
+
+ sequence<Tuner*> TunerSeq;
+ sequence<Channel*> ChannelSeq;
+
+ interface Channelizer extends AbstractReceiver {
+ idempotent ChannelizerStatus status();
+ idempotent Tuner* getTuner();
+ idempotent ChannelSeq getChannels();
+ idempotent ChannelSeq getActiveChannels();
+ idempotent ChannelSeq getInactiveChannels();
+ Channel* createChannel(float freq, float bw, StrStrDict args) throws NotSupported;
+ };
+
+ sequence<Channelizer*> ChannelizerSeq;
+
+ interface Receiver extends AbstractReceiver {
+ idempotent ChannelizerSeq getInputs();
+ idempotent Channel* getChannelByID(string id) throws NotExist;
+ idempotent Channelizer* getChannelizerByID(string id) throws NotExist;
+ idempotent void setInfo(string k, string v) throws ReceiverFailure, NotSupported, InvalidSetting;
+ };
+
+ };
+
+ module Booter {
+ dictionary<string, string> WaveformArgs;
+ exception WaveformRunningError {
+ string waveformClass;
+ float centerFrequencyHz;
+ };
+ exception SignalSourceError {string msg; };
+ interface WaveformBooter extends Frontend::Receiver, ControlPort {
+ string launchWaveform(string waveformClass, WaveformArgs args)
+ throws WaveformRunningError, SignalSourceError;
+ WaveformArgMap getDriverEnum();
+ WaveformArgMap getSourceInfo();
+ idempotent bool waveformRunning();
+ idempotent string getWaveformClass();
+ };
+ };
+};
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..731cbea956
--- /dev/null
+++ b/gnuradio-runtime/lib/gnuradio.ice
@@ -0,0 +1,95 @@
+/*
+ * 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();
+};
+
+};
+
+#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..2830a999ea
--- /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<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..af767da8ec
--- /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<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_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..82737128bb
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_logger.cc
@@ -0,0 +1,295 @@
+/* -*- 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.
+*******************************************************************************/
+
+#ifndef ENABLE_GR_LOG
+#include "config.h"
+#endif
+
+#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/runtime_block_gateway.cc b/gnuradio-runtime/lib/runtime_block_gateway.cc
new file mode 100644
index 0000000000..11d16af41e
--- /dev/null
+++ b/gnuradio-runtime/lib/runtime_block_gateway.cc
@@ -0,0 +1,185 @@
+/*
+ * 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 <runtime_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 runtime_block_gateway_impl : public runtime_block_gateway{
+public:
+ runtime_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<runtime_block_gateway> runtime_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<runtime_block_gateway>(
+ new runtime_block_gateway_impl(handler, name, in_sig, out_sig,
+ work_type, factor)
+ );
+}
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..783cbebc0b
--- /dev/null
+++ b/gnuradio-runtime/lib/test_runtime.cc
@@ -0,0 +1,46 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#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;
+}
diff --git a/gnuradio-runtime/python/CMakeLists.txt b/gnuradio-runtime/python/CMakeLists.txt
new file mode 100644
index 0000000000..74adec3f11
--- /dev/null
+++ b/gnuradio-runtime/python/CMakeLists.txt
@@ -0,0 +1,23 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+include(GrPython)
+
+add_subdirectory(gnuradio)
diff --git a/gnuradio-runtime/python/build_utils.py b/gnuradio-runtime/python/build_utils.py
new file mode 100644
index 0000000000..cf58a97637
--- /dev/null
+++ b/gnuradio-runtime/python/build_utils.py
@@ -0,0 +1,226 @@
+#
+# Copyright 2004,2009,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+"""Misc utilities used at build time
+"""
+
+import re, os, os.path
+from build_utils_codes import *
+
+
+# set srcdir to the directory that contains Makefile.am
+try:
+ srcdir = os.environ['srcdir']
+except KeyError, e:
+ srcdir = "."
+srcdir = srcdir + '/'
+
+# set do_makefile to either true or false dependeing on the environment
+try:
+ if os.environ['do_makefile'] == '0':
+ do_makefile = False
+ else:
+ do_makefile = True
+except KeyError, e:
+ do_makefile = False
+
+# set do_sources to either true or false dependeing on the environment
+try:
+ if os.environ['do_sources'] == '0':
+ do_sources = False
+ else:
+ do_sources = True
+except KeyError, e:
+ do_sources = True
+
+name_dict = {}
+
+def log_output_name (name):
+ (base, ext) = os.path.splitext (name)
+ ext = ext[1:] # drop the leading '.'
+
+ entry = name_dict.setdefault (ext, [])
+ entry.append (name)
+
+def open_and_log_name (name, dir):
+ global do_sources
+ if do_sources:
+ f = open (name, dir)
+ else:
+ f = None
+ log_output_name (name)
+ return f
+
+def expand_template (d, template_filename, extra = ""):
+ '''Given a dictionary D and a TEMPLATE_FILENAME, expand template into output file
+ '''
+ global do_sources
+ output_extension = extract_extension (template_filename)
+ template = open_src (template_filename, 'r')
+ output_name = d['NAME'] + extra + '.' + output_extension
+ log_output_name (output_name)
+ if do_sources:
+ output = open (output_name, 'w')
+ do_substitution (d, template, output)
+ output.close ()
+ template.close ()
+
+def output_glue (dirname):
+ output_makefile_fragment ()
+ output_ifile_include (dirname)
+
+def output_makefile_fragment ():
+ global do_makefile
+ if not do_makefile:
+ return
+# overwrite the source, which must be writable; this should have been
+# checked for beforehand in the top-level Makefile.gen.gen .
+ f = open (os.path.join (os.environ.get('gendir', os.environ.get('srcdir', '.')), 'Makefile.gen'), 'w')
+ f.write ('#\n# This file is machine generated. All edits will be overwritten\n#\n')
+ output_subfrag (f, 'h')
+ output_subfrag (f, 'i')
+ output_subfrag (f, 'cc')
+ f.close ()
+
+def output_ifile_include (dirname):
+ global do_sources
+ if do_sources:
+ f = open ('%s_generated.i' % (dirname,), 'w')
+ f.write ('//\n// This file is machine generated. All edits will be overwritten\n//\n')
+ files = name_dict.setdefault ('i', [])
+ files.sort ()
+ f.write ('%{\n')
+ for file in files:
+ f.write ('#include <%s>\n' % (file[0:-1] + 'h',))
+ f.write ('%}\n\n')
+ for file in files:
+ f.write ('%%include <%s>\n' % (file,))
+
+def output_subfrag (f, ext):
+ files = name_dict.setdefault (ext, [])
+ files.sort ()
+ f.write ("GENERATED_%s =" % (ext.upper ()))
+ for file in files:
+ f.write (" \\\n\t%s" % (file,))
+ f.write ("\n\n")
+
+def extract_extension (template_name):
+ # template name is something like: GrFIRfilterXXX.h.t
+ # we return everything between the penultimate . and .t
+ mo = re.search (r'\.([a-z]+)\.t$', template_name)
+ if not mo:
+ raise ValueError, "Incorrectly formed template_name '%s'" % (template_name,)
+ return mo.group (1)
+
+def open_src (name, mode):
+ global srcdir
+ return open (os.path.join (srcdir, name), mode)
+
+def do_substitution (d, in_file, out_file):
+ def repl (match_obj):
+ key = match_obj.group (1)
+ # print key
+ return d[key]
+
+ inp = in_file.read ()
+ out = re.sub (r"@([a-zA-Z0-9_]+)@", repl, inp)
+ out_file.write (out)
+
+
+
+copyright = '''/* -*- c++ -*- */
+/*
+ * Copyright 2003,2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+'''
+
+def is_complex (code3):
+ if i_code (code3) == 'c' or o_code (code3) == 'c':
+ return '1'
+ else:
+ return '0'
+
+
+def standard_dict (name, code3, package='gr'):
+ d = {}
+ d['NAME'] = name
+ d['NAME_IMPL'] = name+'_impl'
+ d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
+ d['GUARD_NAME_IMPL'] = 'INCLUDED_%s_%s_IMPL_H' % (package.upper(), name.upper())
+ d['BASE_NAME'] = re.sub ('^' + package + '_', '', name)
+ d['SPTR_NAME'] = '%s_sptr' % name
+ d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
+ d['COPYRIGHT'] = copyright
+ d['TYPE'] = i_type (code3)
+ d['I_TYPE'] = i_type (code3)
+ d['O_TYPE'] = o_type (code3)
+ d['TAP_TYPE'] = tap_type (code3)
+ d['IS_COMPLEX'] = is_complex (code3)
+ return d
+
+
+def standard_dict2 (name, code3, package):
+ d = {}
+ d['NAME'] = name
+ d['BASE_NAME'] = name
+ d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
+ d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
+ d['COPYRIGHT'] = copyright
+ d['TYPE'] = i_type (code3)
+ d['I_TYPE'] = i_type (code3)
+ d['O_TYPE'] = o_type (code3)
+ d['TAP_TYPE'] = tap_type (code3)
+ d['IS_COMPLEX'] = is_complex (code3)
+ return d
+
+def standard_impl_dict2 (name, code3, package):
+ d = {}
+ d['NAME'] = name
+ d['IMPL_NAME'] = name
+ d['BASE_NAME'] = name.rstrip("impl").rstrip("_")
+ d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
+ d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
+ d['COPYRIGHT'] = copyright
+ d['FIR_TYPE'] = "fir_filter_" + code3
+ d['CFIR_TYPE'] = "fir_filter_" + code3[0:2] + 'c'
+ d['TYPE'] = i_type (code3)
+ d['I_TYPE'] = i_type (code3)
+ d['O_TYPE'] = o_type (code3)
+ d['TAP_TYPE'] = tap_type (code3)
+ d['IS_COMPLEX'] = is_complex (code3)
+ return d
diff --git a/gnuradio-runtime/python/build_utils_codes.py b/gnuradio-runtime/python/build_utils_codes.py
new file mode 100644
index 0000000000..9ea96baae4
--- /dev/null
+++ b/gnuradio-runtime/python/build_utils_codes.py
@@ -0,0 +1,52 @@
+#
+# Copyright 2004 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+def i_code (code3):
+ return code3[0]
+
+def o_code (code3):
+ if len (code3) >= 2:
+ return code3[1]
+ else:
+ return code3[0]
+
+def tap_code (code3):
+ if len (code3) >= 3:
+ return code3[2]
+ else:
+ return code3[0]
+
+def i_type (code3):
+ return char_to_type[i_code (code3)]
+
+def o_type (code3):
+ return char_to_type[o_code (code3)]
+
+def tap_type (code3):
+ return char_to_type[tap_code (code3)]
+
+
+char_to_type = {}
+char_to_type['s'] = 'short'
+char_to_type['i'] = 'int'
+char_to_type['f'] = 'float'
+char_to_type['c'] = 'gr_complex'
+char_to_type['b'] = 'unsigned char'
diff --git a/gnuradio-runtime/python/gnuradio/CMakeLists.txt b/gnuradio-runtime/python/gnuradio/CMakeLists.txt
new file mode 100644
index 0000000000..bd566edf14
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/CMakeLists.txt
@@ -0,0 +1,38 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+include(GrPython)
+
+add_subdirectory(gr)
+add_subdirectory(gru)
+
+if(ENABLE_GR_CTRLPORT)
+ add_subdirectory(ctrlport)
+endif(ENABLE_GR_CTRLPORT)
+
+GR_PYTHON_INSTALL(FILES
+ __init__.py
+ eng_notation.py
+ eng_option.py
+ gr_unittest.py
+ gr_xmlrunner.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio
+ COMPONENT "runtime_python"
+)
diff --git a/gnuradio-runtime/python/gnuradio/__init__.py b/gnuradio-runtime/python/gnuradio/__init__.py
new file mode 100644
index 0000000000..d55dac79db
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/__init__.py
@@ -0,0 +1,12 @@
+"""
+GNU Radio is a free & open-source software development toolkit that provides signal processing blocks to implement software radios. It can be used with readily-available low-cost external RF hardware to create software-defined radios, or without hardware in a simulation-like environment. It is widely used in hobbyist, academic and commercial environments to support both wireless communications research and real-world radio systems.
+
+GNU Radio applications are primarily written using the Python programming language, while the supplied performance-critical signal-processing path is implemented in C++ using processor floating-point extensions, where available. Thus, the developer is able to implement real-time, high-throughput radio systems in a simple-to-use, rapid-application-development environment.
+
+While not primarily a simulation tool, GNU Radio does support development of signal processing algorithms using pre-recorded or generated data, avoiding the need for actual RF hardware.
+
+GNU Radio is licensed under the GNU General Public License (GPL) version 3. All of the code is copyright of the Free Software Foundation.
+"""
+
+# This file makes gnuradio a package
+# The docstring will be associated with the top level of the package.
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/CMakeLists.txt b/gnuradio-runtime/python/gnuradio/ctrlport/CMakeLists.txt
new file mode 100644
index 0000000000..c68694785f
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/CMakeLists.txt
@@ -0,0 +1,97 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+include(GrPython)
+
+EXECUTE_PROCESS(
+ COMMAND ${ICE_SLICE2PY} -I${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib
+ --output-dir=${CMAKE_BINARY_DIR}/gnuradio-runtime/python
+ ${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib/gnuradio.ice
+)
+
+EXECUTE_PROCESS(
+ COMMAND ${ICE_SLICE2PY} -I${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib
+ --output-dir=${CMAKE_BINARY_DIR}/gnuradio-runtime/python
+ ${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib/frontend.ice
+)
+
+GR_PYTHON_INSTALL(
+ FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/IceRadioClient.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport/
+ COMPONENT "core_python"
+)
+
+# We don't want to install these in the root Python directory, but we
+# aren't given a choice based on the way slice2py generates the
+# information.
+GR_PYTHON_INSTALL(
+ FILES
+ ${CMAKE_BINARY_DIR}/gnuradio-runtime/python/gnuradio_ice.py
+ ${CMAKE_BINARY_DIR}/gnuradio-runtime/python/frontend_ice.py
+ DESTINATION ${GR_PYTHON_DIR}
+ COMPONENT "core_python"
+)
+
+GR_PYTHON_INSTALL(
+ FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/__init__.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport/GNURadio
+ COMPONENT "core_python"
+)
+
+GR_PYTHON_INSTALL(
+ FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/Booter/__init__.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport/GNURadio/Booter
+ COMPONENT "core_python"
+)
+
+GR_PYTHON_INSTALL(
+ FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/Frontend/__init__.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport/GNURadio/Frontend
+ COMPONENT "core_python"
+)
+
+install(
+ FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/icon.png
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport
+ COMPONENT "core_python"
+)
+
+GR_PYTHON_INSTALL(
+ FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/GrDataPlotter.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/monitor.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport/
+ COMPONENT "core_python"
+)
+
+GR_PYTHON_INSTALL(
+ FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr-ctrlport-monitor
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr-ctrlport-curses
+ DESTINATION ${GR_RUNTIME_DIR}
+ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
+ COMPONENT "core_python"
+)
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py b/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py
new file mode 100644
index 0000000000..8597ca6497
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py
@@ -0,0 +1,428 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,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.
+#
+
+from gnuradio import gr
+from gnuradio import blocks
+from gnuradio import filter
+import sys, time
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+class GrDataPlotParent(gr.top_block, QtGui.QWidget):
+ # Setup signals
+ plotupdated = QtCore.pyqtSignal(QtGui.QWidget)
+
+ def __init__(self, name, rate, pmin=None, pmax=None):
+ gr.top_block.__init__(self)
+ QtGui.QWidget.__init__(self, None)
+
+ self._name = name
+ self._npts = 500
+ self._rate = rate
+ self.knobnames = [name,]
+
+ self.layout = QtGui.QVBoxLayout()
+ self.setLayout(self.layout)
+
+ self.setAcceptDrops(True)
+
+ def _setup(self, nconnections):
+ self.stop()
+ self.wait()
+
+ if(self.layout.count() > 0):
+ # Remove and disconnect. Making sure no references to snk
+ # remain so that the plot gets deleted.
+ self.layout.removeWidget(self.py_window)
+ self.disconnect(self.thr, (self.snk, 0))
+ self.disconnect(self.src[0], self.thr)
+ for n in xrange(1, self._ncons):
+ self.disconnect(self.src[n], (self.snk,n))
+
+ self._ncons = nconnections
+ self._data_len = self._ncons*[0,]
+
+ self.thr = blocks.throttle(self._datasize, self._rate)
+ self.snk = self.get_qtsink()
+
+ self.connect(self.thr, (self.snk, 0))
+
+ self._last_data = []
+ self.src = []
+ for n in xrange(self._ncons):
+ self.set_line_label(n, self.knobnames[n])
+
+ self._last_data.append(int(self._npts)*[0,])
+ self.src.append(self.get_vecsource())
+
+ if(n == 0):
+ self.connect(self.src[n], self.thr)
+ else:
+ self.connect(self.src[n], (self.snk,n))
+
+ self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+
+ self.layout.addWidget(self.py_window)
+
+ def __del__(self):
+ pass
+
+ def close(self):
+ self.snk.close()
+
+ def qwidget(self):
+ return self.py_window
+
+ def name(self):
+ return self._name
+
+ def semilogy(self, en=True):
+ self.snk.enable_semilogy(en)
+
+ def dragEnterEvent(self, e):
+ e.acceptProposedAction()
+
+ def dropEvent(self, e):
+ if(e.mimeData().hasFormat("text/plain")):
+ data = str(e.mimeData().text())
+
+ #"PlotData:{0}:{1}".format(tag, iscomplex)
+ datalst = data.split(":::")
+ tag = datalst[0]
+ name = datalst[1]
+ cpx = datalst[2] != "0"
+
+ if(tag == "PlotData" and cpx == self._iscomplex):
+ self.knobnames.append(name)
+
+ # create a new qwidget plot with the new data stream.
+ self._setup(len(self.knobnames))
+
+ # emit that this plot has been updated with a new qwidget.
+ self.plotupdated.emit(self)
+
+ e.acceptProposedAction()
+
+ def data_to_complex(self, data):
+ if(self._iscomplex):
+ data_r = data[0::2]
+ data_i = data[1::2]
+ data = [complex(r,i) for r,i in zip(data_r, data_i)]
+ return data
+
+ def update(self, data):
+ # Ask GUI if there has been a change in nsamps
+ npts = self.get_npts()
+ if(self._npts != npts):
+
+ # Adjust buffers to accomodate new settings
+ for n in xrange(self._ncons):
+ if(npts < self._npts):
+ if(self._data_len[n] < npts):
+ self._last_data[n] = self._last_data[n][0:npts]
+ else:
+ self._last_data[n] = self._last_data[n][self._data_len[n]-npts:self._data_len[n]]
+ self._data_len[n] = npts
+ else:
+ self._last_data[n] += (npts - self._npts)*[0,]
+ self._npts = npts
+ self.snk.reset()
+
+ if(self._stripchart):
+ # Update the plot data depending on type
+ for n in xrange(self._ncons):
+ if(type(data[n]) == list):
+ data[n] = self.data_to_complex(data[n])
+ if(len(data[n]) > self._npts):
+ self.src[n].set_data(data[n])
+ self._last_data[n] = data[n][-self._npts:]
+ else:
+ newdata = self._last_data[n][-(self._npts-len(data)):]
+ newdata += data[n]
+ self.src[n].set_data(newdata)
+ self._last_data[n] = newdata
+
+ else: # single value update
+ if(self._iscomplex):
+ data[n] = complex(data[n][0], data[n][1])
+ if(self._data_len[n] < self._npts):
+ self._last_data[n][self._data_len[n]] = data[n]
+ self._data_len[n] += 1
+ else:
+ self._last_data[n] = self._last_data[n][1:]
+ self._last_data[n].append(data[n])
+ self.src[n].set_data(self._last_data[n])
+ else:
+ for n in xrange(self._ncons):
+ if(type(data[n]) != list):
+ data[n] = [data[n],]
+ data[n] = self.data_to_complex(data[n])
+ self.src[n].set_data(data[n])
+
+
+
+class GrDataPlotterC(GrDataPlotParent):
+ def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False):
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
+
+ self._stripchart = stripchart
+ self._datasize = gr.sizeof_gr_complex
+ self._iscomplex = True
+
+ self._setup(1)
+
+ def stem(self, en=True):
+ self.snk.enable_stem_plot(en)
+
+ def get_qtsink(self):
+ snk = qtgui.time_sink_c(self._npts, 1.0,
+ self._name, self._ncons)
+ snk.enable_autoscale(True)
+ return snk
+
+ def get_vecsource(self):
+ return blocks.vector_source_c([])
+
+ def get_npts(self):
+ self._npts = self.snk.nsamps()
+ return self._npts
+
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(2*n+0, "Re{" + self.knobnames[n] + "}")
+ self.snk.set_line_label(2*n+1, "Im{" + self.knobnames[n] + "}")
+
+
+class GrDataPlotterF(GrDataPlotParent):
+ def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False):
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
+
+ self._stripchart = stripchart
+ self._datasize = gr.sizeof_float
+ self._iscomplex = False
+
+ self._setup(1)
+
+ def stem(self, en=True):
+ self.snk.enable_stem_plot(en)
+
+ def get_qtsink(self):
+ snk = qtgui.time_sink_f(self._npts, 1.0,
+ self._name, self._ncons)
+ snk.enable_autoscale(True)
+ return snk
+
+ def get_vecsource(self):
+ return blocks.vector_source_f([])
+
+ def get_npts(self):
+ self._npts = self.snk.nsamps()
+ return self._npts
+
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
+
+
+class GrDataPlotterConst(GrDataPlotParent):
+ def __init__(self, name, rate, pmin=None, pmax=None):
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
+
+ self._datasize = gr.sizeof_gr_complex
+ self._stripchart = False
+ self._iscomplex = True
+
+ self._setup(1)
+
+ def get_qtsink(self):
+ snk = qtgui.const_sink_c(self._npts,
+ self._name,
+ self._ncons)
+ snk.enable_autoscale(True)
+ return snk
+
+ def get_vecsource(self):
+ return blocks.vector_source_c([])
+
+ def get_npts(self):
+ self._npts = self.snk.nsamps()
+ return self._npts
+
+ def scatter(self, en=True):
+ if(en):
+ self.snk.set_line_style(0, 0)
+ else:
+ self.snk.set_line_style(0, 1)
+
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
+
+
+class GrDataPlotterPsdC(GrDataPlotParent):
+ def __init__(self, name, rate, pmin=None, pmax=None):
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
+
+ self._datasize = gr.sizeof_gr_complex
+ self._stripchart = True
+ self._iscomplex = True
+
+ self._npts = 2048
+ self._wintype = filter.firdes.WIN_BLACKMAN_hARRIS
+ self._fc = 0
+
+ self._setup(1)
+
+ def get_qtsink(self):
+ snk = qtgui.freq_sink_c(self._npts, self._wintype,
+ self._fc, 1.0,
+ self._name,
+ self._ncons)
+ snk.enable_autoscale(True)
+ return snk
+
+ def get_vecsource(self):
+ return blocks.vector_source_c([])
+
+ def get_npts(self):
+ self._npts = self.snk.fft_size()
+ return self._npts
+
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
+
+
+class GrDataPlotterPsdF(GrDataPlotParent):
+ def __init__(self, name, rate, pmin=None, pmax=None):
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
+
+ self._datasize = gr.sizeof_float
+ self._stripchart = True
+ self._iscomplex = False
+
+ self._npts = 2048
+ self._wintype = filter.firdes.WIN_BLACKMAN_hARRIS
+ self._fc = 0
+
+ self._setup(1)
+
+ def get_qtsink(self):
+ snk = qtgui.freq_sink_f(self._npts, self._wintype,
+ self._fc, 1.0,
+ self._name,
+ self._ncons)
+ snk.enable_autoscale(True)
+ return snk
+
+ def get_vecsource(self):
+ return blocks.vector_source_f([])
+
+ def get_npts(self):
+ self._npts = self.snk.fft_size()
+ return self._npts
+
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
+
+
+class GrTimeRasterF(GrDataPlotParent):
+ def __init__(self, name, rate, pmin=None, pmax=None):
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
+
+ self._npts = 10
+ self._rows = 40
+
+ self._datasize = gr.sizeof_float
+ self._stripchart = False
+ self._iscomplex = False
+
+ self._setup(1)
+
+ def get_qtsink(self):
+ snk = qtgui.time_raster_sink_f(1.0, self._npts, self._rows,
+ [], [], self._name,
+ self._ncons)
+ return snk
+
+ def get_vecsource(self):
+ return blocks.vector_source_f([])
+
+ def get_npts(self):
+ self._npts = self.snk.num_cols()
+ return self._npts
+
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
+
+class GrTimeRasterB(GrDataPlotParent):
+ def __init__(self, name, rate, pmin=None, pmax=None):
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
+
+ self._npts = 10
+ self._rows = 40
+
+ self._datasize = gr.sizeof_char
+ self._stripchart = False
+ self._iscomplex = False
+
+ self._setup(1)
+
+ def get_qtsink(self):
+ snk = qtgui.time_raster_sink_b(1.0, self._npts, self._rows,
+ [], [], self._name,
+ self._ncons)
+ return snk
+
+ def get_vecsource(self):
+ return blocks.vector_source_b([])
+
+ def get_npts(self):
+ self._npts = self.snk.num_cols()
+ return self._npts
+
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
+
+
+class GrDataPlotterValueTable:
+ def __init__(self, uid, parent, x, y, xsize, ysize,
+ headers=['Statistic Key ( Source Block :: Stat Name ) ',
+ 'Curent Value', 'Units', 'Description']):
+ # must encapsulate, cuz Qt's bases are not classes
+ self.uid = uid
+ self.treeWidget = QtGui.QTreeWidget(parent)
+ self.treeWidget.setColumnCount(len(headers))
+ self.treeWidget.setGeometry(x,y,xsize,ysize)
+ self.treeWidget.setHeaderLabels(headers)
+ self.treeWidget.resizeColumnToContents(0)
+
+ def updateItems(self, knobs, knobprops):
+ items = [];
+ self.treeWidget.clear()
+ for k, v in knobs.iteritems():
+ items.append(QtGui.QTreeWidgetItem([str(k), str(v.value),
+ knobprops[k].units,
+ knobprops[k].description]))
+ self.treeWidget.insertTopLevelItems(0, items)
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/IceRadioClient.py b/gnuradio-runtime/python/gnuradio/ctrlport/IceRadioClient.py
new file mode 100644
index 0000000000..0964b5a4ba
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/IceRadioClient.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import Ice, Glacier2
+from PyQt4 import QtGui, QtCore
+import sys, time, Ice
+from gnuradio import gr
+from gnuradio.ctrlport import GNURadio
+
+class IceRadioClient(Ice.Application):
+ def __init__(self, parentClass):
+ self.parentClass = parentClass
+
+ def getRadio(self, host, port):
+ radiostr = "gnuradio -t:tcp -h " + host + " -p " + port + " -t 3000"
+ base = self.communicator().stringToProxy(radiostr).ice_twoway()
+ radio = GNURadio.ControlPortPrx.checkedCast(base)
+
+ if not radio:
+ sys.stderr.write("{0} : invalid proxy.\n".format(args[0]))
+ return None
+
+ return radio
+
+ def run(self,args):
+ if len(args) < 2:
+ print "useage: [glacierinstance glacierhost glacierport] host port"
+ return
+ if len(args) == 8:
+ self.useglacier = True
+ guser = args[1]
+ gpass = args[2]
+ ginst = args[3]
+ ghost = args[4]
+ gport = args[5]
+ host = args[6]
+ port = args[7]
+ else:
+ self.useglacier = False
+ host = args[1]
+ port = args[2]
+
+ if self.useglacier:
+ gstring = ginst + "/router -t:tcp -h " + ghost + " -p " + gport
+ print "GLACIER: {0}".format(gstring)
+
+ setrouter = Glacier2.RouterPrx.checkedCast(self.communicator().stringToProxy(gstring))
+ self.communicator().setDefaultRouter(setrouter)
+ defaultRouter = self.communicator().getDefaultRouter()
+ #defaultRouter = self.communicator().stringToProxy(gstring)
+ if not defaultRouter:
+ print self.appName() + ": no default router set"
+ return 1
+ else:
+ print str(defaultRouter)
+ router = Glacier2.RouterPrx.checkedCast(defaultRouter)
+ if not router:
+ print self.appName() + ": configured router is not a Glacier2 router"
+ return 1
+
+ while True:
+ print "This demo accepts any user-id / password combination."
+ if not guser == '' and not gpass == '':
+ id = guser
+ pw = gpass
+ else:
+ id = raw_input("user id: ")
+ pw = raw_input("password: ")
+
+ try:
+ router.createSession(id, pw)
+ break
+ except Glacier2.PermissionDeniedException, ex:
+ print "permission denied:\n" + ex.reason
+
+ radio = self.getRadio(host, port)
+ if(radio is None):
+ return 1
+
+ app = QtGui.QApplication(sys.argv)
+ ex = self.parentClass(radio, port, self)
+ ex.show();
+ app.exec_()
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/__init__.py b/gnuradio-runtime/python/gnuradio/ctrlport/__init__.py
new file mode 100644
index 0000000000..031c3b424e
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/__init__.py
@@ -0,0 +1,30 @@
+#
+# 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 this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+# The presence of this file turns this directory into a Python package
+
+import Ice, IcePy
+
+# import swig generated symbols into the ctrlport namespace
+#from ctrlport_swig import *
+from monitor import *
+
+# import any pure python here
+#import GNURadio
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-curses b/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-curses
new file mode 100755
index 0000000000..1bee3b1a1e
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-curses
@@ -0,0 +1,268 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import threading
+import curses
+import os, sys, time
+from optparse import OptionParser
+
+import Ice
+from gnuradio.ctrlport import GNURadio
+
+ENTER = chr(10)
+UP_ARROW = chr(65)
+DOWN_ARROW = chr(66)
+
+class modem_monitor(threading.Thread):
+ def __init__(self, cb_live, cb_exit, interface):
+ threading.Thread.__init__(self)
+ self.cb_live = cb_live
+ self.cb_exit = cb_exit
+
+ self.running = True
+
+ def __del__(self):
+ rx.close()
+
+ def run(self):
+ while self.running:
+ time.sleep(0.5)
+
+ def shutdown(self):
+ self.running = False
+ self.rx.close()
+
+ def cb(self,contents):
+ (op, sep, payload) = contents.partition(":")
+ if(op == "live"):
+ print "live"
+ self.cb_live(payload)
+ elif(op == "exit"):
+ self.cb_exit(payload)
+ else:
+ print "unknown op arrived! garbage on multicast adx?"
+
+class modem_window(threading.Thread):
+ def __init__(self, locator):
+ threading.Thread.__init__(self)
+ self.locator = locator
+
+ # curses init
+ self.win = curses.newwin(30,100,4,4)
+
+ # Ice/GRCP init
+ self.comm = Ice.initialize()
+ proxy = self.comm.stringToProxy(locator)
+ self.radio = GNURadio.ControlPortPrx.checkedCast(proxy)
+ self.updateKnobs()
+
+ # GUI init
+ self.running = True
+ self.ssel = 0
+ self.start()
+ #self.updateGUI()
+
+ # input loop
+ while(self.running):
+ self.getInput()
+
+ # wait for update thread exit
+ self.join()
+
+ def updateKnobs(self):
+ self.knobs = self.radio.get([])
+
+ def getInput(self):
+ a = self.win.getch()
+ if(a <= 256):
+ a = chr(a)
+ if(a == 'q'):
+ self.running = False
+ elif(a == UP_ARROW):
+ self.ssel = max(self.ssel-1, 0)
+ self.updateGUI()
+ elif(a == DOWN_ARROW):
+ self.ssel = max(min(self.ssel+1, len(self.knobs.keys())-1),0)
+ self.updateGUI()
+ self.updateGUI()
+
+ def updateGUI(self):
+ self.win.clear()
+ self.win.border(0)
+ self.win.addstr(1, 2, "Modem Statistics :: %s"%(self.locator))
+ self.win.addstr(2, 2, "---------------------------------------------------")
+
+ maxnb = 0
+ maxk = 0
+ for k in self.knobs.keys():
+ (nb,k) = k.split("::", 2)
+ maxnb = max(maxnb,len(nb))
+ maxk = max(maxk,len(k))
+
+ offset = 3
+ keys = self.knobs.keys()
+ keys.sort()
+ for k in keys:
+ (nb,sk) = k.split("::", 2)
+ v = self.knobs[k].value
+ sv = str(v)
+ if(len(sv) > 20):
+ sv = sv[0:20]
+ props = 0
+ if(self.ssel == offset-3):
+ props = props | curses.A_REVERSE
+ self.win.addstr(offset, 2, "%s %s %s" % \
+ (nb.rjust(maxnb," "), sk.ljust(maxk," "), sv),props)
+ offset = offset + 1
+ self.win.refresh()
+
+ def run(self):
+ while(self.running):
+ self.updateKnobs()
+ self.updateGUI()
+ time.sleep(1)
+
+class monitor_gui:
+ def __init__(self, interfaces, options):
+
+ locator = None
+
+ # Extract options into a locator
+ if(options.host and options.port):
+ locator = "{0} -t:{1} -h {2} -p {3}".format(
+ options.app, options.protocol,
+ options.host, options.port)
+
+ # Set up GUI
+ self.locators = {}
+
+ self.mode = 0 # modem index screen (modal keyboard input)
+ self.lsel = 0 # selected locator
+ self.scr = curses.initscr()
+ self.updateGUI()
+
+ # Kick off initial monitors
+ self.monitors = []
+ for i in interfaces:
+ self.monitors.append( modem_monitor(self.addModem, self.delModem, i) )
+ self.monitors[-1].start()
+
+ if not ((locator == None) or (locator == "")):
+ self.addModem(locator)
+
+ # wait for user input
+ while(True):
+ self.getInput()
+
+ def addModem(self, locator):
+ if(not self.locators.has_key(locator)):
+ self.locators[locator] = {}
+ self.locators[locator]["update_time"] = time.time()
+ self.locators[locator]["status"] = "live"
+
+ self.updateGUI();
+
+ def delModem(self, locator):
+ #if(self.locators.has_key(locator)):
+ if(not self.locators.has_key(locator)):
+ self.locators[locator] = {}
+ self.locators[locator]["update_time"] = time.time()
+ self.locators[locator]["status"] = "exit"
+
+ self.updateGUI()
+
+ def updateGUI(self):
+ if(self.mode == 0): #redraw locators
+ self.scr.clear()
+ self.scr.border(0)
+ self.scr.addstr(1, 2, " GRCP-Curses Modem Monitor :: (A)dd (R)efresh, (Q)uit, ...")
+ for i in range(len(self.locators.keys())):
+ locator = self.locators.keys()[i]
+ lhash = self.locators[locator]
+ #self.scr.addstr(3+i, 5, locator + str(lhash))
+ props = 0
+ if(self.lsel == i):
+ props = props | curses.A_REVERSE
+ self.scr.addstr(3+i, 5, locator + str(lhash), props)
+ self.scr.refresh()
+
+ def connectGUI(self):
+ self.scr.clear()
+ self.scr.addstr(1, 1, "Connect to radio:")
+ locator = self.scr.getstr(200)
+ self.addModem(locator)
+ self.updateGUI()
+
+ def getInput(self):
+ a = self.scr.getch()
+ self.scr.addstr(20, 2, "got key (%d) " % (int(a)))
+ if(a <= 256):
+ a = chr(a)
+ if(a =='r'):
+ self.updateGUI()
+ elif(a == 'q'):
+ self.shutdown()
+ elif(a == 'a'):
+ self.connectGUI()
+ elif(a == UP_ARROW):
+ self.lsel = max(self.lsel-1, 0)
+ self.updateGUI()
+ elif(a == DOWN_ARROW):
+ self.lsel = max(min(self.lsel+1, len(self.locators.keys())-1),0)
+ self.updateGUI()
+ elif(a == ENTER):
+ try:
+ locator = self.locators.keys()[self.lsel]
+ self.mode = 1
+ mwin = modem_window(locator)
+ self.mode = 0
+ # pop up a new modem display ...
+ self.updateGUI()
+ except:
+ pass
+
+ def shutdown(self):
+ curses.endwin()
+ os._exit(0)
+
+if __name__ == "__main__":
+ parser = OptionParser()
+ parser.add_option("-H", "--host", type="string",
+ help="Hostname of ControlPort server.")
+ parser.add_option("-p", "--port", type="int",
+ help="Port number of host's ControlPort endpoint.")
+ parser.add_option("-i", "--interfaces", type="string",
+ action="append", default=["lo"],
+ help="Interfaces to use. [default=%default]")
+ parser.add_option("-P", "--protocol", type="string", default="tcp",
+ help="Type of protocol to use (usually tcp). [default=%default]")
+ parser.add_option("-a", "--app", type="string", default="gnuradio",
+ help="Name of application [default=%default]")
+ (options, args) = parser.parse_args()
+
+ if((options.host == None) ^ (options.port == None)):
+ print "Please set both a hostname and a port number.\n"
+ parser.print_help()
+ sys.exit(1)
+
+ mg = monitor_gui(options.interfaces, options)
+
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor b/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor
new file mode 100755
index 0000000000..e71cd92ab7
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor
@@ -0,0 +1,721 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,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.
+#
+
+from gnuradio import gr, ctrlport
+
+from PyQt4 import QtCore,Qt
+import PyQt4.QtGui as QtGui
+import os, sys, time
+
+import Ice
+from gnuradio.ctrlport.IceRadioClient import *
+from gnuradio.ctrlport.GrDataPlotter import *
+from gnuradio.ctrlport import GNURadio
+
+class RateDialog(QtGui.QDialog):
+ def __init__(self, delay, parent=None):
+ super(RateDialog, self).__init__(parent)
+ self.gridLayout = QtGui.QGridLayout(self)
+ self.setWindowTitle("Update Delay (ms)");
+ self.delay = QtGui.QLineEdit(self);
+ self.delay.setText(str(delay));
+ self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
+ self.gridLayout.addWidget(self.delay);
+ self.gridLayout.addWidget(self.buttonBox);
+ self.buttonBox.accepted.connect(self.accept)
+ self.buttonBox.rejected.connect(self.reject)
+ def accept(self):
+ self.done(1);
+ def reject(self):
+ self.done(0);
+
+class MAINWindow(QtGui.QMainWindow):
+ def minimumSizeHint(self):
+ return Qtgui.QSize(800,600)
+
+ def __init__(self, radio, port, interface):
+
+ super(MAINWindow, self).__init__()
+ self.updateRate = 1000;
+ self.conns = []
+ self.plots = []
+ self.knobprops = []
+ self.interface = interface
+
+ self.mdiArea = QtGui.QMdiArea()
+ self.mdiArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
+ self.mdiArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
+ self.setCentralWidget(self.mdiArea)
+
+ self.mdiArea.subWindowActivated.connect(self.updateMenus)
+ self.windowMapper = QtCore.QSignalMapper(self)
+ self.windowMapper.mapped[QtGui.QWidget].connect(self.setActiveSubWindow)
+
+ self.createActions()
+ self.createMenus()
+ self.createToolBars()
+ self.createStatusBar()
+ self.updateMenus()
+
+ self.setWindowTitle("GNU Radio Control Port Monitor")
+ self.setUnifiedTitleAndToolBarOnMac(True)
+
+ self.newCon(radio, port)
+ icon = QtGui.QIcon(ctrlport.__path__[0] + "/icon.png" )
+ self.setWindowIcon(icon)
+
+ # Locally turn off ControlPort export from GR. This prevents
+ # our GR-based plotters from launching their own ControlPort
+ # instance (and possibly causing a port collision if one has
+ # been specified).
+ os.environ['GR_CONF_CONTROLPORT_ON'] = 'False'
+
+ def setUpdateRate(self,nur):
+ self.updateRate = int(nur);
+ for c in self.conns:
+ c.updateRate = self.updateRate;
+ c.timer.setInterval(self.updateRate);
+
+ def newCon(self, radio=None, port=None):
+ child = MForm(radio, port, len(self.conns), self.updateRate, self)
+ if(child.radio is not None):
+ child.setWindowTitle(str(child.radio))
+ self.mdiArea.addSubWindow(child)
+ child.showMaximized()
+ self.conns.append(child)
+ self.plots.append([])
+
+ def propertiesMenu(self, key, radio, uid):
+ r = str(radio).split(" ")
+ title = "{0}:{1}".format(r[3], r[5])
+
+ props = radio.properties([key])
+ pmin = props[key].min.value
+ pmax = props[key].max.value
+ if pmin == []:
+ pmin = None
+ else:
+ pmin = 1.1*pmin
+ if pmax == []:
+ pmax = None
+ else:
+ pmax = 1.1*pmax
+
+ # Use display option mask of item to set up available plot
+ # types and default options.
+ disp = self.knobprops[uid][key].display
+ cplx = disp & gr.DISPOPTCPLX | disp & gr.DISPXY
+ strip = disp & gr.DISPOPTSTRIP
+ stem = disp & gr.DISPOPTSTEM
+ log = disp & gr.DISPOPTLOG
+ scatter = disp & gr.DISPOPTSCATTER
+
+ def newUpdaterProxy():
+ self.newUpdater(key, radio)
+
+ def newPlotterFProxy():
+ self.newPlotF(key, uid, title, pmin, pmax,
+ log, strip, stem)
+
+ def newPlotterCProxy():
+ self.newPlotC(key, uid, title, pmin, pmax,
+ log, strip, stem)
+
+ def newPlotterConstProxy():
+ self.newPlotConst(key, uid, title, pmin, pmax, scatter)
+
+ def newPlotterPsdFProxy():
+ self.newPlotPsdF(key, uid, title)
+
+ def newPlotterPsdCProxy():
+ self.newPlotPsdC(key, uid, title)
+
+ def newPlotterRasterFProxy():
+ self.newPlotRasterF(key, uid, title, pmin, pmax)
+
+ def newPlotterRasterBProxy():
+ self.newPlotRasterB(key, uid, title, pmin, pmax)
+
+ menu = QtGui.QMenu(self)
+ menu.setTitle("Item Actions")
+ menu.setTearOffEnabled(False)
+
+ # object properties
+ menu.addAction("Properties", newUpdaterProxy)
+
+ # displays available
+ if(cplx == 0):
+ menu.addAction("Plot Time", newPlotterFProxy)
+ menu.addAction("Plot PSD", newPlotterPsdFProxy)
+ menu.addAction("Plot Raster (real)", newPlotterRasterFProxy)
+ #menu.addAction("Plot Raster (bits)", newPlotterRasterBProxy)
+ else:
+ menu.addAction("Plot Time", newPlotterCProxy)
+ menu.addAction("Plot PSD", newPlotterPsdCProxy)
+ menu.addAction("Plot Constellation", newPlotterConstProxy)
+
+ menu.popup(QtGui.QCursor.pos())
+
+ def newUpdater(self, key, radio):
+ updater = UpdaterWindow(key, radio, None)
+ updater.setWindowTitle("Updater: " + key)
+ updater.setModal(False)
+ updater.exec_()
+
+ def newSub(self, e):
+ tag = str(e.text(0))
+ tree = e.treeWidget().parent()
+ uid = tree.uid
+ knobprop = self.knobprops[uid][tag]
+
+ r = str(tree.radio).split(" ")
+ title = "{0}:{1}".format(r[3], r[5])
+ pmin = knobprop.min.value
+ pmax = knobprop.max.value
+ if pmin == []:
+ pmin = None
+ else:
+ pmin = 1.1*pmin
+ if pmax == []:
+ pmax = None
+ else:
+ pmax = 1.1*pmax
+
+ disp = knobprop.display
+ if(disp & gr.DISPTIME):
+ strip = disp & gr.DISPOPTSTRIP
+ stem = disp & gr.DISPOPTSTEM
+ log = disp & gr.DISPOPTLOG
+ if(disp & gr.DISPOPTCPLX == 0):
+ self.newPlotF(tag, uid, title, pmin, pmax,
+ log, strip, stem)
+ else:
+ self.newPlotC(tag, uid, title, pmin, pmax,
+ log, strip, stem)
+
+ elif(disp & gr.DISPXY):
+ scatter = disp & gr.DISPOPTSCATTER
+ self.newPlotConst(tag, uid, title, pmin, pmax, scatter)
+
+ elif(disp & gr.DISPPSD):
+ if(disp & gr.DISPOPTCPLX == 0):
+ self.newPlotPsdF(tag, uid, title)
+ else:
+ self.newPlotPsdC(tag, uid, title)
+
+ def startDrag(self, e):
+ drag = QtGui.QDrag(self)
+ mime_data = QtCore.QMimeData()
+
+ tag = str(e.text(0))
+ tree = e.treeWidget().parent()
+ knobprop = self.knobprops[tree.uid][tag]
+ disp = knobprop.display
+ iscomplex = (disp & gr.DISPOPTCPLX) or (disp & gr.DISPXY)
+
+ if(disp != gr.DISPNULL):
+ data = "PlotData:::{0}:::{1}".format(tag, iscomplex)
+ else:
+ data = "OtherData:::{0}:::{1}".format(tag, iscomplex)
+
+ mime_data.setText(data)
+ drag.setMimeData(mime_data)
+
+ drop = drag.start()
+
+ def createPlot(self, plot, uid, title):
+ plot.start()
+ self.plots[uid].append(plot)
+
+ self.mdiArea.addSubWindow(plot)
+ plot.setWindowTitle("{0}: {1}".format(title, plot.name()))
+ self.connect(plot.qwidget(),
+ QtCore.SIGNAL('destroyed(QObject*)'),
+ self.destroyPlot)
+
+ # when the plot is updated via drag-and-drop, we need to be
+ # notified of the new qwidget that's created so we can
+ # properly destroy it.
+ plot.plotupdated.connect(self.plotUpdated)
+
+ plot.show()
+
+ def plotUpdated(self, q):
+ # the plot has been updated with a new qwidget; make sure this
+ # gets dies to the destroyPlot function.
+ for i, plots in enumerate(self.plots):
+ for p in plots:
+ if(p == q):
+ #plots.remove(p)
+ #plots.append(q)
+ self.connect(q.qwidget(),
+ QtCore.SIGNAL('destroyed(QObject*)'),
+ self.destroyPlot)
+ break
+
+ def destroyPlot(self, obj):
+ for plots in self.plots:
+ for p in plots:
+ if p.qwidget() == obj:
+ plots.remove(p)
+ break
+
+ def newPlotConst(self, tag, uid, title="", pmin=None, pmax=None,
+ scatter=False):
+ plot = GrDataPlotterConst(tag, 32e6, pmin, pmax)
+ plot.scatter(scatter)
+ self.createPlot(plot, uid, title)
+
+ def newPlotF(self, tag, uid, title="", pmin=None, pmax=None,
+ logy=False, stripchart=False, stem=False):
+ plot = GrDataPlotterF(tag, 32e6, pmin, pmax, stripchart)
+ plot.semilogy(logy)
+ plot.stem(stem)
+ self.createPlot(plot, uid, title)
+
+ def newPlotC(self, tag, uid, title="", pmin=None, pmax=None,
+ logy=False, stripchart=False, stem=False):
+ plot = GrDataPlotterC(tag, 32e6, pmin, pmax, stripchart)
+ plot.semilogy(logy)
+ plot.stem(stem)
+ self.createPlot(plot, uid, title)
+
+ def newPlotPsdF(self, tag, uid, title="", pmin=None, pmax=None):
+ plot = GrDataPlotterPsdF(tag, 32e6, pmin, pmax)
+ self.createPlot(plot, uid, title)
+
+ def newPlotPsdC(self, tag, uid, title="", pmin=None, pmax=None):
+ plot = GrDataPlotterPsdC(tag, 32e6, pmin, pmax)
+ self.createPlot(plot, uid, title)
+
+ def newPlotRasterF(self, tag, uid, title="", pmin=None, pmax=None):
+ plot = GrTimeRasterF(tag, 32e6, pmin, pmax)
+ self.createPlot(plot, uid, title)
+
+ def newPlotRasterB(self, tag, uid, title="", pmin=None, pmax=None):
+ plot = GrTimeRasterB(tag, 32e6, pmin, pmax)
+ self.createPlot(plot, uid, title)
+
+ def update(self, knobs, uid):
+ #sys.stderr.write("KNOB KEYS: {0}\n".format(knobs.keys()))
+ for plot in self.plots[uid]:
+ data = []
+ for n in plot.knobnames:
+ data.append(knobs[n].value)
+ plot.update(data)
+ plot.stop()
+ plot.wait()
+ plot.start()
+
+ def setActiveSubWindow(self, window):
+ if window:
+ self.mdiArea.setActiveSubWindow(window)
+
+
+ def createActions(self):
+ self.newConAct = QtGui.QAction("&New Connection",
+ self, shortcut=QtGui.QKeySequence.New,
+ statusTip="Create a new file", triggered=self.newCon)
+ #self.newAct = QtGui.QAction(QtGui.QIcon(':/images/new.png'), "&New Plot",
+ self.newPlotAct = QtGui.QAction("&New Plot",
+ self,
+ statusTip="Create a new file", triggered=self.newPlotF)
+
+ self.exitAct = QtGui.QAction("E&xit", self, shortcut="Ctrl+Q",
+ statusTip="Exit the application",
+ triggered=QtGui.qApp.closeAllWindows)
+
+ self.closeAct = QtGui.QAction("Cl&ose", self, shortcut="Ctrl+F4",
+ statusTip="Close the active window",
+ triggered=self.mdiArea.closeActiveSubWindow)
+
+ self.closeAllAct = QtGui.QAction("Close &All", self,
+ statusTip="Close all the windows",
+ triggered=self.mdiArea.closeAllSubWindows)
+
+ self.urAct = QtGui.QAction("Update Rate", self, shortcut="F5",
+ statusTip="Change Update Rate",
+ triggered=self.updateRateShow)
+
+ qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_T);
+ self.tileAct = QtGui.QAction("&Tile", self,
+ statusTip="Tile the windows",
+ triggered=self.mdiArea.tileSubWindows,
+ shortcut=qks)
+
+ qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_C);
+ self.cascadeAct = QtGui.QAction("&Cascade", self,
+ statusTip="Cascade the windows", shortcut=qks,
+ triggered=self.mdiArea.cascadeSubWindows)
+
+ self.nextAct = QtGui.QAction("Ne&xt", self,
+ shortcut=QtGui.QKeySequence.NextChild,
+ statusTip="Move the focus to the next window",
+ triggered=self.mdiArea.activateNextSubWindow)
+
+ self.previousAct = QtGui.QAction("Pre&vious", self,
+ shortcut=QtGui.QKeySequence.PreviousChild,
+ statusTip="Move the focus to the previous window",
+ triggered=self.mdiArea.activatePreviousSubWindow)
+
+ self.separatorAct = QtGui.QAction(self)
+ self.separatorAct.setSeparator(True)
+
+ self.aboutAct = QtGui.QAction("&About", self,
+ statusTip="Show the application's About box",
+ triggered=self.about)
+
+ self.aboutQtAct = QtGui.QAction("About &Qt", self,
+ statusTip="Show the Qt library's About box",
+ triggered=QtGui.qApp.aboutQt)
+
+ def createMenus(self):
+ self.fileMenu = self.menuBar().addMenu("&File")
+ self.fileMenu.addAction(self.newConAct)
+ self.fileMenu.addAction(self.newPlotAct)
+ self.fileMenu.addAction(self.urAct)
+ self.fileMenu.addSeparator()
+ self.fileMenu.addAction(self.exitAct)
+
+ self.windowMenu = self.menuBar().addMenu("&Window")
+ self.updateWindowMenu()
+ self.windowMenu.aboutToShow.connect(self.updateWindowMenu)
+
+ self.menuBar().addSeparator()
+
+ self.helpMenu = self.menuBar().addMenu("&Help")
+ self.helpMenu.addAction(self.aboutAct)
+ self.helpMenu.addAction(self.aboutQtAct)
+
+ def updateRateShow(self):
+ askrate = RateDialog(self.updateRate, self);
+ if askrate.exec_():
+ ur = float(str(askrate.delay.text()));
+ self.setUpdateRate(ur);
+ return;
+ else:
+ return;
+
+ def createToolBars(self):
+ self.fileToolBar = self.addToolBar("File")
+ self.fileToolBar.addAction(self.newConAct)
+ self.fileToolBar.addAction(self.newPlotAct)
+ self.fileToolBar.addAction(self.urAct)
+
+ self.fileToolBar = self.addToolBar("Window")
+ self.fileToolBar.addAction(self.tileAct)
+ self.fileToolBar.addAction(self.cascadeAct)
+
+ def createStatusBar(self):
+ self.statusBar().showMessage("Ready")
+
+
+ def activeMdiChild(self):
+ activeSubWindow = self.mdiArea.activeSubWindow()
+ if activeSubWindow:
+ return activeSubWindow.widget()
+ return None
+
+ def updateMenus(self):
+ hasMdiChild = (self.activeMdiChild() is not None)
+ self.closeAct.setEnabled(hasMdiChild)
+ self.closeAllAct.setEnabled(hasMdiChild)
+ self.tileAct.setEnabled(hasMdiChild)
+ self.cascadeAct.setEnabled(hasMdiChild)
+ self.nextAct.setEnabled(hasMdiChild)
+ self.previousAct.setEnabled(hasMdiChild)
+ self.separatorAct.setVisible(hasMdiChild)
+
+ def updateWindowMenu(self):
+ self.windowMenu.clear()
+ self.windowMenu.addAction(self.closeAct)
+ self.windowMenu.addAction(self.closeAllAct)
+ self.windowMenu.addSeparator()
+ self.windowMenu.addAction(self.tileAct)
+ self.windowMenu.addAction(self.cascadeAct)
+ self.windowMenu.addSeparator()
+ self.windowMenu.addAction(self.nextAct)
+ self.windowMenu.addAction(self.previousAct)
+ self.windowMenu.addAction(self.separatorAct)
+
+ def about(self):
+ about_info = \
+'''Copyright 2012 Free Software Foundation, Inc.\n
+This program is part of GNU Radio.\n
+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.\n
+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.\n
+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.'''
+
+ QtGui.QMessageBox.about(None, "gr-ctrlport-monitor", about_info)
+
+
+class ConInfoDialog(QtGui.QDialog):
+ def __init__(self, parent=None):
+ super(ConInfoDialog, self).__init__(parent)
+
+ self.gridLayout = QtGui.QGridLayout(self)
+
+
+ self.host = QtGui.QLineEdit(self);
+ self.port = QtGui.QLineEdit(self);
+ self.host.setText("localhost");
+ self.port.setText("43243");
+
+ self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
+
+ self.gridLayout.addWidget(self.host);
+ self.gridLayout.addWidget(self.port);
+ self.gridLayout.addWidget(self.buttonBox);
+
+ self.buttonBox.accepted.connect(self.accept)
+ self.buttonBox.rejected.connect(self.reject)
+
+
+ def accept(self):
+ self.done(1);
+
+ def reject(self):
+ self.done(0);
+
+
+class UpdaterWindow(QtGui.QDialog):
+ def __init__(self, key, radio, parent):
+ QtGui.QDialog.__init__(self, parent)
+
+ self.key = key;
+ self.radio = radio
+
+ self.resize(300,200)
+ self.layout = QtGui.QVBoxLayout()
+
+ self.props = radio.properties([key])[key]
+ info = str(self.props)
+
+ self.infoLabel = QtGui.QLabel(info)
+ self.layout.addWidget(self.infoLabel)
+
+ # Test here to make sure that a 'set' function
+ try:
+ a = radio.set(radio.get([key]))
+ has_set = True
+ except Ice.UnknownException:
+ has_set = False
+
+ if(has_set is False):
+ self.cancelButton = QtGui.QPushButton("Ok")
+ self.cancelButton.connect(self.cancelButton, QtCore.SIGNAL('clicked()'), self.reject)
+
+ self.buttonlayout = QtGui.QHBoxLayout()
+ self.buttonlayout.addWidget(self.cancelButton)
+ self.layout.addLayout(self.buttonlayout)
+
+ else: # we have a set function
+ self.textInput = QtGui.QLineEdit()
+ self.layout.addWidget(self.textInput)
+
+ self.applyButton = QtGui.QPushButton("Apply")
+ self.setButton = QtGui.QPushButton("OK")
+ self.cancelButton = QtGui.QPushButton("Cancel")
+
+ rv = radio.get([key])
+ self.textInput.setText(str(rv[key].value))
+ self.sv = rv[key]
+
+ self.applyButton.connect(self.applyButton, QtCore.SIGNAL('clicked()'), self._apply)
+ self.setButton.connect(self.setButton, QtCore.SIGNAL('clicked()'), self._set)
+ self.cancelButton.connect(self.cancelButton, QtCore.SIGNAL('clicked()'), self.reject)
+
+ self.is_num = ((type(self.sv.value)==float) or (type(self.sv.value)==int))
+ if(self.is_num):
+ self.sliderlayout = QtGui.QHBoxLayout()
+
+ self.slider = QtGui.QSlider(QtCore.Qt.Horizontal)
+
+ self.sliderlayout.addWidget(QtGui.QLabel(str(self.props.min.value)))
+ self.sliderlayout.addWidget(self.slider)
+ self.sliderlayout.addWidget(QtGui.QLabel(str(self.props.max.value)))
+
+ self.steps = 10000
+ self.valspan = self.props.max.value - self.props.min.value
+
+ self.slider.setRange(0, 10000)
+ self._set_slider_value(self.sv.value)
+
+ self.connect(self.slider, QtCore.SIGNAL("sliderReleased()"), self._slide)
+
+ self.layout.addLayout(self.sliderlayout)
+
+ self.buttonlayout = QtGui.QHBoxLayout()
+ self.buttonlayout.addWidget(self.applyButton)
+ self.buttonlayout.addWidget(self.setButton)
+ self.buttonlayout.addWidget(self.cancelButton)
+ self.layout.addLayout(self.buttonlayout)
+
+ # set layout and go...
+ self.setLayout(self.layout)
+
+ def _set_slider_value(self, val):
+ self.slider.setValue(self.steps*(val-self.props.min.value)/self.valspan)
+
+ def _slide(self):
+ val = (self.slider.value()*self.valspan + self.props.min.value)/float(self.steps)
+ self.textInput.setText(str(val))
+
+ def _apply(self):
+ if(type(self.sv.value) == str):
+ val = str(self.textInput.text())
+ elif(type(self.sv.value) == int):
+ val = int(round(float(self.textInput.text())))
+ elif(type(self.sv.value) == float):
+ val = float(self.textInput.text())
+ else:
+ sys.stderr.write("set type not supported! ({0})\n".format(type(self.sv.value)))
+ sys.exit(-1)
+
+ self.sv.value = val
+ km = {}
+ km[self.key] = self.sv
+ self.radio.set(km)
+ self._set_slider_value(self.sv.value)
+
+ def _set(self):
+ self._apply()
+ self.done(0)
+
+
+class MForm(QtGui.QWidget):
+ def update(self):
+ try:
+ st = time.time();
+ knobs = self.radio.get([]);
+ ft = time.time();
+ latency = ft-st;
+ self.parent.statusBar().showMessage("Current GNU Radio Control Port Query Latency: %f ms"%(latency*1000))
+
+ except Exception, e:
+ sys.stderr.write("ctrlport-monitor: radio.get threw exception ({0}).\n".format(e))
+ if(type(self.parent) is MAINWindow):
+ # Find window of connection
+ remove = []
+ for p in self.parent.mdiArea.subWindowList():
+ if self.parent.conns[self.uid] == p.widget():
+ remove.append(p)
+
+ # Find any subplot windows of connection
+ for p in self.parent.mdiArea.subWindowList():
+ for plot in self.parent.plots[self.uid]:
+ if plot.qwidget() == p.widget():
+ remove.append(p)
+
+ # Clean up local references to these
+ self.parent.conns.remove(self.parent.conns[self.uid])
+ self.parent.plots.remove(self.parent.plots[self.uid])
+
+ # Remove subwindows for connection and plots
+ for r in remove:
+ self.parent.mdiArea.removeSubWindow(r)
+
+ # Clean up self
+ self.close()
+ else:
+ sys.exit(1)
+ return
+
+ tableitems = knobs.keys()
+
+ #UPDATE TABLE:
+ self.table.updateItems(knobs, self.knobprops)
+
+ #UPDATE PLOTS
+ self.parent.update(knobs, self.uid)
+
+
+ def __init__(self, radio=None, port=None, uid=0, updateRate=2000, parent=None):
+
+ super(MForm, self).__init__()
+
+ if(radio == None or port == None):
+ askinfo = ConInfoDialog(self);
+ if askinfo.exec_():
+ host = str(askinfo.host.text());
+ port = str(askinfo.port.text());
+ radio = parent.interface.getRadio(host, port)
+ else:
+ self.radio = None
+ return
+
+ self.uid = uid
+ self.parent = parent
+ self.horizontalLayout = QtGui.QVBoxLayout(self)
+ self.gridLayout = QtGui.QGridLayout()
+
+ self.radio = radio
+ self.knobprops = self.radio.properties([])
+ self.parent.knobprops.append(self.knobprops)
+ self.resize(775,500)
+ self.timer = QtCore.QTimer()
+ self.constupdatediv = 0
+ self.tableupdatediv = 0
+ plotsize=250
+
+ # make table
+ self.table = GrDataPlotterValueTable(uid, self, 0, 0, 400, 200)
+ sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
+ self.table.treeWidget.setSizePolicy(sizePolicy)
+ self.table.treeWidget.setEditTriggers(QtGui.QAbstractItemView.EditKeyPressed)
+ self.table.treeWidget.setSortingEnabled(True)
+ self.table.treeWidget.setDragEnabled(True)
+
+ # add things to layouts
+ self.horizontalLayout.addWidget(self.table.treeWidget)
+
+ # set up timer
+ self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.update)
+ self.updateRate = updateRate;
+ self.timer.start(self.updateRate)
+
+ # set up context menu ..
+ self.table.treeWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
+ self.table.treeWidget.customContextMenuRequested.connect(self.openMenu)
+
+ # Set up double-click to launch default plotter
+ self.connect(self.table.treeWidget,
+ QtCore.SIGNAL('itemDoubleClicked(QTreeWidgetItem*, int)'),
+ self.parent.newSub);
+
+ # Allow drag/drop event from table item to plotter
+ self.connect(self.table.treeWidget,
+ QtCore.SIGNAL('itemPressed(QTreeWidgetItem*, int)'),
+ self.parent.startDrag)
+
+ def openMenu(self, pos):
+ index = self.table.treeWidget.selectedIndexes()
+ item = self.table.treeWidget.itemFromIndex(index[0])
+ itemname = str(item.text(0))
+ self.parent.propertiesMenu(itemname, self.radio, self.uid)
+
+
+class MyClient(IceRadioClient):
+ def __init__(self):
+ IceRadioClient.__init__(self, MAINWindow)
+
+sys.exit(MyClient().main(sys.argv))
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitor b/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitor
new file mode 100755
index 0000000000..f2c01691a1
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitor
@@ -0,0 +1,591 @@
+#!/usr/bin/env python
+#
+# Copyright 2012-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.
+#
+
+from gnuradio import gr, ctrlport
+
+from PyQt4 import QtCore,Qt,Qwt5
+import PyQt4.QtGui as QtGui
+import sys, time, re, pprint
+import itertools
+import scipy
+
+import Ice
+from gnuradio.ctrlport.IceRadioClient import *
+from gnuradio.ctrlport.GrDataPlotter import *
+from gnuradio.ctrlport import GNURadio
+
+class MAINWindow(QtGui.QMainWindow):
+ def minimumSizeHint(self):
+ return QtGui.QSize(800,600)
+
+ def __init__(self, radio, port, interface):
+
+ super(MAINWindow, self).__init__()
+ self.conns = []
+ self.plots = []
+ self.knobprops = []
+ self.interface = interface
+
+ self.mdiArea = QtGui.QMdiArea()
+ self.mdiArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
+ self.mdiArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
+ self.setCentralWidget(self.mdiArea)
+
+ self.mdiArea.subWindowActivated.connect(self.updateMenus)
+ self.windowMapper = QtCore.QSignalMapper(self)
+ self.windowMapper.mapped[QtGui.QWidget].connect(self.setActiveSubWindow)
+
+ self.createActions()
+ self.createMenus()
+ self.createToolBars()
+ self.createStatusBar()
+ self.updateMenus()
+
+ self.setWindowTitle("GNU Radio Performance Monitor")
+ self.setUnifiedTitleAndToolBarOnMac(True)
+
+ self.newCon(radio, port)
+ icon = QtGui.QIcon(ctrlport.__path__[0] + "/icon.png" )
+ self.setWindowIcon(icon)
+
+ def newCon(self, radio=None, port=None):
+ child = MForm(radio, port, len(self.conns), self)
+ if(child.radio is not None):
+ child.setWindowTitle(str(child.radio))
+ horizbar = QtGui.QScrollArea()
+ horizbar.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
+ horizbar.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
+ horizbar.setWidget(child)
+ self.mdiArea.addSubWindow(horizbar)
+ self.mdiArea.currentSubWindow().showMaximized()
+
+ self.conns.append(child)
+ self.plots.append([])
+
+ def newUpdater(self, key, radio):
+ updater = UpdaterWindow(key, radio, None)
+ updater.setWindowTitle("Updater: " + key)
+ updater.setModal(False)
+ updater.exec_()
+
+ def update(self, knobs, uid):
+ #sys.stderr.write("KNOB KEYS: {0}\n".format(knobs.keys()))
+ for plot in self.plots[uid]:
+ data = knobs[plot.name()].value
+ plot.update(data)
+ plot.stop()
+ plot.wait()
+ plot.start()
+
+ def setActiveSubWindow(self, window):
+ if window:
+ self.mdiArea.setActiveSubWindow(window)
+
+
+ def createActions(self):
+ self.newConAct = QtGui.QAction("&New Connection",
+ self, shortcut=QtGui.QKeySequence.New,
+ statusTip="Create a new file", triggered=self.newCon)
+
+ self.exitAct = QtGui.QAction("E&xit", self, shortcut="Ctrl+Q",
+ statusTip="Exit the application",
+ triggered=QtGui.qApp.closeAllWindows)
+
+ self.closeAct = QtGui.QAction("Cl&ose", self, shortcut="Ctrl+F4",
+ statusTip="Close the active window",
+ triggered=self.mdiArea.closeActiveSubWindow)
+
+ self.closeAllAct = QtGui.QAction("Close &All", self,
+ statusTip="Close all the windows",
+ triggered=self.mdiArea.closeAllSubWindows)
+
+
+ qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_T);
+ self.tileAct = QtGui.QAction("&Tile", self,
+ statusTip="Tile the windows",
+ triggered=self.mdiArea.tileSubWindows,
+ shortcut=qks)
+
+ qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_C);
+ self.cascadeAct = QtGui.QAction("&Cascade", self,
+ statusTip="Cascade the windows", shortcut=qks,
+ triggered=self.mdiArea.cascadeSubWindows)
+
+ self.nextAct = QtGui.QAction("Ne&xt", self,
+ shortcut=QtGui.QKeySequence.NextChild,
+ statusTip="Move the focus to the next window",
+ triggered=self.mdiArea.activateNextSubWindow)
+
+ self.previousAct = QtGui.QAction("Pre&vious", self,
+ shortcut=QtGui.QKeySequence.PreviousChild,
+ statusTip="Move the focus to the previous window",
+ triggered=self.mdiArea.activatePreviousSubWindow)
+
+ self.separatorAct = QtGui.QAction(self)
+ self.separatorAct.setSeparator(True)
+
+ self.aboutAct = QtGui.QAction("&About", self,
+ statusTip="Show the application's About box",
+ triggered=self.about)
+
+ self.aboutQtAct = QtGui.QAction("About &Qt", self,
+ statusTip="Show the Qt library's About box",
+ triggered=QtGui.qApp.aboutQt)
+
+ def createMenus(self):
+ self.fileMenu = self.menuBar().addMenu("&File")
+ self.fileMenu.addAction(self.newConAct)
+ self.fileMenu.addSeparator()
+ self.fileMenu.addAction(self.exitAct)
+
+ self.windowMenu = self.menuBar().addMenu("&Window")
+ self.updateWindowMenu()
+ self.windowMenu.aboutToShow.connect(self.updateWindowMenu)
+
+ self.menuBar().addSeparator()
+
+ self.helpMenu = self.menuBar().addMenu("&Help")
+ self.helpMenu.addAction(self.aboutAct)
+ self.helpMenu.addAction(self.aboutQtAct)
+
+ def createToolBars(self):
+ self.fileToolBar = self.addToolBar("File")
+ self.fileToolBar.addAction(self.newConAct)
+
+ self.fileToolBar = self.addToolBar("Window")
+ self.fileToolBar.addAction(self.tileAct)
+ self.fileToolBar.addAction(self.cascadeAct)
+
+ def createStatusBar(self):
+ self.statusBar().showMessage("Ready")
+
+
+ def activeMdiChild(self):
+ activeSubWindow = self.mdiArea.activeSubWindow()
+ if activeSubWindow:
+ return activeSubWindow.widget()
+ return None
+
+ def updateMenus(self):
+ hasMdiChild = (self.activeMdiChild() is not None)
+ self.closeAct.setEnabled(hasMdiChild)
+ self.closeAllAct.setEnabled(hasMdiChild)
+ self.tileAct.setEnabled(hasMdiChild)
+ self.cascadeAct.setEnabled(hasMdiChild)
+ self.nextAct.setEnabled(hasMdiChild)
+ self.previousAct.setEnabled(hasMdiChild)
+ self.separatorAct.setVisible(hasMdiChild)
+
+ def updateWindowMenu(self):
+ self.windowMenu.clear()
+ self.windowMenu.addAction(self.closeAct)
+ self.windowMenu.addAction(self.closeAllAct)
+ self.windowMenu.addSeparator()
+ self.windowMenu.addAction(self.tileAct)
+ self.windowMenu.addAction(self.cascadeAct)
+ self.windowMenu.addSeparator()
+ self.windowMenu.addAction(self.nextAct)
+ self.windowMenu.addAction(self.previousAct)
+ self.windowMenu.addAction(self.separatorAct)
+
+ def about(self):
+ about_info = \
+'''Copyright 2012 Free Software Foundation, Inc.\n
+This program is part of GNU Radio.\n
+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.\n
+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.\n
+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.'''
+
+ QtGui.QMessageBox.about(None, "gr-ctrlport-monitor", about_info)
+
+
+class ConInfoDialog(QtGui.QDialog):
+ def __init__(self, parent=None):
+ super(ConInfoDialog, self).__init__(parent)
+
+ self.gridLayout = QtGui.QGridLayout(self)
+
+
+ self.host = QtGui.QLineEdit(self);
+ self.port = QtGui.QLineEdit(self);
+ self.host.setText("localhost");
+ self.port.setText("43243");
+
+ self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok |
+ QtGui.QDialogButtonBox.Cancel)
+
+ self.gridLayout.addWidget(self.host);
+ self.gridLayout.addWidget(self.port);
+ self.gridLayout.addWidget(self.buttonBox);
+
+ self.buttonBox.accepted.connect(self.accept)
+ self.buttonBox.rejected.connect(self.reject)
+
+
+ def accept(self):
+ self.done(1);
+
+ def reject(self):
+ self.done(0);
+
+
+class UpdaterWindow(QtGui.QDialog):
+ def __init__(self, key, radio, parent):
+ QtGui.QDialog.__init__(self, parent)
+
+ self.key = key;
+ self.radio = radio
+
+ self.resize(300,200)
+ self.layout = QtGui.QVBoxLayout()
+
+ self.props = radio.properties([key])[key]
+ info = str(self.props)
+
+ self.infoLabel = QtGui.QLabel(info)
+ self.layout.addWidget(self.infoLabel)
+
+ self.cancelButton = QtGui.QPushButton("Ok")
+ self.cancelButton.connect(self.cancelButton, QtCore.SIGNAL('clicked()'), self.reject)
+
+ self.buttonlayout = QtGui.QHBoxLayout()
+ self.buttonlayout.addWidget(self.cancelButton)
+ self.layout.addLayout(self.buttonlayout)
+
+ # set layout and go...
+ self.setLayout(self.layout)
+
+ def _set_slider_value(self, val):
+ self.slider.setValue(self.steps*(val-self.props.min.value)/self.valspan)
+
+ def _slide(self):
+ val = (self.slider.value()*self.valspan + self.props.min.value)/float(self.steps)
+ self.textInput.setText(str(val))
+
+ def _apply(self):
+ if(type(self.sv.value) == str):
+ val = str(self.textInput.text())
+ elif(type(self.sv.value) == int):
+ val = int(round(float(self.textInput.text())))
+ elif(type(self.sv.value) == float):
+ val = float(self.textInput.text())
+ else:
+ sys.stderr.write("set type not supported! ({0})\n".format(type(self.sv.value)))
+ sys.exit(-1)
+
+ self.sv.value = val
+ km = {}
+ km[self.key] = self.sv
+ self.radio.set(km)
+ self._set_slider_value(self.sv.value)
+
+ def _set(self):
+ self._apply()
+ self.done(0)
+
+
+def build_edge_graph(sources, sinks, edges):
+ '''
+ Starting from the sources, walks through all of the edges to find
+ the next connected block. The output is stored in 'allblocks'
+ where each row starts with a source and follows one path down
+ until it terminates in either a sink or as an input to a block
+ that is part of another chain.
+ '''
+ def find_edge(src, sinks, edges, row, col):
+ #print "\n\nAll blocks: "
+ #printer.pprint(allblocks)
+ #print "\nLooking for: ", src
+
+ src0 = src.split(":")[0]
+ if(src0 in sinks):
+ if(len(allblocks) <= row):
+ allblocks.append(col*[""])
+ allblocks[row].append(src)
+ return row+1
+
+ for edge in edges:
+ if(re.match(src0, edge)):
+ s = edge.split("->")[0]
+ b = edge.split("->")[1]
+ if(len(allblocks) <= row):
+ allblocks.append(col*[""])
+ allblocks[row].append(s)
+ #print "Source: {0} Sink: {1}".format(s, b)
+ row = find_edge(b, sinks, edges, row, col+1)
+ return row
+
+ # Recursively get all edges as a matrix of source->sink
+ n = 0
+ allblocks = []
+ for src in sources:
+ n = find_edge(src, sinks, edges, n, 0)
+
+ # Sort by longest list
+ allblocks = sorted(allblocks, key=len)
+ allblocks.reverse()
+
+ # Make all rows same length by padding '' in front of sort rows
+ maxrowlen = len(allblocks[0])
+ for i,a in enumerate(allblocks):
+ rowlen = len(a)
+ allblocks[i] = (maxrowlen-rowlen)*[''] + a
+
+ # Dedup rows
+ allblocks = sorted(allblocks)
+ allblocks = list(k for k,_ in itertools.groupby(allblocks))
+ allblocks.reverse()
+
+ return allblocks
+
+
+class MForm(QtGui.QWidget):
+ def update(self):
+ try:
+ st = time.time()
+ knobs = self.radio.get([b[0] for b in self.block_dict])
+
+ ft = time.time()
+ latency = ft-st
+ self.parent.statusBar().showMessage("Current GNU Radio Control Port Query Latency: %f ms"%\
+ (latency*1000))
+
+ except Exception, e:
+ sys.stderr.write("ctrlport-monitor: radio.get threw exception ({0}).\n".format(e))
+ if(type(self.parent) is MAINWindow):
+ # Find window of connection
+ remove = []
+ for p in self.parent.mdiArea.subWindowList():
+ if self.parent.conns[self.uid] == p.widget():
+ remove.append(p)
+
+ # Find any subplot windows of connection
+ for p in self.parent.mdiArea.subWindowList():
+ for plot in self.parent.plots[self.uid]:
+ if plot.qwidget() == p.widget():
+ remove.append(p)
+
+ # Clean up local references to these
+ self.parent.conns.remove(self.parent.conns[self.uid])
+ self.parent.plots.remove(self.parent.plots[self.uid])
+
+ # Remove subwindows for connection and plots
+ for r in remove:
+ self.parent.mdiArea.removeSubWindow(r)
+
+ # Clean up self
+ self.close()
+ else:
+ sys.exit(1)
+ return
+
+ #UPDATE TABLE:
+ self.updateItems(knobs)
+
+ #UPDATE PLOTS
+ self.parent.update(knobs, self.uid)
+
+ def updateItems(self, knobs):
+ for b in self.block_dict:
+ if(knobs[b[0]].ice_id.im_class == GNURadio.KnobVecF):
+ b[1].setText("{0:.4f}".format(knobs[b[0]].value[b[2]]))
+ else:
+ b[1].setText("{0:.4f}".format(knobs[b[0]].value))
+
+ def __init__(self, radio=None, port=None, uid=0, parent=None):
+
+ super(MForm, self).__init__()
+
+ if(radio == None or port == None):
+ askinfo = ConInfoDialog(self);
+ if askinfo.exec_():
+ host = str(askinfo.host.text());
+ port = str(askinfo.port.text());
+ radio = parent.interface.getRadio(host, port)
+ else:
+ self.radio = None
+ return
+
+ self.uid = uid
+ self.parent = parent
+ self.layout = QtGui.QGridLayout(self)
+ self.layout.setSizeConstraint(QtGui.QLayout.SetFixedSize)
+
+ self.radio = radio
+ self.knobprops = self.radio.properties([])
+ self.parent.knobprops.append(self.knobprops)
+ self.resize(775,500)
+ self.timer = QtCore.QTimer()
+ self.constupdatediv = 0
+ self.tableupdatediv = 0
+ plotsize=250
+
+
+ # Set up the graph of blocks
+ input_name = lambda x: x+"::avg input % full"
+ output_name = lambda x: x+"::avg output % full"
+ wtime_name = lambda x: x+"::avg work time"
+ nout_name = lambda x: x+"::avg noutput_items"
+ nprod_name = lambda x: x+"::avg nproduced"
+
+ tmplist = []
+ knobs = self.radio.get([])
+ edgelist = None
+ for k in knobs:
+ propname = k.split("::")
+ blockname = propname[0]
+ keyname = propname[1]
+ if(keyname == "edge list"):
+ edgelist = knobs[k].value
+ elif(blockname not in tmplist):
+ # only take gr_blocks (no hier_block2)
+ if(knobs.has_key(input_name(blockname))):
+ tmplist.append(blockname)
+
+ if not edgelist:
+ sys.stderr.write("Could not find list of edges from flowgraph. " + \
+ "Make sure the option 'edges_list' is enabled " + \
+ "in the ControlPort configuration.\n\n")
+ sys.exit(1)
+
+ edges = edgelist.split("\n")[0:-1]
+ producers = []
+ consumers = []
+ for e in edges:
+ _e = e.split("->")
+ producers.append(_e[0])
+ consumers.append(_e[1])
+
+ # Get producers and consumers as sets while ignoring the
+ # ports.
+ prods = set(map(lambda x: x.split(":")[0], producers))
+ cons = set(map(lambda x: x.split(":")[0], consumers))
+
+ # Split out all blocks, sources, and sinks based on how they
+ # appear as consumers and/or producers.
+ blocks = prods.intersection(cons)
+ sources = prods.difference(blocks)
+ sinks = cons.difference(blocks)
+
+ nblocks = len(prods) + len(cons)
+
+ allblocks = build_edge_graph(sources, sinks, edges)
+ nrows = len(allblocks)
+ ncols = len(allblocks[0])
+
+ col_width = 120
+
+ self.block_dict = []
+
+ for row, blockrow in enumerate(allblocks):
+ for col, block in enumerate(blockrow):
+ if(block == ''):
+ continue
+
+ bgroup = QtGui.QGroupBox(block)
+ playout = QtGui.QFormLayout()
+ bgroup.setLayout(playout)
+ self.layout.addWidget(bgroup, row, 2*col)
+
+ blockname = block.split(":")[0]
+
+ name = wtime_name(blockname)
+ wtime = knobs[name].value
+ newtime = QtGui.QLineEdit()
+ newtime.setMinimumWidth(col_width)
+ newtime.setText("{0:.4f}".format(wtime))
+ self.block_dict.append((name, newtime))
+
+ name = nout_name(blockname)
+ nout = knobs[name].value
+ newnout = QtGui.QLineEdit()
+ newnout.setText("{0:.4f}".format(nout))
+ newnout.setMinimumWidth(col_width)
+ self.block_dict.append((name, newnout))
+
+ name = nprod_name(blockname)
+ nprod = knobs[name].value
+ newnprod = QtGui.QLineEdit()
+ newnprod.setMinimumWidth(col_width)
+ newnprod.setText("{0:.4f}".format(nprod))
+ self.block_dict.append((name, newnprod))
+
+ playout.addRow("Work time", newtime)
+ playout.addRow("noutput_items", newnout)
+ playout.addRow("nproduced", newnprod)
+
+ if blockname in blocks or blockname in sources:
+ # Add a buffer between blocks
+ buffgroup = QtGui.QGroupBox("Buffer")
+ bufflayout = QtGui.QFormLayout()
+ buffgroup.setLayout(bufflayout)
+ self.layout.addWidget(buffgroup, row, 2*col+1)
+
+ i = int(block.split(":")[1])
+ name = output_name(blockname)
+ obuff = knobs[name].value
+ for i,o in enumerate(obuff):
+ newobuff = QtGui.QLineEdit()
+ newobuff.setMinimumWidth(col_width)
+ newobuff.setText("{0:.4f}".format(o))
+ self.block_dict.append((name, newobuff, i))
+ bufflayout.addRow("Out Buffer {0}".format(i),
+ newobuff)
+
+ if blockname in blocks or blockname in sinks:
+ item = self.layout.itemAtPosition(row, 2*col-1)
+ if(item):
+ buffgroup = item.widget()
+ bufflayout = buffgroup.layout()
+ else:
+ buffgroup = QtGui.QGroupBox("Buffer")
+ bufflayout = QtGui.QFormLayout()
+ buffgroup.setLayout(bufflayout)
+ self.layout.addWidget(buffgroup, row, 2*col-1)
+
+ i = int(block.split(":")[1])
+ name = input_name(blockname)
+ ibuff = knobs[name].value[i]
+ newibuff = QtGui.QLineEdit()
+ newibuff.setMinimumWidth(col_width)
+ newibuff.setText("{0:.4f}".format(ibuff))
+ self.block_dict.append((name, newibuff, i))
+ bufflayout.addRow("In Buffer {0}".format(i),
+ newibuff)
+
+ # set up timer
+ self.timer = QtCore.QTimer()
+ self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.update)
+ self.timer.start(1000)
+
+ def openMenu(self, pos):
+ index = self.table.treeWidget.selectedIndexes()
+ item = self.table.treeWidget.itemFromIndex(index[0])
+ itemname = str(item.text(0))
+ self.parent.propertiesMenu(itemname, self.radio, self.uid)
+
+
+class MyClient(IceRadioClient):
+ def __init__(self):
+ IceRadioClient.__init__(self, MAINWindow)
+
+sys.exit(MyClient().main(sys.argv))
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx b/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx
new file mode 100755
index 0000000000..a65b0406e4
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx
@@ -0,0 +1,727 @@
+#!/usr/bin/env python
+#
+# Copyright 2012-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.
+#
+
+import random,math,operator
+import networkx as nx;
+import matplotlib.pyplot as plt
+
+from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
+from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
+from matplotlib.figure import Figure
+
+from gnuradio import gr, ctrlport
+
+from PyQt4 import QtCore,Qt,Qwt5
+import PyQt4.QtGui as QtGui
+import sys, time, re, pprint
+import itertools
+import scipy
+from scipy import spatial
+
+import Ice
+from gnuradio.ctrlport.IceRadioClient import *
+from gnuradio.ctrlport.GrDataPlotter import *
+from gnuradio.ctrlport import GNURadio
+
+class MAINWindow(QtGui.QMainWindow):
+ def minimumSizeHint(self):
+ return QtGui.QSize(800,600)
+
+ def __init__(self, radio, port, interface):
+
+ super(MAINWindow, self).__init__()
+ self.conns = []
+ self.plots = []
+ self.knobprops = []
+ self.interface = interface
+
+ self.mdiArea = QtGui.QMdiArea()
+ self.mdiArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
+ self.mdiArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
+ self.setCentralWidget(self.mdiArea)
+
+ self.mdiArea.subWindowActivated.connect(self.updateMenus)
+ self.windowMapper = QtCore.QSignalMapper(self)
+ self.windowMapper.mapped[QtGui.QWidget].connect(self.setActiveSubWindow)
+
+ self.createActions()
+ self.createMenus()
+ self.createToolBars()
+ self.createStatusBar()
+ self.updateMenus()
+
+ self.setWindowTitle("GNU Radio Performance Monitor")
+ self.setUnifiedTitleAndToolBarOnMac(True)
+
+ self.newCon(radio, port)
+ icon = QtGui.QIcon(ctrlport.__path__[0] + "/icon.png" )
+ self.setWindowIcon(icon)
+
+
+ def newSubWindow(self, window, title):
+ child = window;
+ child.setWindowTitle(title)
+ self.mdiArea.addSubWindow(child)
+ self.conns.append(child)
+ child.show();
+ self.mdiArea.currentSubWindow().showMaximized()
+
+
+ def newCon(self, radio=None, port=None):
+ child = MForm(radio, port, len(self.conns), self)
+ if(child.radio is not None):
+ child.setWindowTitle(str(child.radio))
+# horizbar = QtGui.QScrollArea()
+# horizbar.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
+# horizbar.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
+# horizbar.setWidget(child)
+# self.mdiArea.addSubWindow(horizbar)
+ self.mdiArea.addSubWindow(child)
+ self.mdiArea.currentSubWindow().showMaximized()
+
+ self.conns.append(child)
+ self.plots.append([])
+
+ def update(self, knobs, uid):
+ #sys.stderr.write("KNOB KEYS: {0}\n".format(knobs.keys()))
+ for plot in self.plots[uid]:
+ data = knobs[plot.name()].value
+ plot.update(data)
+ plot.stop()
+ plot.wait()
+ plot.start()
+
+ def setActiveSubWindow(self, window):
+ if window:
+ self.mdiArea.setActiveSubWindow(window)
+
+
+ def createActions(self):
+ self.newConAct = QtGui.QAction("&New Connection",
+ self, shortcut=QtGui.QKeySequence.New,
+ statusTip="Create a new file", triggered=self.newCon)
+
+ self.exitAct = QtGui.QAction("E&xit", self, shortcut="Ctrl+Q",
+ statusTip="Exit the application",
+ triggered=QtGui.qApp.closeAllWindows)
+
+ self.closeAct = QtGui.QAction("Cl&ose", self, shortcut="Ctrl+F4",
+ statusTip="Close the active window",
+ triggered=self.mdiArea.closeActiveSubWindow)
+
+ self.closeAllAct = QtGui.QAction("Close &All", self,
+ statusTip="Close all the windows",
+ triggered=self.mdiArea.closeAllSubWindows)
+
+
+ qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_T);
+ self.tileAct = QtGui.QAction("&Tile", self,
+ statusTip="Tile the windows",
+ triggered=self.mdiArea.tileSubWindows,
+ shortcut=qks)
+
+ qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_C);
+ self.cascadeAct = QtGui.QAction("&Cascade", self,
+ statusTip="Cascade the windows", shortcut=qks,
+ triggered=self.mdiArea.cascadeSubWindows)
+
+ self.nextAct = QtGui.QAction("Ne&xt", self,
+ shortcut=QtGui.QKeySequence.NextChild,
+ statusTip="Move the focus to the next window",
+ triggered=self.mdiArea.activateNextSubWindow)
+
+ self.previousAct = QtGui.QAction("Pre&vious", self,
+ shortcut=QtGui.QKeySequence.PreviousChild,
+ statusTip="Move the focus to the previous window",
+ triggered=self.mdiArea.activatePreviousSubWindow)
+
+ self.separatorAct = QtGui.QAction(self)
+ self.separatorAct.setSeparator(True)
+
+ self.aboutAct = QtGui.QAction("&About", self,
+ statusTip="Show the application's About box",
+ triggered=self.about)
+
+ self.aboutQtAct = QtGui.QAction("About &Qt", self,
+ statusTip="Show the Qt library's About box",
+ triggered=QtGui.qApp.aboutQt)
+
+ def createMenus(self):
+ self.fileMenu = self.menuBar().addMenu("&File")
+ self.fileMenu.addAction(self.newConAct)
+ self.fileMenu.addSeparator()
+ self.fileMenu.addAction(self.exitAct)
+
+ self.windowMenu = self.menuBar().addMenu("&Window")
+ self.updateWindowMenu()
+ self.windowMenu.aboutToShow.connect(self.updateWindowMenu)
+
+ self.menuBar().addSeparator()
+
+ self.helpMenu = self.menuBar().addMenu("&Help")
+ self.helpMenu.addAction(self.aboutAct)
+ self.helpMenu.addAction(self.aboutQtAct)
+
+ def createToolBars(self):
+ self.fileToolBar = self.addToolBar("File")
+ self.fileToolBar.addAction(self.newConAct)
+
+ self.fileToolBar = self.addToolBar("Window")
+ self.fileToolBar.addAction(self.tileAct)
+ self.fileToolBar.addAction(self.cascadeAct)
+
+ def createStatusBar(self):
+ self.statusBar().showMessage("Ready")
+
+
+ def activeMdiChild(self):
+ activeSubWindow = self.mdiArea.activeSubWindow()
+ if activeSubWindow:
+ return activeSubWindow.widget()
+ return None
+
+ def updateMenus(self):
+ hasMdiChild = (self.activeMdiChild() is not None)
+ self.closeAct.setEnabled(hasMdiChild)
+ self.closeAllAct.setEnabled(hasMdiChild)
+ self.tileAct.setEnabled(hasMdiChild)
+ self.cascadeAct.setEnabled(hasMdiChild)
+ self.nextAct.setEnabled(hasMdiChild)
+ self.previousAct.setEnabled(hasMdiChild)
+ self.separatorAct.setVisible(hasMdiChild)
+
+ def updateWindowMenu(self):
+ self.windowMenu.clear()
+ self.windowMenu.addAction(self.closeAct)
+ self.windowMenu.addAction(self.closeAllAct)
+ self.windowMenu.addSeparator()
+ self.windowMenu.addAction(self.tileAct)
+ self.windowMenu.addAction(self.cascadeAct)
+ self.windowMenu.addSeparator()
+ self.windowMenu.addAction(self.nextAct)
+ self.windowMenu.addAction(self.previousAct)
+ self.windowMenu.addAction(self.separatorAct)
+
+ def about(self):
+ about_info = \
+'''Copyright 2012 Free Software Foundation, Inc.\n
+This program is part of GNU Radio.\n
+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.\n
+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.\n
+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.'''
+
+ QtGui.QMessageBox.about(None, "gr-ctrlport-monitor", about_info)
+
+
+class ConInfoDialog(QtGui.QDialog):
+ def __init__(self, parent=None):
+ super(ConInfoDialog, self).__init__(parent)
+
+ self.gridLayout = QtGui.QGridLayout(self)
+
+
+ self.host = QtGui.QLineEdit(self);
+ self.port = QtGui.QLineEdit(self);
+ self.host.setText("localhost");
+ self.port.setText("43243");
+
+ self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok |
+ QtGui.QDialogButtonBox.Cancel)
+
+ self.gridLayout.addWidget(self.host);
+ self.gridLayout.addWidget(self.port);
+ self.gridLayout.addWidget(self.buttonBox);
+
+ self.buttonBox.accepted.connect(self.accept)
+ self.buttonBox.rejected.connect(self.reject)
+
+
+ def accept(self):
+ self.done(1);
+
+ def reject(self):
+ self.done(0);
+
+
+class DataTable(QtGui.QWidget):
+ def update(self):
+ print "update"
+
+ def __init__(self, radio, G):
+ QtGui.QWidget.__init__( self)
+
+ self.layout = QtGui.QVBoxLayout(self);
+ self.hlayout = QtGui.QHBoxLayout();
+ self.layout.addLayout(self.hlayout);
+
+ self.G = G;
+ self.radio = radio;
+
+ self._keymap = None
+
+ # Create a combobox to set the type of statistic we want.
+ self._statistic = "Instantaneous"
+ self._statistics_table = {"Instantaneous": "",
+ "Average": "avg ",
+ "Variance": "var "}
+ self.stattype = QtGui.QComboBox()
+ self.stattype.addItem("Instantaneous")
+ self.stattype.addItem("Average")
+ self.stattype.addItem("Variance")
+ self.stattype.setMaximumWidth(200)
+ self.hlayout.addWidget(self.stattype);
+ self.stattype.currentIndexChanged.connect(self.stat_changed)
+
+ # Create a checkbox to toggle sorting of graphs
+ self._sort = False
+ self.checksort = QtGui.QCheckBox("Sort")
+ self.checksort.setCheckState(self._sort)
+ self.hlayout.addWidget(self.checksort);
+ self.checksort.stateChanged.connect(self.checksort_changed)
+
+ # set up table
+ self.perfTable = Qt.QTableWidget();
+ self.perfTable.setColumnCount(2)
+ self.perfTable.verticalHeader().hide();
+ self.perfTable.setHorizontalHeaderLabels( ["Block Name", "Percent Runtime"] );
+ self.perfTable.horizontalHeader().setStretchLastSection(True);
+ self.perfTable.setSortingEnabled(True)
+ nodes = self.G.nodes(data=True)
+
+ # set up plot
+ self.f = plt.figure(figsize=(10,8), dpi=90)
+ self.sp = self.f.add_subplot(111);
+ self.sp.autoscale_view(True,True,True);
+ self.sp.set_autoscale_on(True)
+ self.canvas = FigureCanvas(self.f)
+
+ # set up tabs
+ self.tabber = QtGui.QTabWidget();
+ self.layout.addWidget(self.tabber);
+ self.tabber.addTab(self.perfTable,"Table View");
+ self.tabber.addTab(self.canvas, "Graph View");
+
+ # set up timer
+ self.timer = QtCore.QTimer()
+ self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.update)
+ self.timer.start(500)
+
+ for i in range(0,len(nodes)):
+ self.perfTable.setItem(
+ i,0,
+ Qt.QTableWidgetItem(nodes[i][0]))
+
+ def table_update(self,data):
+ for k in data.keys():
+ weight = data[k]
+ existing = self.perfTable.findItems(str(k),QtCore.Qt.MatchFixedString)
+ if(len(existing) == 0):
+ i = self.perfTable.rowCount();
+ self.perfTable.setRowCount( i+1)
+ self.perfTable.setItem( i,0, Qt.QTableWidgetItem(str(k)))
+ self.perfTable.setItem( i,1, Qt.QTableWidgetItem(str(weight)))
+ else:
+ self.perfTable.setItem( self.perfTable.row(existing[0]),1, Qt.QTableWidgetItem(str(weight)))
+
+ def stat_changed(self, index):
+ self._statistic = str(self.stattype.currentText())
+
+ def checksort_changed(self, state):
+ self._sort = state > 0
+
+class DataTableBuffers(DataTable):
+ def __init__(self, radio, G):
+ DataTable.__init__(self,radio,G)
+ self.perfTable.setHorizontalHeaderLabels( ["Block Name", "Percent Buffer Full"] );
+
+ def update(self):
+ nodes = self.G.nodes();
+
+ # get buffer fullness for all blocks
+ kl = map(lambda x: "%s::%soutput %% full" % \
+ (x, self._statistics_table[self._statistic]),
+ nodes);
+ buf_knobs = self.radio.get(kl)
+
+ # strip values out of ctrlport response
+ buffer_fullness = dict(zip(
+ map(lambda x: x.split("::")[0], buf_knobs.keys()),
+ map(lambda x: x.value, buf_knobs.values())))
+
+ blockport_fullness = {}
+ for blk in buffer_fullness:
+ for port in range(0,len(buffer_fullness[blk])):
+ blockport_fullness["%s:%d"%(blk,port)] = buffer_fullness[blk][port];
+
+ self.table_update(blockport_fullness);
+
+ if(self._sort):
+ sorted_fullness = sorted(blockport_fullness.iteritems(), key=operator.itemgetter(1))
+ self._keymap = map(operator.itemgetter(0), sorted_fullness)
+ else:
+ if self._keymap:
+ sorted_fullness = len(self._keymap)*['',]
+ for b in blockport_fullness:
+ sorted_fullness[self._keymap.index(b)] = (b, blockport_fullness[b])
+ else:
+ sorted_fullness = blockport_fullness.items()
+
+ self.sp.clear();
+ plt.figure(self.f.number)
+ plt.subplot(111);
+ self.sp.bar(range(0,len(sorted_fullness)), map(lambda x: x[1], sorted_fullness),
+ alpha=0.5)
+ self.sp.set_ylabel("% Buffers Full");
+ self.sp.set_xticks( map(lambda x: x+0.5, range(0,len(sorted_fullness))))
+ self.sp.set_xticklabels( map(lambda x: " " + x, map(lambda x: x[0], sorted_fullness)),
+ rotation="vertical", verticalalignment="bottom" )
+ self.canvas.draw();
+ self.canvas.show();
+
+class DataTableRuntimes(DataTable):
+ def __init__(self, radio, G):
+ DataTable.__init__(self,radio,G)
+ #self.perfTable.setRowCount(len( self.G.nodes() ))
+
+ def update(self):
+ nodes = self.G.nodes();
+
+ # get work time for all blocks
+ kl = map(lambda x: "%s::%swork time" % \
+ (x, self._statistics_table[self._statistic]),
+ nodes);
+ wrk_knobs = self.radio.get(kl)
+
+ # strip values out of ctrlport response
+ total_work = sum(map(lambda x: x.value, wrk_knobs.values()))
+ work_times = dict(zip(
+ map(lambda x: x.split("::")[0], wrk_knobs.keys()),
+ map(lambda x: x.value/total_work, wrk_knobs.values())))
+
+ # update table view
+ self.table_update(work_times)
+
+ if(self._sort):
+ sorted_work = sorted(work_times.iteritems(), key=operator.itemgetter(1))
+ self._keymap = map(operator.itemgetter(0), sorted_work)
+ else:
+ if self._keymap:
+ sorted_work = len(self._keymap)*['',]
+ for b in work_times:
+ sorted_work[self._keymap.index(b)] = (b, work_times[b])
+ else:
+ sorted_work = work_times.items()
+
+ self.sp.clear();
+ plt.figure(self.f.number)
+ plt.subplot(111);
+ self.sp.bar(range(0,len(sorted_work)), map(lambda x: x[1], sorted_work),
+ alpha=0.5)
+ self.sp.set_ylabel("% Runtime");
+ self.sp.set_xticks( map(lambda x: x+0.5, range(0,len(sorted_work))))
+ self.sp.set_xticklabels( map(lambda x: " " + x[0], sorted_work),
+ rotation="vertical", verticalalignment="bottom" )
+
+ self.canvas.draw();
+ self.canvas.show();
+
+class MForm(QtGui.QWidget):
+ def update(self):
+ try:
+
+ nodes = self.G.nodes();
+
+ # get current buffer depths of all output buffers
+ kl = map(lambda x: "%s::%soutput %% full" % \
+ (x, self._statistics_table[self._statistic]),
+ nodes);
+
+ st = time.time()
+ buf_knobs = self.radio.get(kl)
+ td1 = time.time() - st;
+
+ # strip values out of ctrlport response
+ buf_vals = dict(zip(
+ map(lambda x: x.split("::")[0], buf_knobs.keys()),
+ map(lambda x: x.value, buf_knobs.values())))
+
+ # get work time for all blocks
+ kl = map(lambda x: "%s::%swork time" % \
+ (x, self._statistics_table[self._statistic]),
+ nodes);
+ st = time.time()
+ wrk_knobs = self.radio.get(kl)
+ td2 = time.time() - st;
+
+ # strip values out of ctrlport response
+ total_work = sum(map(lambda x: x.value, wrk_knobs.values()))
+ work_times = dict(zip(
+ map(lambda x: x.split("::")[0], wrk_knobs.keys()),
+ map(lambda x: x.value/total_work, wrk_knobs.values())))
+
+ for n in nodes:
+ # ne is the list of edges away from this node!
+ ne = self.G.edges([n],True);
+ for e in ne: # iterate over edges from this block
+ # get the right output buffer/port weight for each edge
+ sourceport = e[2]["sourceport"];
+ newweight = buf_vals[n][sourceport]
+ e[2]["weight"] = newweight;
+
+ # set updated weights
+ self.node_weights = map(lambda x: 20+2000*work_times[x], nodes);
+ self.edge_weights = map(lambda x: 100.0*x[2]["weight"], self.G.edges(data=True));
+
+ # draw graph updates
+ self.updateGraph();
+
+ latency = td1 + td2;
+ self.parent.statusBar().showMessage("Current GNU Radio Control Port Query Latency: %f ms"%\
+ (latency*1000))
+
+ except Exception, e:
+ sys.stderr.write("ctrlport-monitor: radio.get threw exception ({0}).\n".format(e))
+ if(type(self.parent) is MAINWindow):
+ # Find window of connection
+ remove = []
+ for p in self.parent.mdiArea.subWindowList():
+ if self.parent.conns[self.uid] == p.widget():
+ remove.append(p)
+
+ # Remove subwindows for connection and plots
+ for r in remove:
+ self.parent.mdiArea.removeSubWindow(r)
+
+ # Clean up self
+ self.close()
+ else:
+ sys.exit(1)
+ return
+
+ def rtt(self):
+ self.parent.newSubWindow( DataTableRuntimes(self.radio, self.G), "Runtime Table" );
+
+ def bpt(self):
+ self.parent.newSubWindow( DataTableBuffers(self.radio, self.G), "Buffers Table" );
+
+ def stat_changed(self, index):
+ self._statistic = str(self.stattype.currentText())
+
+ def __init__(self, radio=None, port=None, uid=0, parent=None):
+
+ super(MForm, self).__init__()
+
+ if(radio == None or port == None):
+ askinfo = ConInfoDialog(self);
+ if askinfo.exec_():
+ host = str(askinfo.host.text());
+ port = str(askinfo.port.text());
+ radio = parent.interface.getRadio(host, port)
+ else:
+ self.radio = None
+ return
+
+
+ self.uid = uid
+ self.parent = parent
+
+ self.layoutTop = QtGui.QVBoxLayout(self)
+ self.ctlBox = QtGui.QHBoxLayout();
+ self.layout = QtGui.QHBoxLayout()
+
+ self.layoutTop.addLayout(self.ctlBox);
+ self.layoutTop.addLayout(self.layout);
+
+ self.rttAct = QtGui.QAction("Runtime Table",
+ self, statusTip="Runtime Table", triggered=self.rtt)
+ self.rttBut = Qt.QToolButton()
+ self.rttBut.setDefaultAction(self.rttAct);
+ self.ctlBox.addWidget(self.rttBut);
+
+ self.bptAct = QtGui.QAction("Buffer Table",
+ self, statusTip="Buffer Table", triggered=self.bpt)
+ self.bptBut = Qt.QToolButton()
+ self.bptBut.setDefaultAction(self.bptAct);
+ self.ctlBox.addWidget(self.bptBut);
+
+ self._statistic = "Instantaneous"
+ self._statistics_table = {"Instantaneous": "",
+ "Average": "avg ",
+ "Variance": "var "}
+ self.stattype = QtGui.QComboBox()
+ self.stattype.addItem("Instantaneous")
+ self.stattype.addItem("Average")
+ self.stattype.addItem("Variance")
+ self.stattype.setMaximumWidth(200)
+ self.ctlBox.addWidget(self.stattype);
+ self.stattype.currentIndexChanged.connect(self.stat_changed)
+
+# self.setLayout(self.layout);
+
+ self.radio = radio
+ self.knobprops = self.radio.properties([])
+ self.parent.knobprops.append(self.knobprops)
+
+ self.timer = QtCore.QTimer()
+ self.constupdatediv = 0
+ self.tableupdatediv = 0
+ plotsize=250
+
+
+ # Set up the graph of blocks
+ input_name = lambda x: x+"::avg input % full"
+ output_name = lambda x: x+"::avg output % full"
+ wtime_name = lambda x: x+"::avg work time"
+ nout_name = lambda x: x+"::avg noutput_items"
+ nprod_name = lambda x: x+"::avg nproduced"
+
+ tmplist = []
+ knobs = self.radio.get([])
+ edgelist = None
+ for k in knobs:
+ propname = k.split("::")
+ blockname = propname[0]
+ keyname = propname[1]
+ if(keyname == "edge list"):
+ edgelist = knobs[k].value
+ elif(blockname not in tmplist):
+ # only take gr_blocks (no hier_block2)
+ if(knobs.has_key(input_name(blockname))):
+ tmplist.append(blockname)
+
+ if not edgelist:
+ sys.stderr.write("Could not find list of edges from flowgraph. " + \
+ "Make sure the option 'edges_list' is enabled " + \
+ "in the ControlPort configuration.\n\n")
+ sys.exit(1)
+
+ edges = edgelist.split("\n")[0:-1]
+ edgepairs = [];
+ for e in edges:
+ _e = e.split("->")
+ edgepairs.append( (_e[0].split(":")[0], _e[1].split(":")[0],
+ {"sourceport":int(_e[0].split(":")[1])}) );
+
+ self.G = nx.MultiDiGraph();
+ self.G.add_edges_from(edgepairs);
+
+ n_edges = self.G.edges(data=True);
+ for e in n_edges:
+ e[2]["weight"] = 5+random.random()*10;
+
+ self.G.clear();
+ self.G.add_edges_from(n_edges);
+
+
+ self.f = plt.figure(figsize=(10,8), dpi=90)
+ self.sp = self.f.add_subplot(111);
+ self.sp.autoscale_view(True,True,True);
+ self.sp.set_autoscale_on(True)
+
+ self.canvas = FigureCanvas(self.f)
+ self.layout.addWidget(self.canvas);
+
+ self.pos = nx.graphviz_layout(self.G);
+ #self.pos = nx.pygraphviz_layout(self.G);
+ #self.pos = nx.spectral_layout(self.G);
+ #self.pos = nx.circular_layout(self.G);
+ #self.pos = nx.shell_layout(self.G);
+ #self.pos = nx.spring_layout(self.G);
+
+ # generate weights and plot
+ self.update();
+
+ # set up timer
+ self.timer = QtCore.QTimer()
+ self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.update)
+ self.timer.start(1000)
+
+ # Set up mouse callback functions to move blocks around.
+ self._grabbed = False
+ self._current_block = ''
+ self.f.canvas.mpl_connect('button_press_event',
+ self.button_press)
+ self.f.canvas.mpl_connect('motion_notify_event',
+ self.mouse_move)
+ self.f.canvas.mpl_connect('button_release_event',
+ self.button_release)
+
+ def button_press(self, event):
+ x, y = event.xdata, event.ydata
+ thrsh = 100
+
+ if(x is not None and y is not None):
+ nearby = map(lambda z: spatial.distance.euclidean((x,y), z), self.pos.values())
+ i = nearby.index(min(nearby))
+ if(abs(self.pos.values()[i][0] - x) < thrsh and
+ abs(self.pos.values()[i][1]-y) < thrsh):
+ self._current_block = self.pos.keys()[i]
+ #print "MOVING BLOCK: ", self._current_block
+ #print "CUR POS: ", self.pos.values()[i]
+ self._grabbed = True
+
+ def mouse_move(self, event):
+ if self._grabbed:
+ x, y = event.xdata, event.ydata
+ if(x is not None and y is not None):
+ #print "NEW POS: ", (x,y)
+ self.pos[self._current_block] = (x,y)
+ self.updateGraph();
+
+ def button_release(self, event):
+ self._grabbed = False
+
+
+ def openMenu(self, pos):
+ index = self.table.treeWidget.selectedIndexes()
+ item = self.table.treeWidget.itemFromIndex(index[0])
+ itemname = str(item.text(0))
+ self.parent.propertiesMenu(itemname, self.radio, self.uid)
+
+ def updateGraph(self):
+
+ self.canvas.updateGeometry()
+ self.sp.clear();
+ plt.figure(self.f.number)
+ plt.subplot(111);
+ nx.draw(self.G, self.pos,
+ edge_color=self.edge_weights,
+ node_color='#A0CBE2',
+ width=map(lambda x: 3+math.log(x), self.edge_weights),
+ node_shape="s",
+ node_size=self.node_weights,
+ #edge_cmap=plt.cm.Blues,
+ edge_cmap=plt.cm.Reds,
+ ax=self.sp,
+ arrows=False
+ )
+ nx.draw_networkx_labels(self.G, self.pos,
+ font_size=12)
+
+ self.canvas.draw();
+ self.canvas.show();
+
+class MyClient(IceRadioClient):
+ def __init__(self):
+ IceRadioClient.__init__(self, MAINWindow)
+
+sys.exit(MyClient().main(sys.argv))
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/icon.png b/gnuradio-runtime/python/gnuradio/ctrlport/icon.png
new file mode 100644
index 0000000000..4beb204428
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/icon.png
Binary files differ
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py b/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py
new file mode 100644
index 0000000000..53a571a698
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import sys, subprocess, re, signal, time, atexit, os
+from gnuradio import gr
+
+class monitor:
+ def __init__(self):
+ print "ControlPort Monitor running."
+ self.started = False
+ atexit.register(self.shutdown)
+
+ def __del__(self):
+ if(self.started):
+ self.stop()
+
+ def start(self):
+ print "monitor::endpoints() = %s" % (gr.rpcmanager_get().endpoints())
+ try:
+ self.proc = subprocess.Popen(map(lambda a: ["gr-ctrlport-monitor",
+ re.search("\d+\.\d+\.\d+\.\d+",a).group(0),
+ re.search("-p (\d+)",a).group(1)],
+ gr.rpcmanager_get().endpoints())[0])
+ self.started = True
+ except:
+ self.proc = None
+ print "failed to to start ControlPort Monitor on specified port"
+
+ def stop(self):
+ if(self.proc):
+ if(self.proc.returncode == None):
+ print "\tcalling stop on shutdown"
+ self.proc.terminate()
+ else:
+ print "\tno proc to shut down, exiting"
+
+ def shutdown(self):
+ print "ctrlport.monitor received shutdown signal"
+ if(self.started):
+ self.stop()
diff --git a/gnuradio-runtime/python/gnuradio/eng_notation.py b/gnuradio-runtime/python/gnuradio/eng_notation.py
new file mode 100644
index 0000000000..d23f9005f0
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/eng_notation.py
@@ -0,0 +1,74 @@
+#
+# 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.
+#
+"""
+Display numbers as strings using engineering notation.
+"""
+
+scale_factor = {}
+scale_factor['E'] = 1e18
+scale_factor['P'] = 1e15
+scale_factor['T'] = 1e12
+scale_factor['G'] = 1e9
+scale_factor['M'] = 1e6
+scale_factor['k'] = 1e3
+scale_factor['m'] = 1e-3
+scale_factor['u'] = 1e-6
+scale_factor['n'] = 1e-9
+scale_factor['p'] = 1e-12
+scale_factor['f'] = 1e-15
+scale_factor['a'] = 1e-18
+
+def num_to_str (n):
+ '''Convert a number to a string in engineering notation. E.g., 5e-9 -> 5n'''
+ m = abs(n)
+ if m >= 1e9:
+ return "%gG" % (n * 1e-9)
+ elif m >= 1e6:
+ return "%gM" % (n * 1e-6)
+ elif m >= 1e3:
+ return "%gk" % (n * 1e-3)
+ elif m >= 1:
+ return "%g" % (n)
+ elif m >= 1e-3:
+ return "%gm" % (n * 1e3)
+ elif m >= 1e-6:
+ return "%gu" % (n * 1e6) # where's that mu when you need it (unicode?)
+ elif m >= 1e-9:
+ return "%gn" % (n * 1e9)
+ elif m >= 1e-12:
+ return "%gp" % (n * 1e12)
+ elif m >= 1e-15:
+ return "%gf" % (n * 1e15)
+ else:
+ return "%g" % (n)
+
+
+def str_to_num (value):
+ '''Convert a string in engineering notation to a number. E.g., '15m' -> 15e-3'''
+ try:
+ scale = 1.0
+ suffix = value[-1]
+ if scale_factor.has_key (suffix):
+ return float (value[0:-1]) * scale_factor[suffix]
+ return float (value)
+ except:
+ raise RuntimeError (
+ "Invalid engineering notation value: %r" % (value,))
diff --git a/gnuradio-runtime/python/gnuradio/eng_option.py b/gnuradio-runtime/python/gnuradio/eng_option.py
new file mode 100644
index 0000000000..5d8660f0f2
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/eng_option.py
@@ -0,0 +1,63 @@
+#
+# 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.
+#
+
+'''Add support for engineering notation to optparse.OptionParser'''
+
+from copy import copy
+from optparse import Option, OptionValueError
+import eng_notation
+
+def check_eng_float (option, opt, value):
+ try:
+ return eng_notation.str_to_num(value)
+ except:
+ raise OptionValueError (
+ "option %s: invalid engineering notation value: %r" % (opt, value))
+
+def check_intx (option, opt, value):
+ try:
+ return int (value, 0)
+ except:
+ raise OptionValueError (
+ "option %s: invalid integer value: %r" % (opt, value))
+
+def check_subdev (option, opt, value):
+ """
+ Value has the form: (A|B)(:0|1)?
+
+ Returns:
+ a 2-tuple (0|1, 0|1)
+ """
+ d = { 'A' : (0, 0), 'A:0' : (0, 0), 'A:1' : (0, 1), 'A:2' : (0, 2),
+ 'B' : (1, 0), 'B:0' : (1, 0), 'B:1' : (1, 1), 'B:2' : (1, 2) }
+ try:
+ return d[value.upper()]
+ except:
+ raise OptionValueError(
+ "option %s: invalid subdev: '%r', must be one of %s" % (opt, value, ', '.join(sorted(d.keys()))))
+
+class eng_option (Option):
+ TYPES = Option.TYPES + ("eng_float", "intx", "subdev")
+ TYPE_CHECKER = copy (Option.TYPE_CHECKER)
+ TYPE_CHECKER["eng_float"] = check_eng_float
+ TYPE_CHECKER["intx"] = check_intx
+ TYPE_CHECKER["subdev"] = check_subdev
+
diff --git a/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt b/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt
new file mode 100644
index 0000000000..cd57704930
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt
@@ -0,0 +1,46 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+include(GrPython)
+
+GR_PYTHON_INSTALL(FILES
+ __init__.py
+ gateway.py
+ gr_threading.py
+ gr_threading_23.py
+ gr_threading_24.py
+ hier_block2.py
+ tag_utils.py
+ top_block.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/gr
+ COMPONENT "runtime_python"
+)
+
+########################################################################
+# Handle the unit tests
+########################################################################
+if(ENABLE_TESTING)
+include(GrTest)
+file(GLOB py_qa_test_files "qa_*.py")
+foreach(py_qa_test_file ${py_qa_test_files})
+ get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
+ GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+endforeach(py_qa_test_file)
+endif(ENABLE_TESTING)
diff --git a/gnuradio-runtime/python/gnuradio/gr/__init__.py b/gnuradio-runtime/python/gnuradio/gr/__init__.py
new file mode 100644
index 0000000000..c1d6c87629
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/__init__.py
@@ -0,0 +1,39 @@
+#
+# Copyright 2003-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.
+#
+
+# The presence of this file turns this directory into a Python package
+
+"""
+Core contents.
+"""
+
+# This is the main GNU Radio python module.
+# We pull the swig output and the other modules into the gnuradio.gr namespace
+
+from runtime_swig import *
+from exceptions import *
+from top_block import *
+from hier_block2 import *
+from tag_utils import *
+from gateway import basic_block, sync_block, decim_block, interp_block
+
+# Force the preference database to be initialized
+prefs = gr_prefs.singleton
diff --git a/gnuradio-runtime/python/gnuradio/gr/exceptions.py b/gnuradio-runtime/python/gnuradio/gr/exceptions.py
new file mode 100644
index 0000000000..dba04750bc
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/exceptions.py
@@ -0,0 +1,27 @@
+#
+# 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.
+
+class NotDAG (Exception):
+ """Not a directed acyclic graph"""
+ pass
+
+class CantHappen (Exception):
+ """Can't happen"""
+ pass
diff --git a/gnuradio-runtime/python/gnuradio/gr/gateway.py b/gnuradio-runtime/python/gnuradio/gr/gateway.py
new file mode 100644
index 0000000000..b595959494
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/gateway.py
@@ -0,0 +1,243 @@
+#
+# Copyright 2011-2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import runtime_swig as gr
+from runtime_swig import io_signature, io_signaturev
+from runtime_swig import gr_block_gw_message_type
+from runtime_swig import block_gateway
+import numpy
+
+########################################################################
+# Magic to turn pointers into numpy arrays
+# http://docs.scipy.org/doc/numpy/reference/arrays.interface.html
+########################################################################
+def pointer_to_ndarray(addr, dtype, nitems):
+ class array_like:
+ __array_interface__ = {
+ 'data' : (int(addr), False),
+ 'typestr' : dtype.base.str,
+ 'descr' : dtype.base.descr,
+ 'shape' : (nitems,) + dtype.shape,
+ 'strides' : None,
+ 'version' : 3
+ }
+ return numpy.asarray(array_like()).view(dtype.base)
+
+########################################################################
+# Handler that does callbacks from C++
+########################################################################
+class gateway_handler(gr.feval_ll):
+
+ #dont put a constructor, it wont work
+
+ def init(self, callback):
+ self._callback = callback
+
+ def eval(self, arg):
+ try: self._callback()
+ except Exception as ex:
+ print("handler caught exception: %s"%ex)
+ import traceback; traceback.print_exc()
+ raise ex
+ return 0
+
+########################################################################
+# Handler that does callbacks from C++
+########################################################################
+class msg_handler(gr.feval_p):
+
+ #dont put a constructor, it wont work
+
+ def init(self, callback):
+ self._callback = callback
+
+ def eval(self, arg):
+ try: self._callback(arg)
+ except Exception as ex:
+ print("handler caught exception: %s"%ex)
+ import traceback; traceback.print_exc()
+ raise ex
+ return 0
+
+########################################################################
+# The guts that make this into a gr block
+########################################################################
+class gateway_block(object):
+
+ def __init__(self, name, in_sig, out_sig, work_type, factor):
+
+ #ensure that the sigs are iterable dtypes
+ def sig_to_dtype_sig(sig):
+ if sig is None: sig = ()
+ return map(numpy.dtype, sig)
+ self.__in_sig = sig_to_dtype_sig(in_sig)
+ self.__out_sig = sig_to_dtype_sig(out_sig)
+
+ #cache the ranges to iterate when dispatching work
+ self.__in_indexes = range(len(self.__in_sig))
+ self.__out_indexes = range(len(self.__out_sig))
+
+ #convert the signatures into gr.io_signatures
+ def sig_to_gr_io_sigv(sig):
+ if not len(sig): return io_signature(0, 0, 0)
+ return io_signaturev(len(sig), len(sig), [s.itemsize for s in sig])
+ gr_in_sig = sig_to_gr_io_sigv(self.__in_sig)
+ gr_out_sig = sig_to_gr_io_sigv(self.__out_sig)
+
+ #create internal gateway block
+ self.__handler = gateway_handler()
+ self.__handler.init(self.__gr_block_handle)
+ self.__gateway = block_gateway(
+ self.__handler, name, gr_in_sig, gr_out_sig, work_type, factor)
+ self.__message = self.__gateway.gr_block_message()
+
+ #dict to keep references to all message handlers
+ self.__msg_handlers = {}
+
+ #register gr_block functions
+ prefix = 'gr_block__'
+ for attr in [x for x in dir(self.__gateway) if x.startswith(prefix)]:
+ setattr(self, attr.replace(prefix, ''), getattr(self.__gateway, attr))
+ self.pop_msg_queue = lambda: gr.gr_block_gw_pop_msg_queue_safe(self.__gateway)
+
+ def to_basic_block(self):
+ """
+ Makes this block connectable by hier/top block python
+ """
+ return self.__gateway.to_basic_block()
+
+ def __gr_block_handle(self):
+ """
+ Dispatch tasks according to the action type specified in the message.
+ """
+ if self.__message.action == gr_block_gw_message_type.ACTION_GENERAL_WORK:
+ self.__message.general_work_args_return_value = self.general_work(
+
+ input_items=[pointer_to_ndarray(
+ self.__message.general_work_args_input_items[i],
+ self.__in_sig[i],
+ self.__message.general_work_args_ninput_items[i]
+ ) for i in self.__in_indexes],
+
+ output_items=[pointer_to_ndarray(
+ self.__message.general_work_args_output_items[i],
+ self.__out_sig[i],
+ self.__message.general_work_args_noutput_items
+ ) for i in self.__out_indexes],
+ )
+
+ elif self.__message.action == gr_block_gw_message_type.ACTION_WORK:
+ self.__message.work_args_return_value = self.work(
+
+ input_items=[pointer_to_ndarray(
+ self.__message.work_args_input_items[i],
+ self.__in_sig[i],
+ self.__message.work_args_ninput_items
+ ) for i in self.__in_indexes],
+
+ output_items=[pointer_to_ndarray(
+ self.__message.work_args_output_items[i],
+ self.__out_sig[i],
+ self.__message.work_args_noutput_items
+ ) for i in self.__out_indexes],
+ )
+
+ elif self.__message.action == gr_block_gw_message_type.ACTION_FORECAST:
+ self.forecast(
+ noutput_items=self.__message.forecast_args_noutput_items,
+ ninput_items_required=self.__message.forecast_args_ninput_items_required,
+ )
+
+ elif self.__message.action == gr_block_gw_message_type.ACTION_START:
+ self.__message.start_args_return_value = self.start()
+
+ elif self.__message.action == gr_block_gw_message_type.ACTION_STOP:
+ self.__message.stop_args_return_value = self.stop()
+
+ def forecast(self, noutput_items, ninput_items_required):
+ """
+ forecast is only called from a general block
+ this is the default implementation
+ """
+ for ninput_item in ninput_items_required:
+ ninput_item = noutput_items + self.history() - 1;
+ return
+
+ def general_work(self, *args, **kwargs):
+ """general work to be overloaded in a derived class"""
+ raise NotImplementedError("general work not implemented")
+
+ def work(self, *args, **kwargs):
+ """work to be overloaded in a derived class"""
+ raise NotImplementedError("work not implemented")
+
+ def start(self): return True
+ def stop(self): return True
+
+ def set_msg_handler(self, which_port, handler_func):
+ handler = msg_handler()
+ handler.init(handler_func)
+ self.__gateway.set_msg_handler_feval(which_port, handler)
+ # Save handler object in class so it's not garbage collected
+ self.__msg_handlers[which_port] = handler
+
+########################################################################
+# Wrappers for the user to inherit from
+########################################################################
+class basic_block(gateway_block):
+ def __init__(self, name, in_sig, out_sig):
+ gateway_block.__init__(self,
+ name=name,
+ in_sig=in_sig,
+ out_sig=out_sig,
+ work_type=gr.GR_BLOCK_GW_WORK_GENERAL,
+ factor=1, #not relevant factor
+ )
+
+class sync_block(gateway_block):
+ def __init__(self, name, in_sig, out_sig):
+ gateway_block.__init__(self,
+ name=name,
+ in_sig=in_sig,
+ out_sig=out_sig,
+ work_type=gr.GR_BLOCK_GW_WORK_SYNC,
+ factor=1,
+ )
+
+class decim_block(gateway_block):
+ def __init__(self, name, in_sig, out_sig, decim):
+ gateway_block.__init__(self,
+ name=name,
+ in_sig=in_sig,
+ out_sig=out_sig,
+ work_type=gr.GR_BLOCK_GW_WORK_DECIM,
+ factor=decim,
+ )
+
+class interp_block(gateway_block):
+ def __init__(self, name, in_sig, out_sig, interp):
+ gateway_block.__init__(self,
+ name=name,
+ in_sig=in_sig,
+ out_sig=out_sig,
+ work_type=gr.GR_BLOCK_GW_WORK_INTERP,
+ factor=interp,
+ )
diff --git a/gnuradio-runtime/python/gnuradio/gr/gr_threading.py b/gnuradio-runtime/python/gnuradio/gr/gr_threading.py
new file mode 100644
index 0000000000..5d6f0fdaf9
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/gr_threading.py
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+from sys import version_info as _version_info
+
+# import patched version of standard threading module
+
+if _version_info[0:2] == (2, 3):
+ #print "Importing gr_threading_23"
+ from gr_threading_23 import *
+elif _version_info[0:2] == (2, 4):
+ #print "Importing gr_threading_24"
+ from gr_threading_24 import *
+else:
+ # assume the patch was applied...
+ #print "Importing system provided threading"
+ from threading import *
diff --git a/gnuradio-runtime/python/gnuradio/gr/gr_threading_23.py b/gnuradio-runtime/python/gnuradio/gr/gr_threading_23.py
new file mode 100644
index 0000000000..dee8034c1c
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/gr_threading_23.py
@@ -0,0 +1,724 @@
+"""Thread module emulating a subset of Java's threading model."""
+
+# This started life as the threading.py module of Python 2.3
+# It's been patched to fix a problem with join, where a KeyboardInterrupt
+# caused a lock to be left in the acquired state.
+
+import sys as _sys
+
+try:
+ import thread
+except ImportError:
+ del _sys.modules[__name__]
+ raise
+
+from StringIO import StringIO as _StringIO
+from time import time as _time, sleep as _sleep
+from traceback import print_exc as _print_exc
+
+# Rename some stuff so "from threading import *" is safe
+__all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event',
+ 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread',
+ 'Timer', 'setprofile', 'settrace']
+
+_start_new_thread = thread.start_new_thread
+_allocate_lock = thread.allocate_lock
+_get_ident = thread.get_ident
+ThreadError = thread.error
+del thread
+
+
+# Debug support (adapted from ihooks.py).
+# All the major classes here derive from _Verbose. We force that to
+# be a new-style class so that all the major classes here are new-style.
+# This helps debugging (type(instance) is more revealing for instances
+# of new-style classes).
+
+_VERBOSE = False
+
+if __debug__:
+
+ class _Verbose(object):
+
+ def __init__(self, verbose=None):
+ if verbose is None:
+ verbose = _VERBOSE
+ self.__verbose = verbose
+
+ def _note(self, format, *args):
+ if self.__verbose:
+ format = format % args
+ format = "%s: %s\n" % (
+ currentThread().getName(), format)
+ _sys.stderr.write(format)
+
+else:
+ # Disable this when using "python -O"
+ class _Verbose(object):
+ def __init__(self, verbose=None):
+ pass
+ def _note(self, *args):
+ pass
+
+# Support for profile and trace hooks
+
+_profile_hook = None
+_trace_hook = None
+
+def setprofile(func):
+ global _profile_hook
+ _profile_hook = func
+
+def settrace(func):
+ global _trace_hook
+ _trace_hook = func
+
+# Synchronization classes
+
+Lock = _allocate_lock
+
+def RLock(*args, **kwargs):
+ return _RLock(*args, **kwargs)
+
+class _RLock(_Verbose):
+
+ def __init__(self, verbose=None):
+ _Verbose.__init__(self, verbose)
+ self.__block = _allocate_lock()
+ self.__owner = None
+ self.__count = 0
+
+ def __repr__(self):
+ return "<%s(%s, %d)>" % (
+ self.__class__.__name__,
+ self.__owner and self.__owner.getName(),
+ self.__count)
+
+ def acquire(self, blocking=1):
+ me = currentThread()
+ if self.__owner is me:
+ self.__count = self.__count + 1
+ if __debug__:
+ self._note("%s.acquire(%s): recursive success", self, blocking)
+ return 1
+ rc = self.__block.acquire(blocking)
+ if rc:
+ self.__owner = me
+ self.__count = 1
+ if __debug__:
+ self._note("%s.acquire(%s): initial succes", self, blocking)
+ else:
+ if __debug__:
+ self._note("%s.acquire(%s): failure", self, blocking)
+ return rc
+
+ def release(self):
+ me = currentThread()
+ assert self.__owner is me, "release() of un-acquire()d lock"
+ self.__count = count = self.__count - 1
+ if not count:
+ self.__owner = None
+ self.__block.release()
+ if __debug__:
+ self._note("%s.release(): final release", self)
+ else:
+ if __debug__:
+ self._note("%s.release(): non-final release", self)
+
+ # Internal methods used by condition variables
+
+ def _acquire_restore(self, (count, owner)):
+ self.__block.acquire()
+ self.__count = count
+ self.__owner = owner
+ if __debug__:
+ self._note("%s._acquire_restore()", self)
+
+ def _release_save(self):
+ if __debug__:
+ self._note("%s._release_save()", self)
+ count = self.__count
+ self.__count = 0
+ owner = self.__owner
+ self.__owner = None
+ self.__block.release()
+ return (count, owner)
+
+ def _is_owned(self):
+ return self.__owner is currentThread()
+
+
+def Condition(*args, **kwargs):
+ return _Condition(*args, **kwargs)
+
+class _Condition(_Verbose):
+
+ def __init__(self, lock=None, verbose=None):
+ _Verbose.__init__(self, verbose)
+ if lock is None:
+ lock = RLock()
+ self.__lock = lock
+ # Export the lock's acquire() and release() methods
+ self.acquire = lock.acquire
+ self.release = lock.release
+ # If the lock defines _release_save() and/or _acquire_restore(),
+ # these override the default implementations (which just call
+ # release() and acquire() on the lock). Ditto for _is_owned().
+ try:
+ self._release_save = lock._release_save
+ except AttributeError:
+ pass
+ try:
+ self._acquire_restore = lock._acquire_restore
+ except AttributeError:
+ pass
+ try:
+ self._is_owned = lock._is_owned
+ except AttributeError:
+ pass
+ self.__waiters = []
+
+ def __repr__(self):
+ return "<Condition(%s, %d)>" % (self.__lock, len(self.__waiters))
+
+ def _release_save(self):
+ self.__lock.release() # No state to save
+
+ def _acquire_restore(self, x):
+ self.__lock.acquire() # Ignore saved state
+
+ def _is_owned(self):
+ # Return True if lock is owned by currentThread.
+ # This method is called only if __lock doesn't have _is_owned().
+ if self.__lock.acquire(0):
+ self.__lock.release()
+ return False
+ else:
+ return True
+
+ def wait(self, timeout=None):
+ currentThread() # for side-effect
+ assert self._is_owned(), "wait() of un-acquire()d lock"
+ waiter = _allocate_lock()
+ waiter.acquire()
+ self.__waiters.append(waiter)
+ saved_state = self._release_save()
+ try: # restore state no matter what (e.g., KeyboardInterrupt)
+ if timeout is None:
+ waiter.acquire()
+ if __debug__:
+ self._note("%s.wait(): got it", self)
+ else:
+ # Balancing act: We can't afford a pure busy loop, so we
+ # have to sleep; but if we sleep the whole timeout time,
+ # we'll be unresponsive. The scheme here sleeps very
+ # little at first, longer as time goes on, but never longer
+ # than 20 times per second (or the timeout time remaining).
+ endtime = _time() + timeout
+ delay = 0.0005 # 500 us -> initial delay of 1 ms
+ while True:
+ gotit = waiter.acquire(0)
+ if gotit:
+ break
+ remaining = endtime - _time()
+ if remaining <= 0:
+ break
+ delay = min(delay * 2, remaining, .05)
+ _sleep(delay)
+ if not gotit:
+ if __debug__:
+ self._note("%s.wait(%s): timed out", self, timeout)
+ try:
+ self.__waiters.remove(waiter)
+ except ValueError:
+ pass
+ else:
+ if __debug__:
+ self._note("%s.wait(%s): got it", self, timeout)
+ finally:
+ self._acquire_restore(saved_state)
+
+ def notify(self, n=1):
+ currentThread() # for side-effect
+ assert self._is_owned(), "notify() of un-acquire()d lock"
+ __waiters = self.__waiters
+ waiters = __waiters[:n]
+ if not waiters:
+ if __debug__:
+ self._note("%s.notify(): no waiters", self)
+ return
+ self._note("%s.notify(): notifying %d waiter%s", self, n,
+ n!=1 and "s" or "")
+ for waiter in waiters:
+ waiter.release()
+ try:
+ __waiters.remove(waiter)
+ except ValueError:
+ pass
+
+ def notifyAll(self):
+ self.notify(len(self.__waiters))
+
+
+def Semaphore(*args, **kwargs):
+ return _Semaphore(*args, **kwargs)
+
+class _Semaphore(_Verbose):
+
+ # After Tim Peters' semaphore class, but not quite the same (no maximum)
+
+ def __init__(self, value=1, verbose=None):
+ assert value >= 0, "Semaphore initial value must be >= 0"
+ _Verbose.__init__(self, verbose)
+ self.__cond = Condition(Lock())
+ self.__value = value
+
+ def acquire(self, blocking=1):
+ rc = False
+ self.__cond.acquire()
+ while self.__value == 0:
+ if not blocking:
+ break
+ if __debug__:
+ self._note("%s.acquire(%s): blocked waiting, value=%s",
+ self, blocking, self.__value)
+ self.__cond.wait()
+ else:
+ self.__value = self.__value - 1
+ if __debug__:
+ self._note("%s.acquire: success, value=%s",
+ self, self.__value)
+ rc = True
+ self.__cond.release()
+ return rc
+
+ def release(self):
+ self.__cond.acquire()
+ self.__value = self.__value + 1
+ if __debug__:
+ self._note("%s.release: success, value=%s",
+ self, self.__value)
+ self.__cond.notify()
+ self.__cond.release()
+
+
+def BoundedSemaphore(*args, **kwargs):
+ return _BoundedSemaphore(*args, **kwargs)
+
+class _BoundedSemaphore(_Semaphore):
+ """Semaphore that checks that # releases is <= # acquires"""
+ def __init__(self, value=1, verbose=None):
+ _Semaphore.__init__(self, value, verbose)
+ self._initial_value = value
+
+ def release(self):
+ if self._Semaphore__value >= self._initial_value:
+ raise ValueError, "Semaphore released too many times"
+ return _Semaphore.release(self)
+
+
+def Event(*args, **kwargs):
+ return _Event(*args, **kwargs)
+
+class _Event(_Verbose):
+
+ # After Tim Peters' event class (without is_posted())
+
+ def __init__(self, verbose=None):
+ _Verbose.__init__(self, verbose)
+ self.__cond = Condition(Lock())
+ self.__flag = False
+
+ def isSet(self):
+ return self.__flag
+
+ def set(self):
+ self.__cond.acquire()
+ try:
+ self.__flag = True
+ self.__cond.notifyAll()
+ finally:
+ self.__cond.release()
+
+ def clear(self):
+ self.__cond.acquire()
+ try:
+ self.__flag = False
+ finally:
+ self.__cond.release()
+
+ def wait(self, timeout=None):
+ self.__cond.acquire()
+ try:
+ if not self.__flag:
+ self.__cond.wait(timeout)
+ finally:
+ self.__cond.release()
+
+# Helper to generate new thread names
+_counter = 0
+def _newname(template="Thread-%d"):
+ global _counter
+ _counter = _counter + 1
+ return template % _counter
+
+# Active thread administration
+_active_limbo_lock = _allocate_lock()
+_active = {}
+_limbo = {}
+
+
+# Main class for threads
+
+class Thread(_Verbose):
+
+ __initialized = False
+
+ def __init__(self, group=None, target=None, name=None,
+ args=(), kwargs={}, verbose=None):
+ assert group is None, "group argument must be None for now"
+ _Verbose.__init__(self, verbose)
+ self.__target = target
+ self.__name = str(name or _newname())
+ self.__args = args
+ self.__kwargs = kwargs
+ self.__daemonic = self._set_daemon()
+ self.__started = False
+ self.__stopped = False
+ self.__block = Condition(Lock())
+ self.__initialized = True
+
+ def _set_daemon(self):
+ # Overridden in _MainThread and _DummyThread
+ return currentThread().isDaemon()
+
+ def __repr__(self):
+ assert self.__initialized, "Thread.__init__() was not called"
+ status = "initial"
+ if self.__started:
+ status = "started"
+ if self.__stopped:
+ status = "stopped"
+ if self.__daemonic:
+ status = status + " daemon"
+ return "<%s(%s, %s)>" % (self.__class__.__name__, self.__name, status)
+
+ def start(self):
+ assert self.__initialized, "Thread.__init__() not called"
+ assert not self.__started, "thread already started"
+ if __debug__:
+ self._note("%s.start(): starting thread", self)
+ _active_limbo_lock.acquire()
+ _limbo[self] = self
+ _active_limbo_lock.release()
+ _start_new_thread(self.__bootstrap, ())
+ self.__started = True
+ _sleep(0.000001) # 1 usec, to let the thread run (Solaris hack)
+
+ def run(self):
+ if self.__target:
+ self.__target(*self.__args, **self.__kwargs)
+
+ def __bootstrap(self):
+ try:
+ self.__started = True
+ _active_limbo_lock.acquire()
+ _active[_get_ident()] = self
+ del _limbo[self]
+ _active_limbo_lock.release()
+ if __debug__:
+ self._note("%s.__bootstrap(): thread started", self)
+
+ if _trace_hook:
+ self._note("%s.__bootstrap(): registering trace hook", self)
+ _sys.settrace(_trace_hook)
+ if _profile_hook:
+ self._note("%s.__bootstrap(): registering profile hook", self)
+ _sys.setprofile(_profile_hook)
+
+ try:
+ self.run()
+ except SystemExit:
+ if __debug__:
+ self._note("%s.__bootstrap(): raised SystemExit", self)
+ except:
+ if __debug__:
+ self._note("%s.__bootstrap(): unhandled exception", self)
+ s = _StringIO()
+ _print_exc(file=s)
+ _sys.stderr.write("Exception in thread %s:\n%s\n" %
+ (self.getName(), s.getvalue()))
+ else:
+ if __debug__:
+ self._note("%s.__bootstrap(): normal return", self)
+ finally:
+ self.__stop()
+ try:
+ self.__delete()
+ except:
+ pass
+
+ def __stop(self):
+ self.__block.acquire()
+ self.__stopped = True
+ self.__block.notifyAll()
+ self.__block.release()
+
+ def __delete(self):
+ _active_limbo_lock.acquire()
+ del _active[_get_ident()]
+ _active_limbo_lock.release()
+
+ def join(self, timeout=None):
+ assert self.__initialized, "Thread.__init__() not called"
+ assert self.__started, "cannot join thread before it is started"
+ assert self is not currentThread(), "cannot join current thread"
+ if __debug__:
+ if not self.__stopped:
+ self._note("%s.join(): waiting until thread stops", self)
+ self.__block.acquire()
+ try:
+ if timeout is None:
+ while not self.__stopped:
+ self.__block.wait()
+ if __debug__:
+ self._note("%s.join(): thread stopped", self)
+ else:
+ deadline = _time() + timeout
+ while not self.__stopped:
+ delay = deadline - _time()
+ if delay <= 0:
+ if __debug__:
+ self._note("%s.join(): timed out", self)
+ break
+ self.__block.wait(delay)
+ else:
+ if __debug__:
+ self._note("%s.join(): thread stopped", self)
+ finally:
+ self.__block.release()
+
+ def getName(self):
+ assert self.__initialized, "Thread.__init__() not called"
+ return self.__name
+
+ def setName(self, name):
+ assert self.__initialized, "Thread.__init__() not called"
+ self.__name = str(name)
+
+ def isAlive(self):
+ assert self.__initialized, "Thread.__init__() not called"
+ return self.__started and not self.__stopped
+
+ def isDaemon(self):
+ assert self.__initialized, "Thread.__init__() not called"
+ return self.__daemonic
+
+ def setDaemon(self, daemonic):
+ assert self.__initialized, "Thread.__init__() not called"
+ assert not self.__started, "cannot set daemon status of active thread"
+ self.__daemonic = daemonic
+
+# The timer class was contributed by Itamar Shtull-Trauring
+
+def Timer(*args, **kwargs):
+ return _Timer(*args, **kwargs)
+
+class _Timer(Thread):
+ """Call a function after a specified number of seconds:
+
+ t = Timer(30.0, f, args=[], kwargs={})
+ t.start()
+ t.cancel() # stop the timer's action if it's still waiting
+ """
+
+ def __init__(self, interval, function, args=[], kwargs={}):
+ Thread.__init__(self)
+ self.interval = interval
+ self.function = function
+ self.args = args
+ self.kwargs = kwargs
+ self.finished = Event()
+
+ def cancel(self):
+ """Stop the timer if it hasn't finished yet"""
+ self.finished.set()
+
+ def run(self):
+ self.finished.wait(self.interval)
+ if not self.finished.isSet():
+ self.function(*self.args, **self.kwargs)
+ self.finished.set()
+
+# Special thread class to represent the main thread
+# This is garbage collected through an exit handler
+
+class _MainThread(Thread):
+
+ def __init__(self):
+ Thread.__init__(self, name="MainThread")
+ self._Thread__started = True
+ _active_limbo_lock.acquire()
+ _active[_get_ident()] = self
+ _active_limbo_lock.release()
+ import atexit
+ atexit.register(self.__exitfunc)
+
+ def _set_daemon(self):
+ return False
+
+ def __exitfunc(self):
+ self._Thread__stop()
+ t = _pickSomeNonDaemonThread()
+ if t:
+ if __debug__:
+ self._note("%s: waiting for other threads", self)
+ while t:
+ t.join()
+ t = _pickSomeNonDaemonThread()
+ if __debug__:
+ self._note("%s: exiting", self)
+ self._Thread__delete()
+
+def _pickSomeNonDaemonThread():
+ for t in enumerate():
+ if not t.isDaemon() and t.isAlive():
+ return t
+ return None
+
+
+# Dummy thread class to represent threads not started here.
+# These aren't garbage collected when they die,
+# nor can they be waited for.
+# Their purpose is to return *something* from currentThread().
+# They are marked as daemon threads so we won't wait for them
+# when we exit (conform previous semantics).
+
+class _DummyThread(Thread):
+
+ def __init__(self):
+ Thread.__init__(self, name=_newname("Dummy-%d"))
+ self._Thread__started = True
+ _active_limbo_lock.acquire()
+ _active[_get_ident()] = self
+ _active_limbo_lock.release()
+
+ def _set_daemon(self):
+ return True
+
+ def join(self, timeout=None):
+ assert False, "cannot join a dummy thread"
+
+
+# Global API functions
+
+def currentThread():
+ try:
+ return _active[_get_ident()]
+ except KeyError:
+ ##print "currentThread(): no current thread for", _get_ident()
+ return _DummyThread()
+
+def activeCount():
+ _active_limbo_lock.acquire()
+ count = len(_active) + len(_limbo)
+ _active_limbo_lock.release()
+ return count
+
+def enumerate():
+ _active_limbo_lock.acquire()
+ active = _active.values() + _limbo.values()
+ _active_limbo_lock.release()
+ return active
+
+# Create the main thread object
+
+_MainThread()
+
+
+# Self-test code
+
+def _test():
+
+ class BoundedQueue(_Verbose):
+
+ def __init__(self, limit):
+ _Verbose.__init__(self)
+ self.mon = RLock()
+ self.rc = Condition(self.mon)
+ self.wc = Condition(self.mon)
+ self.limit = limit
+ self.queue = []
+
+ def put(self, item):
+ self.mon.acquire()
+ while len(self.queue) >= self.limit:
+ self._note("put(%s): queue full", item)
+ self.wc.wait()
+ self.queue.append(item)
+ self._note("put(%s): appended, length now %d",
+ item, len(self.queue))
+ self.rc.notify()
+ self.mon.release()
+
+ def get(self):
+ self.mon.acquire()
+ while not self.queue:
+ self._note("get(): queue empty")
+ self.rc.wait()
+ item = self.queue.pop(0)
+ self._note("get(): got %s, %d left", item, len(self.queue))
+ self.wc.notify()
+ self.mon.release()
+ return item
+
+ class ProducerThread(Thread):
+
+ def __init__(self, queue, quota):
+ Thread.__init__(self, name="Producer")
+ self.queue = queue
+ self.quota = quota
+
+ def run(self):
+ from random import random
+ counter = 0
+ while counter < self.quota:
+ counter = counter + 1
+ self.queue.put("%s.%d" % (self.getName(), counter))
+ _sleep(random() * 0.00001)
+
+
+ class ConsumerThread(Thread):
+
+ def __init__(self, queue, count):
+ Thread.__init__(self, name="Consumer")
+ self.queue = queue
+ self.count = count
+
+ def run(self):
+ while self.count > 0:
+ item = self.queue.get()
+ print item
+ self.count = self.count - 1
+
+ NP = 3
+ QL = 4
+ NI = 5
+
+ Q = BoundedQueue(QL)
+ P = []
+ for i in range(NP):
+ t = ProducerThread(Q, NI)
+ t.setName("Producer-%d" % (i+1))
+ P.append(t)
+ C = ConsumerThread(Q, NI*NP)
+ for t in P:
+ t.start()
+ _sleep(0.000001)
+ C.start()
+ for t in P:
+ t.join()
+ C.join()
+
+if __name__ == '__main__':
+ _test()
diff --git a/gnuradio-runtime/python/gnuradio/gr/gr_threading_24.py b/gnuradio-runtime/python/gnuradio/gr/gr_threading_24.py
new file mode 100644
index 0000000000..8539bfc047
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/gr_threading_24.py
@@ -0,0 +1,793 @@
+"""Thread module emulating a subset of Java's threading model."""
+
+# This started life as the threading.py module of Python 2.4
+# It's been patched to fix a problem with join, where a KeyboardInterrupt
+# caused a lock to be left in the acquired state.
+
+import sys as _sys
+
+try:
+ import thread
+except ImportError:
+ del _sys.modules[__name__]
+ raise
+
+from time import time as _time, sleep as _sleep
+from traceback import format_exc as _format_exc
+from collections import deque
+
+# Rename some stuff so "from threading import *" is safe
+__all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event',
+ 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread',
+ 'Timer', 'setprofile', 'settrace', 'local']
+
+_start_new_thread = thread.start_new_thread
+_allocate_lock = thread.allocate_lock
+_get_ident = thread.get_ident
+ThreadError = thread.error
+del thread
+
+
+# Debug support (adapted from ihooks.py).
+# All the major classes here derive from _Verbose. We force that to
+# be a new-style class so that all the major classes here are new-style.
+# This helps debugging (type(instance) is more revealing for instances
+# of new-style classes).
+
+_VERBOSE = False
+
+if __debug__:
+
+ class _Verbose(object):
+
+ def __init__(self, verbose=None):
+ if verbose is None:
+ verbose = _VERBOSE
+ self.__verbose = verbose
+
+ def _note(self, format, *args):
+ if self.__verbose:
+ format = format % args
+ format = "%s: %s\n" % (
+ currentThread().getName(), format)
+ _sys.stderr.write(format)
+
+else:
+ # Disable this when using "python -O"
+ class _Verbose(object):
+ def __init__(self, verbose=None):
+ pass
+ def _note(self, *args):
+ pass
+
+# Support for profile and trace hooks
+
+_profile_hook = None
+_trace_hook = None
+
+def setprofile(func):
+ global _profile_hook
+ _profile_hook = func
+
+def settrace(func):
+ global _trace_hook
+ _trace_hook = func
+
+# Synchronization classes
+
+Lock = _allocate_lock
+
+def RLock(*args, **kwargs):
+ return _RLock(*args, **kwargs)
+
+class _RLock(_Verbose):
+
+ def __init__(self, verbose=None):
+ _Verbose.__init__(self, verbose)
+ self.__block = _allocate_lock()
+ self.__owner = None
+ self.__count = 0
+
+ def __repr__(self):
+ return "<%s(%s, %d)>" % (
+ self.__class__.__name__,
+ self.__owner and self.__owner.getName(),
+ self.__count)
+
+ def acquire(self, blocking=1):
+ me = currentThread()
+ if self.__owner is me:
+ self.__count = self.__count + 1
+ if __debug__:
+ self._note("%s.acquire(%s): recursive success", self, blocking)
+ return 1
+ rc = self.__block.acquire(blocking)
+ if rc:
+ self.__owner = me
+ self.__count = 1
+ if __debug__:
+ self._note("%s.acquire(%s): initial succes", self, blocking)
+ else:
+ if __debug__:
+ self._note("%s.acquire(%s): failure", self, blocking)
+ return rc
+
+ def release(self):
+ me = currentThread()
+ assert self.__owner is me, "release() of un-acquire()d lock"
+ self.__count = count = self.__count - 1
+ if not count:
+ self.__owner = None
+ self.__block.release()
+ if __debug__:
+ self._note("%s.release(): final release", self)
+ else:
+ if __debug__:
+ self._note("%s.release(): non-final release", self)
+
+ # Internal methods used by condition variables
+
+ def _acquire_restore(self, (count, owner)):
+ self.__block.acquire()
+ self.__count = count
+ self.__owner = owner
+ if __debug__:
+ self._note("%s._acquire_restore()", self)
+
+ def _release_save(self):
+ if __debug__:
+ self._note("%s._release_save()", self)
+ count = self.__count
+ self.__count = 0
+ owner = self.__owner
+ self.__owner = None
+ self.__block.release()
+ return (count, owner)
+
+ def _is_owned(self):
+ return self.__owner is currentThread()
+
+
+def Condition(*args, **kwargs):
+ return _Condition(*args, **kwargs)
+
+class _Condition(_Verbose):
+
+ def __init__(self, lock=None, verbose=None):
+ _Verbose.__init__(self, verbose)
+ if lock is None:
+ lock = RLock()
+ self.__lock = lock
+ # Export the lock's acquire() and release() methods
+ self.acquire = lock.acquire
+ self.release = lock.release
+ # If the lock defines _release_save() and/or _acquire_restore(),
+ # these override the default implementations (which just call
+ # release() and acquire() on the lock). Ditto for _is_owned().
+ try:
+ self._release_save = lock._release_save
+ except AttributeError:
+ pass
+ try:
+ self._acquire_restore = lock._acquire_restore
+ except AttributeError:
+ pass
+ try:
+ self._is_owned = lock._is_owned
+ except AttributeError:
+ pass
+ self.__waiters = []
+
+ def __repr__(self):
+ return "<Condition(%s, %d)>" % (self.__lock, len(self.__waiters))
+
+ def _release_save(self):
+ self.__lock.release() # No state to save
+
+ def _acquire_restore(self, x):
+ self.__lock.acquire() # Ignore saved state
+
+ def _is_owned(self):
+ # Return True if lock is owned by currentThread.
+ # This method is called only if __lock doesn't have _is_owned().
+ if self.__lock.acquire(0):
+ self.__lock.release()
+ return False
+ else:
+ return True
+
+ def wait(self, timeout=None):
+ assert self._is_owned(), "wait() of un-acquire()d lock"
+ waiter = _allocate_lock()
+ waiter.acquire()
+ self.__waiters.append(waiter)
+ saved_state = self._release_save()
+ try: # restore state no matter what (e.g., KeyboardInterrupt)
+ if timeout is None:
+ waiter.acquire()
+ if __debug__:
+ self._note("%s.wait(): got it", self)
+ else:
+ # Balancing act: We can't afford a pure busy loop, so we
+ # have to sleep; but if we sleep the whole timeout time,
+ # we'll be unresponsive. The scheme here sleeps very
+ # little at first, longer as time goes on, but never longer
+ # than 20 times per second (or the timeout time remaining).
+ endtime = _time() + timeout
+ delay = 0.0005 # 500 us -> initial delay of 1 ms
+ while True:
+ gotit = waiter.acquire(0)
+ if gotit:
+ break
+ remaining = endtime - _time()
+ if remaining <= 0:
+ break
+ delay = min(delay * 2, remaining, .05)
+ _sleep(delay)
+ if not gotit:
+ if __debug__:
+ self._note("%s.wait(%s): timed out", self, timeout)
+ try:
+ self.__waiters.remove(waiter)
+ except ValueError:
+ pass
+ else:
+ if __debug__:
+ self._note("%s.wait(%s): got it", self, timeout)
+ finally:
+ self._acquire_restore(saved_state)
+
+ def notify(self, n=1):
+ assert self._is_owned(), "notify() of un-acquire()d lock"
+ __waiters = self.__waiters
+ waiters = __waiters[:n]
+ if not waiters:
+ if __debug__:
+ self._note("%s.notify(): no waiters", self)
+ return
+ self._note("%s.notify(): notifying %d waiter%s", self, n,
+ n!=1 and "s" or "")
+ for waiter in waiters:
+ waiter.release()
+ try:
+ __waiters.remove(waiter)
+ except ValueError:
+ pass
+
+ def notifyAll(self):
+ self.notify(len(self.__waiters))
+
+
+def Semaphore(*args, **kwargs):
+ return _Semaphore(*args, **kwargs)
+
+class _Semaphore(_Verbose):
+
+ # After Tim Peters' semaphore class, but not quite the same (no maximum)
+
+ def __init__(self, value=1, verbose=None):
+ assert value >= 0, "Semaphore initial value must be >= 0"
+ _Verbose.__init__(self, verbose)
+ self.__cond = Condition(Lock())
+ self.__value = value
+
+ def acquire(self, blocking=1):
+ rc = False
+ self.__cond.acquire()
+ while self.__value == 0:
+ if not blocking:
+ break
+ if __debug__:
+ self._note("%s.acquire(%s): blocked waiting, value=%s",
+ self, blocking, self.__value)
+ self.__cond.wait()
+ else:
+ self.__value = self.__value - 1
+ if __debug__:
+ self._note("%s.acquire: success, value=%s",
+ self, self.__value)
+ rc = True
+ self.__cond.release()
+ return rc
+
+ def release(self):
+ self.__cond.acquire()
+ self.__value = self.__value + 1
+ if __debug__:
+ self._note("%s.release: success, value=%s",
+ self, self.__value)
+ self.__cond.notify()
+ self.__cond.release()
+
+
+def BoundedSemaphore(*args, **kwargs):
+ return _BoundedSemaphore(*args, **kwargs)
+
+class _BoundedSemaphore(_Semaphore):
+ """Semaphore that checks that # releases is <= # acquires"""
+ def __init__(self, value=1, verbose=None):
+ _Semaphore.__init__(self, value, verbose)
+ self._initial_value = value
+
+ def release(self):
+ if self._Semaphore__value >= self._initial_value:
+ raise ValueError, "Semaphore released too many times"
+ return _Semaphore.release(self)
+
+
+def Event(*args, **kwargs):
+ return _Event(*args, **kwargs)
+
+class _Event(_Verbose):
+
+ # After Tim Peters' event class (without is_posted())
+
+ def __init__(self, verbose=None):
+ _Verbose.__init__(self, verbose)
+ self.__cond = Condition(Lock())
+ self.__flag = False
+
+ def isSet(self):
+ return self.__flag
+
+ def set(self):
+ self.__cond.acquire()
+ try:
+ self.__flag = True
+ self.__cond.notifyAll()
+ finally:
+ self.__cond.release()
+
+ def clear(self):
+ self.__cond.acquire()
+ try:
+ self.__flag = False
+ finally:
+ self.__cond.release()
+
+ def wait(self, timeout=None):
+ self.__cond.acquire()
+ try:
+ if not self.__flag:
+ self.__cond.wait(timeout)
+ finally:
+ self.__cond.release()
+
+# Helper to generate new thread names
+_counter = 0
+def _newname(template="Thread-%d"):
+ global _counter
+ _counter = _counter + 1
+ return template % _counter
+
+# Active thread administration
+_active_limbo_lock = _allocate_lock()
+_active = {}
+_limbo = {}
+
+
+# Main class for threads
+
+class Thread(_Verbose):
+
+ __initialized = False
+ # Need to store a reference to sys.exc_info for printing
+ # out exceptions when a thread tries to use a global var. during interp.
+ # shutdown and thus raises an exception about trying to perform some
+ # operation on/with a NoneType
+ __exc_info = _sys.exc_info
+
+ def __init__(self, group=None, target=None, name=None,
+ args=(), kwargs={}, verbose=None):
+ assert group is None, "group argument must be None for now"
+ _Verbose.__init__(self, verbose)
+ self.__target = target
+ self.__name = str(name or _newname())
+ self.__args = args
+ self.__kwargs = kwargs
+ self.__daemonic = self._set_daemon()
+ self.__started = False
+ self.__stopped = False
+ self.__block = Condition(Lock())
+ self.__initialized = True
+ # sys.stderr is not stored in the class like
+ # sys.exc_info since it can be changed between instances
+ self.__stderr = _sys.stderr
+
+ def _set_daemon(self):
+ # Overridden in _MainThread and _DummyThread
+ return currentThread().isDaemon()
+
+ def __repr__(self):
+ assert self.__initialized, "Thread.__init__() was not called"
+ status = "initial"
+ if self.__started:
+ status = "started"
+ if self.__stopped:
+ status = "stopped"
+ if self.__daemonic:
+ status = status + " daemon"
+ return "<%s(%s, %s)>" % (self.__class__.__name__, self.__name, status)
+
+ def start(self):
+ assert self.__initialized, "Thread.__init__() not called"
+ assert not self.__started, "thread already started"
+ if __debug__:
+ self._note("%s.start(): starting thread", self)
+ _active_limbo_lock.acquire()
+ _limbo[self] = self
+ _active_limbo_lock.release()
+ _start_new_thread(self.__bootstrap, ())
+ self.__started = True
+ _sleep(0.000001) # 1 usec, to let the thread run (Solaris hack)
+
+ def run(self):
+ if self.__target:
+ self.__target(*self.__args, **self.__kwargs)
+
+ def __bootstrap(self):
+ try:
+ self.__started = True
+ _active_limbo_lock.acquire()
+ _active[_get_ident()] = self
+ del _limbo[self]
+ _active_limbo_lock.release()
+ if __debug__:
+ self._note("%s.__bootstrap(): thread started", self)
+
+ if _trace_hook:
+ self._note("%s.__bootstrap(): registering trace hook", self)
+ _sys.settrace(_trace_hook)
+ if _profile_hook:
+ self._note("%s.__bootstrap(): registering profile hook", self)
+ _sys.setprofile(_profile_hook)
+
+ try:
+ self.run()
+ except SystemExit:
+ if __debug__:
+ self._note("%s.__bootstrap(): raised SystemExit", self)
+ except:
+ if __debug__:
+ self._note("%s.__bootstrap(): unhandled exception", self)
+ # If sys.stderr is no more (most likely from interpreter
+ # shutdown) use self.__stderr. Otherwise still use sys (as in
+ # _sys) in case sys.stderr was redefined since the creation of
+ # self.
+ if _sys:
+ _sys.stderr.write("Exception in thread %s:\n%s\n" %
+ (self.getName(), _format_exc()))
+ else:
+ # Do the best job possible w/o a huge amt. of code to
+ # approximate a traceback (code ideas from
+ # Lib/traceback.py)
+ exc_type, exc_value, exc_tb = self.__exc_info()
+ try:
+ print>>self.__stderr, (
+ "Exception in thread " + self.getName() +
+ " (most likely raised during interpreter shutdown):")
+ print>>self.__stderr, (
+ "Traceback (most recent call last):")
+ while exc_tb:
+ print>>self.__stderr, (
+ ' File "%s", line %s, in %s' %
+ (exc_tb.tb_frame.f_code.co_filename,
+ exc_tb.tb_lineno,
+ exc_tb.tb_frame.f_code.co_name))
+ exc_tb = exc_tb.tb_next
+ print>>self.__stderr, ("%s: %s" % (exc_type, exc_value))
+ # Make sure that exc_tb gets deleted since it is a memory
+ # hog; deleting everything else is just for thoroughness
+ finally:
+ del exc_type, exc_value, exc_tb
+ else:
+ if __debug__:
+ self._note("%s.__bootstrap(): normal return", self)
+ finally:
+ self.__stop()
+ try:
+ self.__delete()
+ except:
+ pass
+
+ def __stop(self):
+ self.__block.acquire()
+ self.__stopped = True
+ self.__block.notifyAll()
+ self.__block.release()
+
+ def __delete(self):
+ "Remove current thread from the dict of currently running threads."
+
+ # Notes about running with dummy_thread:
+ #
+ # Must take care to not raise an exception if dummy_thread is being
+ # used (and thus this module is being used as an instance of
+ # dummy_threading). dummy_thread.get_ident() always returns -1 since
+ # there is only one thread if dummy_thread is being used. Thus
+ # len(_active) is always <= 1 here, and any Thread instance created
+ # overwrites the (if any) thread currently registered in _active.
+ #
+ # An instance of _MainThread is always created by 'threading'. This
+ # gets overwritten the instant an instance of Thread is created; both
+ # threads return -1 from dummy_thread.get_ident() and thus have the
+ # same key in the dict. So when the _MainThread instance created by
+ # 'threading' tries to clean itself up when atexit calls this method
+ # it gets a KeyError if another Thread instance was created.
+ #
+ # This all means that KeyError from trying to delete something from
+ # _active if dummy_threading is being used is a red herring. But
+ # since it isn't if dummy_threading is *not* being used then don't
+ # hide the exception.
+
+ _active_limbo_lock.acquire()
+ try:
+ try:
+ del _active[_get_ident()]
+ except KeyError:
+ if 'dummy_threading' not in _sys.modules:
+ raise
+ finally:
+ _active_limbo_lock.release()
+
+ def join(self, timeout=None):
+ assert self.__initialized, "Thread.__init__() not called"
+ assert self.__started, "cannot join thread before it is started"
+ assert self is not currentThread(), "cannot join current thread"
+ if __debug__:
+ if not self.__stopped:
+ self._note("%s.join(): waiting until thread stops", self)
+ self.__block.acquire()
+ try:
+ if timeout is None:
+ while not self.__stopped:
+ self.__block.wait()
+ if __debug__:
+ self._note("%s.join(): thread stopped", self)
+ else:
+ deadline = _time() + timeout
+ while not self.__stopped:
+ delay = deadline - _time()
+ if delay <= 0:
+ if __debug__:
+ self._note("%s.join(): timed out", self)
+ break
+ self.__block.wait(delay)
+ else:
+ if __debug__:
+ self._note("%s.join(): thread stopped", self)
+ finally:
+ self.__block.release()
+
+ def getName(self):
+ assert self.__initialized, "Thread.__init__() not called"
+ return self.__name
+
+ def setName(self, name):
+ assert self.__initialized, "Thread.__init__() not called"
+ self.__name = str(name)
+
+ def isAlive(self):
+ assert self.__initialized, "Thread.__init__() not called"
+ return self.__started and not self.__stopped
+
+ def isDaemon(self):
+ assert self.__initialized, "Thread.__init__() not called"
+ return self.__daemonic
+
+ def setDaemon(self, daemonic):
+ assert self.__initialized, "Thread.__init__() not called"
+ assert not self.__started, "cannot set daemon status of active thread"
+ self.__daemonic = daemonic
+
+# The timer class was contributed by Itamar Shtull-Trauring
+
+def Timer(*args, **kwargs):
+ return _Timer(*args, **kwargs)
+
+class _Timer(Thread):
+ """Call a function after a specified number of seconds:
+
+ t = Timer(30.0, f, args=[], kwargs={})
+ t.start()
+ t.cancel() # stop the timer's action if it's still waiting
+ """
+
+ def __init__(self, interval, function, args=[], kwargs={}):
+ Thread.__init__(self)
+ self.interval = interval
+ self.function = function
+ self.args = args
+ self.kwargs = kwargs
+ self.finished = Event()
+
+ def cancel(self):
+ """Stop the timer if it hasn't finished yet"""
+ self.finished.set()
+
+ def run(self):
+ self.finished.wait(self.interval)
+ if not self.finished.isSet():
+ self.function(*self.args, **self.kwargs)
+ self.finished.set()
+
+# Special thread class to represent the main thread
+# This is garbage collected through an exit handler
+
+class _MainThread(Thread):
+
+ def __init__(self):
+ Thread.__init__(self, name="MainThread")
+ self._Thread__started = True
+ _active_limbo_lock.acquire()
+ _active[_get_ident()] = self
+ _active_limbo_lock.release()
+ import atexit
+ atexit.register(self.__exitfunc)
+
+ def _set_daemon(self):
+ return False
+
+ def __exitfunc(self):
+ self._Thread__stop()
+ t = _pickSomeNonDaemonThread()
+ if t:
+ if __debug__:
+ self._note("%s: waiting for other threads", self)
+ while t:
+ t.join()
+ t = _pickSomeNonDaemonThread()
+ if __debug__:
+ self._note("%s: exiting", self)
+ self._Thread__delete()
+
+def _pickSomeNonDaemonThread():
+ for t in enumerate():
+ if not t.isDaemon() and t.isAlive():
+ return t
+ return None
+
+
+# Dummy thread class to represent threads not started here.
+# These aren't garbage collected when they die,
+# nor can they be waited for.
+# Their purpose is to return *something* from currentThread().
+# They are marked as daemon threads so we won't wait for them
+# when we exit (conform previous semantics).
+
+class _DummyThread(Thread):
+
+ def __init__(self):
+ Thread.__init__(self, name=_newname("Dummy-%d"))
+ self._Thread__started = True
+ _active_limbo_lock.acquire()
+ _active[_get_ident()] = self
+ _active_limbo_lock.release()
+
+ def _set_daemon(self):
+ return True
+
+ def join(self, timeout=None):
+ assert False, "cannot join a dummy thread"
+
+
+# Global API functions
+
+def currentThread():
+ try:
+ return _active[_get_ident()]
+ except KeyError:
+ ##print "currentThread(): no current thread for", _get_ident()
+ return _DummyThread()
+
+def activeCount():
+ _active_limbo_lock.acquire()
+ count = len(_active) + len(_limbo)
+ _active_limbo_lock.release()
+ return count
+
+def enumerate():
+ _active_limbo_lock.acquire()
+ active = _active.values() + _limbo.values()
+ _active_limbo_lock.release()
+ return active
+
+# Create the main thread object
+
+_MainThread()
+
+# get thread-local implementation, either from the thread
+# module, or from the python fallback
+
+try:
+ from thread import _local as local
+except ImportError:
+ from _threading_local import local
+
+
+# Self-test code
+
+def _test():
+
+ class BoundedQueue(_Verbose):
+
+ def __init__(self, limit):
+ _Verbose.__init__(self)
+ self.mon = RLock()
+ self.rc = Condition(self.mon)
+ self.wc = Condition(self.mon)
+ self.limit = limit
+ self.queue = deque()
+
+ def put(self, item):
+ self.mon.acquire()
+ while len(self.queue) >= self.limit:
+ self._note("put(%s): queue full", item)
+ self.wc.wait()
+ self.queue.append(item)
+ self._note("put(%s): appended, length now %d",
+ item, len(self.queue))
+ self.rc.notify()
+ self.mon.release()
+
+ def get(self):
+ self.mon.acquire()
+ while not self.queue:
+ self._note("get(): queue empty")
+ self.rc.wait()
+ item = self.queue.popleft()
+ self._note("get(): got %s, %d left", item, len(self.queue))
+ self.wc.notify()
+ self.mon.release()
+ return item
+
+ class ProducerThread(Thread):
+
+ def __init__(self, queue, quota):
+ Thread.__init__(self, name="Producer")
+ self.queue = queue
+ self.quota = quota
+
+ def run(self):
+ from random import random
+ counter = 0
+ while counter < self.quota:
+ counter = counter + 1
+ self.queue.put("%s.%d" % (self.getName(), counter))
+ _sleep(random() * 0.00001)
+
+
+ class ConsumerThread(Thread):
+
+ def __init__(self, queue, count):
+ Thread.__init__(self, name="Consumer")
+ self.queue = queue
+ self.count = count
+
+ def run(self):
+ while self.count > 0:
+ item = self.queue.get()
+ print item
+ self.count = self.count - 1
+
+ NP = 3
+ QL = 4
+ NI = 5
+
+ Q = BoundedQueue(QL)
+ P = []
+ for i in range(NP):
+ t = ProducerThread(Q, NI)
+ t.setName("Producer-%d" % (i+1))
+ P.append(t)
+ C = ConsumerThread(Q, NI*NP)
+ for t in P:
+ t.start()
+ _sleep(0.000001)
+ C.start()
+ for t in P:
+ t.join()
+ C.join()
+
+if __name__ == '__main__':
+ _test()
diff --git a/gnuradio-runtime/python/gnuradio/gr/hier_block2.py b/gnuradio-runtime/python/gnuradio/gr/hier_block2.py
new file mode 100644
index 0000000000..31e4065a25
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/hier_block2.py
@@ -0,0 +1,132 @@
+#
+# 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.
+#
+
+from runtime_swig import hier_block2_swig
+
+try:
+ import pmt
+except ImportError:
+ from gruel import pmt
+
+#
+# This hack forces a 'has-a' relationship to look like an 'is-a' one.
+#
+# It allows Python classes to subclass this one, while passing through
+# method calls to the C++ class shared pointer from SWIG.
+#
+# It also allows us to intercept method calls if needed
+#
+class hier_block2(object):
+ """
+ Subclass this to create a python hierarchical block.
+
+ This is a python wrapper around the C++ hierarchical block implementation.
+ Provides convenience functions and allows proper Python subclassing.
+ """
+
+ def __init__(self, name, input_signature, output_signature):
+ """
+ Create a hierarchical block with a given name and I/O signatures.
+ """
+ self._hb = hier_block2_swig(name, input_signature, output_signature)
+
+ def __getattr__(self, name):
+ """
+ Pass-through member requests to the C++ object.
+ """
+ if not hasattr(self, "_hb"):
+ raise RuntimeError("hier_block2: invalid state--did you forget to call gr.hier_block2.__init__ in a derived class?")
+ return getattr(self._hb, name)
+
+ def connect(self, *points):
+ """
+ Connect two or more block endpoints. An endpoint is either a (block, port)
+ tuple or a block instance. In the latter case, the port number is assumed
+ to be zero.
+
+ To connect the hierarchical block external inputs or outputs to internal block
+ inputs or outputs, use 'self' in the connect call.
+
+ If multiple arguments are provided, connect will attempt to wire them in series,
+ interpreting the endpoints as inputs or outputs as appropriate.
+ """
+
+ if len (points) < 1:
+ raise ValueError, ("connect requires at least one endpoint; %d provided." % (len (points),))
+ else:
+ if len(points) == 1:
+ self._hb.primitive_connect(points[0].to_basic_block())
+ else:
+ for i in range (1, len (points)):
+ self._connect(points[i-1], points[i])
+
+ def _connect(self, src, dst):
+ (src_block, src_port) = self._coerce_endpoint(src)
+ (dst_block, dst_port) = self._coerce_endpoint(dst)
+ self._hb.primitive_connect(src_block.to_basic_block(), src_port,
+ dst_block.to_basic_block(), dst_port)
+
+ def _coerce_endpoint(self, endp):
+ if hasattr(endp, 'to_basic_block'):
+ return (endp, 0)
+ else:
+ if hasattr(endp, "__getitem__") and len(endp) == 2:
+ return endp # Assume user put (block, port)
+ else:
+ raise ValueError("unable to coerce endpoint")
+
+ def disconnect(self, *points):
+ """
+ Disconnect two endpoints in the flowgraph.
+
+ To disconnect the hierarchical block external inputs or outputs to internal block
+ inputs or outputs, use 'self' in the connect call.
+
+ If more than two arguments are provided, they are disconnected successively.
+ """
+
+ if len (points) < 1:
+ raise ValueError, ("disconnect requires at least one endpoint; %d provided." % (len (points),))
+ else:
+ if len (points) == 1:
+ self._hb.primitive_disconnect(points[0].to_basic_block())
+ else:
+ for i in range (1, len (points)):
+ self._disconnect(points[i-1], points[i])
+
+ def _disconnect(self, src, dst):
+ (src_block, src_port) = self._coerce_endpoint(src)
+ (dst_block, dst_port) = self._coerce_endpoint(dst)
+ self._hb.primitive_disconnect(src_block.to_basic_block(), src_port,
+ dst_block.to_basic_block(), dst_port)
+
+ def msg_connect(self, src, srcport, dst, dstport):
+ self.primitive_msg_connect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport);
+
+ def msg_disconnect(self, src, srcport, dst, dstport):
+ self.primitive_msg_disconnect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport);
+
+ def message_port_register_hier_in(self, portname):
+ self.primitive_message_port_register_hier_in(pmt.intern(portname));
+
+ def message_port_register_hier_out(self, portname):
+ self.primitive_message_port_register_hier_out(pmt.intern(portname));
+
diff --git a/gnuradio-runtime/python/gnuradio/gr/prefs.py b/gnuradio-runtime/python/gnuradio/gr/prefs.py
new file mode 100644
index 0000000000..25fa8cd6ae
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/prefs.py
@@ -0,0 +1,127 @@
+#
+# 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.
+#
+
+import gnuradio_core as gsp
+_prefs_base = gsp.gr_prefs
+
+
+import ConfigParser
+import os
+import os.path
+import sys
+import glob
+
+
+def _user_prefs_filename():
+ return os.path.expanduser('~/.gnuradio/config.conf')
+
+def _sys_prefs_dirname():
+ return gsp.prefsdir()
+
+def _bool(x):
+ """
+ Try to coerce obj to a True or False
+ """
+ if isinstance(x, bool):
+ return x
+ if isinstance(x, (float, int)):
+ return bool(x)
+ raise TypeError, x
+
+
+class _prefs(_prefs_base):
+ """
+ Derive our 'real class' from the stubbed out base class that has support
+ for SWIG directors. This allows C++ code to magically and transparently
+ invoke the methods in this python class.
+ """
+ def __init__(self):
+ _prefs_base.__init__(self)
+ self.cp = ConfigParser.RawConfigParser()
+ self.__getattr__ = lambda self, name: getattr(self.cp, name)
+
+ def _sys_prefs_filenames(self):
+ dir = _sys_prefs_dirname()
+ try:
+ fnames = glob.glob(os.path.join(dir, '*.conf'))
+ except (IOError, OSError):
+ return []
+ fnames.sort()
+ return fnames
+
+ def _read_files(self):
+ filenames = self._sys_prefs_filenames()
+ filenames.append(_user_prefs_filename())
+ #print "filenames: ", filenames
+ self.cp.read(filenames)
+
+ # ----------------------------------------------------------------
+ # These methods override the C++ virtual methods of the same name
+ # ----------------------------------------------------------------
+ def has_section(self, section):
+ return self.cp.has_section(section)
+
+ def has_option(self, section, option):
+ return self.cp.has_option(section, option)
+
+ def get_string(self, section, option, default_val):
+ try:
+ return self.cp.get(section, option)
+ except:
+ return default_val
+
+ def get_bool(self, section, option, default_val):
+ try:
+ return self.cp.getboolean(section, option)
+ except:
+ return default_val
+
+ def get_long(self, section, option, default_val):
+ try:
+ return self.cp.getint(section, option)
+ except:
+ return default_val
+
+ def get_double(self, section, option, default_val):
+ try:
+ return self.cp.getfloat(section, option)
+ except:
+ return default_val
+ # ----------------------------------------------------------------
+ # End override of C++ virtual methods
+ # ----------------------------------------------------------------
+
+
+_prefs_db = _prefs()
+
+# if GR_DONT_LOAD_PREFS is set, don't load them.
+# (make check uses this to avoid interactions.)
+if os.getenv("GR_DONT_LOAD_PREFS", None) is None:
+ _prefs_db._read_files()
+
+
+_prefs_base.set_singleton(_prefs_db) # tell C++ what instance to use
+
+def prefs():
+ """
+ Return the global preference data base
+ """
+ return _prefs_db
diff --git a/gnuradio-runtime/python/gnuradio/gr/pubsub.py b/gnuradio-runtime/python/gnuradio/gr/pubsub.py
new file mode 100644
index 0000000000..90568418fc
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/pubsub.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+"""
+Abstract GNU Radio publisher/subscriber interface
+
+This is a proof of concept implementation, will likely change significantly.
+"""
+
+class pubsub(dict):
+ def __init__(self):
+ self._publishers = { }
+ self._subscribers = { }
+ self._proxies = { }
+
+ def __missing__(self, key, value=None):
+ dict.__setitem__(self, key, value)
+ self._publishers[key] = None
+ self._subscribers[key] = []
+ self._proxies[key] = None
+
+ def __setitem__(self, key, val):
+ if not self.has_key(key):
+ self.__missing__(key, val)
+ elif self._proxies[key] is not None:
+ (p, newkey) = self._proxies[key]
+ p[newkey] = val
+ else:
+ dict.__setitem__(self, key, val)
+ for sub in self._subscribers[key]:
+ # Note this means subscribers will get called in the thread
+ # context of the 'set' caller.
+ sub(val)
+
+ def __getitem__(self, key):
+ if not self.has_key(key): self.__missing__(key)
+ if self._proxies[key] is not None:
+ (p, newkey) = self._proxies[key]
+ return p[newkey]
+ elif self._publishers[key] is not None:
+ return self._publishers[key]()
+ else:
+ return dict.__getitem__(self, key)
+
+ def publish(self, key, publisher):
+ if not self.has_key(key): self.__missing__(key)
+ if self._proxies[key] is not None:
+ (p, newkey) = self._proxies[key]
+ p.publish(newkey, publisher)
+ else:
+ self._publishers[key] = publisher
+
+ def subscribe(self, key, subscriber):
+ if not self.has_key(key): self.__missing__(key)
+ if self._proxies[key] is not None:
+ (p, newkey) = self._proxies[key]
+ p.subscribe(newkey, subscriber)
+ else:
+ self._subscribers[key].append(subscriber)
+
+ def unpublish(self, key):
+ if self._proxies[key] is not None:
+ (p, newkey) = self._proxies[key]
+ p.unpublish(newkey)
+ else:
+ self._publishers[key] = None
+
+ def unsubscribe(self, key, subscriber):
+ if self._proxies[key] is not None:
+ (p, newkey) = self._proxies[key]
+ p.unsubscribe(newkey, subscriber)
+ else:
+ self._subscribers[key].remove(subscriber)
+
+ def proxy(self, key, p, newkey=None):
+ if not self.has_key(key): self.__missing__(key)
+ if newkey is None: newkey = key
+ self._proxies[key] = (p, newkey)
+
+ def unproxy(self, key):
+ self._proxies[key] = None
+
+# Test code
+if __name__ == "__main__":
+ import sys
+ o = pubsub()
+
+ # Non-existent key gets auto-created with None value
+ print "Auto-created key 'foo' value:", o['foo']
+
+ # Add some subscribers
+ # First is a bare function
+ def print_len(x):
+ print "len=%i" % (len(x), )
+ o.subscribe('foo', print_len)
+
+ # The second is a class member function
+ class subber(object):
+ def __init__(self, param):
+ self._param = param
+ def printer(self, x):
+ print self._param, `x`
+ s = subber('param')
+ o.subscribe('foo', s.printer)
+
+ # The third is a lambda function
+ o.subscribe('foo', lambda x: sys.stdout.write('val='+`x`+'\n'))
+
+ # Update key 'foo', will notify subscribers
+ print "Updating 'foo' with three subscribers:"
+ o['foo'] = 'bar';
+
+ # Remove first subscriber
+ o.unsubscribe('foo', print_len)
+
+ # Update now will only trigger second and third subscriber
+ print "Updating 'foo' after removing a subscriber:"
+ o['foo'] = 'bar2';
+
+ # Publish a key as a function, in this case, a lambda function
+ o.publish('baz', lambda : 42)
+ print "Published value of 'baz':", o['baz']
+
+ # Unpublish the key
+ o.unpublish('baz')
+
+ # This will return None, as there is no publisher
+ print "Value of 'baz' with no publisher:", o['baz']
+
+ # Set 'baz' key, it gets cached
+ o['baz'] = 'bazzz'
+
+ # Now will return cached value, since no provider
+ print "Cached value of 'baz' after being set:", o['baz']
diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_feval.py b/gnuradio-runtime/python/gnuradio/gr/qa_feval.py
new file mode 100755
index 0000000000..9018e12f36
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/qa_feval.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+#
+# Copyright 2006,2007,2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+
+class my_add2_dd(gr.feval_dd):
+ def eval(self, x):
+ return x + 2
+
+class my_add2_ll(gr.feval_ll):
+ def eval(self, x):
+ return x + 2
+
+class my_add2_cc(gr.feval_cc):
+ def eval(self, x):
+ return x + (2 - 2j)
+
+class my_feval(gr.feval):
+ def __init__(self):
+ gr.feval.__init__(self)
+ self.fired = False
+ def eval(self):
+ self.fired = True
+
+class test_feval(gr_unittest.TestCase):
+
+ def test_dd_1(self):
+ f = my_add2_dd()
+ src_data = (0.0, 1.0, 2.0, 3.0, 4.0)
+ expected_result = (2.0, 3.0, 4.0, 5.0, 6.0)
+ # this is all in python...
+ actual_result = tuple([f.eval(x) for x in src_data])
+ self.assertEqual(expected_result, actual_result)
+
+ def test_dd_2(self):
+ f = my_add2_dd()
+ src_data = (0.0, 1.0, 2.0, 3.0, 4.0)
+ expected_result = (2.0, 3.0, 4.0, 5.0, 6.0)
+ # this is python -> C++ -> python and back again...
+ actual_result = tuple([gr.feval_dd_example(f, x) for x in src_data])
+ self.assertEqual(expected_result, actual_result)
+
+
+ def test_ll_1(self):
+ f = my_add2_ll()
+ src_data = (0, 1, 2, 3, 4)
+ expected_result = (2, 3, 4, 5, 6)
+ # this is all in python...
+ actual_result = tuple([f.eval(x) for x in src_data])
+ self.assertEqual(expected_result, actual_result)
+
+ def test_ll_2(self):
+ f = my_add2_ll()
+ src_data = (0, 1, 2, 3, 4)
+ expected_result = (2, 3, 4, 5, 6)
+ # this is python -> C++ -> python and back again...
+ actual_result = tuple([gr.feval_ll_example(f, x) for x in src_data])
+ self.assertEqual(expected_result, actual_result)
+
+
+ def test_cc_1(self):
+ f = my_add2_cc()
+ src_data = (0+1j, 2+3j, 4+5j, 6+7j)
+ expected_result = (2-1j, 4+1j, 6+3j, 8+5j)
+ # this is all in python...
+ actual_result = tuple([f.eval(x) for x in src_data])
+ self.assertEqual(expected_result, actual_result)
+
+ def test_cc_2(self):
+ f = my_add2_cc()
+ src_data = (0+1j, 2+3j, 4+5j, 6+7j)
+ expected_result = (2-1j, 4+1j, 6+3j, 8+5j)
+ # this is python -> C++ -> python and back again...
+ actual_result = tuple([gr.feval_cc_example(f, x) for x in src_data])
+ self.assertEqual(expected_result, actual_result)
+
+ def test_void_1(self):
+ # this is all in python
+ f = my_feval()
+ f.eval()
+ self.assertEqual(True, f.fired)
+
+ def test_void_2(self):
+ # this is python -> C++ -> python and back again
+ f = my_feval()
+ gr.feval_example(f)
+ self.assertEqual(True, f.fired)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(test_feval, "test_feval.xml")
diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_kludged_imports.py b/gnuradio-runtime/python/gnuradio/gr/qa_kludged_imports.py
new file mode 100755
index 0000000000..f80188c9fc
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/qa_kludged_imports.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+#
+# Copyright 2005,2008,2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+
+class test_kludged_imports (gr_unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_gru_import(self):
+ # make sure that this somewhat magic import works
+ from gnuradio import gru
+
+
+if __name__ == '__main__':
+ gr_unittest.run(test_kludged_imports, "test_kludged_imports.xml")
diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py b/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py
new file mode 100755
index 0000000000..de1b5aa002
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+#
+# Copyright 2007,2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import tag_utils
+
+try:
+ import pmt_swig as pmt
+except ImportError:
+ import pmt
+
+class test_tag_utils (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001(self):
+ t = gr.gr_tag_t()
+ t.offset = 10
+ t.key = pmt.string_to_symbol('key')
+ t.value = pmt.from_long(23)
+ t.srcid = pmt.from_bool(False)
+ pt = tag_utils.tag_to_python(t)
+ self.assertEqual(pt.key, 'key')
+ self.assertEqual(pt.value, 23)
+ self.assertEqual(pt.offset, 10)
+
+
+if __name__ == '__main__':
+ print 'hi'
+ gr_unittest.run(test_tag_utils, "test_tag_utils.xml")
+
diff --git a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py
new file mode 100644
index 0000000000..1c9594d6d0
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py
@@ -0,0 +1,57 @@
+#
+# Copyright 2003-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.
+#
+""" Conversion tools between stream tags and Python objects """
+
+try: import pmt
+except: from gruel import pmt
+
+try:
+ from gnuradio import gr
+except ImportError:
+ from runtime_swig import gr_tag_t
+
+class PythonTag(object):
+ " Python container for tags "
+ def __init__(self):
+ self.offset = None
+ self.key = None
+ self.value = None
+ self.srcid = None
+
+def tag_to_python(tag):
+ """ Convert a stream tag to a Python-readable object """
+ newtag = PythonTag()
+ newtag.offset = tag.offset
+ newtag.key = pmt.to_python(tag.key)
+ newtag.value = pmt.to_python(tag.value)
+ newtag.srcid = pmt.to_python(tag.srcid)
+ return newtag
+
+def tag_to_pmt(tag):
+ """ Convert a Python-readable object to a stream tag """
+ newtag = gr_tag_t()
+ newtag.offset = tag.offset
+ newtag.key = pmt.to_python(tag.key)
+ newtag.value = pmt.from_python(tag.value)
+ newtag.srcid = pmt.from_python(tag.srcid)
+ return newtag
+
+
diff --git a/gnuradio-runtime/python/gnuradio/gr/top_block.py b/gnuradio-runtime/python/gnuradio/gr/top_block.py
new file mode 100644
index 0000000000..944e95e5ae
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr/top_block.py
@@ -0,0 +1,170 @@
+#
+# 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.
+#
+
+from runtime_swig import top_block_swig, \
+ top_block_wait_unlocked, top_block_run_unlocked
+
+#import gnuradio.gr.gr_threading as _threading
+import gr_threading as _threading
+
+#
+# There is no problem that can't be solved with an additional
+# level of indirection...
+#
+# This kludge allows ^C to interrupt top_block.run and top_block.wait
+#
+# The problem that we are working around is that Python only services
+# signals (e.g., KeyboardInterrupt) in its main thread. If the main
+# thread is blocked in our C++ version of wait, even though Python's
+# SIGINT handler fires, and even though there may be other python
+# threads running, no one will know. Thus instead of directly waiting
+# in the thread that calls wait (which is likely to be the Python main
+# thread), we create a separate thread that does the blocking wait,
+# and then use the thread that called wait to do a slow poll of an
+# event queue. That thread, which is executing "wait" below is
+# interruptable, and if it sees a KeyboardInterrupt, executes a stop
+# on the top_block, then goes back to waiting for it to complete.
+# This ensures that the unlocked wait that was in progress (in the
+# _top_block_waiter thread) can complete, release its mutex and back
+# out. If we don't do that, we are never able to clean up, and nasty
+# things occur like leaving the USRP transmitter sending a carrier.
+#
+# See also top_block.wait (below), which uses this class to implement
+# the interruptable wait.
+#
+class _top_block_waiter(_threading.Thread):
+ def __init__(self, tb):
+ _threading.Thread.__init__(self)
+ self.setDaemon(1)
+ self.tb = tb
+ self.event = _threading.Event()
+ self.start()
+
+ def run(self):
+ top_block_wait_unlocked(self.tb)
+ self.event.set()
+
+ def wait(self):
+ try:
+ while not self.event.isSet():
+ self.event.wait(0.100)
+ except KeyboardInterrupt:
+ self.tb.stop()
+ self.wait()
+
+
+#
+# This hack forces a 'has-a' relationship to look like an 'is-a' one.
+#
+# It allows Python classes to subclass this one, while passing through
+# method calls to the C++ class shared pointer from SWIG.
+#
+# It also allows us to intercept method calls if needed.
+#
+# This allows the 'run_locked' methods, which are defined in gr_top_block.i,
+# to release the Python global interpreter lock before calling the actual
+# method in gr_top_block
+#
+class top_block(object):
+ """
+ Top-level hierarchical block representing a flow-graph.
+
+ This is a python wrapper around the C++ implementation to allow
+ python subclassing.
+ """
+ def __init__(self, name="top_block"):
+ self._tb = top_block_swig(name)
+
+ def __getattr__(self, name):
+ if not hasattr(self, "_tb"):
+ raise RuntimeError("top_block: invalid state--did you forget to call gr.top_block.__init__ in a derived class?")
+ return getattr(self._tb, name)
+
+ def start(self, max_noutput_items=10000000):
+ self._tb.start(max_noutput_items)
+
+ def stop(self):
+ self._tb.stop()
+
+ def run(self, max_noutput_items=10000000):
+ self.start(max_noutput_items)
+ self.wait()
+
+ def wait(self):
+ _top_block_waiter(self._tb).wait()
+
+
+ # FIXME: these are duplicated from hier_block2.py; they should really be implemented
+ # in the original C++ class (gr_hier_block2), then they would all be inherited here
+
+ def connect(self, *points):
+ '''connect requires one or more arguments that can be coerced to endpoints.
+ If more than two arguments are provided, they are connected together successively.
+ '''
+ if len (points) < 1:
+ raise ValueError, ("connect requires at least one endpoint; %d provided." % (len (points),))
+ else:
+ if len(points) == 1:
+ self._tb.primitive_connect(points[0].to_basic_block())
+ else:
+ for i in range (1, len (points)):
+ self._connect(points[i-1], points[i])
+
+ def msg_connect(self, src, srcport, dst, dstport):
+ self.primitive_msg_connect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport);
+
+ def msg_disconnect(self, src, srcport, dst, dstport):
+ self.primitive_msg_disconnect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport);
+
+ def _connect(self, src, dst):
+ (src_block, src_port) = self._coerce_endpoint(src)
+ (dst_block, dst_port) = self._coerce_endpoint(dst)
+ self._tb.primitive_connect(src_block.to_basic_block(), src_port,
+ dst_block.to_basic_block(), dst_port)
+
+ def _coerce_endpoint(self, endp):
+ if hasattr(endp, 'to_basic_block'):
+ return (endp, 0)
+ else:
+ if hasattr(endp, "__getitem__") and len(endp) == 2:
+ return endp # Assume user put (block, port)
+ else:
+ raise ValueError("unable to coerce endpoint")
+
+ def disconnect(self, *points):
+ '''disconnect requires one or more arguments that can be coerced to endpoints.
+ If more than two arguments are provided, they are disconnected successively.
+ '''
+ if len (points) < 1:
+ raise ValueError, ("disconnect requires at least one endpoint; %d provided." % (len (points),))
+ else:
+ if len(points) == 1:
+ self._tb.primitive_disconnect(points[0].to_basic_block())
+ else:
+ for i in range (1, len (points)):
+ self._disconnect(points[i-1], points[i])
+
+ def _disconnect(self, src, dst):
+ (src_block, src_port) = self._coerce_endpoint(src)
+ (dst_block, dst_port) = self._coerce_endpoint(dst)
+ self._tb.primitive_disconnect(src_block.to_basic_block(), src_port,
+ dst_block.to_basic_block(), dst_port)
+
diff --git a/gnuradio-runtime/python/gnuradio/gr_unittest.py b/gnuradio-runtime/python/gnuradio/gr_unittest.py
new file mode 100755
index 0000000000..c729566e88
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr_unittest.py
@@ -0,0 +1,170 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+"""
+GNU radio specific extension of unittest.
+"""
+
+import unittest
+import gr_xmlrunner
+import sys, os, stat
+
+class TestCase(unittest.TestCase):
+ """A subclass of unittest.TestCase that adds additional assertions
+
+ Adds new methods assertComplexAlmostEqual,
+ assertComplexTuplesAlmostEqual and assertFloatTuplesAlmostEqual
+ """
+
+ def assertComplexAlmostEqual (self, first, second, places=7, msg=None):
+ """Fail if the two complex objects are unequal as determined by their
+ difference rounded to the given number of decimal places
+ (default 7) and comparing to zero.
+
+ Note that decimal places (from zero) is usually not the same
+ as significant digits (measured from the most signficant digit).
+ """
+ if round(second.real-first.real, places) != 0:
+ raise self.failureException, \
+ (msg or '%s != %s within %s places' % (`first`, `second`, `places` ))
+ if round(second.imag-first.imag, places) != 0:
+ raise self.failureException, \
+ (msg or '%s != %s within %s places' % (`first`, `second`, `places` ))
+
+ def assertComplexAlmostEqual2 (self, ref, x, abs_eps=1e-12, rel_eps=1e-6, msg=None):
+ """
+ Fail if the two complex objects are unequal as determined by...
+ """
+ if abs(ref - x) < abs_eps:
+ return
+
+ if abs(ref) > abs_eps:
+ if abs(ref-x)/abs(ref) > rel_eps:
+ raise self.failureException, \
+ (msg or '%s != %s rel_error = %s rel_limit = %s' % (
+ `ref`, `x`, abs(ref-x)/abs(ref), `rel_eps` ))
+ else:
+ raise self.failureException, \
+ (msg or '%s != %s rel_error = %s rel_limit = %s' % (
+ `ref`, `x`, abs(ref-x)/abs(ref), `rel_eps` ))
+
+
+
+ def assertComplexTuplesAlmostEqual (self, a, b, places=7, msg=None):
+ self.assertEqual (len(a), len(b))
+ for i in xrange (len(a)):
+ self.assertComplexAlmostEqual (a[i], b[i], places, msg)
+
+ def assertComplexTuplesAlmostEqual2 (self, ref, x,
+ abs_eps=1e-12, rel_eps=1e-6, msg=None):
+ self.assertEqual (len(ref), len(x))
+ for i in xrange (len(ref)):
+ try:
+ self.assertComplexAlmostEqual2 (ref[i], x[i], abs_eps, rel_eps, msg)
+ except self.failureException, e:
+ #sys.stderr.write("index = %d " % (i,))
+ #sys.stderr.write("%s\n" % (e,))
+ raise
+
+ def assertFloatTuplesAlmostEqual (self, a, b, places=7, msg=None):
+ self.assertEqual (len(a), len(b))
+ for i in xrange (len(a)):
+ self.assertAlmostEqual (a[i], b[i], places, msg)
+
+
+ def assertFloatTuplesAlmostEqual2 (self, ref, x,
+ abs_eps=1e-12, rel_eps=1e-6, msg=None):
+ self.assertEqual (len(ref), len(x))
+ for i in xrange (len(ref)):
+ try:
+ self.assertComplexAlmostEqual2 (ref[i], x[i], abs_eps, rel_eps, msg)
+ except self.failureException, e:
+ #sys.stderr.write("index = %d " % (i,))
+ #sys.stderr.write("%s\n" % (e,))
+ raise
+
+
+TestResult = unittest.TestResult
+TestSuite = unittest.TestSuite
+FunctionTestCase = unittest.FunctionTestCase
+TestLoader = unittest.TestLoader
+TextTestRunner = unittest.TextTestRunner
+TestProgram = unittest.TestProgram
+main = TestProgram
+
+def run(PUT, filename=None):
+ '''
+ Runs the unittest on a TestCase and produces an optional XML report
+ PUT: the program under test and should be a gr_unittest.TestCase
+ filename: an optional filename to save the XML report of the tests
+ this will live in ./.unittests/python
+ '''
+
+ # Run this is given a file name
+ if(filename is not None):
+ basepath = "./.unittests"
+ path = basepath + "/python"
+
+ if not os.path.exists(basepath):
+ os.makedirs(basepath, 0750)
+
+ xmlrunner = None
+ # only proceed if .unittests is writable
+ st = os.stat(basepath)[stat.ST_MODE]
+ if(st & stat.S_IWUSR > 0):
+ # Test if path exists; if not, build it
+ if not os.path.exists(path):
+ os.makedirs(path, 0750)
+
+ # Just for safety: make sure we can write here, too
+ st = os.stat(path)[stat.ST_MODE]
+ if(st & stat.S_IWUSR > 0):
+ # Create an XML runner to filename
+ fout = file(path+"/"+filename, "w")
+ xmlrunner = gr_xmlrunner.XMLTestRunner(fout)
+
+ txtrunner = TextTestRunner(verbosity=1)
+
+ # Run the test; runner also creates XML output file
+ # FIXME: make xmlrunner output to screen so we don't have to do run and main
+ suite = TestLoader().loadTestsFromTestCase(PUT)
+
+ # use the xmlrunner if we can write the the directory
+ if(xmlrunner is not None):
+ xmlrunner.run(suite)
+
+ main()
+
+ # This will run and fail make check if problem
+ # but does not output to screen.
+ #main(testRunner = xmlrunner)
+
+ else:
+ # If no filename is given, just run the test
+ main()
+
+
+##############################################################################
+# Executing this module from the command line
+##############################################################################
+
+if __name__ == "__main__":
+ main(module=None)
diff --git a/gnuradio-runtime/python/gnuradio/gr_xmlrunner.py b/gnuradio-runtime/python/gnuradio/gr_xmlrunner.py
new file mode 100644
index 0000000000..31298197ff
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gr_xmlrunner.py
@@ -0,0 +1,387 @@
+"""
+XML Test Runner for PyUnit
+"""
+
+# Written by Sebastian Rittau <srittau@jroger.in-berlin.de> and placed in
+# the Public Domain. With contributions by Paolo Borelli and others.
+# Added to GNU Radio Oct. 3, 2010
+
+__version__ = "0.1"
+
+import os.path
+import re
+import sys
+import time
+import traceback
+import unittest
+from xml.sax.saxutils import escape
+
+try:
+ from StringIO import StringIO
+except ImportError:
+ from io import StringIO
+
+
+class _TestInfo(object):
+
+ """Information about a particular test.
+
+ Used by _XMLTestResult.
+
+ """
+
+ def __init__(self, test, time):
+ (self._class, self._method) = test.id().rsplit(".", 1)
+ self._time = time
+ self._error = None
+ self._failure = None
+
+ @staticmethod
+ def create_success(test, time):
+ """Create a _TestInfo instance for a successful test."""
+ return _TestInfo(test, time)
+
+ @staticmethod
+ def create_failure(test, time, failure):
+ """Create a _TestInfo instance for a failed test."""
+ info = _TestInfo(test, time)
+ info._failure = failure
+ return info
+
+ @staticmethod
+ def create_error(test, time, error):
+ """Create a _TestInfo instance for an erroneous test."""
+ info = _TestInfo(test, time)
+ info._error = error
+ return info
+
+ def print_report(self, stream):
+ """Print information about this test case in XML format to the
+ supplied stream.
+
+ """
+ stream.write(' <testcase classname="%(class)s" name="%(method)s" time="%(time).4f">' % \
+ {
+ "class": self._class,
+ "method": self._method,
+ "time": self._time,
+ })
+ if self._failure is not None:
+ self._print_error(stream, 'failure', self._failure)
+ if self._error is not None:
+ self._print_error(stream, 'error', self._error)
+ stream.write('</testcase>\n')
+
+ def _print_error(self, stream, tagname, error):
+ """Print information from a failure or error to the supplied stream."""
+ text = escape(str(error[1]))
+ stream.write('\n')
+ stream.write(' <%s type="%s">%s\n' \
+ % (tagname, _clsname(error[0]), text))
+ tb_stream = StringIO()
+ traceback.print_tb(error[2], None, tb_stream)
+ stream.write(escape(tb_stream.getvalue()))
+ stream.write(' </%s>\n' % tagname)
+ stream.write(' ')
+
+
+def _clsname(cls):
+ return cls.__module__ + "." + cls.__name__
+
+
+class _XMLTestResult(unittest.TestResult):
+
+ """A test result class that stores result as XML.
+
+ Used by XMLTestRunner.
+
+ """
+
+ def __init__(self, classname):
+ unittest.TestResult.__init__(self)
+ self._test_name = classname
+ self._start_time = None
+ self._tests = []
+ self._error = None
+ self._failure = None
+
+ def startTest(self, test):
+ unittest.TestResult.startTest(self, test)
+ self._error = None
+ self._failure = None
+ self._start_time = time.time()
+
+ def stopTest(self, test):
+ time_taken = time.time() - self._start_time
+ unittest.TestResult.stopTest(self, test)
+ if self._error:
+ info = _TestInfo.create_error(test, time_taken, self._error)
+ elif self._failure:
+ info = _TestInfo.create_failure(test, time_taken, self._failure)
+ else:
+ info = _TestInfo.create_success(test, time_taken)
+ self._tests.append(info)
+
+ def addError(self, test, err):
+ unittest.TestResult.addError(self, test, err)
+ self._error = err
+
+ def addFailure(self, test, err):
+ unittest.TestResult.addFailure(self, test, err)
+ self._failure = err
+
+ def print_report(self, stream, time_taken, out, err):
+ """Prints the XML report to the supplied stream.
+
+ The time the tests took to perform as well as the captured standard
+ output and standard error streams must be passed in.a
+
+ """
+ stream.write('<testsuite errors="%(e)d" failures="%(f)d" ' % \
+ { "e": len(self.errors), "f": len(self.failures) })
+ stream.write('name="%(n)s" tests="%(t)d" time="%(time).3f">\n' % \
+ {
+ "n": self._test_name,
+ "t": self.testsRun,
+ "time": time_taken,
+ })
+ for info in self._tests:
+ info.print_report(stream)
+ stream.write(' <system-out><![CDATA[%s]]></system-out>\n' % out)
+ stream.write(' <system-err><![CDATA[%s]]></system-err>\n' % err)
+ stream.write('</testsuite>\n')
+
+
+class XMLTestRunner(object):
+
+ """A test runner that stores results in XML format compatible with JUnit.
+
+ XMLTestRunner(stream=None) -> XML test runner
+
+ The XML file is written to the supplied stream. If stream is None, the
+ results are stored in a file called TEST-<module>.<class>.xml in the
+ current working directory (if not overridden with the path property),
+ where <module> and <class> are the module and class name of the test class.
+
+ """
+
+ def __init__(self, stream=None):
+ self._stream = stream
+ self._path = "."
+
+ def run(self, test):
+ """Run the given test case or test suite."""
+ class_ = test.__class__
+ classname = class_.__module__ + "." + class_.__name__
+ if self._stream == None:
+ filename = "TEST-%s.xml" % classname
+ stream = file(os.path.join(self._path, filename), "w")
+ stream.write('<?xml version="1.0" encoding="utf-8"?>\n')
+ else:
+ stream = self._stream
+
+ result = _XMLTestResult(classname)
+ start_time = time.time()
+
+ fss = _fake_std_streams()
+ fss.__enter__()
+ try:
+ test(result)
+ try:
+ out_s = sys.stdout.getvalue()
+ except AttributeError:
+ out_s = ""
+ try:
+ err_s = sys.stderr.getvalue()
+ except AttributeError:
+ err_s = ""
+ finally:
+ fss.__exit__(None, None, None)
+
+ time_taken = time.time() - start_time
+ result.print_report(stream, time_taken, out_s, err_s)
+ if self._stream is None:
+ stream.close()
+
+ return result
+
+ def _set_path(self, path):
+ self._path = path
+
+ path = property(lambda self: self._path, _set_path, None,
+ """The path where the XML files are stored.
+
+ This property is ignored when the XML file is written to a file
+ stream.""")
+
+
+class _fake_std_streams(object):
+
+ def __enter__(self):
+ self._orig_stdout = sys.stdout
+ self._orig_stderr = sys.stderr
+ #sys.stdout = StringIO()
+ #sys.stderr = StringIO()
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ sys.stdout = self._orig_stdout
+ sys.stderr = self._orig_stderr
+
+
+class XMLTestRunnerTest(unittest.TestCase):
+
+ def setUp(self):
+ self._stream = StringIO()
+
+ def _try_test_run(self, test_class, expected):
+
+ """Run the test suite against the supplied test class and compare the
+ XML result against the expected XML string. Fail if the expected
+ string doesn't match the actual string. All time attributes in the
+ expected string should have the value "0.000". All error and failure
+ messages are reduced to "Foobar".
+
+ """
+
+ runner = XMLTestRunner(self._stream)
+ runner.run(unittest.makeSuite(test_class))
+
+ got = self._stream.getvalue()
+ # Replace all time="X.YYY" attributes by time="0.000" to enable a
+ # simple string comparison.
+ got = re.sub(r'time="\d+\.\d+"', 'time="0.000"', got)
+ # Likewise, replace all failure and error messages by a simple "Foobar"
+ # string.
+ got = re.sub(r'(?s)<failure (.*?)>.*?</failure>', r'<failure \1>Foobar</failure>', got)
+ got = re.sub(r'(?s)<error (.*?)>.*?</error>', r'<error \1>Foobar</error>', got)
+ # And finally Python 3 compatibility.
+ got = got.replace('type="builtins.', 'type="exceptions.')
+
+ self.assertEqual(expected, got)
+
+ def test_no_tests(self):
+ """Regression test: Check whether a test run without any tests
+ matches a previous run.
+
+ """
+ class TestTest(unittest.TestCase):
+ pass
+ self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="0" time="0.000">
+ <system-out><![CDATA[]]></system-out>
+ <system-err><![CDATA[]]></system-err>
+</testsuite>
+""")
+
+ def test_success(self):
+ """Regression test: Check whether a test run with a successful test
+ matches a previous run.
+
+ """
+ class TestTest(unittest.TestCase):
+ def test_foo(self):
+ pass
+ self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000">
+ <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase>
+ <system-out><![CDATA[]]></system-out>
+ <system-err><![CDATA[]]></system-err>
+</testsuite>
+""")
+
+ def test_failure(self):
+ """Regression test: Check whether a test run with a failing test
+ matches a previous run.
+
+ """
+ class TestTest(unittest.TestCase):
+ def test_foo(self):
+ self.assert_(False)
+ self._try_test_run(TestTest, """<testsuite errors="0" failures="1" name="unittest.TestSuite" tests="1" time="0.000">
+ <testcase classname="__main__.TestTest" name="test_foo" time="0.000">
+ <failure type="exceptions.AssertionError">Foobar</failure>
+ </testcase>
+ <system-out><![CDATA[]]></system-out>
+ <system-err><![CDATA[]]></system-err>
+</testsuite>
+""")
+
+ def test_error(self):
+ """Regression test: Check whether a test run with a erroneous test
+ matches a previous run.
+
+ """
+ class TestTest(unittest.TestCase):
+ def test_foo(self):
+ raise IndexError()
+ self._try_test_run(TestTest, """<testsuite errors="1" failures="0" name="unittest.TestSuite" tests="1" time="0.000">
+ <testcase classname="__main__.TestTest" name="test_foo" time="0.000">
+ <error type="exceptions.IndexError">Foobar</error>
+ </testcase>
+ <system-out><![CDATA[]]></system-out>
+ <system-err><![CDATA[]]></system-err>
+</testsuite>
+""")
+
+ def test_stdout_capture(self):
+ """Regression test: Check whether a test run with output to stdout
+ matches a previous run.
+
+ """
+ class TestTest(unittest.TestCase):
+ def test_foo(self):
+ sys.stdout.write("Test\n")
+ self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000">
+ <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase>
+ <system-out><![CDATA[Test
+]]></system-out>
+ <system-err><![CDATA[]]></system-err>
+</testsuite>
+""")
+
+ def test_stderr_capture(self):
+ """Regression test: Check whether a test run with output to stderr
+ matches a previous run.
+
+ """
+ class TestTest(unittest.TestCase):
+ def test_foo(self):
+ sys.stderr.write("Test\n")
+ self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000">
+ <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase>
+ <system-out><![CDATA[]]></system-out>
+ <system-err><![CDATA[Test
+]]></system-err>
+</testsuite>
+""")
+
+ class NullStream(object):
+ """A file-like object that discards everything written to it."""
+ def write(self, buffer):
+ pass
+
+ def test_unittests_changing_stdout(self):
+ """Check whether the XMLTestRunner recovers gracefully from unit tests
+ that change stdout, but don't change it back properly.
+
+ """
+ class TestTest(unittest.TestCase):
+ def test_foo(self):
+ sys.stdout = XMLTestRunnerTest.NullStream()
+
+ runner = XMLTestRunner(self._stream)
+ runner.run(unittest.makeSuite(TestTest))
+
+ def test_unittests_changing_stderr(self):
+ """Check whether the XMLTestRunner recovers gracefully from unit tests
+ that change stderr, but don't change it back properly.
+
+ """
+ class TestTest(unittest.TestCase):
+ def test_foo(self):
+ sys.stderr = XMLTestRunnerTest.NullStream()
+
+ runner = XMLTestRunner(self._stream)
+ runner.run(unittest.makeSuite(TestTest))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/gnuradio-runtime/python/gnuradio/gru/CMakeLists.txt b/gnuradio-runtime/python/gnuradio/gru/CMakeLists.txt
new file mode 100644
index 0000000000..c147981472
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/CMakeLists.txt
@@ -0,0 +1,36 @@
+# Copyright 2010-2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+include(GrPython)
+
+GR_PYTHON_INSTALL(FILES
+ __init__.py
+ freqz.py
+ gnuplot_freqz.py
+ hexint.py
+ listmisc.py
+ mathmisc.py
+ msgq_runner.py
+ os_read_exactly.py
+ seq_with_cursor.py
+ socket_stuff.py
+ daemon.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/gru
+ COMPONENT "core_python"
+)
diff --git a/gnuradio-runtime/python/gnuradio/gru/__init__.py b/gnuradio-runtime/python/gnuradio/gru/__init__.py
new file mode 100644
index 0000000000..4e41d03a74
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/__init__.py
@@ -0,0 +1,13 @@
+# make this a package
+
+# Import gru stuff
+from daemon import *
+from freqz import *
+from gnuplot_freqz import *
+from hexint import *
+from listmisc import *
+from mathmisc import *
+from msgq_runner import *
+from os_read_exactly import *
+from seq_with_cursor import *
+from socket_stuff import *
diff --git a/gnuradio-runtime/python/gnuradio/gru/daemon.py b/gnuradio-runtime/python/gnuradio/gru/daemon.py
new file mode 100644
index 0000000000..e04702152d
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/daemon.py
@@ -0,0 +1,102 @@
+#
+# 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.
+#
+import os, sys, signal
+
+# Turn application into a background daemon process.
+#
+# When this function returns:
+#
+# 1) The calling process is disconnected from its controlling terminal
+# and will not exit when the controlling session exits
+# 2) If a pidfile name is provided, it is created and the new pid is
+# written into it.
+# 3) If a logfile name is provided, it is opened and stdout/stderr are
+# redirected to it.
+# 4) The process current working directory is changed to '/' to avoid
+# pinning any filesystem mounts.
+# 5) The process umask is set to 0111.
+#
+# The return value is the new pid.
+#
+# To create GNU Radio applications that operate as daemons, add a call to this
+# function after all initialization but just before calling gr.top_block.run()
+# or .start().
+#
+# Daemonized GNU Radio applications may be stopped by sending them a
+# SIGINT, SIGKILL, or SIGTERM, e.g., using 'kill pid' from the command line.
+#
+# If your application uses gr.top_block.run(), the flowgraph will be stopped
+# and the function will return. You should allow your daemon program to exit
+# at this point.
+#
+# If your application uses gr.top_block.start(), you are responsible for hooking
+# the Python signal handler (see 'signal' module) and calling gr.top_block.stop()
+# on your top block, and otherwise causing your daemon process to exit.
+#
+
+def daemonize(pidfile=None, logfile=None):
+ # fork() into background
+ try:
+ pid = os.fork()
+ except OSError, e:
+ raise Exception, "%s [%d]" % (e.strerror, e.errno)
+
+ if pid == 0: # First child of first fork()
+ # Become session leader of new session
+ os.setsid()
+
+ # fork() into background again
+ try:
+ pid = os.fork()
+ except OSError, e:
+ raise Exception, "%s [%d]" % (e.strerror, e.errno)
+
+ if pid != 0:
+ os._exit(0) # Second child of second fork()
+
+ else: # Second child of first fork()
+ os._exit(0)
+
+ os.umask(0111)
+
+ # Write pid
+ pid = os.getpid()
+ if pidfile is not None:
+ open(pidfile, 'w').write('%d\n'%pid)
+
+ # Redirect streams
+ if logfile is not None:
+ lf = open(logfile, 'a+')
+ sys.stdout = lf
+ sys.stderr = lf
+
+ # Prevent pinning any filesystem mounts
+ os.chdir('/')
+
+ # Tell caller what pid to send future signals to
+ return pid
+
+if __name__ == "__main__":
+ import time
+ daemonize()
+ print "Hello, world, from daemon process."
+ time.sleep(20)
+ print "Goodbye, world, from daemon process."
diff --git a/gnuradio-runtime/python/gnuradio/gru/freqz.py b/gnuradio-runtime/python/gnuradio/gru/freqz.py
new file mode 100644
index 0000000000..60dca64a58
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/freqz.py
@@ -0,0 +1,344 @@
+#!/usr/bin/env python
+#
+# Copyright 2005,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.
+#
+
+# This code lifted from various parts of www.scipy.org -eb 2005-01-24
+
+# Copyright (c) 2001, 2002 Enthought, Inc.
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# a. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# b. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# c. Neither the name of the Enthought nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+#
+
+__all__ = ['freqz']
+
+import numpy
+from numpy import *
+Num=numpy
+
+def atleast_1d(*arys):
+ """ Force a sequence of arrays to each be at least 1D.
+
+ Description:
+ Force an array to be at least 1D. If an array is 0D, the
+ array is converted to a single row of values. Otherwise,
+ the array is unaltered.
+ Arguments:
+ *arys -- arrays to be converted to 1 or more dimensional array.
+ Returns:
+ input array converted to at least 1D array.
+ """
+ res = []
+ for ary in arys:
+ ary = asarray(ary)
+ if len(ary.shape) == 0:
+ result = numpy.array([ary[0]])
+ else:
+ result = ary
+ res.append(result)
+ if len(res) == 1:
+ return res[0]
+ else:
+ return res
+
+
+def polyval(p,x):
+ """Evaluate the polynomial p at x. If x is a polynomial then composition.
+
+ Description:
+
+ If p is of length N, this function returns the value:
+ p[0]*(x**N-1) + p[1]*(x**N-2) + ... + p[N-2]*x + p[N-1]
+
+ x can be a sequence and p(x) will be returned for all elements of x.
+ or x can be another polynomial and the composite polynomial p(x) will be
+ returned.
+ """
+ p = asarray(p)
+ if isinstance(x,poly1d):
+ y = 0
+ else:
+ x = asarray(x)
+ y = numpy.zeros(x.shape,x.typecode())
+ for i in range(len(p)):
+ y = x * y + p[i]
+ return y
+
+class poly1d:
+ """A one-dimensional polynomial class.
+
+ p = poly1d([1,2,3]) constructs the polynomial x**2 + 2 x + 3
+
+ p(0.5) evaluates the polynomial at the location
+ p.r is a list of roots
+ p.c is the coefficient array [1,2,3]
+ p.order is the polynomial order (after leading zeros in p.c are removed)
+ p[k] is the coefficient on the kth power of x (backwards from
+ sequencing the coefficient array.
+
+ polynomials can be added, substracted, multplied and divided (returns
+ quotient and remainder).
+ asarray(p) will also give the coefficient array, so polynomials can
+ be used in all functions that accept arrays.
+ """
+ def __init__(self, c_or_r, r=0):
+ if isinstance(c_or_r,poly1d):
+ for key in c_or_r.__dict__.keys():
+ self.__dict__[key] = c_or_r.__dict__[key]
+ return
+ if r:
+ c_or_r = poly(c_or_r)
+ c_or_r = atleast_1d(c_or_r)
+ if len(c_or_r.shape) > 1:
+ raise ValueError, "Polynomial must be 1d only."
+ c_or_r = trim_zeros(c_or_r, trim='f')
+ if len(c_or_r) == 0:
+ c_or_r = numpy.array([0])
+ self.__dict__['coeffs'] = c_or_r
+ self.__dict__['order'] = len(c_or_r) - 1
+
+ def __array__(self,t=None):
+ if t:
+ return asarray(self.coeffs,t)
+ else:
+ return asarray(self.coeffs)
+
+ def __coerce__(self,other):
+ return None
+
+ def __repr__(self):
+ vals = repr(self.coeffs)
+ vals = vals[6:-1]
+ return "poly1d(%s)" % vals
+
+ def __len__(self):
+ return self.order
+
+ def __str__(self):
+ N = self.order
+ thestr = "0"
+ for k in range(len(self.coeffs)):
+ coefstr ='%.4g' % abs(self.coeffs[k])
+ if coefstr[-4:] == '0000':
+ coefstr = coefstr[:-5]
+ power = (N-k)
+ if power == 0:
+ if coefstr != '0':
+ newstr = '%s' % (coefstr,)
+ else:
+ if k == 0:
+ newstr = '0'
+ else:
+ newstr = ''
+ elif power == 1:
+ if coefstr == '0':
+ newstr = ''
+ elif coefstr == '1':
+ newstr = 'x'
+ else:
+ newstr = '%s x' % (coefstr,)
+ else:
+ if coefstr == '0':
+ newstr = ''
+ elif coefstr == '1':
+ newstr = 'x**%d' % (power,)
+ else:
+ newstr = '%s x**%d' % (coefstr, power)
+
+ if k > 0:
+ if newstr != '':
+ if self.coeffs[k] < 0:
+ thestr = "%s - %s" % (thestr, newstr)
+ else:
+ thestr = "%s + %s" % (thestr, newstr)
+ elif (k == 0) and (newstr != '') and (self.coeffs[k] < 0):
+ thestr = "-%s" % (newstr,)
+ else:
+ thestr = newstr
+ return _raise_power(thestr)
+
+
+ def __call__(self, val):
+ return polyval(self.coeffs, val)
+
+ def __mul__(self, other):
+ if isscalar(other):
+ return poly1d(self.coeffs * other)
+ else:
+ other = poly1d(other)
+ return poly1d(polymul(self.coeffs, other.coeffs))
+
+ def __rmul__(self, other):
+ if isscalar(other):
+ return poly1d(other * self.coeffs)
+ else:
+ other = poly1d(other)
+ return poly1d(polymul(self.coeffs, other.coeffs))
+
+ def __add__(self, other):
+ other = poly1d(other)
+ return poly1d(polyadd(self.coeffs, other.coeffs))
+
+ def __radd__(self, other):
+ other = poly1d(other)
+ return poly1d(polyadd(self.coeffs, other.coeffs))
+
+ def __pow__(self, val):
+ if not isscalar(val) or int(val) != val or val < 0:
+ raise ValueError, "Power to non-negative integers only."
+ res = [1]
+ for k in range(val):
+ res = polymul(self.coeffs, res)
+ return poly1d(res)
+
+ def __sub__(self, other):
+ other = poly1d(other)
+ return poly1d(polysub(self.coeffs, other.coeffs))
+
+ def __rsub__(self, other):
+ other = poly1d(other)
+ return poly1d(polysub(other.coeffs, self.coeffs))
+
+ def __div__(self, other):
+ if isscalar(other):
+ return poly1d(self.coeffs/other)
+ else:
+ other = poly1d(other)
+ return map(poly1d,polydiv(self.coeffs, other.coeffs))
+
+ def __rdiv__(self, other):
+ if isscalar(other):
+ return poly1d(other/self.coeffs)
+ else:
+ other = poly1d(other)
+ return map(poly1d,polydiv(other.coeffs, self.coeffs))
+
+ def __setattr__(self, key, val):
+ raise ValueError, "Attributes cannot be changed this way."
+
+ def __getattr__(self, key):
+ if key in ['r','roots']:
+ return roots(self.coeffs)
+ elif key in ['c','coef','coefficients']:
+ return self.coeffs
+ elif key in ['o']:
+ return self.order
+ else:
+ return self.__dict__[key]
+
+ def __getitem__(self, val):
+ ind = self.order - val
+ if val > self.order:
+ return 0
+ if val < 0:
+ return 0
+ return self.coeffs[ind]
+
+ def __setitem__(self, key, val):
+ ind = self.order - key
+ if key < 0:
+ raise ValueError, "Does not support negative powers."
+ if key > self.order:
+ zr = numpy.zeros(key-self.order,self.coeffs.typecode())
+ self.__dict__['coeffs'] = numpy.concatenate((zr,self.coeffs))
+ self.__dict__['order'] = key
+ ind = 0
+ self.__dict__['coeffs'][ind] = val
+ return
+
+ def integ(self, m=1, k=0):
+ return poly1d(polyint(self.coeffs,m=m,k=k))
+
+ def deriv(self, m=1):
+ return poly1d(polyder(self.coeffs,m=m))
+
+def freqz(b, a, worN=None, whole=0, plot=None):
+ """Compute frequency response of a digital filter.
+
+ Description:
+
+ Given the numerator (b) and denominator (a) of a digital filter compute
+ its frequency response.
+
+ jw -jw -jmw
+ jw B(e) b[0] + b[1]e + .... + b[m]e
+ H(e) = ---- = ------------------------------------
+ jw -jw -jnw
+ A(e) a[0] + a[2]e + .... + a[n]e
+
+ Inputs:
+
+ b, a --- the numerator and denominator of a linear filter.
+ worN --- If None, then compute at 512 frequencies around the unit circle.
+ If a single integer, the compute at that many frequencies.
+ Otherwise, compute the response at frequencies given in worN
+ whole -- Normally, frequencies are computed from 0 to pi (upper-half of
+ unit-circle. If whole is non-zero compute frequencies from 0
+ to 2*pi.
+
+ Outputs: (h,w)
+
+ h -- The frequency response.
+ w -- The frequencies at which h was computed.
+ """
+ b, a = map(atleast_1d, (b,a))
+ if whole:
+ lastpoint = 2*pi
+ else:
+ lastpoint = pi
+ if worN is None:
+ N = 512
+ w = Num.arange(0,lastpoint,lastpoint/N)
+ elif isinstance(worN, types.IntType):
+ N = worN
+ w = Num.arange(0,lastpoint,lastpoint/N)
+ else:
+ w = worN
+ w = atleast_1d(w)
+ zm1 = exp(-1j*w)
+ h = polyval(b[::-1], zm1) / polyval(a[::-1], zm1)
+ # if not plot is None:
+ # plot(w, h)
+ return h, w
diff --git a/gnuradio-runtime/python/gnuradio/gru/gnuplot_freqz.py b/gnuradio-runtime/python/gnuradio/gru/gnuplot_freqz.py
new file mode 100755
index 0000000000..dd483e4277
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/gnuplot_freqz.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+#
+# Copyright 2005,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.
+#
+
+__all__ = ['gnuplot_freqz']
+
+import tempfile
+import os
+import math
+import numpy
+
+from gnuradio import gr
+from gnuradio.gru.freqz import freqz
+
+
+def gnuplot_freqz (hw, Fs=None, logfreq=False):
+
+ """hw is a tuple of the form (h, w) where h is sequence of complex
+ freq responses, and w is a sequence of corresponding frequency
+ points. Plot the frequency response using gnuplot. If Fs is
+ provide, use it as the sampling frequency, else use 2*pi.
+
+ Returns a handle to the gnuplot graph. When the handle is reclaimed
+ the graph is torn down."""
+
+ data_file = tempfile.NamedTemporaryFile ()
+ cmd_file = os.popen ('gnuplot', 'w')
+
+ h, w = hw
+ ampl = 20 * numpy.log10 (numpy.absolute (h) + 1e-9)
+ phase = map (lambda x: math.atan2 (x.imag, x.real), h)
+
+ if Fs:
+ w *= (Fs/(2*math.pi))
+
+ for freq, a, ph in zip (w, ampl, phase):
+ data_file.write ("%g\t%g\t%g\n" % (freq, a, ph))
+
+ data_file.flush ()
+
+ cmd_file.write ("set grid\n")
+ if logfreq:
+ cmd_file.write ("set logscale x\n")
+ else:
+ cmd_file.write ("unset logscale x\n")
+ cmd_file.write ("plot '%s' using 1:2 with lines\n" % (data_file.name,))
+ cmd_file.flush ()
+
+ return (cmd_file, data_file)
+
+
+def test_plot ():
+ sample_rate = 2.0e6
+ #taps = firdes.low_pass(1, sample_rate, 200000, 100000, firdes.WIN_HAMMING)
+ taps = (0.0007329441141337156, 0.0007755281985737383, 0.0005323155201040208,
+ -7.679847761841656e-19, -0.0007277769618667662, -0.001415981911122799,
+ -0.0017135187517851591, -0.001282231998629868, 1.61239866282397e-18,
+ 0.0018589380197227001, 0.0035909228026866913, 0.004260237794369459,
+ 0.00310456077568233, -3.0331308923229716e-18, -0.004244099836796522,
+ -0.007970594801008701, -0.009214458055794239, -0.006562007591128349,
+ 4.714311174044374e-18, 0.008654761128127575, 0.01605774275958538,
+ 0.01841980405151844, 0.013079923577606678, -6.2821650235090215e-18,
+ -0.017465557903051376, -0.032989680767059326, -0.03894065320491791,
+ -0.028868533670902252, 7.388111706347014e-18, 0.04517475143074989,
+ 0.09890196472406387, 0.14991308748722076, 0.18646684288978577,
+ 0.19974154233932495, 0.18646684288978577, 0.14991308748722076,
+ 0.09890196472406387, 0.04517475143074989, 7.388111706347014e-18,
+ -0.028868533670902252, -0.03894065320491791, -0.032989680767059326,
+ -0.017465557903051376, -6.2821650235090215e-18, 0.013079923577606678,
+ 0.01841980405151844, 0.01605774275958538, 0.008654761128127575,
+ 4.714311174044374e-18, -0.006562007591128349, -0.009214458055794239,
+ -0.007970594801008701, -0.004244099836796522, -3.0331308923229716e-18,
+ 0.00310456077568233, 0.004260237794369459, 0.0035909228026866913,
+ 0.0018589380197227001, 1.61239866282397e-18, -0.001282231998629868,
+ -0.0017135187517851591, -0.001415981911122799, -0.0007277769618667662,
+ -7.679847761841656e-19, 0.0005323155201040208, 0.0007755281985737383,
+ 0.0007329441141337156)
+
+ # print len (taps)
+ return gnuplot_freqz (freqz (taps, 1), sample_rate)
+
+if __name__ == '__main__':
+ handle = test_plot ()
+ raw_input ('Press Enter to continue: ')
diff --git a/gnuradio-runtime/python/gnuradio/gru/hexint.py b/gnuradio-runtime/python/gnuradio/gru/hexint.py
new file mode 100644
index 0000000000..0fb5ecde04
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/hexint.py
@@ -0,0 +1,44 @@
+#
+# 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.
+#
+
+def hexint(mask):
+ """
+ Convert unsigned masks into signed ints.
+
+ This allows us to use hex constants like 0xf0f0f0f2 when talking to
+ our hardware and not get screwed by them getting treated as python
+ longs.
+ """
+ if mask >= 2**31:
+ return int(mask-2**32)
+ return mask
+
+def hexshort(mask):
+ """
+ Convert unsigned masks into signed shorts.
+
+ This allows us to use hex constants like 0x8000 when talking to
+ our hardware and not get screwed by them getting treated as python
+ longs.
+ """
+ if mask >= 2**15:
+ return int(mask-2**16)
+ return mask
diff --git a/gnuradio-runtime/python/gnuradio/gru/listmisc.py b/gnuradio-runtime/python/gnuradio/gru/listmisc.py
new file mode 100644
index 0000000000..9e70eb863c
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/listmisc.py
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+
+def list_reverse(x):
+ """
+ Return a copy of x that is reverse order.
+ """
+ r = list(x)
+ r.reverse()
+ return r
+
diff --git a/gnuradio-runtime/python/gnuradio/gru/mathmisc.py b/gnuradio-runtime/python/gnuradio/gru/mathmisc.py
new file mode 100644
index 0000000000..7e6f23a346
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/mathmisc.py
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+
+import math
+
+def gcd(a,b):
+ while b:
+ a,b = b, a % b
+ return a
+
+def lcm(a,b):
+ return a * b / gcd(a, b)
+
+def log2(x):
+ return math.log(x)/math.log(2)
diff --git a/gnuradio-runtime/python/gnuradio/gru/msgq_runner.py b/gnuradio-runtime/python/gnuradio/gru/msgq_runner.py
new file mode 100644
index 0000000000..767a74a717
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/msgq_runner.py
@@ -0,0 +1,82 @@
+#
+# 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+"""
+Convenience class for dequeuing messages from a gr.msg_queue and
+invoking a callback.
+
+Creates a Python thread that does a blocking read on the supplied
+gr.msg_queue, then invokes callback each time a msg is received.
+
+If the msg type is not 0, then it is treated as a signal to exit
+its loop.
+
+If the callback raises an exception, and the runner was created
+with 'exit_on_error' equal to True, then the runner will store the
+exception and exit its loop, otherwise the exception is ignored.
+
+To get the exception that the callback raised, if any, call
+exit_error() on the object.
+
+To manually stop the runner, call stop() on the object.
+
+To determine if the runner has exited, call exited() on the object.
+"""
+
+from gnuradio import gr
+import gnuradio.gr.gr_threading as _threading
+
+class msgq_runner(_threading.Thread):
+
+ def __init__(self, msgq, callback, exit_on_error=False):
+ _threading.Thread.__init__(self)
+
+ self._msgq = msgq
+ self._callback = callback
+ self._exit_on_error = exit_on_error
+ self._done = False
+ self._exited = False
+ self._exit_error = None
+ self.setDaemon(1)
+ self.start()
+
+ def run(self):
+ while not self._done:
+ msg = self._msgq.delete_head()
+ if msg.type() != 0:
+ self.stop()
+ else:
+ try:
+ self._callback(msg)
+ except Exception, e:
+ if self._exit_on_error:
+ self._exit_error = e
+ self.stop()
+ self._exited = True
+
+ def stop(self):
+ self._done = True
+
+ def exited(self):
+ return self._exited
+
+ def exit_error(self):
+ return self._exit_error
diff --git a/gnuradio-runtime/python/gnuradio/gru/os_read_exactly.py b/gnuradio-runtime/python/gnuradio/gru/os_read_exactly.py
new file mode 100644
index 0000000000..40b053770e
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/os_read_exactly.py
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+
+import os
+
+def os_read_exactly(file_descriptor, nbytes):
+ """
+ Replacement for os.read that blocks until it reads exactly nbytes.
+
+ """
+ s = ''
+ while nbytes > 0:
+ sbuf = os.read(file_descriptor, nbytes)
+ if not(sbuf):
+ return ''
+ nbytes -= len(sbuf)
+ s = s + sbuf
+ return s
diff --git a/gnuradio-runtime/python/gnuradio/gru/seq_with_cursor.py b/gnuradio-runtime/python/gnuradio/gru/seq_with_cursor.py
new file mode 100644
index 0000000000..def3299b69
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/seq_with_cursor.py
@@ -0,0 +1,77 @@
+#
+# Copyright 2003,2004 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+# misc utilities
+
+import types
+import exceptions
+
+class seq_with_cursor (object):
+ __slots__ = [ 'items', 'index' ]
+
+ def __init__ (self, items, initial_index = None, initial_value = None):
+ assert len (items) > 0, "seq_with_cursor: len (items) == 0"
+ self.items = items
+ self.set_index (initial_index)
+ if initial_value is not None:
+ self.set_index_by_value(initial_value)
+
+ def set_index (self, initial_index):
+ if initial_index is None:
+ self.index = len (self.items) / 2
+ elif initial_index >= 0 and initial_index < len (self.items):
+ self.index = initial_index
+ else:
+ raise exceptions.ValueError
+
+ def set_index_by_value(self, v):
+ """
+ Set index to the smallest value such that items[index] >= v.
+ If there is no such item, set index to the maximum value.
+ """
+ self.set_index(0) # side effect!
+ cv = self.current()
+ more = True
+ while cv < v and more:
+ cv, more = self.next() # side effect!
+
+ def next (self):
+ new_index = self.index + 1
+ if new_index < len (self.items):
+ self.index = new_index
+ return self.items[new_index], True
+ else:
+ return self.items[self.index], False
+
+ def prev (self):
+ new_index = self.index - 1
+ if new_index >= 0:
+ self.index = new_index
+ return self.items[new_index], True
+ else:
+ return self.items[self.index], False
+
+ def current (self):
+ return self.items[self.index]
+
+ def get_seq (self):
+ return self.items[:] # copy of items
+
diff --git a/gnuradio-runtime/python/gnuradio/gru/socket_stuff.py b/gnuradio-runtime/python/gnuradio/gru/socket_stuff.py
new file mode 100644
index 0000000000..489b6ab255
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/gru/socket_stuff.py
@@ -0,0 +1,62 @@
+#
+# 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.
+#
+
+# random socket related stuff
+
+import socket
+import os
+import sys
+
+def tcp_connect_or_die(sock_addr):
+ """
+
+ Args:
+ sock_addr: (host, port) to connect to (tuple)
+
+ Returns:
+ : socket or exits
+ """
+ s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
+ try:
+ s.connect(sock_addr)
+ except socket.error, err:
+ sys.stderr.write('Failed to connect to %s: %s\n' %
+ (sock_addr, os.strerror (err.args[0]),))
+ sys.exit(1)
+ return s
+
+def udp_connect_or_die(sock_addr):
+ """
+
+ Args:
+ sock_addr: (host, port) to connect to (tuple)
+
+ Returns:
+ : socket or exits
+ """
+ s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM)
+ try:
+ s.connect(sock_addr)
+ except socket.error, err:
+ sys.stderr.write('Failed to connect to %s: %s\n' %
+ (sock_addr, os.strerror (err.args[0]),))
+ sys.exit(1)
+ return s
diff --git a/gnuradio-runtime/swig/CMakeLists.txt b/gnuradio-runtime/swig/CMakeLists.txt
new file mode 100644
index 0000000000..cccb9a5741
--- /dev/null
+++ b/gnuradio-runtime/swig/CMakeLists.txt
@@ -0,0 +1,101 @@
+# 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.
+
+########################################################################
+# Setup swig generation
+########################################################################
+include(GrPython)
+include(GrSwig)
+
+set(GR_SWIG_INCLUDE_DIRS
+ ${GRUEL_INCLUDE_DIRS}
+ ${GNURADIO_RUNTIME_INCLUDE_DIRS}
+ ${GNURADIO_RUNTIME_SWIG_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${LOG4CPP_INCLUDE_DIRS}
+ ${Boost_INCLUDE_DIRS}
+)
+
+link_directories(${Boost_LIBRARY_DIRS})
+
+set(GR_SWIG_LIBRARIES
+ gnuradio-runtime
+ ${LOG4CPP_LIBRARIES}
+)
+
+# Only use if log4cpp is installed
+# Define ENABLE_GR_LOG for the .i file to ignore it.
+if(ENABLE_GR_LOG)
+ SET(GR_SWIG_FLAGS "-DENABLE_GR_LOG")
+endif(ENABLE_GR_LOG)
+
+if(ENABLE_GR_CTRLPORT)
+ list(APPEND GR_SWIG_FLAGS -DGR_CTRLPORT)
+ list(APPEND GR_SWIG_LIBRARIES ${ICE_LIBRARIES})
+ list(APPEND GR_SWIG_INCLUDE_DIRS ${ICE_INCLUDE_DIR})
+endif(ENABLE_GR_CTRLPORT)
+
+set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/runtime_swig_doc.i)
+set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../lib)
+set(GR_RUNTIME_SWIG_DOC_FILE ${GR_SWIG_DOC_FILE})
+
+GR_SWIG_MAKE(runtime_swig runtime_swig.i)
+
+GR_SWIG_INSTALL(
+ TARGETS runtime_swig
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/gr
+ COMPONENT "runtime_python"
+)
+
+install(
+ FILES
+ gnuradio_swig_bug_workaround.h
+ complex_vec_test.i
+ gnuradio.i
+ gr_basic_block.i
+ gr_block_detail.i
+ gr_block.i
+ gr_buffer.i
+ gr_constants.i
+ gr_dispatcher.i
+ gr_error_handler.i
+ gr_feval.i
+ gr_hier_block2.i
+ gr_io_signature.i
+ gr_logger.i
+ gr_message.i
+ gr_msg_handler.i
+ gr_msg_queue.i
+ gr_prefs.i
+ gr_realtime.i
+ gr_shared_ptr.i
+ gr_single_threaded_scheduler.i
+ gr_swig_block_magic.i
+ gr_sync_block.i
+ gr_sync_decimator.i
+ gr_sync_interpolator.i
+ gr_tagged_stream_block.i
+ gr_tags.i
+ gr_top_block.i
+ runtime_block_gateway.i
+ runtime_swig.i
+ ${CMAKE_CURRENT_BINARY_DIR}/runtime_swig_doc.i
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig
+ COMPONENT "runtime_swig"
+)
diff --git a/gnuradio-runtime/swig/complex_vec_test.i b/gnuradio-runtime/swig/complex_vec_test.i
new file mode 100644
index 0000000000..4b95633be7
--- /dev/null
+++ b/gnuradio-runtime/swig/complex_vec_test.i
@@ -0,0 +1,25 @@
+
+std::vector<std::complex<float> >
+complex_vec_test0();
+
+std::vector<std::complex<float> >
+complex_vec_test1(const std::vector<std::complex<float> > &input);
+
+std::complex<float>
+complex_scalar_test0();
+
+std::complex<float>
+complex_scalar_test1(std::complex<float> input);
+
+std::vector<int>
+int_vec_test0();
+
+std::vector<int>
+int_vec_test1(const std::vector<int> &input);
+
+std::vector<float>
+float_vec_test0();
+
+std::vector<float>
+float_vec_test1(const std::vector<float> &input);
+
diff --git a/gnuradio-runtime/swig/gen-swig-bug-fix b/gnuradio-runtime/swig/gen-swig-bug-fix
new file mode 100755
index 0000000000..5e9f82e7d7
--- /dev/null
+++ b/gnuradio-runtime/swig/gen-swig-bug-fix
@@ -0,0 +1,111 @@
+#!/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 sys
+import re
+
+def write_header (f):
+ f.write ('''/* -*- 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_GNURADIO_SWIG_BUG_WORKAROUND_H
+#define INCLUDED_GNURADIO_SWIG_BUG_WORKAROUND_H
+
+/*
+ * This include files works around a bug in SWIG 1.3.21 and 22
+ * where it fails to emit these declarations when doing
+ * %import "gnuradio.i"
+ */
+
+''')
+
+def write_trailer (f):
+ f.write ('''
+#endif /* INCLUDED_GNURADIO_SWIG_BUG_WORKAROUND_H */
+''')
+
+def doit (input, output):
+ re_RULES_BEGIN = re.compile ('RULES \(BEGIN\)')
+ re_RULES_END = re.compile ('RULES \(END\)')
+ re_RETURN = re.compile ('^\s*return')
+ re_NOT_ID = re.compile ('[^a-zA-Z0-9_]')
+ words = {}
+
+ write_header (output)
+ for line in input:
+ if re_RULES_BEGIN.search (line):
+ break
+
+ for line in input:
+ if re_RULES_END.search (line):
+ break
+ if not re_RETURN.match (line):
+ continue
+ line = re_NOT_ID.sub (' ', line)
+ line = re.sub (' +', ' ', line)
+ for w in line.split (' '):
+ words[w] = 1
+
+ for w in ('', 'return', 'void', 'x'):
+ del words[w]
+
+ wl = words.keys()
+ wl.sort ()
+ for w in wl:
+ output.write ('class ' + w + ';\n')
+
+ write_trailer (output)
+
+
+def main ():
+ if len (sys.argv) != 3:
+ sys.stderr.write ("usage: %s gnuradio_swig_python.cc gnuradio_swig_bug_workaround.h\n"
+ % (sys.argv[0],))
+ sys.exit (1)
+ input_filename = sys.argv[1]
+ output_filename = sys.argv[2]
+ input = open (input_filename, "r")
+ output = open (output_filename, "w")
+ doit (input, output)
+
+if __name__ == '__main__':
+ main ()
+
diff --git a/gnuradio-runtime/swig/gnuradio.i b/gnuradio-runtime/swig/gnuradio.i
new file mode 100644
index 0000000000..d85082aae2
--- /dev/null
+++ b/gnuradio-runtime/swig/gnuradio.i
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2004,2009,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+// Disable warning about base class types
+#pragma SWIG nowarn=401
+
+////////////////////////////////////////////////////////////////////////
+// gnuradio.i
+// SWIG interface definition
+////////////////////////////////////////////////////////////////////////
+
+%include <gruel_common.i>
+
+////////////////////////////////////////////////////////////////////////
+// Headers
+
+%{
+#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix
+#include <gr_types.h>
+#include <stddef.h> // size_t
+#include <complex>
+%}
+
+%feature("autodoc","1");
+
+// local file
+%include <gr_shared_ptr.i>
+%include <gr_types.h>
+%include <std_complex.i>
+%include <std_vector.i>
+%include <stl.i>
+%include <std_except.i>
+
+typedef std::complex<float> gr_complex;
+typedef std::complex<double> gr_complexd;
+typedef unsigned long long uint64_t;
+typedef long long int64_t;
+
+
+// instantiate the required template specializations
+
+namespace std {
+ %template() vector<unsigned char>;
+ %template() vector<char>;
+ %template() vector<short>;
+ %template() vector<int>;
+ %template() vector<float>;
+ %template() vector<double>;
+ // %template() std::complex<float>;
+
+ %template() vector< std::complex<float> >;
+ %template() vector< std::vector< unsigned char > >;
+ %template() vector< std::vector< char > >;
+ %template() vector< std::vector< short > >;
+ %template() vector< std::vector< int > >;
+ %template() vector< std::vector< float > >;
+ %template() vector< std::vector< double > >;
+ %template() vector< std::vector< std::complex<float> > >;
+};
+
+////////////////////////////////////////////////////////////////////////
+
+#ifndef SW_RUNTIME
+// import runtime_swig.i for all but sw_runtime, since it needs to %include
+%import <runtime_swig.i>
+#endif
+
+////////////////////////////////////////////////////////////////////////
diff --git a/gnuradio-runtime/swig/gnuradio_swig_bug_workaround.h b/gnuradio-runtime/swig/gnuradio_swig_bug_workaround.h
new file mode 100644
index 0000000000..1994f06609
--- /dev/null
+++ b/gnuradio-runtime/swig/gnuradio_swig_bug_workaround.h
@@ -0,0 +1,45 @@
+/* -*- 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_GNURADIO_SWIG_BUG_WORKAROUND_H
+#define INCLUDED_GNURADIO_SWIG_BUG_WORKAROUND_H
+
+/*
+ * This include files works around a bug in SWIG 1.3.21 and 22
+ * where it fails to emit these declarations when doing
+ * %import "gnuradio.i"
+ */
+
+class gr_base_error_handler;
+class gr_basic_block;
+class gr_block;
+class gr_error_handler;
+class gr_file_error_handler;
+class gr_hier_block2;
+class gr_msg_handler;
+class gr_msg_queue;
+class gr_sync_block;
+class gr_sync_decimator;
+class gr_sync_interpolator;
+class gr_top_block;
+
+#endif /* INCLUDED_GNURADIO_SWIG_BUG_WORKAROUND_H */
diff --git a/gnuradio-runtime/swig/gr_basic_block.i b/gnuradio-runtime/swig/gr_basic_block.i
new file mode 100644
index 0000000000..62f16462d6
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_basic_block.i
@@ -0,0 +1,62 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,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.
+ */
+
+class gr_basic_block;
+typedef boost::shared_ptr<gr_basic_block> gr_basic_block_sptr;
+%template(gr_basic_block_sptr) boost::shared_ptr<gr_basic_block>;
+%include "pmt_swig.i"
+using namespace pmt;
+
+// support vectors of these...
+namespace std {
+ %template(x_vector_gr_basic_block_sptr) vector<gr_basic_block_sptr>;
+};
+
+class gr_basic_block
+{
+protected:
+ gr_basic_block();
+
+public:
+ virtual ~gr_basic_block();
+ std::string name() const;
+ std::string symbol_name() const;
+ gr_io_signature_sptr input_signature() const;
+ gr_io_signature_sptr output_signature() const;
+ long unique_id() const;
+ gr_basic_block_sptr to_basic_block();
+ bool check_topology (int ninputs, int noutputs);
+ std::string alias();
+ void set_block_alias(std::string name);
+ void _post(pmt_t which_port, pmt_t msg);
+ pmt_t message_ports_in();
+ pmt_t message_ports_out();
+};
+
+%rename(block_ncurrently_allocated) gr_basic_block_ncurrently_allocated;
+long gr_basic_block_ncurrently_allocated();
+
+#ifdef SWIGPYTHON
+%pythoncode %{
+gr_basic_block_sptr.__repr__ = lambda self: "<gr_basic_block %s (%d)>" % (self.name(), self.unique_id ())
+%}
+#endif
diff --git a/gnuradio-runtime/swig/gr_block.i b/gnuradio-runtime/swig/gr_block.i
new file mode 100644
index 0000000000..a53489f9a2
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_block.i
@@ -0,0 +1,93 @@
+/* -*- 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.
+ */
+
+%include <gr_basic_block.i>
+
+class gr_block;
+typedef boost::shared_ptr<gr_block> gr_block_sptr;
+%template(gr_block_sptr) boost::shared_ptr<gr_block>;
+
+// support vectors of these...
+namespace std {
+ %template(x_vector_gr_block_sptr) vector<gr_block_sptr>;
+};
+
+class gr_block : public gr_basic_block {
+ protected:
+ gr_block (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature);
+
+ public:
+
+ virtual ~gr_block ();
+
+ unsigned history () const;
+
+ int output_multiple () const;
+ double relative_rate () const;
+
+ bool start();
+ bool stop();
+
+ uint64_t nitems_read(unsigned int which_input);
+ uint64_t nitems_written(unsigned int which_output);
+
+ // Methods to manage the block's max_noutput_items size.
+ int max_noutput_items();
+ void set_max_noutput_items(int m);
+ void unset_max_noutput_items();
+ bool is_set_max_noutput_items();
+
+ // Methods to manage block's min/max buffer sizes.
+ long max_output_buffer(int i);
+ void set_max_output_buffer(long max_output_buffer);
+ void set_max_output_buffer(int port, long max_output_buffer);
+ long min_output_buffer(int i);
+ void set_min_output_buffer(long min_output_buffer);
+ void set_min_output_buffer(int port, long min_output_buffer);
+
+ // Methods to access performance counters
+ float pc_noutput_items();
+ float pc_noutput_items_var();
+ float pc_nproduced();
+ float pc_nproduced_var();
+ float pc_input_buffers_full(int which);
+ float pc_input_buffers_full_var(int which);
+ std::vector<float> pc_input_buffers_full();
+ std::vector<float> pc_input_buffers_full_var();
+ float pc_output_buffers_full(int which);
+ float pc_output_buffers_full_var(int which);
+ std::vector<float> pc_output_buffers_full();
+ std::vector<float> pc_output_buffers_full_var();
+ float pc_work_time();
+ float pc_work_time_var();
+
+ // Methods to manage processor affinity.
+ void set_processor_affinity(const std::vector<int> &mask);
+ void unset_processor_affinity();
+ std::vector<int> processor_affinity();
+
+ // internal use
+ gr_block_detail_sptr detail () const { return d_detail; }
+ void set_detail (gr_block_detail_sptr detail) { d_detail = detail; }
+};
diff --git a/gnuradio-runtime/swig/gr_block_detail.i b/gnuradio-runtime/swig/gr_block_detail.i
new file mode 100644
index 0000000000..74ff463604
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_block_detail.i
@@ -0,0 +1,66 @@
+/* -*- 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.
+ */
+
+class gr_block_detail;
+typedef boost::shared_ptr<gr_block_detail> gr_block_detail_sptr;
+%template(gr_block_detail_sptr) boost::shared_ptr<gr_block_detail>;
+%rename(block_detail) gr_make_block_detail;
+%ignore gr_block_detail;
+
+gr_block_detail_sptr gr_make_block_detail (unsigned int ninputs, unsigned int noutputs);
+
+class gr_block_detail {
+ public:
+
+ ~gr_block_detail ();
+
+ int ninputs () const { return d_ninputs; }
+ int noutputs () const { return d_noutputs; }
+ bool sink_p () const { return d_noutputs == 0; }
+ bool source_p () const { return d_ninputs == 0; }
+
+ void set_input (unsigned int which, gr_buffer_reader_sptr reader);
+ gr_buffer_reader_sptr input (unsigned int which)
+ {
+ if (which >= d_ninputs)
+ throw std::invalid_argument ("gr_block_detail::input");
+ return d_input[which];
+ }
+
+ void set_output (unsigned int which, gr_buffer_sptr buffer);
+ gr_buffer_sptr output (unsigned int which)
+ {
+ if (which >= d_noutputs)
+ throw std::invalid_argument ("gr_block_detail::output");
+ return d_output[which];
+ }
+
+ // ----------------------------------------------------------------------------
+
+ private:
+ gr_block_detail (unsigned int ninputs, unsigned int noutputs);
+
+};
+
+
+%rename(block_detail_ncurrently_allocated) gr_block_detail_ncurrently_allocated;
+long gr_block_detail_ncurrently_allocated ();
diff --git a/gnuradio-runtime/swig/gr_buffer.i b/gnuradio-runtime/swig/gr_buffer.i
new file mode 100644
index 0000000000..390a94e050
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_buffer.i
@@ -0,0 +1,63 @@
+/* -*- 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.
+ */
+
+class gr_buffer;
+typedef boost::shared_ptr<gr_buffer> gr_buffer_sptr;
+%template(gr_buffer_sptr) boost::shared_ptr<gr_buffer>;
+%rename(buffer) gr_make_buffer;
+%ignore gr_buffer;
+
+gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link);
+
+class gr_buffer {
+ public:
+ ~gr_buffer ();
+
+ private:
+ gr_buffer (int nitems, size_t sizeof_item, gr_block_sptr link);
+};
+
+
+class gr_buffer_reader;
+typedef boost::shared_ptr<gr_buffer_reader> gr_buffer_reader_sptr;
+%template(gr_buffer_reader_sptr) boost::shared_ptr<gr_buffer_reader>;
+%ignore gr_buffer_reader;
+
+%rename(buffer_add_reader) gr_buffer_add_reader;
+gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link);
+
+class gr_buffer_reader {
+ public:
+ ~gr_buffer_reader ();
+
+ private:
+ friend class gr_buffer;
+ gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index, gr_block_sptr link);
+};
+
+
+%rename(buffer_ncurrently_allocated) gr_buffer_ncurrently_allocated;
+long gr_buffer_ncurrently_allocated ();
+
+%rename(buffer_reader_ncurrently_allocated) gr_buffer_reader_ncurrently_allocated;
+long gr_buffer_reader_ncurrently_allocated ();
+
diff --git a/gnuradio-runtime/swig/gr_constants.i b/gnuradio-runtime/swig/gr_constants.i
new file mode 100644
index 0000000000..a5aef14925
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_constants.i
@@ -0,0 +1,13 @@
+/* -*- c++ -*- */
+
+%rename(prefix) gr_prefix;
+%rename(sysconfdir) gr_sysconfdir;
+%rename(prefsdir) gr_prefsdir;
+%rename(build_date) gr_build_date;
+%rename(version) gr_version;
+
+const std::string gr_prefix();
+const std::string gr_sysconfdir();
+const std::string gr_prefsdir();
+const std::string gr_build_date();
+const std::string gr_version();
diff --git a/gnuradio-runtime/swig/gr_dispatcher.i b/gnuradio-runtime/swig/gr_dispatcher.i
new file mode 100644
index 0000000000..28737cd317
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_dispatcher.i
@@ -0,0 +1,55 @@
+/* -*- 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.
+ */
+
+class gr_dispatcher;
+typedef boost::shared_ptr<gr_dispatcher> gr_dispatcher_sptr;
+%template(gr_dispatcher_sptr) boost::shared_ptr<gr_dispatcher>;
+
+%rename(dispatcher) gr_make_dispatcher;
+gr_dispatcher_sptr gr_make_dispatcher();
+
+%rename(dispatcher_singleton) gr_dispatcher_singleton;
+gr_dispatcher_sptr gr_dispatcher_singleton();
+
+/*!
+ * \brief invoke callbacks based on select.
+ *
+ * \sa gr_select_handler
+ */
+class gr_dispatcher
+{
+ gr_dispatcher();
+
+public:
+ ~gr_dispatcher();
+
+ /*!
+ * \brief Event dispatching loop.
+ *
+ * Enter a polling loop that only terminates after all gr_select_handlers
+ * have been removed. \p timeout sets the timeout parameter to the select()
+ * call, measured in seconds.
+ *
+ * \param timeout maximum number of seconds to block in select.
+ */
+ void loop(double timeout=10);
+};
diff --git a/gnuradio-runtime/swig/gr_error_handler.i b/gnuradio-runtime/swig/gr_error_handler.i
new file mode 100644
index 0000000000..072394a727
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_error_handler.i
@@ -0,0 +1,69 @@
+/* -*- 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.
+ */
+
+%rename(error_handler) gr_error_handler;
+%rename(file_error_handler) gr_file_error_handler;
+
+class gr_error_handler {
+public:
+ enum seriousness {
+ ERR_DEBUG = 0x00000000,
+ ERR_MESSAGE = 0x00010000,
+ ERR_WARNING = 0x00020000,
+ ERR_ERROR = 0x00030000,
+ ERR_FATAL = 0x00040000
+ };
+
+ gr_error_handler() {}
+ virtual ~gr_error_handler();
+
+ static gr_error_handler *default_handler();
+ static gr_error_handler *silent_handler();
+
+ static bool has_default_handler();
+ static void set_default_handler(gr_error_handler *errh);
+
+ virtual int nwarnings() const = 0;
+ virtual int nerrors() const = 0;
+ virtual void reset_counts() = 0;
+
+ void verror_text(seriousness s, const std::string &text);
+};
+
+%ignore gr_base_error_handler;
+class gr_base_error_handler : public gr_error_handler {
+ int d_nwarnings;
+ int d_nerrors;
+
+public:
+ gr_base_error_handler() : d_nwarnings(0), d_nerrors(0) {}
+ int nwarnings() const { return d_nwarnings; }
+ int nerrors() const { return d_nerrors; }
+ void reset_counts() { d_nwarnings = d_nerrors = 0; }
+ void count_error(seriousness s);
+};
+
+class gr_file_error_handler : public gr_base_error_handler {
+public:
+ gr_file_error_handler(int file_descriptor);
+ ~gr_file_error_handler();
+};
diff --git a/gnuradio-runtime/swig/gr_feval.i b/gnuradio-runtime/swig/gr_feval.i
new file mode 100644
index 0000000000..bcf4f1e646
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_feval.i
@@ -0,0 +1,233 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,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.
+ */
+
+
+/*
+ * N.B., this is a _very_ non-standard SWIG .i file
+ *
+ * It contains a bunch of magic that is required to ensure that when
+ * these classes are used as base classes for python code,
+ * everything works when calling back from C++ into Python.
+ *
+ * The gist of the problem is that our C++ code is usually not holding
+ * the Python Global Interpreter Lock (GIL). Thus if we invoke a
+ * "director" method from C++, we'll end up in Python not holding the
+ * GIL. Disaster (SIGSEGV) will result. To avoid this we insert a
+ * "shim" that grabs and releases the GIL.
+ *
+ * If you don't understand SWIG "directors" or the Python GIL,
+ * don't bother trying to understand what's going on in here.
+ *
+ * [We could eliminate a bunch of this hair by requiring SWIG 1.3.29
+ * or later and some additional magic declarations, but many systems
+ * aren't shipping that version yet. Thus we kludge...]
+ */
+
+
+// Directors are only supported in Python, Java and C#
+#ifdef SWIGPYTHON
+%include "pmt_swig.i"
+using namespace pmt;
+
+// Enable SWIG directors for these classes
+%feature("director") gr_py_feval_dd;
+%feature("director") gr_py_feval_cc;
+%feature("director") gr_py_feval_ll;
+%feature("director") gr_py_feval;
+%feature("director") gr_py_feval_p;
+
+%feature("nodirector") gr_py_feval_dd::calleval;
+%feature("nodirector") gr_py_feval_cc::calleval;
+%feature("nodirector") gr_py_feval_ll::calleval;
+%feature("nodirector") gr_py_feval::calleval;
+%feature("nodirector") gr_py_feval_p::calleval;
+
+
+%rename(feval_dd) gr_py_feval_dd;
+%rename(feval_cc) gr_py_feval_cc;
+%rename(feval_ll) gr_py_feval_ll;
+%rename(feval) gr_py_feval;
+%rename(feval_p) gr_py_feval_p;
+
+//%exception {
+// try { $action }
+// catch (Swig::DirectorException &e) { std::cerr << e.getMessage(); SWIG_fail; }
+//}
+
+%{
+
+// class that ensures we acquire and release the Python GIL
+
+class ensure_py_gil_state {
+ PyGILState_STATE d_gstate;
+public:
+ ensure_py_gil_state() { d_gstate = PyGILState_Ensure(); }
+ ~ensure_py_gil_state() { PyGILState_Release(d_gstate); }
+};
+
+%}
+
+/*
+ * These are the real C++ base classes, however we don't want these exposed.
+ */
+%ignore gr_feval_dd;
+class gr_feval_dd
+{
+protected:
+ virtual double eval(double x);
+
+public:
+ gr_feval_dd() {}
+ virtual ~gr_feval_dd();
+
+ virtual double calleval(double x);
+};
+
+%ignore gr_feval_cc;
+class gr_feval_cc
+{
+protected:
+ virtual gr_complex eval(gr_complex x);
+
+public:
+ gr_feval_cc() {}
+ virtual ~gr_feval_cc();
+
+ virtual gr_complex calleval(gr_complex x);
+};
+
+%ignore gr_feval_ll;
+class gr_feval_ll
+{
+protected:
+ virtual long eval(long x);
+
+public:
+ gr_feval_ll() {}
+ virtual ~gr_feval_ll();
+
+ virtual long calleval(long x);
+};
+
+%ignore gr_feval;
+class gr_feval
+{
+protected:
+ virtual void eval();
+
+public:
+ gr_feval() {}
+ virtual ~gr_feval();
+
+ virtual void calleval();
+};
+
+%ignore gr_feval_p;
+class gr_feval_p
+{
+protected:
+ virtual void eval(pmt_t x);
+
+public:
+ gr_feval_p() {}
+ virtual ~gr_feval_p();
+
+ virtual void calleval(pmt_t x);
+};
+
+/*
+ * These are the ones to derive from in Python. They have the magic shim
+ * that ensures that we're holding the Python GIL when we enter Python land...
+ */
+
+%inline %{
+#include <gruel/pmt.h>
+
+class gr_py_feval_dd : public gr_feval_dd
+{
+ public:
+ double calleval(double x)
+ {
+ ensure_py_gil_state _lock;
+ return eval(x);
+ }
+};
+
+class gr_py_feval_cc : public gr_feval_cc
+{
+ public:
+ gr_complex calleval(gr_complex x)
+ {
+ ensure_py_gil_state _lock;
+ return eval(x);
+ }
+};
+
+class gr_py_feval_ll : public gr_feval_ll
+{
+ public:
+ long calleval(long x)
+ {
+ ensure_py_gil_state _lock;
+ return eval(x);
+ }
+};
+
+class gr_py_feval : public gr_feval
+{
+ public:
+ void calleval()
+ {
+ ensure_py_gil_state _lock;
+ eval();
+ }
+};
+
+class gr_py_feval_p : public gr_feval_p
+{
+ public:
+ void calleval(pmt::pmt_t x)
+ {
+ ensure_py_gil_state _lock;
+ eval(x);
+ }
+};
+
+%}
+
+
+
+// examples / test cases
+
+%rename(feval_dd_example) gr_feval_dd_example;
+double gr_feval_dd_example(gr_feval_dd *f, double x);
+
+%rename(feval_cc_example) gr_feval_cc_example;
+gr_complex gr_feval_cc_example(gr_feval_cc *f, gr_complex x);
+
+%rename(feval_ll_example) gr_feval_ll_example;
+long gr_feval_ll_example(gr_feval_ll *f, long x);
+
+%rename(feval_example) gr_feval_example;
+void gr_feval_example(gr_feval *f);
+
+#endif // SWIGPYTHON
diff --git a/gnuradio-runtime/swig/gr_hier_block2.i b/gnuradio-runtime/swig/gr_hier_block2.i
new file mode 100644
index 0000000000..a857394ca7
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_hier_block2.i
@@ -0,0 +1,88 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,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.
+ */
+
+%include <gr_basic_block.i>
+
+class gr_hier_block2;
+typedef boost::shared_ptr<gr_hier_block2> gr_hier_block2_sptr;
+%template(gr_hier_block2_sptr) boost::shared_ptr<gr_hier_block2>;
+
+// Hack to have a Python shim implementation of gr.hier_block2
+// that instantiates one of these and passes through calls
+%rename(hier_block2_swig) gr_make_hier_block2;
+gr_hier_block2_sptr gr_make_hier_block2(const std::string name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature)
+ throw (std::runtime_error);
+
+// Rename connect and disconnect so that we can more easily build a
+// better interface in scripting land.
+%rename(primitive_connect) gr_hier_block2::connect;
+%rename(primitive_disconnect) gr_hier_block2::disconnect;
+%rename(primitive_msg_connect) gr_hier_block2::msg_connect;
+%rename(primitive_msg_disconnect) gr_hier_block2::msg_disconnect;
+%rename(primitive_message_port_register_hier_in) gr_hier_block2::message_port_register_hier_in;
+%rename(primitive_message_port_register_hier_out) gr_hier_block2::message_port_register_hier_out;
+
+class gr_hier_block2 : public gr_basic_block
+{
+private:
+ gr_hier_block2(const std::string name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature);
+
+public:
+ ~gr_hier_block2 ();
+
+ void connect(gr_basic_block_sptr block)
+ throw (std::invalid_argument);
+ void connect(gr_basic_block_sptr src, int src_port,
+ gr_basic_block_sptr dst, int dst_port)
+ throw (std::invalid_argument);
+ void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport)
+ throw (std::runtime_error);
+ void msg_connect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport)
+ throw (std::runtime_error);
+ void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport,
+ gr_basic_block_sptr dst, pmt::pmt_t dstport)
+ throw (std::runtime_error);
+ void msg_disconnect(gr_basic_block_sptr src, std::string srcport,
+ gr_basic_block_sptr dst, std::string dstport)
+ throw (std::runtime_error);
+
+ void disconnect(gr_basic_block_sptr block)
+ throw (std::invalid_argument);
+ void disconnect(gr_basic_block_sptr src, int src_port,
+ gr_basic_block_sptr dst, int dst_port)
+ throw (std::invalid_argument);
+ void disconnect_all();
+ void lock();
+ void unlock();
+
+ void message_port_register_hier_in(pmt::pmt_t port_id);
+ void message_port_register_hier_out(pmt::pmt_t port_id);
+
+
+ gr_hier_block2_sptr to_hier_block2(); // Needed for Python type coercion
+};
diff --git a/gnuradio-runtime/swig/gr_io_signature.i b/gnuradio-runtime/swig/gr_io_signature.i
new file mode 100644
index 0000000000..fe1707e410
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_io_signature.i
@@ -0,0 +1,73 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2005,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.
+ */
+
+class gr_io_signature;
+typedef boost::shared_ptr<gr_io_signature> gr_io_signature_sptr;
+%template(gr_io_signature_sptr) boost::shared_ptr<gr_io_signature>;
+
+%rename(io_signature) gr_make_io_signature;
+%rename(io_signature2) gr_make_io_signature2;
+%rename(io_signature3) gr_make_io_signature3;
+%rename(io_signaturev) gr_make_io_signaturev;
+
+
+gr_io_signature_sptr
+gr_make_io_signature(int min_streams, int max_streams,
+ int sizeof_stream_item);
+
+gr_io_signature_sptr
+gr_make_io_signature2(int min_streams, int max_streams,
+ int sizeof_stream_item1,
+ int sizeof_stream_item2
+ );
+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
+ );
+gr_io_signature_sptr
+gr_make_io_signaturev(int min_streams, int max_streams,
+ const std::vector<int> &sizeof_stream_items);
+
+
+class gr_io_signature {
+ gr_io_signature (int min_streams, int max_streams, int sizeof_stream_item);
+
+ friend gr_io_signature_sptr
+ gr_make_io_signaturev(int min_streams,
+ int max_streams,
+ const std::vector<int> &sizeof_stream_item);
+
+ public:
+
+ // disabled. Suspected bug in SWIG 1.3.24
+ // static const int IO_INFINITE = -1;
+
+ ~gr_io_signature ();
+
+ int min_streams () const { return d_min_streams; }
+ int max_streams () const { return d_max_streams; }
+ int sizeof_stream_item (int index) const;
+ std::vector<int> sizeof_stream_items() const;
+};
+
diff --git a/gnuradio-runtime/swig/gr_logger.i b/gnuradio-runtime/swig/gr_logger.i
new file mode 100644
index 0000000000..b43bff5a89
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_logger.i
@@ -0,0 +1,79 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*******************************************************************************
+* Copyright 2011 Johns Hopkins University Applied Physics Lab
+* Author: Mark Plett
+* Description:
+* SWIG interface generator file for gr_logger module. gr_logger wraps log4cpp logging
+* for gnuradio.
+*******************************************************************************/
+
+%feature("autodoc", "1"); // generate python docstrings
+
+%include "exception.i"
+%import "gnuradio.i" // the common stuff
+
+%{
+#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix
+#include <stdexcept>
+%}
+
+//-----------------------------------
+
+%{
+// The .h files
+#include <gr_logger.h>
+%}
+
+%rename(logger) gr_logger;
+%rename(logger_config) gr_logger_config;
+%rename(logger_get_names) gr_logger_get_logger_names;
+%rename(logger_reset_config) gr_logger_reset_config;
+
+
+void gr_logger_config(const std::string config_filename,unsigned int watch_period = 0);
+std::vector<std::string> gr_logger_get_logger_names(void);
+void gr_logger_reset_config(void);
+
+class gr_logger
+{
+ public:
+ gr_logger(std::string logger_name);
+ void set_level(std::string level){GR_LOG_SET_LEVEL(d_logger,level);}
+ void get_level(std::string &level){GR_LOG_GET_LEVEL(d_logger,level);}
+ void debug(std::string msg){GR_LOG_DEBUG(d_logger,msg);};
+ void info(std::string msg){GR_LOG_INFO(d_logger,msg);};
+ void notice(std::string msg){GR_LOG_NOTICE(d_logger,msg);};
+ void warn(std::string msg){GR_LOG_WARN(d_logger,msg);};
+ void error(std::string msg){GR_LOG_ERROR(d_logger,msg);};
+ void crit(std::string msg){GR_LOG_CRIT(d_logger,msg);};
+ void alert(std::string msg){GR_LOG_ALERT(d_logger,msg);};
+ void fatal(std::string msg){GR_LOG_FATAL(d_logger,msg);};
+ void emerg(std::string msg){GR_LOG_EMERG(d_logger,msg);};
+ void errorIF(bool cond,std::string msg){GR_LOG_ERRORIF(d_logger,cond,msg);};
+ void log_assert(bool cond,std::string msg){GR_LOG_ASSERT(d_logger,cond,msg);};
+ void add_console_appender(std::string target,std::string pattern);
+ void add_file_appender(std::string filename,bool append,std::string pattern);
+ void add_rollingfile_appender(std::string filename,size_t filesize,int bkup_index,bool append,mode_t mode,std::string pattern);
+};
+
+
diff --git a/gnuradio-runtime/swig/gr_message.i b/gnuradio-runtime/swig/gr_message.i
new file mode 100644
index 0000000000..356bba5b58
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_message.i
@@ -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.
+ */
+
+class gr_message;
+typedef boost::shared_ptr<gr_message> gr_message_sptr;
+%template(gr_message_sptr) boost::shared_ptr<gr_message>;
+
+%rename(message_from_string) gr_make_message_from_string;
+gr_message_sptr
+gr_make_message_from_string(const std::string s, long type = 0, double arg1 = 0, double arg2 = 0);
+
+%rename(message) gr_make_message;
+gr_message_sptr
+gr_make_message(long type = 0, double arg1 = 0, double arg2 = 0, size_t length = 0);
+
+/*!
+ * \brief Message.
+ *
+ * The ideas and method names for adjustable message length were
+ * lifted from the click modular router "Packet" class.
+ */
+class gr_message {
+ gr_message (long type, double arg1, double arg2, size_t length);
+
+ unsigned char *buf_data() const { return d_buf_start; }
+ size_t buf_len() const { return d_buf_end - d_buf_start; }
+
+public:
+ ~gr_message ();
+
+ long type() const { return d_type; }
+ double arg1() const { return d_arg1; }
+ double arg2() const { return d_arg2; }
+
+ void set_type(long type) { d_type = type; }
+ void set_arg1(double arg1) { d_arg1 = arg1; }
+ void set_arg2(double arg2) { d_arg2 = arg2; }
+
+ size_t length() const;
+ std::string to_string() const;
+
+};
+
+%rename(message_ncurrently_allocated) gr_message_ncurrently_allocated;
+long gr_message_ncurrently_allocated();
+
diff --git a/gnuradio-runtime/swig/gr_msg_handler.i b/gnuradio-runtime/swig/gr_msg_handler.i
new file mode 100644
index 0000000000..f493dac1b2
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_msg_handler.i
@@ -0,0 +1,32 @@
+/* -*- 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.
+ */
+
+/*!
+ * \brief abstract class of message handlers
+ */
+class gr_msg_handler {
+public:
+ virtual ~gr_msg_handler () = 0;
+
+ //! handle \p msg
+ virtual void handle (gr_message_sptr msg) = 0;
+};
diff --git a/gnuradio-runtime/swig/gr_msg_queue.i b/gnuradio-runtime/swig/gr_msg_queue.i
new file mode 100644
index 0000000000..65cbe782b9
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_msg_queue.i
@@ -0,0 +1,107 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2009,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.
+ */
+
+class gr_msg_queue;
+typedef boost::shared_ptr<gr_msg_queue> gr_msg_queue_sptr;
+%template(gr_msg_queue_sptr) boost::shared_ptr<gr_msg_queue>;
+
+%rename(msg_queue) gr_make_msg_queue;
+gr_msg_queue_sptr gr_make_msg_queue(unsigned limit=0);
+
+/*!
+ * \brief thread-safe message queue
+ */
+%ignore gr_msg_queue;
+class gr_msg_queue : public gr_msg_handler {
+public:
+ gr_msg_queue(unsigned int limit);
+ ~gr_msg_queue();
+
+ //! Generic msg_handler method: insert the message.
+ //void handle(gr_message_sptr msg) { insert_tail (msg); }
+
+ /*!
+ * \brief Insert message at tail of queue.
+ * \param msg message
+ *
+ * Block if queue if full.
+ */
+ //void insert_tail(gr_message_sptr msg);
+
+ /*!
+ * \brief Delete message from head of queue and return it.
+ * Block if no message is available.
+ */
+ //gr_message_sptr delete_head();
+
+ /*!
+ * \brief If there's a message in the q, delete it and return it.
+ * If no message is available, return 0.
+ */
+ gr_message_sptr delete_head_nowait();
+
+ //! is the queue empty?
+ bool empty_p() const;
+
+ //! is the queue full?
+ bool full_p() const;
+
+ //! return number of messages in queue
+ unsigned int count() const;
+
+ //! Delete all messages from the queue
+ void flush();
+};
+
+/*
+ * The following kludge-o-rama releases the Python global interpreter
+ * lock around these potentially blocking calls. We don't want
+ * libgnuradio-core to be dependent on Python, thus we create these
+ * functions that serve as replacements for the normal C++ delete_head
+ * and insert_tail methods. The %pythoncode smashes these new C++
+ * functions into the gr.msg_queue wrapper class, so that everything
+ * appears normal. (An evil laugh is heard in the distance...)
+ */
+#ifdef SWIGPYTHON
+%inline %{
+ gr_message_sptr gr_py_msg_queue__delete_head(gr_msg_queue_sptr q) {
+ gr_message_sptr msg;
+ GR_PYTHON_BLOCKING_CODE(
+ msg = q->delete_head();
+ )
+ return msg;
+ }
+
+ void gr_py_msg_queue__insert_tail(gr_msg_queue_sptr q, gr_message_sptr msg) {
+ GR_PYTHON_BLOCKING_CODE(
+ q->insert_tail(msg);
+ )
+ }
+%}
+
+// smash in new python delete_head and insert_tail methods...
+%pythoncode %{
+gr_msg_queue_sptr.delete_head = gr_py_msg_queue__delete_head
+gr_msg_queue_sptr.insert_tail = gr_py_msg_queue__insert_tail
+gr_msg_queue_sptr.handle = gr_py_msg_queue__insert_tail
+%}
+#endif // SWIGPYTHON
diff --git a/gnuradio-runtime/swig/gr_prefs.i b/gnuradio-runtime/swig/gr_prefs.i
new file mode 100644
index 0000000000..c8c4242002
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_prefs.i
@@ -0,0 +1,63 @@
+/* -*- 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.
+ */
+
+class gr_prefs
+{
+public:
+ static gr_prefs *singleton();
+ static void set_singleton(gr_prefs *p);
+
+ virtual ~gr_prefs();
+
+ std::string to_string();
+
+ void save();
+
+ virtual bool has_section(const std::string &section);
+ virtual bool has_option(const std::string &section, const std::string &option);
+
+ virtual const std::string get_string(const std::string &section,
+ const std::string &option,
+ const std::string &default_val);
+ virtual void set_string(const std::string &section,
+ const std::string &option,
+ const std::string &val);
+ virtual bool get_bool(const std::string &section,
+ const std::string &option,
+ bool default_val);
+ virtual void set_bool(const std::string &section,
+ const std::string &option,
+ bool val);
+ virtual long get_long(const std::string &section,
+ const std::string &option,
+ long default_val);
+ virtual void set_long(const std::string &section,
+ const std::string &option,
+ long val);
+ virtual double get_double(const std::string &section,
+ const std::string &option,
+ double default_val);
+ virtual void set_double(const std::string &section,
+ const std::string &option,
+ double val);
+};
+
diff --git a/gnuradio-runtime/swig/gr_realtime.i b/gnuradio-runtime/swig/gr_realtime.i
new file mode 100644
index 0000000000..1051d3e2b3
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_realtime.i
@@ -0,0 +1,44 @@
+/* -*- 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.
+ */
+
+%rename(enable_realtime_scheduling) gr_enable_realtime_scheduling;
+
+// NOTE: This is duplicated from gruel/src/include/gruel/gr_realtime.h,
+// and must be kept in sync with it. This is the least evil workaround
+// for allowing 3rd party code builds to work when GNU Radio is
+// installed from binary packages into the standard system directories.
+// Otherwise, they can't find #include <gruel/gr_realtime.h>, since
+// pkg-config strips -I/usr/include from the --cflags path.
+
+namespace gruel {
+
+ typedef enum {
+ RT_OK = 0,
+ RT_NOT_IMPLEMENTED,
+ RT_NO_PRIVS,
+ RT_OTHER_ERROR
+ } rt_status_t;
+
+}
+
+typedef gruel::rt_status_t gr_rt_status_t;
+gr_rt_status_t gr_enable_realtime_scheduling();
diff --git a/gnuradio-runtime/swig/gr_shared_ptr.i b/gnuradio-runtime/swig/gr_shared_ptr.i
new file mode 100644
index 0000000000..323d33ad73
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_shared_ptr.i
@@ -0,0 +1,43 @@
+//
+// shared_ptr
+//
+// An enhanced relative of scoped_ptr with reference counted copy semantics.
+// The object pointed to is deleted when the last shared_ptr pointing to it
+// is destroyed or reset.
+//
+
+//
+// This is highly hacked up version of boost::shared_ptr
+// We just need enough to get SWIG to "do the right thing" and
+// generate "Smart Pointer" code.
+//
+
+namespace boost {
+
+template<class T> class shared_ptr
+{
+public:
+
+ shared_ptr()
+ {
+ }
+
+ shared_ptr (T * p)
+ {
+ }
+
+
+ T * operator-> () // never throws
+ {
+ return px;
+ }
+
+
+private:
+
+ T * px; // contained pointer
+ int pn;
+
+}; // shared_ptr
+
+}; \ No newline at end of file
diff --git a/gnuradio-runtime/swig/gr_single_threaded_scheduler.i b/gnuradio-runtime/swig/gr_single_threaded_scheduler.i
new file mode 100644
index 0000000000..7305cc9ada
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_single_threaded_scheduler.i
@@ -0,0 +1,54 @@
+/* -*- 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 <gr_runtime.h>
+
+class gr_single_threaded_scheduler;
+typedef boost::shared_ptr<gr_single_threaded_scheduler> gr_single_threaded_scheduler_sptr;
+%template(gr_single_threaded_scheduler_sptr) boost::shared_ptr<gr_single_threaded_scheduler>;
+%rename(single_threaded_scheduler) gr_make_single_threaded_scheduler;
+%ignore gr_single_threaded_scheduler;
+
+gr_single_threaded_scheduler_sptr
+gr_make_single_threaded_scheduler (const std::vector<gr_block_sptr> &modules);
+
+class gr_single_threaded_scheduler {
+ public:
+ ~gr_single_threaded_scheduler ();
+
+ // void run ();
+ void stop ();
+
+ private:
+ gr_single_threaded_scheduler (const std::vector<gr_block_sptr> &modules);
+};
+
+#ifdef SWIGPYTHON
+%inline %{
+ void sts_pyrun (gr_single_threaded_scheduler_sptr s) {
+ Py_BEGIN_ALLOW_THREADS; // release global interpreter lock
+ s->run ();
+ Py_END_ALLOW_THREADS; // acquire global interpreter lock
+ }
+%}
+#endif
+
diff --git a/gnuradio-runtime/swig/gr_swig_block_magic.i b/gnuradio-runtime/swig/gr_swig_block_magic.i
new file mode 100644
index 0000000000..6d1af6136d
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_swig_block_magic.i
@@ -0,0 +1,58 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+%define GR_SWIG_BLOCK_MAGIC(PKG, BASE_NAME)
+_GR_SWIG_BLOCK_MAGIC_HELPER(PKG, BASE_NAME, PKG ## _ ## BASE_NAME)
+%enddef
+
+%define _GR_SWIG_BLOCK_MAGIC_HELPER_COMMON(PKG, BASE_NAME, FULL_NAME)
+class FULL_NAME;
+typedef boost::shared_ptr<FULL_NAME> FULL_NAME ## _sptr;
+%template(FULL_NAME ## _sptr) boost::shared_ptr<FULL_NAME>;
+%rename(BASE_NAME) PKG ## _make_ ## BASE_NAME;
+%ignore FULL_NAME;
+%enddef
+
+#ifdef SWIGPYTHON
+%define _GR_SWIG_BLOCK_MAGIC_HELPER(PKG, BASE_NAME, FULL_NAME)
+_GR_SWIG_BLOCK_MAGIC_HELPER_COMMON(PKG, BASE_NAME, FULL_NAME)
+%pythoncode %{
+FULL_NAME ## _sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), self.unique_id ())
+%}
+%enddef
+#endif
+
+%define GR_SWIG_BLOCK_MAGIC2(PKG, BASE_NAME)
+%template(BASE_NAME ## _sptr) boost::shared_ptr<gr:: ## PKG ## :: ## BASE_NAME>;
+%pythoncode %{
+BASE_NAME ## _sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), self.unique_id())
+BASE_NAME = BASE_NAME.make;
+%}
+%enddef
+
+%define GR_SWIG_BLOCK_MAGIC_FACTORY(PKG, BASE_NAME, FACTORY)
+%template(FACTORY ## _sptr) boost::shared_ptr<gr:: ## PKG ## :: ## BASE_NAME>;
+%pythoncode %{
+FACTORY ## _sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), self.unique_id())
+FACTORY = BASE_NAME ## _make_ ## FACTORY;
+%}
+%enddef
diff --git a/gnuradio-runtime/swig/gr_sync_block.i b/gnuradio-runtime/swig/gr_sync_block.i
new file mode 100644
index 0000000000..d3e1bb9578
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_sync_block.i
@@ -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.
+ */
+class gr_sync_block : public gr_block
+{
+ protected:
+
+ gr_sync_block (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature);
+};
diff --git a/gnuradio-runtime/swig/gr_sync_decimator.i b/gnuradio-runtime/swig/gr_sync_decimator.i
new file mode 100644
index 0000000000..af4574b193
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_sync_decimator.i
@@ -0,0 +1,31 @@
+/* -*- 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.
+ */
+
+class gr_sync_decimator : public gr_sync_block
+{
+ protected:
+
+ gr_sync_decimator (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature,
+ unsigned decimation);
+};
diff --git a/gnuradio-runtime/swig/gr_sync_interpolator.i b/gnuradio-runtime/swig/gr_sync_interpolator.i
new file mode 100644
index 0000000000..6f8b08252f
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_sync_interpolator.i
@@ -0,0 +1,31 @@
+/* -*- 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.
+ */
+
+class gr_sync_interpolator : public gr_sync_block
+{
+ protected:
+
+ gr_sync_interpolator (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature,
+ unsigned interpolation);
+};
diff --git a/gnuradio-runtime/swig/gr_tagged_stream_block.i b/gnuradio-runtime/swig/gr_tagged_stream_block.i
new file mode 100644
index 0000000000..9fc803dca1
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_tagged_stream_block.i
@@ -0,0 +1,30 @@
+/* -*- 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.
+ */
+class gr_tagged_stream_block : public gr_block
+{
+ protected:
+ 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);
+};
+
diff --git a/gnuradio-runtime/swig/gr_tags.i b/gnuradio-runtime/swig/gr_tags.i
new file mode 100644
index 0000000000..828d0147ce
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_tags.i
@@ -0,0 +1,32 @@
+/*
+ * 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_tags.h>
+%}
+
+%include <pmt_swig.i> //for pmt support
+
+%include <gr_tags.h>
+
+//gives support for a vector of tags (get tags in range)
+%include "std_vector.i"
+%template(tags_vector_t) std::vector<gr_tag_t>;
diff --git a/gnuradio-runtime/swig/gr_top_block.i b/gnuradio-runtime/swig/gr_top_block.i
new file mode 100644
index 0000000000..1612ddf8c5
--- /dev/null
+++ b/gnuradio-runtime/swig/gr_top_block.i
@@ -0,0 +1,74 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,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.
+ */
+
+class gr_top_block;
+typedef boost::shared_ptr<gr_top_block> gr_top_block_sptr;
+%template(gr_top_block_sptr) boost::shared_ptr<gr_top_block>;
+
+// Hack to have a Python shim implementation of gr.top_block
+// that instantiates one of these and passes through calls
+%rename(top_block_swig) gr_make_top_block;
+gr_top_block_sptr gr_make_top_block(const std::string name)
+ throw (std::logic_error);
+
+class gr_top_block : public gr_hier_block2
+{
+private:
+ gr_top_block(const std::string &name);
+
+public:
+ ~gr_top_block();
+
+ void start(int max_noutput_items=100000000) throw (std::runtime_error);
+ void stop();
+ //void wait();
+ //void run() throw (std::runtime_error);
+ void lock();
+ void unlock() throw (std::runtime_error);
+ std::string edge_list();
+ void dump();
+
+ int max_noutput_items();
+ void set_max_noutput_items(int nmax);
+
+ gr_top_block_sptr to_top_block(); // Needed for Python type coercion
+};
+
+#ifdef SWIGPYTHON
+
+%inline %{
+void top_block_run_unlocked(gr_top_block_sptr r) throw (std::runtime_error)
+{
+ Py_BEGIN_ALLOW_THREADS; // release global interpreter lock
+ r->run();
+ Py_END_ALLOW_THREADS; // acquire global interpreter lock
+}
+
+void top_block_wait_unlocked(gr_top_block_sptr r) throw (std::runtime_error)
+{
+ Py_BEGIN_ALLOW_THREADS; // release global interpreter lock
+ r->wait();
+ Py_END_ALLOW_THREADS; // acquire global interpreter lock
+}
+%}
+
+#endif
diff --git a/gnuradio-runtime/swig/runtime_block_gateway.i b/gnuradio-runtime/swig/runtime_block_gateway.i
new file mode 100644
index 0000000000..94428c0d5e
--- /dev/null
+++ b/gnuradio-runtime/swig/runtime_block_gateway.i
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2011-2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+////////////////////////////////////////////////////////////////////////
+// standard includes
+////////////////////////////////////////////////////////////////////////
+%include <gnuradio.i>
+%include <gr_tags.i>
+%include <gr_feval.i>
+
+////////////////////////////////////////////////////////////////////////
+// data type support
+////////////////////////////////////////////////////////////////////////
+%template(int_vector_t) std::vector<int>;
+%template(void_star_vector_t) std::vector<void *>;
+
+////////////////////////////////////////////////////////////////////////
+// block headers
+////////////////////////////////////////////////////////////////////////
+%{
+#include <runtime_block_gateway.h>
+%}
+
+////////////////////////////////////////////////////////////////////////
+// block magic
+////////////////////////////////////////////////////////////////////////
+GR_SWIG_BLOCK_MAGIC(runtime, block_gateway);
+%include <runtime_block_gateway.h>
diff --git a/gnuradio-runtime/swig/runtime_swig.i b/gnuradio-runtime/swig/runtime_swig.i
new file mode 100644
index 0000000000..5b84a71c9f
--- /dev/null
+++ b/gnuradio-runtime/swig/runtime_swig.i
@@ -0,0 +1,170 @@
+/* -*- 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.
+ */
+
+#define GR_RUNTIME_API
+
+#ifndef SWIGIMPORTED
+%include "runtime_swig_doc.i"
+%module(directors="1") gnuradio_runtime
+#endif
+
+//%feature("autodoc", "1"); // generate python docstrings
+
+#define SW_RUNTIME
+%include "gnuradio.i" // the common stuff
+
+%{
+#include <gr_endianness.h>
+#include <gr_block.h>
+#include <gr_block_detail.h>
+#include <gr_buffer.h>
+#include <gr_constants.h>
+#include <gr_dispatcher.h>
+#include <gr_error_handler.h>
+#include <gr_feval.h>
+#include <gr_hier_block2.h>
+#include <gr_io_signature.h>
+#include <gr_message.h>
+#include <gr_msg_handler.h>
+#include <gr_msg_queue.h>
+#include <gr_prefs.h>
+#include <gr_realtime.h>
+#include <gr_runtime_types.h>
+#include <gr_single_threaded_scheduler.h>
+#include <gr_sync_block.h>
+#include <gr_sync_decimator.h>
+#include <gr_sync_interpolator.h>
+#include <gr_tagged_stream_block.h>
+#include <gr_tags.h>
+#include <gr_top_block.h>
+%}
+
+%constant int sizeof_char = sizeof(char);
+%constant int sizeof_short = sizeof(short);
+%constant int sizeof_int = sizeof(int);
+%constant int sizeof_float = sizeof(float);
+%constant int sizeof_double = sizeof(double);
+%constant int sizeof_gr_complex = sizeof(gr_complex);
+
+%include <gr_endianness.h>
+%include <gr_basic_block.i>
+%include <gr_block.i>
+%include <gr_block_detail.i>
+%include <gr_buffer.i>
+%include <gr_constants.i>
+%include <gr_dispatcher.i>
+%include <gr_error_handler.i>
+%include <gr_feval.i>
+%include <gr_hier_block2.i>
+%include <gr_io_signature.i>
+%include <gr_message.i>
+%include <gr_msg_handler.i>
+%include <gr_msg_queue.i>
+%include <gr_prefs.i>
+%include <gr_realtime.i>
+%include <gr_single_threaded_scheduler.i>
+%include <gr_swig_block_magic.i>
+%include <gr_sync_block.i>
+%include <gr_sync_decimator.i>
+%include <gr_sync_interpolator.i>
+%include <gr_tagged_stream_block.i>
+%include <gr_tags.i>
+%include <gr_top_block.i>
+%include <runtime_block_gateway.i>
+
+#ifdef GR_CTRLPORT
+
+typedef uint32_t DisplayType;
+
+// DisplayType Plotting types
+const uint32_t DISPNULL = 0x0000;
+const uint32_t DISPTIME = 0x0001;
+const uint32_t DISPXY = 0x0002;
+const uint32_t DISPPSD = 0x0004;
+const uint32_t DISPSPEC = 0x0008;
+const uint32_t DISPRAST = 0x0010;
+
+// DisplayType Options
+const uint32_t DISPOPTCPLX = 0x0100;
+const uint32_t DISPOPTLOG = 0x0200;
+const uint32_t DISPOPTSTEM = 0x0400;
+const uint32_t DISPOPTSTRIP = 0x0800;
+const uint32_t DISPOPTSCATTER = 0x1000;
+
+enum priv_lvl_t {
+ RPC_PRIVLVL_ALL = 0,
+ RPC_PRIVLVL_MIN = 9,
+ RPC_PRIVLVL_NONE = 10
+};
+
+enum KnobType {
+ KNOBBOOL, KNOBCHAR, KNOBINT, KNOBFLOAT,
+ KNOBDOUBLE, KNOBSTRING, KNOBLONG, KNOBVECBOOL,
+ KNOBVECCHAR, KNOBVECINT, KNOBVECFLOAT, KNOBVECDOUBLE,
+ KNOBVECSTRING, KNOBVECLONG
+};
+
+%template(StrVector) std::vector<std::string>;
+
+%{
+#include <rpcserver_booter_base.h>
+#include <rpcserver_booter_aggregator.h>
+#include <pycallback_object.h>
+%}
+
+%include <rpcserver_booter_base.h>
+%include <rpcserver_booter_aggregator.h>
+%include <pycallback_object.h>
+
+// Declare this class here but without the nested templated class
+// inside (replaces include of rpcmanager.h)
+class GR_RUNTIME_API rpcmanager : public virtual rpcmanager_base
+{
+ public:
+ rpcmanager();
+ ~rpcmanager();
+
+ static rpcserver_booter_base* get();
+
+ static void register_booter(rpcserver_booter_base* booter);
+};
+
+
+// Attach a new python callback method to Python function
+%extend pycallback_object {
+ // Set a Python function object as a callback function
+ // Note : PyObject *pyfunc is remapped with a typempap
+ void activate(PyObject *pyfunc)
+ {
+ self->set_callback(pyfunc);
+ Py_INCREF(pyfunc);
+ }
+}
+
+%template(RPC_get_string) pycallback_object<std::string>;
+%template(RPC_get_int) pycallback_object<int>;
+%template(RPC_get_float) pycallback_object<float>;
+%template(RPC_get_double) pycallback_object<double>;
+%template(RPC_get_vector_float) pycallback_object<std::vector<float> >;
+%template(RPC_get_vector_gr_complex) pycallback_object<std::vector<gr_complex> >;
+
+#endif /* GR_CTRLPORT */