summaryrefslogtreecommitdiff
path: root/gnuradio-core/src
diff options
context:
space:
mode:
authorTom Rondeau <trondeau@vt.edu>2012-12-04 11:38:47 -0500
committerTom Rondeau <trondeau@vt.edu>2012-12-04 11:38:47 -0500
commitaa29be054648c23dd9771c2acc6198e92174bca9 (patch)
tree12e7f6fc980968d594d6103b1ac6d1e636b26072 /gnuradio-core/src
parent744e351c408eba97030aa25c31eeddd6139114db (diff)
parente0d7e5251ed968007664a0c0314dd845381e8c76 (diff)
Merge branch 'next-ctrlport' into next
Diffstat (limited to 'gnuradio-core/src')
-rw-r--r--gnuradio-core/src/examples/CMakeLists.txt7
-rw-r--r--gnuradio-core/src/examples/ctrlport/CMakeLists.txt25
-rw-r--r--gnuradio-core/src/examples/ctrlport/pfb_sync_test-qt.grc772
-rw-r--r--gnuradio-core/src/examples/ctrlport/pfb_sync_test.grc705
-rw-r--r--gnuradio-core/src/lib/CMakeLists.txt38
-rw-r--r--gnuradio-core/src/lib/general/CMakeLists.txt9
-rw-r--r--gnuradio-core/src/lib/general/general.i13
-rw-r--r--gnuradio-core/src/lib/general/gr_ctrlport_probe2_c.cc139
-rw-r--r--gnuradio-core/src/lib/general/gr_ctrlport_probe2_c.h72
-rw-r--r--gnuradio-core/src/lib/general/gr_ctrlport_probe2_c.i36
-rw-r--r--gnuradio-core/src/lib/general/gr_ctrlport_probe_c.cc86
-rw-r--r--gnuradio-core/src/lib/general/gr_ctrlport_probe_c.h63
-rw-r--r--gnuradio-core/src/lib/general/gr_ctrlport_probe_c.i34
-rw-r--r--gnuradio-core/src/lib/general/gr_nop.cc28
-rw-r--r--gnuradio-core/src/lib/general/gr_nop.h6
-rw-r--r--gnuradio-core/src/lib/general/gr_nop.i3
-rw-r--r--gnuradio-core/src/lib/runtime/CMakeLists.txt36
-rw-r--r--gnuradio-core/src/lib/runtime/ICE_LICENSE54
-rw-r--r--gnuradio-core/src/lib/runtime/IcePy_Communicator.h35
-rw-r--r--gnuradio-core/src/lib/runtime/frontend.ice102
-rw-r--r--gnuradio-core/src/lib/runtime/gnuradio.ice150
-rw-r--r--gnuradio-core/src/lib/runtime/gr_basic_block.h35
-rw-r--r--gnuradio-core/src/lib/runtime/gr_top_block.cc26
-rw-r--r--gnuradio-core/src/lib/runtime/gr_top_block.h2
-rw-r--r--gnuradio-core/src/lib/runtime/ice_application_base.cc43
-rw-r--r--gnuradio-core/src/lib/runtime/ice_application_base.h242
-rw-r--r--gnuradio-core/src/lib/runtime/ice_server_template.h96
-rw-r--r--gnuradio-core/src/lib/runtime/nop.h57
-rw-r--r--gnuradio-core/src/lib/runtime/nop_impl.cc120
-rw-r--r--gnuradio-core/src/lib/runtime/nop_impl.h67
-rw-r--r--gnuradio-core/src/lib/runtime/pycallback_object.h183
-rw-r--r--gnuradio-core/src/lib/runtime/rpccallbackregister_base.h96
-rw-r--r--gnuradio-core/src/lib/runtime/rpcmanager.cc72
-rw-r--r--gnuradio-core/src/lib/runtime/rpcmanager.h59
-rw-r--r--gnuradio-core/src/lib/runtime/rpcmanager_base.h46
-rw-r--r--gnuradio-core/src/lib/runtime/rpcpmtconverters_ice.cc113
-rw-r--r--gnuradio-core/src/lib/runtime/rpcpmtconverters_ice.h35
-rw-r--r--gnuradio-core/src/lib/runtime/rpcregisterhelpers.h489
-rw-r--r--gnuradio-core/src/lib/runtime/rpcserver_aggregator.cc93
-rw-r--r--gnuradio-core/src/lib/runtime/rpcserver_aggregator.h100
-rw-r--r--gnuradio-core/src/lib/runtime/rpcserver_base.h47
-rw-r--r--gnuradio-core/src/lib/runtime/rpcserver_booter_aggregator.cc62
-rw-r--r--gnuradio-core/src/lib/runtime/rpcserver_booter_aggregator.h56
-rw-r--r--gnuradio-core/src/lib/runtime/rpcserver_booter_base.h44
-rw-r--r--gnuradio-core/src/lib/runtime/rpcserver_booter_ice.cc54
-rw-r--r--gnuradio-core/src/lib/runtime/rpcserver_booter_ice.h49
-rw-r--r--gnuradio-core/src/lib/runtime/rpcserver_ice.cc165
-rw-r--r--gnuradio-core/src/lib/runtime/rpcserver_ice.h221
-rw-r--r--gnuradio-core/src/lib/runtime/rpcserver_resource.cc126
-rw-r--r--gnuradio-core/src/lib/runtime/rpcserver_selector.cc40
-rw-r--r--gnuradio-core/src/lib/runtime/rpcserver_selector.h32
-rw-r--r--gnuradio-core/src/lib/runtime/runtime.i70
-rw-r--r--gnuradio-core/src/lib/swig/CMakeLists.txt10
-rw-r--r--gnuradio-core/src/python/gnuradio/CMakeLists.txt1
-rw-r--r--gnuradio-core/src/python/gnuradio/ctrlport/CMakeLists.txt129
-rw-r--r--gnuradio-core/src/python/gnuradio/ctrlport/DataPlotter.py382
-rw-r--r--gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py423
-rw-r--r--gnuradio-core/src/python/gnuradio/ctrlport/IceRadioClient.py102
-rw-r--r--gnuradio-core/src/python/gnuradio/ctrlport/__init__.py30
-rwxr-xr-xgnuradio-core/src/python/gnuradio/ctrlport/ctrlport-monitor477
-rwxr-xr-xgnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor581
-rw-r--r--gnuradio-core/src/python/gnuradio/ctrlport/icon.pngbin0 -> 1532 bytes
-rw-r--r--gnuradio-core/src/python/gnuradio/ctrlport/monitor.py60
-rwxr-xr-xgnuradio-core/src/python/gnuradio/ctrlport/qa_cpp_py_binding.py170
-rwxr-xr-xgnuradio-core/src/python/gnuradio/ctrlport/qa_cpp_py_binding_set.py148
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt1
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_nlog10.py1
67 files changed, 7865 insertions, 3 deletions
diff --git a/gnuradio-core/src/examples/CMakeLists.txt b/gnuradio-core/src/examples/CMakeLists.txt
index fc06c23476..7e27b123ee 100644
--- a/gnuradio-core/src/examples/CMakeLists.txt
+++ b/gnuradio-core/src/examples/CMakeLists.txt
@@ -20,4 +20,9 @@
add_subdirectory(mp-sched)
add_subdirectory(network)
add_subdirectory(tags)
-add_subdirectory(volk_benchmark) \ No newline at end of file
+add_subdirectory(volk_benchmark)
+
+if(ENABLE_GR_CTRLPORT)
+add_subdirectory(ctrlport)
+endif(ENABLE_GR_CTRLPORT)
+ \ No newline at end of file
diff --git a/gnuradio-core/src/examples/ctrlport/CMakeLists.txt b/gnuradio-core/src/examples/ctrlport/CMakeLists.txt
new file mode 100644
index 0000000000..47ef4c225e
--- /dev/null
+++ b/gnuradio-core/src/examples/ctrlport/CMakeLists.txt
@@ -0,0 +1,25 @@
+# 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
+ DESTINATION ${GR_PKG_CTRLPORT_EXAMPLES_DIR}
+ COMPONENT "core_python"
+)
diff --git a/gnuradio-core/src/examples/ctrlport/pfb_sync_test-qt.grc b/gnuradio-core/src/examples/ctrlport/pfb_sync_test-qt.grc
new file mode 100644
index 0000000000..7dffe82c8d
--- /dev/null
+++ b/gnuradio-core/src/examples/ctrlport/pfb_sync_test-qt.grc
@@ -0,0 +1,772 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Fri Nov 30 13:35:55 2012</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>pfb_sync_test_qt</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>qt_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>graymap</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>[[3,1,0,2]]</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(32, 387)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>amps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>[1]</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(32, 451)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>nfilts</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>32</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(99, 451)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_throttle</key>
+ <param>
+ <key>id</key>
+ <value>gr_throttle_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(623, 64)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_file_source</key>
+ <param>
+ <key>id</key>
+ <value>gr_file_source_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>file</key>
+ <value>/dev/urandom</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>repeat</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(228, 56)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_packed_to_unpacked_xx</key>
+ <param>
+ <key>id</key>
+ <value>gr_packed_to_unpacked_xx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>bits_per_chunk</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>endianness</key>
+ <value>gr.GR_MSB_FIRST</value>
+ </param>
+ <param>
+ <key>num_ports</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(408, 56)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(105, 126)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>300000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(14, 124)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>import</key>
+ <param>
+ <key>id</key>
+ <value>import_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>import</key>
+ <value>import random, math, cmath</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(14, 77)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_qtgui_range</key>
+ <param>
+ <key>id</key>
+ <value>phase</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Phase</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>0.5</value>
+ </param>
+ <param>
+ <key>start</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>stop</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>step</key>
+ <value>0.01</value>
+ </param>
+ <param>
+ <key>widget</key>
+ <value>counter_slider</value>
+ </param>
+ <param>
+ <key>orient</key>
+ <value>Qt.Horizontal</value>
+ </param>
+ <param>
+ <key>min_len</key>
+ <value>200</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(175, 387)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_null_sink</key>
+ <param>
+ <key>id</key>
+ <value>gr_null_sink_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(939, 313)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_qtgui_range</key>
+ <param>
+ <key>id</key>
+ <value>noise</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Noise</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>0.050</value>
+ </param>
+ <param>
+ <key>start</key>
+ <value>0.0001</value>
+ </param>
+ <param>
+ <key>stop</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>step</key>
+ <value>0.01</value>
+ </param>
+ <param>
+ <key>widget</key>
+ <value>counter_slider</value>
+ </param>
+ <param>
+ <key>orient</key>
+ <value>Qt.Horizontal</value>
+ </param>
+ <param>
+ <key>min_len</key>
+ <value>200</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(316, 389)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_const_sink_x</key>
+ <param>
+ <key>id</key>
+ <value>qtgui_const_sink_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>QT GUI Plot</value>
+ </param>
+ <param>
+ <key>size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-2</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>xmin</key>
+ <value>-2</value>
+ </param>
+ <param>
+ <key>xmax</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(949, 232)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>monitor</key>
+ <param>
+ <key>id</key>
+ <value>monitor_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>en</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(229, 6)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_pfb_clock_sync_xxx</key>
+ <param>
+ <key>id</key>
+ <value>digital_pfb_clock_sync_xxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>ccf</value>
+ </param>
+ <param>
+ <key>sps</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>loop_bw</key>
+ <value>2*3.14/100.0</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>firdes.root_raised_cosine(nfilts, nfilts,1.0/sps, 0.35, int(22*sps*nfilts))</value>
+ </param>
+ <param>
+ <key>filter_size</key>
+ <value>nfilts</value>
+ </param>
+ <param>
+ <key>init_phase</key>
+ <value>nfilts/2</value>
+ </param>
+ <param>
+ <key>max_dev</key>
+ <value>1.5</value>
+ </param>
+ <param>
+ <key>osps</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(322, 231)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_psk_mod</key>
+ <param>
+ <key>id</key>
+ <value>digital_psk_mod_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>constellation_points</key>
+ <value>4</value>
+ </param>
+ <param>
+ <key>mod_code</key>
+ <value>"gray"</value>
+ </param>
+ <param>
+ <key>differential</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>samples_per_symbol</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>excess_bw</key>
+ <value>0.35</value>
+ </param>
+ <param>
+ <key>verbose</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>log</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(846, 32)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>channels_channel_model</key>
+ <param>
+ <key>id</key>
+ <value>channels_channel_model_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>noise_voltage</key>
+ <value>noise</value>
+ </param>
+ <param>
+ <key>freq_offset</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>epsilon</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>cmath.exp(1j*noise)</value>
+ </param>
+ <param>
+ <key>seed</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(80, 247)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_costas_loop_cc</key>
+ <param>
+ <key>id</key>
+ <value>digital_costas_loop_cc_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>w</key>
+ <value>6.28/100.0</value>
+ </param>
+ <param>
+ <key>order</key>
+ <value>4</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(641, 313)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_ctrlport_probe2_c</key>
+ <param>
+ <key>id</key>
+ <value>probe2_c_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>constellation</value>
+ </param>
+ <param>
+ <key>desc</key>
+ <value>Constellation Points</value>
+ </param>
+ <param>
+ <key>len</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(936, 396)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>gr_packed_to_unpacked_xx_0</source_block_id>
+ <sink_block_id>gr_throttle_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_throttle_0</source_block_id>
+ <sink_block_id>digital_psk_mod_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_pfb_clock_sync_xxx_0</source_block_id>
+ <sink_block_id>digital_costas_loop_cc_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_file_source_0</source_block_id>
+ <sink_block_id>gr_packed_to_unpacked_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_pfb_clock_sync_xxx_0</source_block_id>
+ <sink_block_id>qtgui_const_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_costas_loop_cc_0</source_block_id>
+ <sink_block_id>qtgui_const_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_costas_loop_cc_0</source_block_id>
+ <sink_block_id>gr_null_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>channels_channel_model_0</source_block_id>
+ <sink_block_id>digital_pfb_clock_sync_xxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_psk_mod_0</source_block_id>
+ <sink_block_id>channels_channel_model_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_costas_loop_cc_0</source_block_id>
+ <sink_block_id>probe2_c_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gnuradio-core/src/examples/ctrlport/pfb_sync_test.grc b/gnuradio-core/src/examples/ctrlport/pfb_sync_test.grc
new file mode 100644
index 0000000000..9789086b9a
--- /dev/null
+++ b/gnuradio-core/src/examples/ctrlport/pfb_sync_test.grc
@@ -0,0 +1,705 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Tue Nov 27 16:02:43 2012</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>pfb_sync_test</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>wx_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>import</key>
+ <param>
+ <key>id</key>
+ <value>import_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>import</key>
+ <value>import random, math, cmath</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(14, 77)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>300000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(14, 124)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>graymap</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>[[3,1,0,2]]</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(32, 387)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>amps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>[1]</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(32, 451)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>nfilts</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>32</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(99, 451)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_costas_loop_cc</key>
+ <param>
+ <key>id</key>
+ <value>digital_costas_loop_cc_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>w</key>
+ <value>6.28/100.0</value>
+ </param>
+ <param>
+ <key>order</key>
+ <value>4</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(626, 223)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(105, 126)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_null_sink</key>
+ <param>
+ <key>id</key>
+ <value>gr_null_sink_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(964, 200)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_slider</key>
+ <param>
+ <key>id</key>
+ <value>noise</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value></value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>0.05</value>
+ </param>
+ <param>
+ <key>min</key>
+ <value>0.00000001</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>num_steps</key>
+ <value>100</value>
+ </param>
+ <param>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(281, 406)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_slider</key>
+ <param>
+ <key>id</key>
+ <value>phase</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value></value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>min</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>num_steps</key>
+ <value>100</value>
+ </param>
+ <param>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(167, 405)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_file_source</key>
+ <param>
+ <key>id</key>
+ <value>gr_file_source_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>file</key>
+ <value>/dev/urandom</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>repeat</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(228, 56)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_packed_to_unpacked_xx</key>
+ <param>
+ <key>id</key>
+ <value>gr_packed_to_unpacked_xx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>bits_per_chunk</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>endianness</key>
+ <value>gr.GR_MSB_FIRST</value>
+ </param>
+ <param>
+ <key>num_ports</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(408, 56)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_throttle</key>
+ <param>
+ <key>id</key>
+ <value>gr_throttle_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(623, 64)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>monitor</key>
+ <param>
+ <key>id</key>
+ <value>monitor_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>en</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(229, 6)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_pfb_clock_sync_xxx</key>
+ <param>
+ <key>id</key>
+ <value>digital_pfb_clock_sync_xxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>ccf</value>
+ </param>
+ <param>
+ <key>sps</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>loop_bw</key>
+ <value>2*3.14/100.0</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>firdes.root_raised_cosine(nfilts, nfilts,1.0/sps, 0.35, int(22*sps*nfilts))</value>
+ </param>
+ <param>
+ <key>filter_size</key>
+ <value>nfilts</value>
+ </param>
+ <param>
+ <key>init_phase</key>
+ <value>nfilts/2</value>
+ </param>
+ <param>
+ <key>max_dev</key>
+ <value>1.5</value>
+ </param>
+ <param>
+ <key>osps</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(322, 231)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_psk_mod</key>
+ <param>
+ <key>id</key>
+ <value>digital_psk_mod_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>constellation_points</key>
+ <value>4</value>
+ </param>
+ <param>
+ <key>mod_code</key>
+ <value>"gray"</value>
+ </param>
+ <param>
+ <key>differential</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>samples_per_symbol</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>excess_bw</key>
+ <value>0.35</value>
+ </param>
+ <param>
+ <key>verbose</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>log</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(846, 32)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>channels_channel_model</key>
+ <param>
+ <key>id</key>
+ <value>channels_channel_model_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>noise_voltage</key>
+ <value>noise</value>
+ </param>
+ <param>
+ <key>freq_offset</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>epsilon</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>cmath.exp(1j*phase)</value>
+ </param>
+ <param>
+ <key>seed</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(73, 247)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>probe2_c</key>
+ <param>
+ <key>id</key>
+ <value>probe2_c_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>constellation</value>
+ </param>
+ <param>
+ <key>desc</key>
+ <value>Constellation Points</value>
+ </param>
+ <param>
+ <key>len</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(912, 243)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>gr_packed_to_unpacked_xx_0</source_block_id>
+ <sink_block_id>gr_throttle_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_file_source_0</source_block_id>
+ <sink_block_id>gr_packed_to_unpacked_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_throttle_0</source_block_id>
+ <sink_block_id>digital_psk_mod_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_pfb_clock_sync_xxx_0</source_block_id>
+ <sink_block_id>digital_costas_loop_cc_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_costas_loop_cc_0</source_block_id>
+ <sink_block_id>gr_null_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>channels_channel_model_0</source_block_id>
+ <sink_block_id>digital_pfb_clock_sync_xxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_psk_mod_0</source_block_id>
+ <sink_block_id>channels_channel_model_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>channels_channel_model_0</source_block_id>
+ <sink_block_id>probe2_c_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gnuradio-core/src/lib/CMakeLists.txt b/gnuradio-core/src/lib/CMakeLists.txt
index dcb81c36a2..84b4fc131b 100644
--- a/gnuradio-core/src/lib/CMakeLists.txt
+++ b/gnuradio-core/src/lib/CMakeLists.txt
@@ -69,10 +69,46 @@ endif()
# Link against libvolk
list(APPEND gnuradio_core_libs volk)
-add_library(gnuradio-core SHARED ${gnuradio_core_sources})
+if(ENABLE_GR_CTRLPORT)
+
+########################################################################
+# Run ICE To compile Slice files
+########################################################################
+EXECUTE_PROCESS(
+ COMMAND "${ICE_SLICE2CPP}" "-I${CMAKE_CURRENT_SOURCE_DIR}/runtime"
+ "--output-dir=${CMAKE_CURRENT_BINARY_DIR}"
+ "${CMAKE_CURRENT_SOURCE_DIR}/runtime/gnuradio.ice"
+ )
+
+# Append generated file in build directory
+list(APPEND gnuradio_core_generated_sources
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio.cpp
+)
+
+list(APPEND gnuradio_core_generated_includes
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio.h
+)
+
+########################################################################
+# Add controlport stuff to gnuradio-core
+########################################################################
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+list(APPEND gnuradio_core_libs
+ ${ICE_LIBRARIES}
+)
+
+endif(ENABLE_GR_CTRLPORT)
+
+add_library(gnuradio-core SHARED ${gnuradio_core_sources} ${gnuradio_core_generated_sources})
target_link_libraries(gnuradio-core ${gnuradio_core_libs})
GR_LIBRARY_FOO(gnuradio-core RUNTIME_COMPONENT "core_runtime" DEVEL_COMPONENT "core_devel")
set_target_properties(gnuradio-core PROPERTIES LINK_INTERFACE_LIBRARIES "gruel")
+ADD_DEPENDENCIES(gnuradio-core
+ gnuradio_core_generated_sources
+ gnuradio_core_generated_includes
+ gnuradio_core_generated_swigs)
########################################################################
# Setup executables
diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt
index 80097c9db4..5978a035c7 100644
--- a/gnuradio-core/src/lib/general/CMakeLists.txt
+++ b/gnuradio-core/src/lib/general/CMakeLists.txt
@@ -242,6 +242,15 @@ set(gr_core_general_triple_threats
gr_message_strobe
)
+if(ENABLE_GR_CTRLPORT)
+ADD_DEFINITIONS(-DGR_CTRLPORT)
+list(APPEND gr_core_general_triple_threats
+ gr_ctrlport_probe_c
+ gr_ctrlport_probe2_c
+)
+endif(ENABLE_GR_CTRLPORT)
+
+
foreach(file_tt ${gr_core_general_triple_threats})
list(APPEND gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/${file_tt}.cc)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${file_tt}.h DESTINATION ${GR_INCLUDE_DIR}/gnuradio COMPONENT "core_devel")
diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i
index af275686f0..9af804afed 100644
--- a/gnuradio-core/src/lib/general/general.i
+++ b/gnuradio-core/src/lib/general/general.i
@@ -183,3 +183,16 @@
%include "gr_tag_debug.i"
%include "gr_block_gateway.i"
%include "gr_message_strobe.i"
+
+
+#ifdef GR_CTRLPORT
+
+%{
+#include <gr_ctrlport_probe_c.h>
+#include <gr_ctrlport_probe2_c.h>
+%}
+
+%include "gr_ctrlport_probe_c.i"
+%include "gr_ctrlport_probe2_c.i"
+
+#endif /* GR_CTRLPORT */
diff --git a/gnuradio-core/src/lib/general/gr_ctrlport_probe2_c.cc b/gnuradio-core/src/lib/general/gr_ctrlport_probe2_c.cc
new file mode 100644
index 0000000000..5d6abd2ee5
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_ctrlport_probe2_c.cc
@@ -0,0 +1,139 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_ctrlport_probe2_c.h>
+#include <gr_io_signature.h>
+
+gr_ctrlport_probe2_c_sptr
+gr_make_ctrlport_probe2_c(const std::string &id,
+ const std::string &desc, int len)
+{
+ return gnuradio::get_initial_sptr
+ (new gr_ctrlport_probe2_c(id, desc, len));
+}
+
+gr_ctrlport_probe2_c::gr_ctrlport_probe2_c(const std::string &id,
+ const std::string &desc, int len)
+ : gr_sync_block("probe2_c",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature(0, 0, 0)),
+ d_len(len),
+ d_const_rpc(d_name, id.c_str(), this, unique_id(), &gr_ctrlport_probe2_c::get,
+ pmt::pmt_make_c32vector(0,-2),
+ pmt::pmt_make_c32vector(0,2),
+ pmt::pmt_make_c32vector(0,0),
+ "volts", desc.c_str(), RPC_PRIVLVL_MIN, DISPXYSCATTER),
+ d_len_get_rpc(d_name, "length", this, unique_id(), &gr_ctrlport_probe2_c::length,
+ pmt::mp(1), pmt::mp(10*len), pmt::mp(len),
+ "samples", "get vector length", RPC_PRIVLVL_MIN, DISPNULL),
+ d_len_set_rpc(d_name, "length", this, unique_id(), &gr_ctrlport_probe2_c::set_length,
+ pmt::mp(1), pmt::mp(10*len), pmt::mp(len),
+ "samples", "set vector length", RPC_PRIVLVL_MIN, DISPNULL)
+{
+ set_length(len);
+}
+
+gr_ctrlport_probe2_c::~gr_ctrlport_probe2_c()
+{
+}
+
+void
+gr_ctrlport_probe2_c::forecast(int noutput_items, gr_vector_int &ninput_items_required)
+{
+ // make sure all inputs have noutput_items available
+ unsigned ninputs = ninput_items_required.size();
+ for(unsigned i = 0; i < ninputs; i++)
+ ninput_items_required[i] = d_len;
+}
+
+// boost::shared_mutex mutex_buffer;
+// mutable boost::mutex mutex_notify;
+// boost::condition_variable condition_buffer_ready;
+std::vector<gr_complex>
+gr_ctrlport_probe2_c::get()
+{
+ mutex_buffer.lock();
+ d_buffer.clear();
+ mutex_buffer.unlock();
+
+ // wait for condition
+ boost::mutex::scoped_lock lock(mutex_notify);
+ condition_buffer_ready.wait(lock);
+
+ mutex_buffer.lock();
+ std::vector<gr_complex> buf_copy = d_buffer;
+ assert(buf_copy.size() == d_len);
+ mutex_buffer.unlock();
+
+ return buf_copy;
+}
+
+void
+gr_ctrlport_probe2_c::set_length(int len)
+{
+ if(len > 8191) {
+ std::cerr << "probe2_c: length " << len
+ << " exceeds maximum buffer size of 8191" << std::endl;
+ len = 8191;
+ }
+
+ d_len = len;
+ d_buffer.reserve(d_len);
+}
+
+int
+gr_ctrlport_probe2_c::length() const
+{
+ return (int)d_len;
+}
+
+int
+gr_ctrlport_probe2_c::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const gr_complex *in = (const gr_complex*)input_items[0];
+
+ // copy samples to get buffer if we need samples
+ mutex_buffer.lock();
+ if(d_buffer.size() < d_len) {
+ // copy smaller of remaining buffer space and num inputs to work()
+ int num_copy = std::min( (int)(d_len - d_buffer.size()), noutput_items );
+
+ // TODO: convert this to a copy operator for speed...
+ for(int i = 0; i < num_copy; i++) {
+ d_buffer.push_back(in[i]);
+ }
+
+ // notify the waiting get() if we fill up the buffer
+ if(d_buffer.size() == d_len) {
+ condition_buffer_ready.notify_one();
+ }
+ }
+ mutex_buffer.unlock();
+
+ return noutput_items;
+}
diff --git a/gnuradio-core/src/lib/general/gr_ctrlport_probe2_c.h b/gnuradio-core/src/lib/general/gr_ctrlport_probe2_c.h
new file mode 100644
index 0000000000..aa0f86f635
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_ctrlport_probe2_c.h
@@ -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.
+ */
+
+#ifndef INCLUDED_CTRLPORT_PROBE2_C_H
+#define INCLUDED_CTRLPORT_PROBE2_C_H
+
+#include <gr_core_api.h>
+#include <gr_sync_block.h>
+#include <rpcregisterhelpers.h>
+#include <boost/thread/shared_mutex.hpp>
+
+class gr_ctrlport_probe2_c;
+typedef boost::shared_ptr<gr_ctrlport_probe2_c> gr_ctrlport_probe2_c_sptr;
+
+GR_CORE_API gr_ctrlport_probe2_c_sptr
+gr_make_ctrlport_probe2_c(const std::string &id, const std::string &desc, int len);
+
+class GR_CORE_API gr_ctrlport_probe2_c : public gr_sync_block
+{
+ private:
+ friend GR_CORE_API gr_ctrlport_probe2_c_sptr gr_make_ctrlport_probe2_c
+ (const std::string &id, const std::string &desc, int len);
+
+ gr_ctrlport_probe2_c(const std::string &id, const std::string &desc, int len);
+
+ size_t d_len;
+ boost::shared_mutex mutex_buffer;
+ mutable boost::mutex mutex_notify;
+ boost::condition_variable condition_buffer_ready;
+
+ std::vector<gr_complex> d_buffer;
+
+ rpcbasic_register_get<gr_ctrlport_probe2_c, std::vector<std::complex<float> > > d_const_rpc;
+ rpcbasic_register_get<gr_ctrlport_probe2_c, int> d_len_get_rpc;
+ rpcbasic_register_set<gr_ctrlport_probe2_c, int> d_len_set_rpc;
+
+ public:
+ ~gr_ctrlport_probe2_c();
+
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+
+ std::vector<gr_complex> get();
+
+ void set_length(int len);
+ int length() const;
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_CTRLPORT_PROBE2_C_H */
+
diff --git a/gnuradio-core/src/lib/general/gr_ctrlport_probe2_c.i b/gnuradio-core/src/lib/general/gr_ctrlport_probe2_c.i
new file mode 100644
index 0000000000..18858595ea
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_ctrlport_probe2_c.i
@@ -0,0 +1,36 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,ctrlport_probe2_c)
+
+gr_ctrlport_probe2_c_sptr
+gr_make_ctrlport_probe2_c(const std::string &id, const std::string &desc, int len);
+
+class gr_ctrlport_probe2_c : public gr_sync_block
+{
+public:
+ ~gr_ctrlport_probe2_c();
+ std::vector<gr_complex> get();
+ void set_length(int len);
+ int length() const;
+};
+
diff --git a/gnuradio-core/src/lib/general/gr_ctrlport_probe_c.cc b/gnuradio-core/src/lib/general/gr_ctrlport_probe_c.cc
new file mode 100644
index 0000000000..017a1fdcf7
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_ctrlport_probe_c.cc
@@ -0,0 +1,86 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_ctrlport_probe_c.h>
+#include <gr_io_signature.h>
+
+gr_ctrlport_probe_c_sptr
+gr_make_ctrlport_probe_c(const std::string &id,
+ const std::string &desc)
+{
+ return gnuradio::get_initial_sptr
+ (new gr_ctrlport_probe_c(id, desc));
+}
+
+
+gr_ctrlport_probe_c::gr_ctrlport_probe_c(const std::string &id,
+ const std::string &desc)
+ : gr_sync_block("probe_c",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature(0, 0, 0)),
+ d_ptr(NULL), d_ptrLen(0),
+ d_const_rpc(d_name, id.c_str(), this, unique_id(), &gr_ctrlport_probe_c::get,
+ pmt::pmt_make_c32vector(0,-2),
+ pmt::pmt_make_c32vector(0,2),
+ pmt::pmt_make_c32vector(0,0),
+ "volts", desc.c_str(), RPC_PRIVLVL_MIN, DISPXYSCATTER)
+{
+}
+
+gr_ctrlport_probe_c::~gr_ctrlport_probe_c()
+{
+}
+
+std::vector<gr_complex>
+gr_ctrlport_probe_c::get()
+{
+ if(d_ptr != NULL && d_ptrLen > 0) {
+ ptrlock.lock();
+ std::vector<gr_complex> vec(d_ptr, d_ptr+d_ptrLen);
+ ptrlock.unlock();
+ return vec;
+ }
+ else {
+ std::vector<gr_complex> vec;
+ return vec;
+ }
+}
+
+int
+gr_ctrlport_probe_c::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const gr_complex *in = (const gr_complex*)input_items[0];
+
+ // keep reference to symbols
+ ptrlock.lock();
+ d_ptr = in;
+ d_ptrLen = noutput_items;
+ ptrlock.unlock();
+
+ return noutput_items;
+}
diff --git a/gnuradio-core/src/lib/general/gr_ctrlport_probe_c.h b/gnuradio-core/src/lib/general/gr_ctrlport_probe_c.h
new file mode 100644
index 0000000000..bf9b4ffa4c
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_ctrlport_probe_c.h
@@ -0,0 +1,63 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_CTRLPORT_PROBE_C_H
+#define INCLUDED_CTRLPORT_PROBE_C_H
+
+#include <gr_core_api.h>
+#include <gr_sync_block.h>
+#include <rpcregisterhelpers.h>
+#include <boost/thread/shared_mutex.hpp>
+
+class gr_ctrlport_probe_c;
+typedef boost::shared_ptr<gr_ctrlport_probe_c> gr_ctrlport_probe_c_sptr;
+
+GR_CORE_API gr_ctrlport_probe_c_sptr
+gr_make_ctrlport_probe_c(const std::string &id, const std::string &desc);
+
+class GR_CORE_API gr_ctrlport_probe_c : public gr_sync_block
+{
+ private:
+ friend GR_CORE_API gr_ctrlport_probe_c_sptr gr_make_ctrlport_probe_c
+ (const std::string &id, const std::string &desc);
+
+ gr_ctrlport_probe_c(const std::string &id, const std::string &desc);
+
+ boost::shared_mutex ptrlock;
+
+ const gr_complex* d_ptr;
+ size_t d_ptrLen;
+
+ rpcbasic_register_get<gr_ctrlport_probe_c, std::vector<std::complex<float> > > d_const_rpc;
+
+ public:
+ ~gr_ctrlport_probe_c();
+
+ std::vector<gr_complex> get();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_CTRLPORT_GR_CTRLPORT_PROBE_C_H */
+
diff --git a/gnuradio-core/src/lib/general/gr_ctrlport_probe_c.i b/gnuradio-core/src/lib/general/gr_ctrlport_probe_c.i
new file mode 100644
index 0000000000..cd4c521cb0
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_ctrlport_probe_c.i
@@ -0,0 +1,34 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,ctrlport_probe_c)
+
+gr_ctrlport_probe_c_sptr
+gr_make_ctrlport_probe_c(const std::string &id, const std::string &desc);
+
+class gr_ctrlport_probe_c : public gr_sync_block
+{
+public:
+ ~gr_ctrlport_probe_c();
+ std::vector<gr_complex> get();
+};
+
diff --git a/gnuradio-core/src/lib/general/gr_nop.cc b/gnuradio-core/src/lib/general/gr_nop.cc
index edfe1d76d9..bfecc861dc 100644
--- a/gnuradio-core/src/lib/general/gr_nop.cc
+++ b/gnuradio-core/src/lib/general/gr_nop.cc
@@ -27,6 +27,10 @@
#include <gr_io_signature.h>
#include <boost/bind.hpp>
+#ifdef GR_CTRLPORT
+#include <rpcregisterhelpers.h>
+#endif
+
gr_nop_sptr
gr_make_nop (size_t sizeof_stream_item)
{
@@ -39,6 +43,8 @@ gr_nop::gr_nop (size_t sizeof_stream_item)
gr_make_io_signature (0, -1, sizeof_stream_item)),
d_nmsgs_recvd(0)
{
+ set_rpc();
+
// Arrange to have count_received_msgs called when messages are received.
message_port_register_in(pmt::mp("port"));
set_msg_handler(pmt::mp("port"), boost::bind(&gr_nop::count_received_msgs, this, _1));
@@ -64,3 +70,25 @@ gr_nop::general_work (int noutput_items,
return noutput_items;
}
+
+void
+gr_nop::set_rpc()
+{
+#ifdef GR_CTRLPORT
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_get<gr_nop, int>(
+ d_name, "test", this, unique_id(),
+ &gr_nop::ctrlport_test,
+ pmt::mp(-256), pmt::mp(255), pmt::mp(0),
+ "", "Simple testing variable",
+ RPC_PRIVLVL_MIN, DISPNULL)));
+
+ d_rpc_vars.push_back(
+ rpcbasic_sptr(new rpcbasic_register_set<gr_nop, int>(
+ d_name, "test", this, unique_id(),
+ &gr_nop::set_ctrlport_test,
+ pmt::mp(-256), pmt::mp(255), pmt::mp(0),
+ "", "Simple testing variable",
+ RPC_PRIVLVL_MIN, DISPNULL)));
+#endif /* GR_CTRLPORT */
+}
diff --git a/gnuradio-core/src/lib/general/gr_nop.h b/gnuradio-core/src/lib/general/gr_nop.h
index e0d59280f9..09bd900129 100644
--- a/gnuradio-core/src/lib/general/gr_nop.h
+++ b/gnuradio-core/src/lib/general/gr_nop.h
@@ -42,8 +42,12 @@ class GR_CORE_API gr_nop : public gr_block
friend GR_CORE_API gr_nop_sptr gr_make_nop (size_t sizeof_stream_item);
gr_nop (size_t sizeof_stream_item);
+ std::vector<boost::any> d_rpc_vars;
+ void set_rpc();
+
protected:
int d_nmsgs_recvd;
+ int d_ctrlport_test;
// Method that just counts any received messages.
void count_received_msgs(pmt::pmt_t msg);
@@ -56,6 +60,8 @@ protected:
int nmsgs_received() const { return d_nmsgs_recvd; }
+ int ctrlport_test() { return d_ctrlport_test; }
+ void set_ctrlport_test(int x) { d_ctrlport_test = x; }
};
#endif /* INCLUDED_GR_NOP_H */
diff --git a/gnuradio-core/src/lib/general/gr_nop.i b/gnuradio-core/src/lib/general/gr_nop.i
index 977a15d186..73ffa93630 100644
--- a/gnuradio-core/src/lib/general/gr_nop.i
+++ b/gnuradio-core/src/lib/general/gr_nop.i
@@ -25,6 +25,9 @@ GR_SWIG_BLOCK_MAGIC(gr,nop)
gr_nop_sptr gr_make_nop (size_t sizeof_stream_item);
class gr_nop : public gr_block {
+public:
+ int ctrlport_test();
+ void set_ctrlport_test(int x);
private:
gr_nop (size_t sizeof_stream_item);
};
diff --git a/gnuradio-core/src/lib/runtime/CMakeLists.txt b/gnuradio-core/src/lib/runtime/CMakeLists.txt
index 70938a0f17..11bfcfe279 100644
--- a/gnuradio-core/src/lib/runtime/CMakeLists.txt
+++ b/gnuradio-core/src/lib/runtime/CMakeLists.txt
@@ -90,6 +90,20 @@ list(APPEND gnuradio_core_sources
${CMAKE_CURRENT_SOURCE_DIR}/gr_select_handler.cc
)
+if(ENABLE_GR_CTRLPORT)
+list(APPEND gnuradio_core_sources
+ ${CMAKE_CURRENT_SOURCE_DIR}/ice_application_base.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_ice.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_booter_ice.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_booter_aggregator.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_aggregator.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_selector.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcpmtconverters_ice.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcmanager.cc
+)
+endif(ENABLE_GR_CTRLPORT)
+
+
########################################################################
# Append gnuradio-core test sources
########################################################################
@@ -157,6 +171,28 @@ install(FILES
COMPONENT "core_devel"
)
+
+if(ENABLE_GR_CTRLPORT)
+ADD_DEFINITIONS(-DGR_CTRLPORT)
+INSTALL(FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/ice_application_base.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/ice_server_template.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpccallbackregister_base.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcmanager_base.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcmanager.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcpmtconverters_ice.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcregisterhelpers.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_aggregator.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_base.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_booter_aggregator.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_booter_base.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_booter_ice.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_selector.h
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio
+ COMPONENT "core_devel"
+)
+endif(ENABLE_GR_CTRLPORT)
+
########################################################################
# Install swig headers
########################################################################
diff --git a/gnuradio-core/src/lib/runtime/ICE_LICENSE b/gnuradio-core/src/lib/runtime/ICE_LICENSE
new file mode 100644
index 0000000000..43ea7572d9
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/IcePy_Communicator.h b/gnuradio-core/src/lib/runtime/IcePy_Communicator.h
new file mode 100644
index 0000000000..d613190d2c
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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_core_api.h>
+
+namespace IcePy
+{
+
+extern PyTypeObject CommunicatorType;
+
+GR_CORE_API bool initCommunicator(PyObject*);
+
+GR_CORE_API Ice::CommunicatorPtr getCommunicator(PyObject*);
+
+GR_CORE_API PyObject* createCommunicator(const Ice::CommunicatorPtr&);
+GR_CORE_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-core/src/lib/runtime/frontend.ice b/gnuradio-core/src/lib/runtime/frontend.ice
new file mode 100644
index 0000000000..befb5b7a97
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/frontend.ice
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gnuradio.ice>
+
+[["python:package:gnuradio.ctrlport"]]
+module GNURadio {
+ module Frontend {
+
+ exception NotSupported {};
+ exception InvalidSetting { string msg; };
+ exception ReceiverFailure { string msg; };
+ exception NotExist {};
+ dictionary<string, string> TunerArgs;
+
+ struct TunerStatus {
+ int a2dbits;
+ float gain;
+ bool isInverted;
+ };
+
+ interface Tuner {
+ TunerStatus configureTuner(TunerArgs args); //ADDED
+ idempotent TunerStatus status();
+ idempotent float setGain(float gain) throws NotSupported, InvalidSetting;
+ idempotent bool setInversion(bool inverted) throws NotSupported, InvalidSetting;
+ };
+
+ struct ChannelStatus {
+ string uid;
+ bool active;
+ float freq;
+ float bandwidth;
+ int payloadBits;
+ bool isComplex;
+ string signalName;
+ };
+
+ interface Channel extends Component {
+ idempotent ChannelStatus status();
+ idempotent FeedInfo feed();
+ idempotent bool active();
+ void start();
+ void stop();
+ idempotent float setCenterFreq(float freq) throws NotSupported, InvalidSetting;
+ idempotent float setBandwidth(float bw) throws NotSupported, InvalidSetting;
+ idempotent int setPayloadBits(int bits) throws NotSupported, InvalidSetting;
+ idempotent bool setComplex(bool complex) throws NotSupported, InvalidSetting;
+ void removeChannel() throws NotSupported;
+ };
+
+ sequence<Tuner*> TunerSeq;
+ sequence<Channel*> ChannelSeq;
+
+ struct ChannelizerStatus {
+ string uid;
+ string signalName;
+ };
+
+ interface Channelizer extends Component {
+ idempotent ChannelizerStatus status();
+ idempotent Tuner* getTuner();
+ idempotent ChannelSeq getChannels();
+ idempotent ChannelSeq getActiveChannels();
+ idempotent ChannelSeq getInactiveChannels();
+ Channel* createChannel(float freq, float bw, int payloadBits, string address, int port) throws NotSupported;
+ };
+
+ sequence<Channelizer*> ChannelizerSeq;
+
+ interface Receiver extends AbstractReceiver {
+ idempotent ChannelizerSeq getInputs();
+// idempotent ChannelizerSeq getActiveInputs();
+// idempotent ChannelizerSeq getInactiveInputs();
+ idempotent Channel* getChannelByID(string id) throws NotExist;
+ idempotent Channelizer* getChannelizerByID(string id) throws NotExist;
+ };
+
+
+ };
+
+
+
+};
diff --git a/gnuradio-core/src/lib/runtime/gnuradio.ice b/gnuradio-core/src/lib/runtime/gnuradio.ice
new file mode 100644
index 0000000000..971d8fa0e6
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/gnuradio.ice
@@ -0,0 +1,150 @@
+/*
+ * 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 };
+
+enum DisplayType {
+ DISPNULL,
+ DISPTIMESERIESF,
+ DISPTIMESERIESC,
+ DISPXYSCATTER,
+ DISPXYLINE
+};
+
+struct KnobProp {
+ KnobType type;
+ string units;
+ string description;
+ DisplayType display;
+ Knob min;
+ Knob max;
+ Knob defaultvalue;
+};
+
+sequence<string> KnobIDList;
+dictionary<string, Knob> KnobMap;
+dictionary<string, KnobProp> KnobPropMap;
+dictionary<string, string> WaveformArgMap;
+
+interface StreamReceiver {
+ void push(VectorC data);
+};
+
+interface ControlPort {
+ void set(KnobMap knobs);
+ idempotent KnobMap get(KnobIDList knobs);
+ idempotent KnobPropMap properties(KnobIDList knobs);
+ void shutdown();
+
+// string subscribe(StreamReceiver* proxy, string streamName, int requestedPeriod, int RequestedSize);
+// idempotent void unsubscribe(string streamID);
+};
+
+struct FeedInfo {
+ string protocol;
+ string address;
+ string iface;
+ string port;
+};
+
+//TODO: convert this part to a Feed Info
+struct ReceiverInfo {
+ string uid;
+ string signalType;
+ string signalName;
+ string allocatableObjectID;
+ string signalProtocol;
+ string signalAddress;
+ string signalInterface;
+ string signalPort;
+};
+
+interface Component {
+ void setName(string newName);
+};
+
+module Frontend {
+ interface AbstractReceiver extends Component {
+ idempotent ReceiverInfo getReceiverInfo();
+ };
+};
+
+module Booter {
+ dictionary<string, string> WaveformArgs;
+
+ exception WaveformRunningError {
+ string waveformClass;
+ float centerFrequencyHz;
+ };
+ exception SignalSourceError {string msg; };
+
+ interface WaveformBooter extends Frontend::AbstractReceiver {
+ string launchWaveform(string waveformClass, WaveformArgs args)
+ throws WaveformRunningError, SignalSourceError;
+
+// string launchWaveformWithSession(string waveformClass, WaveformArgs args, IceGrid::Session* session)
+// throws WaveformRunningError;
+ WaveformArgMap getDriverEnum();
+ WaveformArgMap getSourceInfo();
+ idempotent bool waveformRunning();
+ idempotent string getWaveformClass();
+ void shutdown();
+ };
+};
+
+//interface Pingable {
+// bool ping();
+//};
+
+};
+
+#endif
diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.h b/gnuradio-core/src/lib/runtime/gr_basic_block.h
index e0fd5d2afd..7ad9191b72 100644
--- a/gnuradio-core/src/lib/runtime/gr_basic_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_basic_block.h
@@ -37,6 +37,10 @@
#include <boost/foreach.hpp>
#include <boost/thread/condition_variable.hpp>
+#ifdef GR_CTRLPORT
+#include <rpcregisterhelpers.h>
+#endif
+
/*!
* \brief The abstract base class for all signal processing blocks.
* \ingroup internal
@@ -95,6 +99,8 @@ protected:
std::string d_symbol_alias;
vcolor d_color;
+ 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
@@ -229,6 +235,35 @@ public:
throw std::runtime_error("attempt to set_msg_handler() on bad input message port!"); }
d_msg_handlers[which_port] = msg_handler_t(msg_handler);
}
+
+#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() {};
};
inline bool operator<(gr_basic_block_sptr lhs, gr_basic_block_sptr rhs)
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.cc b/gnuradio-core/src/lib/runtime/gr_top_block.cc
index e47473edd8..05cebe7d7f 100644
--- a/gnuradio-core/src/lib/runtime/gr_top_block.cc
+++ b/gnuradio-core/src/lib/runtime/gr_top_block.cc
@@ -42,6 +42,8 @@ gr_top_block::gr_top_block(const std::string &name)
gr_make_io_signature(0,0,0))
{
+ setup_rpc();
+
d_impl = new gr_top_block_impl(this);
}
@@ -113,3 +115,27 @@ 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>(
+ d_name, "max nouptut_items", this, unique_id(),
+ &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)));
+
+ // Setters
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_set<gr_top_block, int>(
+ d_name, "max noutput_items", this, unique_id(),
+ &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-core/src/lib/runtime/gr_top_block.h b/gnuradio-core/src/lib/runtime/gr_top_block.h
index 482a2beb1e..10a21a6434 100644
--- a/gnuradio-core/src/lib/runtime/gr_top_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_top_block.h
@@ -123,6 +123,8 @@ public:
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) {
diff --git a/gnuradio-core/src/lib/runtime/ice_application_base.cc b/gnuradio-core/src/lib/runtime/ice_application_base.cc
new file mode 100644
index 0000000000..88db6056c1
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/ice_application_base.h b/gnuradio-core/src/lib/runtime/ice_application_base.h
new file mode 100644
index 0000000000..44671f84b4
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/ice_application_base.h
@@ -0,0 +1,242 @@
+/* -*- 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_core_api.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_CORE_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 derp[] = ""; char* argv[2]; argv[0]=derp;
+ char buf[1024]; buf[0] = 0;
+ const char iceconf[] = "--Ice.Config=";
+ FILE *fp;
+
+ sprintf(buf, "/proc/%d/cmdline", getpid());
+
+ if(NULL == (fp = fopen(buf, "r"))) {
+ fprintf(stderr, "Cannot open file %s\n", buf);
+ exit(EXIT_FAILURE);
+ }
+
+ unsigned int counter(0);
+ while(fread(buf, 1, 1, fp)) {
+ if(*buf == iceconf[counter]) {
+ if(++counter == sizeof(iceconf) - 1) {
+ int result = fread(buf, sizeof(buf), 1, fp);
+ if((result == 0) && (feof(fp) == 0)) {
+ fprintf(stderr, "ICE file read failur %d\n", ferror(fp));
+ clearerr(fp);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ }
+ }
+ }
+ fclose(fp);
+
+ if(buf[0]) {
+ ice_application_common::d_have_ice_config = true;
+ ice_application_common::d_main_called = true;
+ d_application->main(0, argv, buf);
+ }
+ 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-core/src/lib/runtime/ice_server_template.h b/gnuradio-core/src/lib/runtime/ice_server_template.h
new file mode 100644
index 0000000000..8ddb03cc8e
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/nop.h b/gnuradio-core/src/lib/runtime/nop.h
new file mode 100644
index 0000000000..5b3166da7b
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/nop.h
@@ -0,0 +1,57 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_CTRLPORT_NOP_H
+#define INCLUDED_CTRLPORT_NOP_H
+
+#include <ctrlport/api.h>
+#include <gr_sync_block.h>
+
+namespace gr {
+ namespace ctrlport {
+
+ /*!
+ * \brief A NOP block for testing ctrlport
+ *
+ */
+ class CTRLPORT_API nop : virtual public gr_sync_block
+ {
+ public:
+ // gr::ctrlport::nop::sptr
+ typedef boost::shared_ptr<nop> sptr;
+
+ /*!
+ * Build a simple test block
+ */
+ static sptr make(size_t itemsize, int a, int b);
+
+ virtual void set_a(int b) = 0;
+ virtual void set_b(int b) = 0;
+ virtual int a() const = 0;
+ virtual int b() const = 0;
+ };
+
+ } /* namespace ctrlport */
+} /* namespace gr */
+
+#endif /* INCLUDED_CTRLPORT_NOP_H */
+
diff --git a/gnuradio-core/src/lib/runtime/nop_impl.cc b/gnuradio-core/src/lib/runtime/nop_impl.cc
new file mode 100644
index 0000000000..1aaba1b0cd
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/nop_impl.cc
@@ -0,0 +1,120 @@
+/* -*- 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 "nop_impl.h"
+#include <gr_io_signature.h>
+
+namespace gr {
+ namespace ctrlport {
+
+ nop::sptr
+ nop::make(size_t itemsize, int a, int b)
+ {
+ return gnuradio::get_initial_sptr
+ (new nop_impl(itemsize, a, b));
+ }
+
+
+ nop_impl::nop_impl(size_t itemsize, int a, int b)
+ : gr_sync_block("nop",
+ gr_make_io_signature(1, 1, itemsize),
+ gr_make_io_signature(0, 0, 0))
+ {
+ set_a(a);
+ set_b(b);
+ setup_rpc();
+ }
+
+ nop_impl::~nop_impl()
+ {
+ }
+
+ void
+ nop_impl::set_a(int a)
+ {
+ d_a = a;
+ }
+
+ void
+ nop_impl::set_b(int b)
+ {
+ d_b = b;
+ }
+
+ int
+ nop_impl::a() const
+ {
+ return d_a;
+ }
+
+ int
+ nop_impl::b() const
+ {
+ return d_b;
+ }
+
+ int
+ nop_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ return noutput_items;
+ }
+
+ void
+ nop_impl::setup_rpc()
+ {
+ d_get_32i_rpcs.push_back(get_32i_sptr
+ (new get_32i_t(d_name, "a", this, unique_id(),
+ &nop_impl::a,
+ pmt::mp(-128), pmt::mp(127), pmt::mp(0),
+ "", "Value of a",
+ RPC_PRIVLVL_MIN, DISPTIMESERIESF)));
+
+ d_get_32i_rpcs.push_back(get_32i_sptr
+ (new get_32i_t(d_name, "b", this, unique_id(),
+ &nop_impl::b,
+ pmt::mp(-128), pmt::mp(127), pmt::mp(0),
+ "", "Value of b",
+ RPC_PRIVLVL_MIN, DISPTIMESERIESF)));
+
+ d_set_32i_rpcs.push_back(set_32i_sptr
+ (new set_32i_t(d_name, "a", this, unique_id(),
+ &nop_impl::set_a,
+ pmt::mp(-128), pmt::mp(127), pmt::mp(0),
+ "", "Value of a",
+ RPC_PRIVLVL_MIN, DISPNULL)));
+
+ d_set_32i_rpcs.push_back(set_32i_sptr
+ (new set_32i_t(d_name, "b", this, unique_id(),
+ &nop_impl::set_b,
+ pmt::mp(-128), pmt::mp(127), pmt::mp(0),
+ "", "Value of b",
+ RPC_PRIVLVL_MIN, DISPNULL)));
+ }
+
+ } /* namespace ctrlport */
+} /* namespace gr */
diff --git a/gnuradio-core/src/lib/runtime/nop_impl.h b/gnuradio-core/src/lib/runtime/nop_impl.h
new file mode 100644
index 0000000000..a39ddac8f9
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/nop_impl.h
@@ -0,0 +1,67 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_CTRLPORT_NOP_IMPL_H
+#define INCLUDED_CTRLPORT_NOP_IMPL_H
+
+#include <ctrlport/nop.h>
+#include <ctrlport/rpcregisterhelpers.h>
+#include <boost/thread/shared_mutex.hpp>
+
+namespace gr {
+ namespace ctrlport {
+
+ class CTRLPORT_API nop_impl : public nop
+ {
+ private:
+ typedef rpcbasic_register_get<nop_impl, int> get_32i_t;
+ typedef rpcbasic_register_set<nop_impl, int> set_32i_t;
+
+ typedef boost::shared_ptr<get_32i_t> get_32i_sptr;
+ typedef boost::shared_ptr<set_32i_t> set_32i_sptr;
+
+ std::vector<get_32i_sptr> d_get_32i_rpcs;
+ std::vector<set_32i_sptr> d_set_32i_rpcs;
+
+ void setup_rpc();
+
+ int d_a, d_b;
+
+ public:
+ nop_impl(size_t itemsize, int a, int b);
+ ~nop_impl();
+
+ void set_a(int a);
+ void set_b(int b);
+ int a() const;
+ int b() const;
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace ctrlport */
+} /* namespace gr */
+
+#endif /* INCLUDED_CTRLPORT_NOP_IMPL_H */
+
diff --git a/gnuradio-core/src/lib/runtime/pycallback_object.h b/gnuradio-core/src/lib/runtime/pycallback_object.h
new file mode 100644
index 0000000000..c27bf00508
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/pycallback_object.h
@@ -0,0 +1,183 @@
+/* -*- 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>
+
+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::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::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_rpc(name, functionbase.c_str(), this, pycallback_object_count++,
+ &pycallback_object::get, pmt_assist<myType>::make(min),
+ pmt_assist<myType>::make(max), pmt_assist<myType>::make(deflt),
+ units.c_str(), desc.c_str(), RPC_PRIVLVL_MIN, dtype)
+ //pmt::mp(min), pmt::mp(max), pmt::mp(deflt), units.c_str(), desc.c_str(), RPC_PRIVLVL_MIN, dtype)
+ {
+ d_callback = NULL;
+ }
+
+ 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;
+ }
+
+private:
+ PyObject* d_callback;
+ rpcbasic_register_get<pycallback_object, myType> d_rpc;
+
+ myType pyCast(PyObject* obj) {
+ printf("TYPE NOT IMPLEMENTED!\n");
+ assert(0);
+ };
+};
+
+
+// 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-core/src/lib/runtime/rpccallbackregister_base.h b/gnuradio-core/src/lib/runtime/rpccallbackregister_base.h
new file mode 100644
index 0000000000..c8f60b310c
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/rpccallbackregister_base.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 RPCCALLBACKREGISTER_BASE_H
+#define RPCCALLBACKREGISTER_BASE_H
+
+#include <gruel/msg_accepter.h>
+#include <gruel/msg_producer.h>
+
+enum DisplayType {
+ DISPNULL,
+ DISPTIMESERIESF,
+ DISPTIMESERIESC,
+ DISPXYSCATTER,
+ DISPXYLINE
+};
+
+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-core/src/lib/runtime/rpcmanager.cc b/gnuradio-core/src/lib/runtime/rpcmanager.cc
new file mode 100644
index 0000000000..4d164b63f3
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/rpcmanager.h b/gnuradio-core/src/lib/runtime/rpcmanager.h
new file mode 100644
index 0000000000..8cb176b2e5
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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_core_api.h>
+#include <rpcmanager_base.h>
+#include <rpcserver_booter_aggregator.h>
+#include <memory>
+#include <iostream>
+
+class GR_CORE_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-core/src/lib/runtime/rpcmanager_base.h b/gnuradio-core/src/lib/runtime/rpcmanager_base.h
new file mode 100644
index 0000000000..60425c4a15
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/rpcpmtconverters_ice.cc b/gnuradio-core/src/lib/runtime/rpcpmtconverters_ice.cc
new file mode 100644
index 0000000000..31953fd09c
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/rpcpmtconverters_ice.cc
@@ -0,0 +1,113 @@
+/* -*- 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::pmt_is_real(knob)) {
+ return new GNURadio::KnobD(Ice::Double(pmt::pmt_to_double(knob)));
+ }
+ else if(pmt::pmt_is_symbol(knob)) {
+ std::string stuff = pmt::pmt_symbol_to_string(knob);
+ if(stuff.length() != 1) {
+ return new GNURadio::KnobS(stuff);
+ }
+ else {
+ return new GNURadio::KnobC(stuff[0]);
+ }
+
+ //TODO: FLOAT!!!
+ }
+ else if(pmt::pmt_is_integer(knob)) {
+ return new GNURadio::KnobI(pmt::pmt_to_long(knob));
+ }
+ else if(pmt::pmt_is_bool(knob)) {
+ return new GNURadio::KnobB(pmt::pmt_to_bool(knob));
+ }
+ else if(pmt::pmt_is_uint64(knob)) {
+ return new GNURadio::KnobL(pmt::pmt_to_uint64(knob));
+ //const std::complex<float> *pmt_c32vector_elements(pmt_t v, size_t &len); //< len is in elements
+ }
+ else if(pmt::pmt_is_c32vector(knob)) { // c32 sent as interleaved floats
+ size_t size(pmt::pmt_length(knob));
+ const float* start((const float*) pmt::pmt_c32vector_elements(knob,size));
+ return new GNURadio::KnobVecF(std::vector<float>(start,start+size*2));
+ }
+ else if(pmt::pmt_is_f32vector(knob)) {
+ size_t size(pmt::pmt_length(knob));
+ const float* start((const float*) pmt::pmt_f32vector_elements(knob,size));
+ return new GNURadio::KnobVecF(std::vector<float>(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::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 == "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-core/src/lib/runtime/rpcpmtconverters_ice.h b/gnuradio-core/src/lib/runtime/rpcpmtconverters_ice.h
new file mode 100644
index 0000000000..4403b96a2a
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/rpcregisterhelpers.h b/gnuradio-core/src/lib/runtime/rpcregisterhelpers.h
new file mode 100644
index 0000000000..bbe4f6c7d3
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/rpcregisterhelpers.h
@@ -0,0 +1,489 @@
+/* -*- 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>
+
+// 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::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::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::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::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::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::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::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::pmt_from_uint64((rpcinserter_base<T,uint64_t>::
+ _source->*rpcinserter_base<T,uint64_t>::_func)());
+ }
+};
+
+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::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::pmt_init_f32vector(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
+{
+ rpcbasic_register_set(const std::string& namebase,
+ const char* functionbase, T* obj,
+ const unsigned int serial,
+ 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_;
+#ifdef RPCSERVER_ENABLED
+ callbackregister_base::configureCallback_t
+ extractor(new rpcbasic_extractor<T,Tto>(obj, function),
+ minpriv_, std::string(units_),
+ display_, std::string(desc_), min, max, def);
+ std::ostringstream oss(std::ostringstream::out);
+ oss << namebase << serial << "::" << 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;
+};
+
+
+template<typename T, typename Tfrom>
+class rpcbasic_register_get : public rpcbasic_base
+{
+public:
+ // primary constructor to allow for T get() functions
+ rpcbasic_register_get(const std::string& namebase,
+ const char* functionbase, T* obj,
+ const int serial,
+ 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_;
+#ifdef RPCSERVER_ENABLED
+ callbackregister_base::queryCallback_t
+ inserter(new rpcbasic_inserter<T,Tfrom>(obj, function),
+ minpriv_, std::string(units_), display_, std::string(desc_), min, max, def);
+ std::ostringstream oss(std::ostringstream::out);
+ oss << namebase << serial << "::" << 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& namebase,
+ const char* functionbase, T* obj,
+ const int serial,
+ 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_;
+#ifdef RPCSERVER_ENABLED
+ callbackregister_base::queryCallback_t
+ inserter(new rpcbasic_inserter<T,Tfrom>(obj, (Tfrom (T::*)())function),
+ minpriv_, std::string(units_), display_, std::string(desc_), min, max, def);
+ std::ostringstream oss(std::ostringstream::out);
+ oss << namebase << serial << "::" << 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;
+};
+
+/*
+ * 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
+{
+private:
+ 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
+ rpcbasic_register_variable() :
+ d_rpc_reg("FAIL", "FAIL", this, -1, &rpcbasic_register_variable::get,
+ pmt::PMT_NIL, pmt::PMT_NIL, pmt::PMT_NIL, DISPNULL,
+ "FAIL", "FAIL", RPC_PRIVLVL_MIN),
+ d_variable(NULL)
+ {
+ std::cerr << "ERROR: rpcbasic_register_variable called with no args. "
+ << "If this happens, someone has tried to use rpcbasic_register_variable incorrectly.\n";
+ assert(0);
+ };
+
+ void set(Tfrom* _variable) { d_variable = _variable; }
+
+ rpcbasic_register_variable(const std::string& namebase,
+ const char* functionbase,
+ const int serial,
+ 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,serial,&rpcbasic_register_variable::get,
+ min,max,def,units_,desc_,minpriv_,display_),
+ d_variable(variable)
+ {
+ //std::cerr << "REGISTERING VAR: " << serial << " " << desc_ << std::endl;
+ }
+};
+
+#endif
diff --git a/gnuradio-core/src/lib/runtime/rpcserver_aggregator.cc b/gnuradio-core/src/lib/runtime/rpcserver_aggregator.cc
new file mode 100644
index 0000000000..d750d64905
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/rpcserver_aggregator.h b/gnuradio-core/src/lib/runtime/rpcserver_aggregator.h
new file mode 100644
index 0000000000..050d9bb1e5
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/rpcserver_base.h b/gnuradio-core/src/lib/runtime/rpcserver_base.h
new file mode 100644
index 0000000000..bc985c8d53
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/rpcserver_booter_aggregator.cc b/gnuradio-core/src/lib/runtime/rpcserver_booter_aggregator.cc
new file mode 100644
index 0000000000..c4c1b03c15
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/rpcserver_booter_aggregator.h b/gnuradio-core/src/lib/runtime/rpcserver_booter_aggregator.h
new file mode 100644
index 0000000000..da190a0be1
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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_core_api.h>
+#include <rpcserver_booter_base.h>
+#include <rpcserver_aggregator.h>
+#include <boost/shared_ptr.hpp>
+#include <string>
+
+class rpcserver_server;
+
+class GR_CORE_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-core/src/lib/runtime/rpcserver_booter_base.h b/gnuradio-core/src/lib/runtime/rpcserver_booter_base.h
new file mode 100644
index 0000000000..682944dada
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/rpcserver_booter_ice.cc b/gnuradio-core/src/lib/runtime/rpcserver_booter_ice.cc
new file mode 100644
index 0000000000..7cc8cc8938
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/rpcserver_booter_ice.h b/gnuradio-core/src/lib/runtime/rpcserver_booter_ice.h
new file mode 100644
index 0000000000..69dfcc7602
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/rpcserver_ice.cc b/gnuradio-core/src/lib/runtime/rpcserver_ice.cc
new file mode 100644
index 0000000000..12229a0688
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/rpcserver_ice.h b/gnuradio-core/src/lib/runtime/rpcserver_ice.h
new file mode 100644
index 0000000000..98847bbe05
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/rpcserver_ice.h
@@ -0,0 +1,221 @@
+/* -*- 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>
+
+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 {
+ throw IceUtil::NullHandleException(__FILE__, __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<GNURadio::DisplayType>(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<GNURadio::DisplayType>(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-core/src/lib/runtime/rpcserver_resource.cc b/gnuradio-core/src/lib/runtime/rpcserver_resource.cc
new file mode 100644
index 0000000000..fbc83d05a5
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/rpcserver_resource.cc
@@ -0,0 +1,126 @@
+/* -*- 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_resource.h>
+#include <rpcpmtconverters_resource.h>
+#include <iostream>
+
+rpcserver_resource::rpcserver_resource()
+{;}
+
+rpcserver_resource::~rpcserver_resource()
+{;}
+
+char*
+rpcserver_resource::identifier()
+{
+#warning "Code missing in function <char* rpcserver_resource::identifier()>"
+}
+
+void
+rpcserver_resource::start()
+{
+#warning "Code missing in function <void rpcserver_resource::start()>"
+}
+
+void
+rpcserver_resource::stop()
+{
+#warning "Code missing in function <void rpcserver_resource::stop()>"
+}
+
+void
+rpcserver_resource::initialize()
+{
+#warning "Code missing in function <void rpcserver_resource::initialize()>"
+}
+
+void
+rpcserver_resource::releaseObject()
+{
+#warning "Code missing in function <void rpcserver_resource::releaseObject()>"
+}
+
+void
+rpcserver_resource::runTest(::CORBA::ULong testid, CF::Properties& testValues)
+{
+#warning "Code missing in function <void rpcserver_resource::runTest(::CORBA::ULong testid, CF::Properties& testValues)>"
+}
+
+void
+rpcserver_resource::registerConfigureCallback(const std::string &id, const configureCallback_t callback)
+{
+ std::cout << "rpcserver_resource::registering: " << id << std::endl;
+ d_callbackmap.insert(ConfigureCallbackMap_t::value_type(id, callback));
+}
+
+void
+rpcserver_resource::configure(const CF::Properties& configProperties)
+{
+ for(unsigned int i=0;i<configProperties.length();++i) {
+ std::string id((const char*) configProperties[i].id);
+ ConfigureCallbackMap_t::const_iterator iter = d_setcallbackmap.begin();
+ iter = d_setcallbackmap.find(id);
+ if(iter != d_setcallbackmap.end()) {
+ (*iter->second).post(rpcpmtconverter::to_pmt(configProperties[i].value));
+ }
+ else {
+ throw IceUtil::NullHandleException(__FILE__, __LINE__);
+ }
+ }
+}
+
+//template<class T> struct rpcserver_resource::extractQuery : public std::unary_function<T, void> {
+// void operator()(T& x) {
+// x++;
+// }
+//};
+
+void
+rpcserver_resource::query(CF::Properties& configProperties)
+{
+ if(configProperties.length() == 0) {
+ //std::for_each(d_getcallbackmap.begin(), d_getcallbackmap.end(), extractQuery<getCallback_t>());
+ configProperties.length(d_getcallbackmap.size());
+
+ }
+ else {
+ for(unsigned int i=0;i<configProperties.length();++i) {
+ std::string id((const char*) configProperties[i].id);
+ QueryCallbackMap_t::const_iterator iter = d_getcallbackmap.begin();
+ iter = d_getcallbackmap.find(id);
+ if (iter != d_getcallbackmap.end()) {
+ //(*iter->second).post(rpcpmtconverter::to_pmt(configProperties[i].value));
+ = from_pmt((*iter->second.callback).retrieve(), c);
+ }
+ else {
+ throw IceUtil::NullHandleException(__FILE__, __LINE__);
+ }
+ }
+ }
+}
+
+CORBA::Object_ptr
+rpcserver_resource::getPort(const char* name)
+{
+#warning "Code missing in function <CORBA::Object_ptr rpcserver_resource::getPort(const char* name)>"
+}
diff --git a/gnuradio-core/src/lib/runtime/rpcserver_selector.cc b/gnuradio-core/src/lib/runtime/rpcserver_selector.cc
new file mode 100644
index 0000000000..362d5f060a
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/rpcserver_selector.h b/gnuradio-core/src/lib/runtime/rpcserver_selector.h
new file mode 100644
index 0000000000..fa63c9a2dc
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/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-core/src/lib/runtime/runtime.i b/gnuradio-core/src/lib/runtime/runtime.i
index 8e35df8342..f9945e8060 100644
--- a/gnuradio-core/src/lib/runtime/runtime.i
+++ b/gnuradio-core/src/lib/runtime/runtime.i
@@ -67,3 +67,73 @@
%include <gr_sync_decimator.i>
%include <gr_sync_interpolator.i>
%include <gr_top_block.i>
+
+
+#ifdef GR_CTRLPORT
+
+enum DisplayType {
+ DISPNULL,
+ DISPTIMESERIESF,
+ DISPTIMESERIESC,
+ DISPXYSCATTER,
+ DISPXYLINE
+};
+
+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_CORE_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 */
diff --git a/gnuradio-core/src/lib/swig/CMakeLists.txt b/gnuradio-core/src/lib/swig/CMakeLists.txt
index cf07cd3848..2c97588686 100644
--- a/gnuradio-core/src/lib/swig/CMakeLists.txt
+++ b/gnuradio-core/src/lib/swig/CMakeLists.txt
@@ -32,6 +32,13 @@ set(GR_SWIG_INCLUDE_DIRS
)
set(GR_SWIG_LIBRARIES gnuradio-core)
+if(ENABLE_GR_CTRLPORT)
+ list(APPEND GR_SWIG_FLAGS -DGR_CTRLPORT)
+ list(APPEND GR_SWIG_LIBRARIES
+ ${ICE_LIBRARIES}
+ )
+endif(ENABLE_GR_CTRLPORT)
+
########################################################################
# Build and install the swig targets
########################################################################
@@ -42,7 +49,8 @@ set(GR_SWIG_LIBRARIES gnuradio-core)
# X86_64, g++'s resident set size was 650MB!
# ----------------------------------------------------------------
-set(GR_SWIG_TARGET_DEPS general_generated gengen_generated filter_generated pmt_swig)
+set(GR_SWIG_TARGET_DEPS gnuradio_core_generated_sources
+ general_generated gengen_generated filter_generated pmt_swig)
foreach(what runtime general gengen io)
SET(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/${what}_swig_doc.i)
diff --git a/gnuradio-core/src/python/gnuradio/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/CMakeLists.txt
index bf696e0d34..ab46dbb92a 100644
--- a/gnuradio-core/src/python/gnuradio/CMakeLists.txt
+++ b/gnuradio-core/src/python/gnuradio/CMakeLists.txt
@@ -24,6 +24,7 @@ add_subdirectory(gru)
add_subdirectory(gruimpl)
add_subdirectory(blks2)
add_subdirectory(blks2impl)
+add_subdirectory(ctrlport)
GR_PYTHON_INSTALL(FILES
__init__.py
diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/ctrlport/CMakeLists.txt
new file mode 100644
index 0000000000..1268030ebb
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/CMakeLists.txt
@@ -0,0 +1,129 @@
+# 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_CUSTOM_COMMAND(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/../../gnuradio_ice.py
+ ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/__init__.py
+ ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/Booter/__init__.py
+ COMMAND ${ICE_SLICE2PY} -I${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/runtime
+ --output-dir=${CMAKE_CURRENT_BINARY_DIR}/../../
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/runtime/gnuradio.ice
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/runtime/gnuradio.ice
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "Slicing gnuradio.slice"
+)
+
+ADD_CUSTOM_COMMAND(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/frontend_ice.py
+ ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/Frontend/__init__.py
+ COMMAND ${ICE_SLICE2PY} -I${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/runtime
+ --output-dir=${CMAKE_CURRENT_BINARY_DIR}/../../
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/runtime/frontend.ice
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../../../lib/runtime/frontend.ice
+ ${CMAKE_CURRENT_BINARY_DIR}/../../gnuradio_ice.py
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "Slicing frontend.slice"
+)
+
+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_CURRENT_BINARY_DIR}/../../gnuradio_ice.py
+ ${CMAKE_CURRENT_BINARY_DIR}/../../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}/DataPlotter.py
+ ${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}/ctrlport-monitor
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr-ctrlport-monitor
+ DESTINATION ${GR_RUNTIME_DIR}
+ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
+ COMPONENT "core_python"
+)
+
+########################################################################
+# Handle the unit tests
+########################################################################
+if(ENABLE_GR_CTRLPORT)
+ 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)
+ set(GR_TEST_PYTHON_DIRS
+ ${CMAKE_BINARY_DIR}/gnuradio-core/src/python
+ ${CMAKE_BINARY_DIR}/gnuradio-core/src/lib/swig
+ )
+ set(GR_TEST_TARGET_DEPS gruel gnuradio-core)
+ GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${py_qa_test_file})
+ endforeach(py_qa_test_file)
+ endif(ENABLE_TESTING)
+endif(ENABLE_GR_CTRLPORT)
diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/DataPlotter.py b/gnuradio-core/src/python/gnuradio/ctrlport/DataPlotter.py
new file mode 100644
index 0000000000..c689bfa055
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/DataPlotter.py
@@ -0,0 +1,382 @@
+#!/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
+
+try:
+ from PyQt4.QtCore import Qt;
+ from PyQt4 import QtGui, QtCore
+except ImportError:
+ print "Error: Program requires PyQt4."
+ sys.exit(1)
+
+try:
+ import PyQt4.Qwt5 as Qwt
+ from PyQt4.Qwt5.anynumpy import *
+except ImportError:
+ print "Error: Program requires PyQwt5."
+ sys.exit(1)
+
+
+class Zoomer(Qwt.QwtPlotZoomer):
+ def __init__(self, a,b,c,d,e):
+ Qwt.QwtPlotZoomer.__init__(self,a,b,c,d,e);
+ self.zoomers = [];
+
+ def zoom(self, r):
+ Qwt.QwtPlotZoomer.zoom(self,r);
+ if(r == 0):
+ #self.plot().setAxisAutoScale(True);
+ self.plot().setAxisAutoScale(Qwt.QwtPlot.xBottom)
+ self.plot().setAxisAutoScale(Qwt.QwtPlot.yLeft)
+ self.plot().replot();
+
+
+class DataPlotterBase(Qwt.QwtPlot):
+ DefaultColors = ( Qt.green, Qt.red, Qt.blue,
+ Qt.cyan, Qt.magenta, Qt.black, Qt.darkRed,
+ Qt.darkGray, Qt.darkGreen, Qt.darkBlue, Qt.yellow)
+
+ dropSignal = QtCore.pyqtSignal(QtCore.QEvent)
+
+ def contextMenuEvent(self,e):
+ menu = QtGui.QMenu(self);
+ menu.addAction(self.gridAct);
+ menu.addAction(self.axesAct);
+ menu.addAction(self.curvAct);
+ menu.exec_(e.globalPos());
+
+ def dragEnterEvent(self,e):
+ e.accept();
+
+ def dropEvent(self, e):
+ Qwt.QwtPlot.dropEvent(self,e)
+ self.dropSignal.emit( e );
+
+
+
+ def __init__(self, parent, title, xlabel, ylabel, size, x, y):
+ Qwt.QwtPlot.__init__(self, parent)
+ self.callback = None;
+
+ self.gridAct = QtGui.QAction("Toggle &Grid", self, triggered=self.toggleGrid);
+ self.axesAct = QtGui.QAction("Toggle &Axes", self, triggered=self.toggleAxes);
+ self.curvAct = QtGui.QAction("Toggle &Lines", self, triggered=self.toggleCurve);
+
+ # Set up the zoomer
+ self.zoomer = Zoomer(Qwt.QwtPlot.xBottom,
+ Qwt.QwtPlot.yLeft,
+ Qwt.QwtPicker.DragSelection,
+ Qwt.QwtPicker.AlwaysOff,
+ self.canvas())
+
+ # Crosshairs + Data labels
+ self.picker = Qwt.QwtPlotPicker(
+ Qwt.QwtPlot.xBottom,
+ Qwt.QwtPlot.yLeft,
+ Qwt.QwtPicker.PointSelection | Qwt.QwtPicker.DragSelection,
+ Qwt.QwtPlotPicker.CrossRubberBand,
+ Qwt.QwtPicker.AlwaysOn,
+ self.canvas())
+ self.picker.setRubberBandPen(QtGui.QPen(QtCore.Qt.white, 1, QtCore.Qt.DashLine))
+ self.picker.setTrackerPen(QtGui.QPen(QtCore.Qt.white))
+
+ self.axisEnable = False;
+ # Turn off bloated data labels
+ self.enableAxis(Qwt.QwtPlot.yLeft, False);
+ self.enableAxis(Qwt.QwtPlot.xBottom, False);
+
+ # Allow panning with middle mouse
+ panner = Qwt.QwtPlotPanner(self.canvas())
+ panner.setAxisEnabled(Qwt.QwtPlot.yRight, False)
+ panner.setMouseButton(Qt.MidButton)
+
+ # Accept dropping of stats
+ self.setAcceptDrops(True);
+ self.grid = None
+ self.curve_en = False
+ self.setCanvasBackground(Qt.black)
+
+ self.insertLegend(Qwt.QwtLegend(), Qwt.QwtPlot.TopLegend);
+
+ self.axisEnabled(True);
+
+ self.resize(size, size)
+ self.setAutoReplot(False)
+ self.show()
+ self.updateTimerInt = 500
+ self.startTimer(self.updateTimerInt)
+
+ # Set Axis on and Grid off by default
+ #self.toggleGrid();
+ self.toggleAxes();
+
+
+ def toggleAxes(self):
+ self.axisEnable = not self.axisEnable;
+ self.enableAxis(Qwt.QwtPlot.yLeft, self.axisEnable);
+ self.enableAxis(Qwt.QwtPlot.xBottom, self.axisEnable);
+
+
+ def toggleGrid(self):
+ # grid
+ if self.grid == None:
+ self.grid = Qwt.QwtPlotGrid()
+ self.grid.enableXMin(True)
+ self.grid.setMajPen(QtGui.QPen(Qt.gray, 0, Qt.DotLine))
+ self.grid.setMinPen(QtGui.QPen(Qt.gray, 0 , Qt.DotLine))
+ self.grid.attach(self)
+ else:
+ self.grid.detach()
+ self.grid = None
+
+ return self
+
+ def toggleCurve(self):
+ self.curve_en = not self.curve_en;
+
+
+class DataPlotterVector(DataPlotterBase):
+ def __init__(self, parent, legend, title, xlabel, ylabel, size, x, y):
+ DataPlotterBase.__init__(self, parent, title, xlabel, ylabel, size, x, y)
+ self.curve = Qwt.QwtPlotCurve(legend)
+ self.curve.attach(self)
+ self.tag = None;
+ self.x = self.y = [0.0];
+
+ def offerData(self, data, tag):
+ if(tag == self.tag):
+ self.x = data[::2]; self.y = data[1::2]
+
+ def timerEvent(self, e):
+ if(self.curve_en):
+ self.curve.setStyle(Qwt.QwtPlotCurve.Lines)
+ self.curve.setPen(QtGui.QPen(Qt.green))
+ else:
+ self.curve.setStyle(Qwt.QwtPlotCurve.NoCurve)
+
+ self.curve.setData(self.x, self.y)
+ self.replot()
+
+ def enableLegend(self):
+ self.insertLegend(Qwt.QwtLegend(), Qwt.QwtPlot.BottomLegend);
+ return self
+
+ def setSeries(self,tag,name):
+ self.tag = tag;
+ self.curve.setTitle(name)
+
+
+class DataPlotterVectorOne(DataPlotterVector):
+ def __init__(self, parent, legend, title, xlabel, ylabel, size, x, y):
+ DataPlotterVector.__init__(self, parent, legend, title, xlabel, ylabel, size, x, y)
+ self.curve.setSymbol(Qwt.QwtSymbol(Qwt.QwtSymbol.XCross,
+ QtGui.QBrush(), QtGui.QPen(Qt.green), QtCore.QSize(2, 2)))
+ self.setAxisAutoScale(True)
+ self.axisSet = False;
+
+ # Lines on by default
+ self.toggleCurve();
+
+ def offerData(self, data, tag):
+ if(tag == self.tag):
+ if not self.axisSet:
+ self.setAxisScale(1, 0, len(data));
+ self.axisSet = True;
+ self.x = range(0,len(data));
+ self.y = data;
+
+
+class DataPlotterConst(DataPlotterVector):
+ def __init__(self, parent, legend, title, xlabel, ylabel, size, x, y):
+ DataPlotterVector.__init__(self, parent, legend, title, xlabel, ylabel, size, x, y)
+ self.x = arange(-2, 100.1, 2)
+ self.y = zeros(len(self.x), Float)
+ self.curve.setSymbol(Qwt.QwtSymbol(Qwt.QwtSymbol.XCross,
+ QtGui.QBrush(), QtGui.QPen(Qt.green), QtCore.QSize(2, 2)))
+ self.curve.setStyle(Qwt.QwtPlotCurve.NoCurve)
+ self.setAxisAutoScale(False)
+
+class DataPlotterEqTaps(DataPlotterVector):
+ def __init__(self, parent, legend, title, xlabel, ylabel, size, x, y, qtcolor):
+ DataPlotterVector.__init__(self, parent, legend, title, xlabel, ylabel, size, x, y)
+ self.x = arange(-.5, .5, 1)
+ self.y = zeros(len(self.x), Float)
+ self.curve.setPen(QtGui.QPen(qtcolor))
+
+class DataPlotterTicker(DataPlotterBase):
+ def __init__(self, parent, title, xlabel, ylabel, size, x, y, seconds = 60):
+ DataPlotterBase.__init__(self, parent, title, xlabel, ylabel, size, x, y)
+ self.series = {}
+ self.setTimeScale(seconds)
+
+# AAAAAAAAAA - enable for legend at bottom
+# self.insertLegend(Qwt.QwtLegend(), Qwt.QwtPlot.BottomLegend);
+ self.skipEvents=1
+
+ def setTimeScale(self, seconds):
+ intv = float(self.updateTimerInt) / 1000
+ self.x = arange(0, seconds, intv)
+ #self.x = arange(0, seconds, 1)
+ return self
+
+ def addSeries(self, tag, label, qtcolor = None, alpha = 1):
+ class Series:
+ def __init__(self, tag, label, qtcolor, x, plot):
+ self.vec = zeros(len(x), Float)
+ self.value = None
+ self.alpha = alpha
+ self.curve = Qwt.QwtPlotCurve(label)
+ self.curve.setPen(QtGui.QPen(qtcolor))
+ self.plot = plot
+
+ if qtcolor == None: qtcolor = self.DefaultColors[len(self.series)]
+ self.series[tag] = s = Series(tag, label, qtcolor, self.x, self)
+ self.enableSeries(tag)
+ return self
+
+ def enableSeries(self, tag):
+ if self.hasSeries(tag):
+ s = self.series[tag]
+ s.enabled = True
+ s.curve.attach(s.plot)
+ return self
+
+ def disableSeries(self, tag):
+ if self.hasSeries(tag):
+ s = self.series[tag]
+ s.enabled = False
+ s.curve.detach()
+ return self
+
+ def toggleSeries(self,tag):
+ if self.seriesIsEnabled(tag):
+ self.disableSeries(tag)
+ else:
+ self.enableSeries(tag)
+ return self
+
+ def timerEvent(self, e):
+ for k, v in self.series.iteritems():
+ if v.value == None: continue
+ elif v.vec[0] == 0: v.vec = ones(len(v.vec), Float)*v.value
+
+ prev = v.vec[0]
+ v.vec = concatenate((v.vec[:1], v.vec[:-1]), 1)
+ v.vec[0] = v.value*v.alpha + prev*(1-v.alpha)
+ self.series[k] = v
+ v.curve.setData(self.x, v.vec)
+ self.replot()
+
+ def offerData(self, value, tag):
+ if(self.series.has_key(tag)):
+ if not value == NaN:
+ self.series[tag].value = value
+ #print "Data Offer %s items:"%(tag)
+ return self
+
+ def hasSeries(self, tag):
+ return self.series.has_key(tag);
+
+ def seriesIsEnabled(self, tag):
+ if self.hasSeries(tag): return self.series[tag].enabled
+ else: return False
+
+class DataPlotterTickerWithSeriesButtons(DataPlotterTicker):
+ def __init__(self, parent, title, xlabel, ylabel, size, x, y, seconds = 60):
+ DataPlotterTicker.__init__(self, parent, title, xlabel, ylabel, size, x, y, seconds)
+ DataPlotterTicker.setAcceptDrops(self,True);
+ self.buttonx = 50; self.buttony = 20; self.buttonSize = 16
+ self.btns = []
+
+
+
+
+ def addSeriesWithButton(self, tag, legend, qtcolor=None, alpha = 1):
+ self.addSeries(tag, legend, qtcolor, alpha)
+ lenbtns = len(self.btns)
+
+ btn = QtGui.QToolButton(self)
+ btn.rank = lenbtns
+ btn.setText(str(btn.rank))
+ btn.tag = tag
+ #btn.setIcon(Qt.QIcon(Qt.QPixmap(print_xpm)))
+ #btn.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
+ #btn.setForegroundColor(Qt.red)
+ self.btns.append(btn)
+ btn.setGeometry(self.buttonx, self.buttony, self.buttonSize, self.buttonSize)
+ self.buttonx += self.buttonSize
+
+ if lenbtns == 0: callback = self.print_0
+ if lenbtns == 1: callback = self.print_1
+ if lenbtns == 2: callback = self.print_2
+ if lenbtns == 3: callback = self.print_3
+ if lenbtns == 4: callback = self.print_4
+ if lenbtns == 5: callback = self.print_5
+ if lenbtns == 6: callback = self.print_6
+ if lenbtns == 7: callback = self.print_7
+ self.connect(btn, QtCore.SIGNAL('clicked()'), callback)
+ return self
+
+ def toggleSeriesWithButton(self,btn):
+ DataPlotterTicker.toggleSeries(self, btn.tag)
+
+ if self.seriesIsEnabled(btn.tag):
+ # btn.setForegroundRole(Qt.QPalette.NoRole)
+ btn.setText(str(btn.rank))
+ else:
+ btn.setText('x')
+ # btn.setForegroundRole(Qt.QPalette.Light)
+
+ def print_0(self): self.toggleSeriesWithButton(self.btns[0])
+ def print_1(self): self.toggleSeriesWithButton(self.btns[1])
+ def print_2(self): self.toggleSeriesWithButton(self.btns[2])
+ def print_3(self): self.toggleSeriesWithButton(self.btns[3])
+ def print_4(self): self.toggleSeriesWithButton(self.btns[4])
+ def print_5(self): self.toggleSeriesWithButton(self.btns[5])
+ def print_6(self): self.toggleSeriesWithButton(self.btns[6])
+ def print_7(self): self.toggleSeriesWithButton(self.btns[7])
+
+class DataPlotterValueTable:
+ def __init__(self, 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.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):
+ # save previous selection if exists
+ sel = self.treeWidget.currentItem();
+ row = self.treeWidget.indexOfTopLevelItem(sel);
+ 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)
+ # re-set previous selection if exists
+ if(row != -1):
+ try:
+ self.treeWidget.setCurrentItem(self.treeWidget.topLevelItem(row));
+ except:
+ pass
diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py b/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py
new file mode 100644
index 0000000000..f33160aca2
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py
@@ -0,0 +1,423 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr
+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 GrDataPlotterC(gr.top_block):
+ def __init__(self, name, rate, pmin=None, pmax=None):
+ gr.top_block.__init__(self)
+
+ self._name = name
+ self._npts = 500
+ samp_rate = 1.0
+
+ self._last_data = self._npts*[0,]
+ self._data_len = 0
+
+ self.src = gr.vector_source_c([])
+ self.thr = gr.throttle(gr.sizeof_gr_complex, rate)
+ self.snk = qtgui.time_sink_c(self._npts, samp_rate,
+ self._name, 1)
+
+ if(pmin is not None or not pmax is None):
+ self.snk.set_y_axis(pmin, pmax)
+
+ self.connect(self.src, self.thr, (self.snk, 0))
+
+ self.snk.set_line_label(0, "Real")
+ self.snk.set_line_label(1, "Imag")
+
+ self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+
+ def __del__(self):
+ pass
+
+ def qwidget(self):
+ return self.py_window
+
+ def name(self):
+ return self._name
+
+ def update(self, data):
+ # Ask GUI if there has been a change in nsamps
+ npts = self.snk.nsamps()
+ if(self._npts != npts):
+
+ # Adjust buffers to accomodate new settings
+ if(npts < self._npts):
+ if(self._data_len < npts):
+ self._last_data = self._last_data[0:npts]
+ else:
+ self._last_data = self._last_data[self._data_len-npts:self._data_len]
+ self._data_len = npts
+ else:
+ self._last_data += (npts - self._npts)*[0,]
+ self._npts = npts
+ self.snk.reset()
+
+ # Update the plot data depending on type
+ if(type(data) == list):
+ data_r = data[0::2]
+ data_i = data[1::2]
+ data = [complex(r,i) for r,i in zip(data_r, data_i)]
+ if(len(data) > self._npts):
+ self.src.set_data(data)
+ self._last_data = data[-self._npts:]
+ else:
+ newdata = self._last_data[-(self._npts-len(data)):]
+ newdata += data
+ self.src.set_data(newdata)
+ self._last_data = newdata
+
+ else: # single value update
+ if(self._data_len < self._npts):
+ self._last_data[self._data_len] = data
+ self._data_len += 1
+ else:
+ self._last_data = self._last_data[1:]
+ self._last_data.append(data)
+ self.src.set_data(self._last_data)
+
+class GrDataPlotterF(gr.top_block):
+ def __init__(self, name, rate, pmin=None, pmax=None):
+ gr.top_block.__init__(self)
+
+ self._name = name
+ self._npts = 500
+ samp_rate = 1.0
+
+ self._last_data = self._npts*[0,]
+ self._data_len = 0
+
+ self.src = gr.vector_source_f([])
+ self.thr = gr.throttle(gr.sizeof_float, rate)
+ self.snk = qtgui.time_sink_f(self._npts, samp_rate,
+ self._name, 1)
+
+ if(pmin is not None or not pmax is None):
+ self.snk.set_y_axis(pmin, pmax)
+
+ self.connect(self.src, self.thr, (self.snk, 0))
+
+ self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+
+ def __del__(self):
+ pass
+
+ def qwidget(self):
+ return self.py_window
+
+ def name(self):
+ return self._name
+
+ def update(self, data):
+ # Ask GUI if there has been a change in nsamps
+ npts = self.snk.nsamps()
+ if(self._npts != npts):
+
+ # Adjust buffers to accomodate new settings
+ if(npts < self._npts):
+ if(self._data_len < npts):
+ self._last_data = self._last_data[0:npts]
+ else:
+ self._last_data = self._last_data[self._data_len-npts:self._data_len]
+ self._data_len = npts
+ else:
+ self._last_data += (npts - self._npts)*[0,]
+ self._npts = npts
+ self.snk.reset()
+
+ # Update the plot data depending on type
+ if(type(data) == list):
+ if(len(data) > self._npts):
+ self.src.set_data(data)
+ self._last_data = data[-self._npts:]
+ else:
+ newdata = self._last_data[-(self._npts-len(data)):]
+ newdata += data
+ self.src.set_data(newdata)
+ self._last_data = newdata
+
+ else: # single value update
+ if(self._data_len < self._npts):
+ self._last_data[self._data_len] = data
+ self._data_len += 1
+ else:
+ self._last_data = self._last_data[1:]
+ self._last_data.append(data)
+ self.src.set_data(self._last_data)
+
+
+class GrDataPlotterConst(gr.top_block):
+ def __init__(self, name, rate, pmin=None, pmax=None):
+ gr.top_block.__init__(self)
+
+ self._name = name
+ self._npts = 500
+ samp_rate = 1.0
+
+ self._last_data = self._npts*[0,]
+ self._data_len = 0
+
+ self.src = gr.vector_source_c([])
+ self.thr = gr.throttle(gr.sizeof_gr_complex, rate)
+ self.snk = qtgui.const_sink_c(self._npts,
+ self._name, 1)
+
+ if(pmin is not None or not pmax is None):
+ self.snk.set_x_axis(pmin, pmax)
+ self.snk.set_y_axis(pmin, pmax)
+
+ self.connect(self.src, self.thr, (self.snk, 0))
+
+ self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+
+ def __del__(self):
+ pass
+
+ def qwidget(self):
+ return self.py_window
+
+ def name(self):
+ return self._name
+
+ def update(self, data):
+ # Ask GUI if there has been a change in nsamps
+ npts = self.snk.nsamps()
+ if(self._npts != npts):
+
+ # Adjust buffers to accomodate new settings
+ if(npts < self._npts):
+ if(self._data_len < npts):
+ self._last_data = self._last_data[0:npts]
+ else:
+ self._last_data = self._last_data[self._data_len-npts:self._data_len]
+ self._data_len = npts
+ else:
+ self._last_data += (npts - self._npts)*[0,]
+ self._npts = npts
+ self.snk.reset()
+
+ # Update the plot data depending on type
+ if(type(data) == list):
+ data_r = data[0::2]
+ data_i = data[1::2]
+ data = [complex(r,i) for r,i in zip(data_r, data_i)]
+ if(len(data) > self._npts):
+ self.src.set_data(data)
+ self._last_data = data[-self._npts:]
+ else:
+ newdata = self._last_data[-(self._npts-len(data)):]
+ newdata += data
+ self.src.set_data(newdata)
+ self._last_data = newdata
+
+ else: # single value update
+ if(self._data_len < self._npts):
+ self._last_data[self._data_len] = data
+ self._data_len += 1
+ else:
+ self._last_data = self._last_data[1:]
+ self._last_data.append(data)
+ self.src.set_data(self._last_data)
+
+
+class GrDataPlotterPsdC(gr.top_block):
+ def __init__(self, name, rate, pmin=None, pmax=None):
+ gr.top_block.__init__(self)
+
+ self._name = name
+ self._samp_rate = 1.0
+ self._fftsize = 2048
+ self._wintype = gr.firdes.WIN_BLACKMAN_hARRIS
+ self._fc = 0
+
+ self._last_data = self._fftsize*[0,]
+ self._data_len = 0
+
+ self.src = gr.vector_source_c([])
+ self.thr = gr.throttle(gr.sizeof_gr_complex, rate)
+ self.snk = qtgui.freq_sink_c(self._fftsize, self._wintype,
+ self._fc, self._samp_rate,
+ self._name, 1)
+
+ if(pmin is not None or not pmax is None):
+ self.snk.set_y_axis(pmin, pmax)
+
+ self.connect(self.src, self.thr, (self.snk, 0))
+
+ self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+
+ def __del__(self):
+ pass
+
+ def qwidget(self):
+ return self.py_window
+
+ def name(self):
+ return self._name
+
+ def update(self, data):
+ # Ask GUI if there has been a change in nsamps
+ fftsize = self.snk.fft_size()
+ if(self._fftsize != fftsize):
+
+ # Adjust buffers to accomodate new settings
+ if(fftsize < self._fftsize):
+ if(self._data_len < fftsize):
+ self._last_data = self._last_data[0:fftsize]
+ else:
+ self._last_data = self._last_data[self._data_len-fftsize:self._data_len]
+ self._data_len = fftsize
+ else:
+ self._last_data += (fftsize - self._fftsize)*[0,]
+ self._fftsize = fftsize
+ self.snk.reset()
+
+ # Update the plot data depending on type
+ if(type(data) == list):
+ data_r = data[0::2]
+ data_i = data[1::2]
+ data = [complex(r,i) for r,i in zip(data_r, data_i)]
+ if(len(data) > self._fftsize):
+ self.src.set_data(data)
+ self._last_data = data[-self._fftsize:]
+ else:
+ newdata = self._last_data[-(self._fftsize-len(data)):]
+ newdata += data
+ self.src.set_data(newdata)
+ self._last_data = newdata
+
+ else: # single value update
+ if(self._data_len < self._fftsize):
+ self._last_data[self._data_len] = data
+ self._data_len += 1
+ else:
+ self._last_data = self._last_data[1:]
+ self._last_data.append(data)
+ self.src.set_data(self._last_data)
+
+class GrDataPlotterPsdF(gr.top_block):
+ def __init__(self, name, rate, pmin=None, pmax=None):
+ gr.top_block.__init__(self)
+
+ self._name = name
+ self._samp_rate = 1.0
+ self._fftsize = 2048
+ self._wintype = gr.firdes.WIN_BLACKMAN_hARRIS
+ self._fc = 0
+
+ self._last_data = self._fftsize*[0,]
+ self._data_len = 0
+
+ self.src = gr.vector_source_f([])
+ self.thr = gr.throttle(gr.sizeof_float, rate)
+ self.snk = qtgui.freq_sink_f(self._fftsize, self._wintype,
+ self._fc, self._samp_rate,
+ self._name, 1)
+
+ if(pmin is not None or not pmax is None):
+ self.snk.set_y_axis(pmin, pmax)
+
+ self.connect(self.src, self.thr, (self.snk, 0))
+
+ self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+
+ def __del__(self):
+ pass
+
+ def qwidget(self):
+ return self.py_window
+
+ def name(self):
+ return self._name
+
+ def update(self, data):
+ # Ask GUI if there has been a change in nsamps
+ fftsize = self.snk.fft_size()
+ if(self._fftsize != fftsize):
+
+ # Adjust buffers to accomodate new settings
+ if(fftsize < self._fftsize):
+ if(self._data_len < fftsize):
+ self._last_data = self._last_data[0:fftsize]
+ else:
+ self._last_data = self._last_data[self._data_len-fftsize:self._data_len]
+ self._data_len = fftsize
+ else:
+ self._last_data += (fftsize - self._fftsize)*[0,]
+ self._fftsize = fftsize
+ self.snk.reset()
+
+ # Update the plot data depending on type
+ if(type(data) == list):
+ data_r = data[0::2]
+ data_i = data[1::2]
+ data = [complex(r,i) for r,i in zip(data_r, data_i)]
+ if(len(data) > self._fftsize):
+ self.src.set_data(data)
+ self._last_data = data[-self._fftsize:]
+ else:
+ newdata = self._last_data[-(self._fftsize-len(data)):]
+ newdata += data
+ self.src.set_data(newdata)
+ self._last_data = newdata
+
+ else: # single value update
+ if(self._data_len < self._fftsize):
+ self._last_data[self._data_len] = data
+ self._data_len += 1
+ else:
+ self._last_data = self._last_data[1:]
+ self._last_data.append(data)
+ self.src.set_data(self._last_data)
+
+
+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-core/src/python/gnuradio/ctrlport/IceRadioClient.py b/gnuradio-core/src/python/gnuradio/ctrlport/IceRadioClient.py
new file mode 100644
index 0000000000..0964b5a4ba
--- /dev/null
+++ b/gnuradio-core/src/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-core/src/python/gnuradio/ctrlport/__init__.py b/gnuradio-core/src/python/gnuradio/ctrlport/__init__.py
new file mode 100644
index 0000000000..031c3b424e
--- /dev/null
+++ b/gnuradio-core/src/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-core/src/python/gnuradio/ctrlport/ctrlport-monitor b/gnuradio-core/src/python/gnuradio/ctrlport/ctrlport-monitor
new file mode 100755
index 0000000000..0230c4cf7a
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/ctrlport-monitor
@@ -0,0 +1,477 @@
+#!/usr/bin/env python
+
+from gnuradio import ctrlport
+
+from PyQt4.QtCore import Qt;
+from PyQt4 import QtCore
+import PyQt4.QtGui as QtGui
+import sys, time, Ice, subprocess;
+from gnuradio.ctrlport.IceRadioClient import *;
+from gnuradio.ctrlport.DataPlotter import *;
+
+_gr_prefs = gr.prefs()
+ice_directory = _gr_prefs.get_string('ctrlport', 'ice_directory', '')
+print ice_directory
+Ice.loadSlice(ice_directory + '/gnuradio.ice')
+
+import GNURadio
+
+class MAINWindow(QtGui.QMainWindow):
+ def minimumSizeHint(self):
+ return Qtgui.QSize(800,600);
+ def __init__(self, radio, port):
+
+ super(MAINWindow, self).__init__()
+ self.plots = [];
+
+ 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.readSettings()
+
+ self.setWindowTitle("GNU Radio Control Port Monitor")
+ self.setUnifiedTitleAndToolBarOnMac(True)
+
+# self.resize(QtCore.QSize(1024,768));
+
+ self.newCon(radio,port);
+# self.mdiArea.addSubWindow(child);
+# child.resize(QtCore.QSize(800,600));
+ icon = QtGui.QIcon( ctrlport.__path__[0] + "/icon.png" );
+ self.setWindowIcon(icon);
+
+# add empty plots ?
+# self.plots = [];
+# for i in range(3):
+# self.newPlot();
+
+ def newCon(self,host=None,port=None):
+ child = MForm(host,port,self);
+ #child.setWindowTitle("Modem Connected :: %s:%s"%(host,port));
+ child.setWindowTitle(str(host));
+ self.mdiArea.addSubWindow(child);
+ child.resize(QtCore.QSize(800,600));
+ child.showMaximized();
+ return child;
+
+
+ def newUpd(self,k,r):
+ updater = UpdaterWindow(k,r,None);
+ updater.setWindowTitle("Updater: " + k);
+ self.mdiArea.addSubWindow(updater);
+ updater.show();
+
+
+ def newSub(self,e):
+ tag = str(e.text(0));
+ knobprop = self.knobprops[tag]
+
+ if(type(knobprop.min) in [GNURadio.KnobVecB, GNURadio.KnobVecC,
+ GNURadio.KnobVecI,GNURadio.KnobVecF,
+ GNURadio.KnobVecD,GNURadio.KnobVecL]):
+ if(knobprop.display == ctrlport.DISPTIMESERIES):
+ #plot = self.newConstPlot();
+ plot = self.newVecSeriesPlot();
+ plot.setSeries(tag,tag);
+ plot.setWindowTitle(str(tag));
+ else: # Plot others as XY for now
+ plot = self.newConstPlot();
+ plot.setSeries(tag,tag);
+ plot.setWindowTitle(str(tag));
+ elif(type(knobprop.min) in [GNURadio.KnobB,GNURadio.KnobC,GNURadio.KnobI,
+ GNURadio.KnobF,GNURadio.KnobD,GNURadio.KnobL]):
+ plot = self.newPlot();
+ plot.addSeriesWithButton(tag, knobprop.description + ' (' + knobprop.units + ')', None, 1.0);
+ plot.setWindowTitle(str(tag));
+ else:
+ print "WARNING: plotting of this knob-type not yet supported, ignoring attempt..."
+
+
+ def newVecSeriesPlot(self):
+ #plot = DataPlotterEqTaps(None, 'legend', 'title', 'xlabel', 'ylabel', 250, 0, 0, Qt.green)
+ plot = DataPlotterVectorOne(None, 'legend', 'title', 'xlabel', 'ylabel', 250, 0, 0);
+ self.mdiArea.addSubWindow(plot);
+ plot.dropSignal.connect(self.plotDropEvent );
+ plot.show();
+ self.plots.append(plot);
+ return plot;
+
+ def newConstPlot(self):
+ plot = DataPlotterConst(None, 'legend', 'title', 'xlabel', 'ylabel', 250, 0, 0)
+ self.mdiArea.addSubWindow(plot);
+ plot.dropSignal.connect(self.plotDropEvent );
+ plot.show();
+ self.plots.append(plot);
+ return plot;
+
+ def newPlot(self):
+ plot = DataPlotterTickerWithSeriesButtons(None,"",'units', '', 250,0,0,120);
+ self.mdiArea.addSubWindow(plot);
+ plot.dropSignal.connect(self.plotDropEvent );
+ plot.show();
+ self.plots.append(plot);
+ return plot;
+
+
+ def update(self, knobs):
+ for item in knobs.keys():
+ for plot in self.plots:
+ plot.offerData( knobs[item].value, item );
+
+ def plotDropEvent(self, e):
+ model = QtGui.QStandardItemModel()
+ model.dropMimeData(e.mimeData(), QtCore.Qt.CopyAction,0,0,QtCore.QModelIndex())
+ tag = str(QtGui.QTreeWidgetItem([model.item(0,0).text()]).text(0));
+ knobprop = self.knobprops[tag]
+ try:
+ self.sender().addSeriesWithButton(tag, knobprop.description + ' (' + knobprop.units + ')', None, 1.0);
+ except:
+ print "This plot does not accept additional data items! ignoring..."
+
+
+ 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, shortcut=QtGui.QKeySequence.New,
+ statusTip="Create a new file", triggered=self.newPlot)
+
+ 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.addAction(self.newPlotAct)
+ 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.addAction(self.newPlotAct)
+
+ 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.QWidget):
+ def __init__(self, key, radio, parent):
+ QtGui.QWidget.__init__(self,parent)
+
+ self.key = key;
+ self.radio = radio;
+
+ self.resize(300,200)
+ self.layout = QtGui.QVBoxLayout();
+
+ self.textInput = QtGui.QLineEdit();
+ self.setButton = QtGui.QPushButton("Set Value")
+
+ rv = radio.get([key]);
+ self.textInput.setText(str(rv[key].value));
+ self.sv = rv[key];
+
+
+ self.props = radio.properties([key])[key];
+ info = str(self.props);
+
+ self.infoLabel = QtGui.QLabel(info);
+ self.layout.addWidget(self.infoLabel);
+
+ self.layout.addWidget(self.textInput);
+
+ self.setButton.connect(self.setButton, QtCore.SIGNAL('clicked()'), self._set)
+
+ 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(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( self.props.min.value, self.props.max.value );
+ self.slider.setRange( 0,10000 );
+
+ self.slider.setValue( self.sv.value );
+ self.slider.setValue( self.steps*(self.sv.value-self.props.min.value)/self.valspan);
+
+ self.connect(self.slider, QtCore.SIGNAL("sliderReleased()"), self._slide);
+
+ self.layout.addLayout(self.sliderlayout);
+
+ self.layout.addWidget(self.setButton);
+
+ # set layout and go...
+ self.setLayout(self.layout);
+
+ def _slide(self):
+ val = (self.slider.value()*self.valspan + self.props.min.value)/float(self.steps);
+ self.textInput.setText(str(val));
+
+ def _set(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:
+ print "set type not supported! (%s)"%(type(self.sv.value));
+ sys.exit(-1);
+ #self.sv.value = int(val);
+ self.sv.value = val;
+ km = {};
+ km[self.key] = self.sv;
+ self.radio.set(km);
+
+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):
+ # closing all of these seems to help control shutdown order.
+ self.parent.closeAct.trigger()
+ else:
+ sys.exit(1)
+ return
+
+ tableitems = knobs.keys();
+
+ #UPDATE TABLE:
+ self.table.updateItems(knobs, self.knobprops)
+
+ #UPDATE PLOTS
+ self.parent.update( knobs );
+
+
+ def __init__(self, radio=None, port=None, parent=None):
+
+ super(MForm, self).__init__()
+
+ if(radio == None or port == None):
+ askinfo = ConInfoDialog(self);
+ if askinfo.exec_():
+ print "connecting..."
+ radio = str(askinfo.host.text());
+ port = str(askinfo.port.text());
+ print "this is broken"
+ return;
+ else:
+ return;
+
+ self.parent = parent;
+ self.horizontalLayout = QtGui.QVBoxLayout(self);
+ self.gridLayout = QtGui.QGridLayout()
+
+
+ self.radio = radio
+ self.knobprops = self.radio.properties([])
+ self.parent.knobprops = self.knobprops;
+ self.resize(775,500)
+ self.timer = QtCore.QTimer()
+ self.constupdatediv = 0
+ self.tableupdatediv = 0
+ plotsize=250;
+
+
+ # make table
+ self.table = DataPlotterValueTable(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.connect(self.table.treeWidget, QtCore.SIGNAL('itemDoubleClicked(QTreeWidgetItem*, int)'), self.parent.newSub);
+
+ # set up context menu ..
+ self.table.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu);
+ self.table.treeWidget.customContextMenuRequested.connect(self.openMenu);
+
+ self.timer.start(2000)
+
+ def plotDropEvent(self, e):
+ model = QtGui.QStandardItemModel()
+ model.dropMimeData(e.mimeData(), QtCore.Qt.CopyAction,0,0,QtCore.QModelIndex())
+ tag = str(QtGui.QTreeWidgetItem([model.item(0,0).text()]).text(0));
+ knobprop = self.knobprops[tag]
+ self.sender().addSeriesWithButton(tag, knobprop.description + ' (' + knobprop.units + ')', None, 1.0);
+
+ def openMenu(self, pos):
+ index = self.table.treeWidget.selectedIndexes();
+ item = self.table.treeWidget.itemFromIndex(index[0]);
+ itemname = str(item.text(0));
+ self.parent.newUpd(itemname, self.radio);
+# updater = UpdaterWindow(itemname, self.radio, self.parent);
+# updater.setWindowTitle("Updater: " + itemname);
+# self.parent.mdiArea.addSubWindow(updater);
+# print "done"
+
+
+class MyClient(IceRadioClient):
+ def __init__(self): IceRadioClient.__init__(self, MAINWindow)
+
+sys.exit(MyClient().main(sys.argv))
diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor b/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor
new file mode 100755
index 0000000000..241b8a2043
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor
@@ -0,0 +1,581 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, ctrlport
+
+from PyQt4 import QtCore,Qt
+import PyQt4.QtGui as QtGui
+import sys, time
+
+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 Control Port 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))
+ 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
+
+ def newUpdaterProxy():
+ self.newUpdater(key, radio)
+
+ def newPlotterFProxy():
+ self.newPlotF(key, uid, title, pmin, pmax)
+
+ def newPlotterCProxy():
+ self.newPlotC(key, uid, title, pmin, pmax)
+
+ def newPlotterConstProxy():
+ self.newPlotConst(key, uid, title, pmin, pmax)
+
+ def newPlotterPsdFProxy():
+ self.newPlotPsdF(key, uid, title)
+
+ def newPlotterPsdCProxy():
+ self.newPlotPsdC(key, uid, title)
+
+ menu = QtGui.QMenu(self)
+ menu.setTitle("Item Actions")
+ menu.setTearOffEnabled(False)
+
+ # object properties
+ menu.addAction("Properties", newUpdaterProxy)
+
+ # displays available if not complex
+ menu.addAction("Plot Time", newPlotterFProxy)
+ menu.addAction("Plot PSD", newPlotterPsdFProxy)
+
+ # displays available if complex
+ menu.addAction("Plot Time (cpx)", newPlotterCProxy)
+ menu.addAction("Plot Constellation", newPlotterConstProxy)
+ menu.addAction("Plot PSD cpx", newPlotterPsdCProxy)
+
+ 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
+
+ if(knobprop.display == GNURadio.DisplayType.DISPXYSCATTER):
+ self.newPlotConst(tag, uid, title, pmin, pmax)
+ elif(knobprop.display == GNURadio.DisplayType.DISPTIMESERIESF):
+ self.newPlotF(tag, uid, title, pmin, pmax)
+ elif(knobprop.display == GNURadio.DisplayType.DISPTIMESERIESC):
+ self.newPlotC(tag, uid, title, pmin, pmax)
+
+ def createPlot(self, plot, uid, title):
+ plot.start()
+ self.plots[uid].append(plot)
+
+ self.mdiArea.addSubWindow(plot.qwidget())
+ plot.qwidget().setWindowTitle("{0}: {1}".format(title, plot.name()))
+ self.connect(plot.qwidget(),
+ QtCore.SIGNAL('destroyed(QObject*)'),
+ self.destroyPlot)
+ plot.qwidget().show()
+
+
+ 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):
+ plot = GrDataPlotterConst(tag, 32e6, pmin, pmax)
+ self.createPlot(plot, uid, title)
+
+ def newPlotF(self, tag, uid, title="", pmin=None, pmax=None):
+ plot = GrDataPlotterF(tag, 32e6, pmin, pmax)
+ self.createPlot(plot, uid, title)
+
+ def newPlotC(self, tag, uid, title="", pmin=None, pmax=None):
+ plot = GrDataPlotterC(tag, 32e6, pmin, pmax)
+ 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 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.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)
+
+
+ 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.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.addAction(self.newPlotAct)
+
+ 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, 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.timer.start(1000)
+
+ # 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);
+
+ 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-core/src/python/gnuradio/ctrlport/icon.png b/gnuradio-core/src/python/gnuradio/ctrlport/icon.png
new file mode 100644
index 0000000000..4beb204428
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/icon.png
Binary files differ
diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/monitor.py b/gnuradio-core/src/python/gnuradio/ctrlport/monitor.py
new file mode 100644
index 0000000000..1e74a814f0
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/monitor.py
@@ -0,0 +1,60 @@
+#!/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
+ self.start()
+ 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-core/src/python/gnuradio/ctrlport/qa_cpp_py_binding.py b/gnuradio-core/src/python/gnuradio/ctrlport/qa_cpp_py_binding.py
new file mode 100755
index 0000000000..760252b4df
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/qa_cpp_py_binding.py
@@ -0,0 +1,170 @@
+#!/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.
+#
+
+#
+# This program tests mixed python and c++ ctrlport exports in a single app
+#
+
+import Ice
+import sys, time, random, numpy
+from gnuradio import gr, gr_unittest
+
+from gnuradio.ctrlport import GNURadio
+from gnuradio import ctrlport
+
+def get1():
+ return "success"
+
+def get2():
+ return "failure"
+
+class inc_class:
+ def __init__(self):
+ self.val = 1
+ def pp(self):
+ self.val = self.val+1
+ return self.val
+
+get3 = inc_class()
+
+def get4():
+ random.seed(0)
+ rv = random.random()
+ return rv
+
+def get5():
+ numpy.random.seed(0)
+ samp_t = numpy.random.randn(24)+1j*numpy.random.randn(24);
+ samp_f = numpy.fft.fft(samp_t);
+ log_pow_f = 20*numpy.log10(numpy.abs(samp_f))
+ rv = list(log_pow_f)
+ return rv;
+
+def get6():
+ numpy.random.seed(0)
+ samp_t = numpy.random.randn(1024)+1j*numpy.random.randn(1024);
+ rv = list(samp_t)
+ return rv;
+
+class test_cpp_py_binding(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_001(self):
+ v1 = gr.RPC_get_string("pyland", "v1", "unit_1_string",
+ "Python Exported String", "", "", "",
+ gr.DISPNULL)
+ v1.activate(get1)
+
+ v2 = gr.RPC_get_string("pyland", "v2", "unit_2_string",
+ "Python Exported String", "", "", "",
+ gr.DISPNULL)
+ v2.activate(get2)
+
+ v3 = gr.RPC_get_int("pyland", "v3", "unit_3_int",
+ "Python Exported Int", 0, 100, 1,
+ gr.DISPNULL)
+ v3.activate(get3.pp)
+
+ v4 = gr.RPC_get_double("pyland", "time", "unit_4_time_double",
+ "Python Exported Double", 0, 1000, 1,
+ gr.DISPNULL)
+ v4.activate(get4)
+
+ v5 = gr.RPC_get_vector_float("pyland", "fvec", "unit_5_float_vector",
+ "Python Exported Float Vector", [], [], [],
+ gr.DISPTIMESERIESC)
+ v5.activate(get5)
+
+ v6 = gr.RPC_get_vector_gr_complex("pyland", "cvec", "unit_6_gr_complex_vector",
+ "Python Exported Complex Vector", [], [], [],
+ gr.DISPXYSCATTER)
+ v6.activate(get6)
+
+ # print some variables locally
+ val = get1()
+ rval = v1.get()
+ self.assertEqual(val, rval)
+
+ val = get2()
+ rval = v2.get()
+ self.assertEqual(val, rval)
+
+ val = get3.pp()
+ rval = v3.get()
+ self.assertEqual(val+1, rval)
+
+ val = get4()
+ rval = v4.get()
+ self.assertEqual(val, rval)
+
+ val = get5()
+ rval = v5.get()
+ self.assertComplexTuplesAlmostEqual(val, rval, 5)
+
+ val = get6()
+ rval = v6.get()
+ self.assertComplexTuplesAlmostEqual(val, rval, 5)
+
+ def test_002(self):
+ data = range(1,9)
+
+ self.src = gr.vector_source_c(data)
+ self.p1 = gr.ctrlport_probe_c("aaa","C++ exported variable")
+ self.p2 = gr.ctrlport_probe_c("bbb","C++ exported variable")
+ probe_name = self.p2.name() + str(self.p2.unique_id())
+
+ self.tb.connect(self.src, self.p1)
+ self.tb.connect(self.src, self.p2)
+ self.tb.start()
+
+ # Probes return complex values as list of floats with re, im
+ # Imaginary parts of this data set are 0.
+ expected_result = [1, 0, 2, 0, 3, 0, 4, 0,
+ 5, 0, 6, 0, 7, 0, 8, 0]
+
+ # Make sure we have time for flowgraph to run
+ time.sleep(0.1)
+
+ # Get available endpoint
+ ep = gr.rpcmanager_get().endpoints()[0]
+
+ # Initialize a simple Ice client from endpoint
+ ic = Ice.initialize(sys.argv)
+ base = ic.stringToProxy(ep)
+ radio = GNURadio.ControlPortPrx.checkedCast(base)
+
+ # Get all exported knobs
+ ret = radio.get([probe_name + "::bbb"])
+ for name in ret.keys():
+ result = ret[name].value
+ self.assertEqual(result, expected_result)
+
+ self.tb.stop()
+
+if __name__ == '__main__':
+ gr_unittest.run(test_cpp_py_binding, "test_cpp_py_binding.xml")
+
diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/qa_cpp_py_binding_set.py b/gnuradio-core/src/python/gnuradio/ctrlport/qa_cpp_py_binding_set.py
new file mode 100755
index 0000000000..fe7e5bcb60
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/qa_cpp_py_binding_set.py
@@ -0,0 +1,148 @@
+#!/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.
+#
+
+#
+# This program tests mixed python and c++ GRCP sets in a single app
+#
+
+import Ice
+import sys, time, random, numpy
+from gnuradio import gr, gr_unittest
+
+from gnuradio.ctrlport import GNURadio
+from gnuradio import ctrlport
+
+class inc_class:
+ def __init__(self,val):
+ self.val = val;
+
+ def _get(self):
+ #print "returning get (val = %s)"%(str(self.val));
+ return self.val;
+
+ def _set(self,val):
+ #print "updating val to %s"%(str(val));
+ self.val = val;
+ return;
+
+getset1 = inc_class(10);
+getset2 = inc_class(100.0);
+getset3 = inc_class("test");
+
+class test_cpp_py_binding_set(gr_unittest.TestCase):
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_001(self):
+
+ g1 = gr.RPC_get_int("pyland", "v1", "unit_1_int",
+ "Python Exported Int", 0, 100, 10,
+ gr.DISPNULL)
+ g1.activate(getset1._get)
+ s1 = gr.RPC_get_int("pyland", "v1", "unit_1_int",
+ "Python Exported Int", 0, 100, 10,
+ gr.DISPNULL)
+ s1.activate(getset1._set)
+ time.sleep(0.01)
+
+ # test int variables
+ getset1._set(21)
+ val = getset1._get()
+ rval = g1.get()
+ self.assertEqual(val, rval)
+
+ g2 = gr.RPC_get_float("pyland", "v2", "unit_2_float",
+ "Python Exported Float", -100, 1000.0, 100.0,
+ gr.DISPNULL)
+ g2.activate(getset2._get)
+ s2 = gr.RPC_get_float("pyland", "v2", "unit_2_float",
+ "Python Exported Float", -100, 1000.0, 100.0,
+ gr.DISPNULL)
+ s2.activate(getset2._set)
+ time.sleep(0.01)
+
+ # test float variables
+ getset2._set(123.456)
+ val = getset2._get()
+ rval = g2.get()
+ self.assertAlmostEqual(val, rval, 4)
+
+ g3 = gr.RPC_get_string("pyland", "v3", "unit_3_string",
+ "Python Exported String", "", "", "",
+ gr.DISPNULL)
+ g3.activate(getset3._get)
+ s3 = gr.RPC_get_string("pyland", "v3", "unit_3_string",
+ "Python Exported String", "", "", "",
+ gr.DISPNULL)
+ s3.activate(getset3._set)
+ time.sleep(0.01)
+
+ # test string variables
+ getset3._set("third test")
+ val = getset3._get()
+ rval = g3.get()
+ self.assertEqual(val, rval)
+
+
+ def test_002(self):
+ data = range(1, 10)
+
+ self.src = gr.vector_source_c(data, True)
+ self.p = gr.nop(gr.sizeof_gr_complex)
+ self.p.set_ctrlport_test(0);
+ probe_info = "{0}{1}".format(self.p.name(), self.p.unique_id())
+
+ self.tb.connect(self.src, self.p)
+
+ # Get available endpoint
+ ep = gr.rpcmanager_get().endpoints()[0]
+
+ # Initialize a simple Ice client from endpoint
+ ic = Ice.initialize(sys.argv)
+ base = ic.stringToProxy(ep)
+ radio = GNURadio.ControlPortPrx.checkedCast(base)
+
+ self.tb.start()
+
+ # Make sure we have time for flowgraph to run
+ time.sleep(0.1)
+
+ # Get all exported knobs
+ key_name_test = probe_info+"::test"
+ ret = radio.get([key_name_test,])
+
+ ret[key_name_test].value = 10
+ radio.set({key_name_test: ret[key_name_test]})
+
+ ret = radio.get([])
+ result_test = ret[key_name_test].value
+ self.assertEqual(result_test, 10)
+
+ self.tb.stop()
+ self.tb.wait()
+
+if __name__ == '__main__':
+ gr_unittest.run(test_cpp_py_binding_set, "test_cpp_py_binding_set.xml")
+
diff --git a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt
index 62f3d7e46d..c5ff2a0c14 100644
--- a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt
+++ b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt
@@ -47,6 +47,7 @@ foreach(py_qa_test_file ${py_qa_test_files})
${CMAKE_SOURCE_DIR}/gruel/src/python
${CMAKE_BINARY_DIR}/gruel/src/swig
${CMAKE_BINARY_DIR}/gnuradio-core/src/python
+ ${CMAKE_BINARY_DIR}/gnuradio-core/src/python/ctrlport
${CMAKE_BINARY_DIR}/gnuradio-core/src/lib/swig
)
set(GR_TEST_TARGET_DEPS volk gruel gnuradio-core)
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_nlog10.py b/gnuradio-core/src/python/gnuradio/gr/qa_nlog10.py
index a87ed87eef..239911851c 100755
--- a/gnuradio-core/src/python/gnuradio/gr/qa_nlog10.py
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_nlog10.py
@@ -20,6 +20,7 @@
# Boston, MA 02110-1301, USA.
#
+import sys, time, random, numpy
from gnuradio import gr, gr_unittest
class test_nlog10(gr_unittest.TestCase):