summaryrefslogtreecommitdiff
path: root/grc
diff options
context:
space:
mode:
Diffstat (limited to 'grc')
-rw-r--r--grc/CMakeLists.txt128
-rw-r--r--grc/__init__.py0
-rw-r--r--grc/base/Block.py253
-rw-r--r--grc/base/CMakeLists.txt42
-rw-r--r--grc/base/Connection.py97
-rw-r--r--grc/base/Constants.py25
-rw-r--r--grc/base/Element.py89
-rw-r--r--grc/base/FlowGraph.py219
-rw-r--r--grc/base/Param.py181
-rw-r--r--grc/base/ParseXML.py102
-rw-r--r--grc/base/Platform.py178
-rw-r--r--grc/base/Port.py83
-rw-r--r--grc/base/__init__.py20
-rw-r--r--grc/base/block_tree.dtd26
-rw-r--r--grc/base/flow_graph.dtd36
-rw-r--r--grc/base/odict.py93
-rw-r--r--grc/blocks/CMakeLists.txt22
-rw-r--r--grc/blocks/band_pass_filter.xml166
-rw-r--r--grc/blocks/band_reject_filter.xml132
-rw-r--r--grc/blocks/blks2_am_demod_cf.xml47
-rw-r--r--grc/blocks/blks2_analysis_filterbank.xml32
-rw-r--r--grc/blocks/blks2_error_rate.xml69
-rw-r--r--grc/blocks/blks2_fm_deemph.xml31
-rw-r--r--grc/blocks/blks2_fm_demod_cf.xml68
-rw-r--r--grc/blocks/blks2_fm_preemph.xml31
-rw-r--r--grc/blocks/blks2_logpwrfft_x.xml90
-rw-r--r--grc/blocks/blks2_nbfm_rx.xml48
-rw-r--r--grc/blocks/blks2_nbfm_tx.xml48
-rw-r--r--grc/blocks/blks2_packet_decoder.xml75
-rw-r--r--grc/blocks/blks2_packet_encoder.xml110
-rw-r--r--grc/blocks/blks2_pfb_arb_resampler.xml45
-rw-r--r--grc/blocks/blks2_pfb_channelizer.xml62
-rw-r--r--grc/blocks/blks2_rational_resampler_xxx.xml88
-rw-r--r--grc/blocks/blks2_selector.xml97
-rw-r--r--grc/blocks/blks2_standard_squelch.xml32
-rw-r--r--grc/blocks/blks2_stream_to_vector_decimator.xml77
-rw-r--r--grc/blocks/blks2_synthesis_filterbank.xml32
-rw-r--r--grc/blocks/blks2_tcp_sink.xml89
-rw-r--r--grc/blocks/blks2_tcp_source.xml89
-rw-r--r--grc/blocks/blks2_valve.xml72
-rw-r--r--grc/blocks/blks2_wfm_rcv.xml33
-rw-r--r--grc/blocks/blks2_wfm_rcv_pll.xml37
-rw-r--r--grc/blocks/blks2_wfm_tx.xml48
-rw-r--r--grc/blocks/block_tree.xml283
-rw-r--r--grc/blocks/const_source_x.xml52
-rw-r--r--grc/blocks/gr_add_const_vxx.xml67
-rw-r--r--grc/blocks/gr_add_xx.xml63
-rw-r--r--grc/blocks/gr_additive_scrambler_bb.xml44
-rw-r--r--grc/blocks/gr_agc2_xx.xml70
-rw-r--r--grc/blocks/gr_agc_xx.xml59
-rw-r--r--grc/blocks/gr_and_const_xx.xml48
-rw-r--r--grc/blocks/gr_and_xx.xml48
-rw-r--r--grc/blocks/gr_argmax_xx.xml61
-rw-r--r--grc/blocks/gr_burst_tagger.xml87
-rw-r--r--grc/blocks/gr_channel_model.xml61
-rw-r--r--grc/blocks/gr_char_to_float.xml35
-rw-r--r--grc/blocks/gr_char_to_short.xml28
-rw-r--r--grc/blocks/gr_chunks_to_symbols.xml77
-rw-r--r--grc/blocks/gr_complex_to_arg.xml29
-rw-r--r--grc/blocks/gr_complex_to_float.xml36
-rw-r--r--grc/blocks/gr_complex_to_imag.xml29
-rw-r--r--grc/blocks/gr_complex_to_interleaved_short.xml20
-rw-r--r--grc/blocks/gr_complex_to_mag.xml29
-rw-r--r--grc/blocks/gr_complex_to_mag_squared.xml29
-rw-r--r--grc/blocks/gr_complex_to_real.xml29
-rw-r--r--grc/blocks/gr_conjugate_cc.xml20
-rw-r--r--grc/blocks/gr_copy.xml75
-rw-r--r--grc/blocks/gr_cpfsk_bc.xml37
-rw-r--r--grc/blocks/gr_ctcss_squelch_ff.xml79
-rw-r--r--grc/blocks/gr_dc_blocker.xml51
-rw-r--r--grc/blocks/gr_decode_ccsds_27_fb.xml20
-rw-r--r--grc/blocks/gr_deinterleave.xml67
-rw-r--r--grc/blocks/gr_delay.xml75
-rw-r--r--grc/blocks/gr_descrambler_bb.xml38
-rw-r--r--grc/blocks/gr_diff_decoder_bb.xml25
-rw-r--r--grc/blocks/gr_diff_encoder_bb.xml25
-rw-r--r--grc/blocks/gr_diff_phasor_cc.xml20
-rw-r--r--grc/blocks/gr_divide_xx.xml63
-rw-r--r--grc/blocks/gr_dpll_bb.xml30
-rw-r--r--grc/blocks/gr_encode_ccsds_27_bb.xml20
-rw-r--r--grc/blocks/gr_endian_swap.xml41
-rw-r--r--grc/blocks/gr_feedforward_agc_cc.xml32
-rw-r--r--grc/blocks/gr_fft_filter_xxx.xml59
-rw-r--r--grc/blocks/gr_fft_vxx.xml88
-rw-r--r--grc/blocks/gr_file_sink.xml78
-rw-r--r--grc/blocks/gr_file_source.xml75
-rw-r--r--grc/blocks/gr_filter_delay_fc.xml31
-rw-r--r--grc/blocks/gr_fir_filter_xxx.xml80
-rw-r--r--grc/blocks/gr_float_to_char.xml35
-rw-r--r--grc/blocks/gr_float_to_complex.xml36
-rw-r--r--grc/blocks/gr_float_to_int.xml35
-rw-r--r--grc/blocks/gr_float_to_short.xml35
-rw-r--r--grc/blocks/gr_float_to_uchar.xml20
-rw-r--r--grc/blocks/gr_fractional_interpolator_xx.xml46
-rw-r--r--grc/blocks/gr_freq_xlating_fir_filter_xxx.xml93
-rw-r--r--grc/blocks/gr_frequency_modulator_fc.xml26
-rw-r--r--grc/blocks/gr_glfsr_source_x.xml59
-rw-r--r--grc/blocks/gr_goertzel_fc.xml37
-rw-r--r--grc/blocks/gr_head.xml65
-rw-r--r--grc/blocks/gr_hilbert_fc.xml26
-rw-r--r--grc/blocks/gr_iir_filter_ffd.xml31
-rw-r--r--grc/blocks/gr_int_to_float.xml35
-rw-r--r--grc/blocks/gr_integrate_xx.xml50
-rw-r--r--grc/blocks/gr_interleave.xml67
-rw-r--r--grc/blocks/gr_interleaved_short_to_complex.xml20
-rw-r--r--grc/blocks/gr_interp_fir_filter_xxx.xml80
-rw-r--r--grc/blocks/gr_iqcomp_cc.xml25
-rw-r--r--grc/blocks/gr_keep_m_in_n.xml76
-rw-r--r--grc/blocks/gr_keep_one_in_n.xml67
-rw-r--r--grc/blocks/gr_kludge_copy.xml68
-rw-r--r--grc/blocks/gr_map_bb.xml25
-rw-r--r--grc/blocks/gr_max_xx.xml58
-rw-r--r--grc/blocks/gr_message_burst_source.xml58
-rw-r--r--grc/blocks/gr_message_debug.xml27
-rw-r--r--grc/blocks/gr_message_sink.xml72
-rw-r--r--grc/blocks/gr_message_source.xml58
-rw-r--r--grc/blocks/gr_message_strobe.xml35
-rw-r--r--grc/blocks/gr_moving_average_xx.xml68
-rw-r--r--grc/blocks/gr_mpsk_sync_cc.xml69
-rw-r--r--grc/blocks/gr_multiply_const_vxx.xml67
-rw-r--r--grc/blocks/gr_multiply_xx.xml63
-rw-r--r--grc/blocks/gr_mute_xx.xml61
-rw-r--r--grc/blocks/gr_nlog10_ff.xml42
-rw-r--r--grc/blocks/gr_noise_source_x.xml77
-rw-r--r--grc/blocks/gr_nop.xml68
-rw-r--r--grc/blocks/gr_not_xx.xml40
-rw-r--r--grc/blocks/gr_null_sink.xml54
-rw-r--r--grc/blocks/gr_null_source.xml54
-rw-r--r--grc/blocks/gr_or_xx.xml48
-rw-r--r--grc/blocks/gr_pack_k_bits_bb.xml30
-rw-r--r--grc/blocks/gr_packed_to_unpacked_xx.xml68
-rw-r--r--grc/blocks/gr_pdu_to_tagged_stream.xml40
-rw-r--r--grc/blocks/gr_peak_detector2_fb.xml38
-rw-r--r--grc/blocks/gr_peak_detector_xb.xml64
-rw-r--r--grc/blocks/gr_pfb_clock_sync.xml100
-rw-r--r--grc/blocks/gr_pfb_synthesizer.xml57
-rw-r--r--grc/blocks/gr_phase_modulator_fc.xml25
-rw-r--r--grc/blocks/gr_pll_carriertracking_cc.xml36
-rw-r--r--grc/blocks/gr_pll_freqdet_cf.xml36
-rw-r--r--grc/blocks/gr_pll_refout_cc.xml36
-rw-r--r--grc/blocks/gr_pn_correlator_cc.xml35
-rw-r--r--grc/blocks/gr_probe_avg_mag_sqrd_x.xml50
-rw-r--r--grc/blocks/gr_probe_density_b.xml34
-rw-r--r--grc/blocks/gr_probe_signal_f.xml21
-rw-r--r--grc/blocks/gr_pwr_squelch_xx.xml65
-rw-r--r--grc/blocks/gr_quadrature_demod_cf.xml26
-rw-r--r--grc/blocks/gr_random_pdu.xml35
-rw-r--r--grc/blocks/gr_rational_resampler_base_xxx.xml86
-rw-r--r--grc/blocks/gr_repeat.xml64
-rw-r--r--grc/blocks/gr_rms_xx.xml41
-rw-r--r--grc/blocks/gr_sample_and_hold_xx.xml49
-rw-r--r--grc/blocks/gr_scrambler_bb.xml38
-rw-r--r--grc/blocks/gr_short_to_char.xml28
-rw-r--r--grc/blocks/gr_short_to_float.xml35
-rw-r--r--grc/blocks/gr_sig_source_x.xml104
-rw-r--r--grc/blocks/gr_simple_correlator.xml25
-rw-r--r--grc/blocks/gr_simple_framer.xml25
-rw-r--r--grc/blocks/gr_simple_squelch_cc.xml32
-rw-r--r--grc/blocks/gr_single_pole_iir_filter_xx.xml51
-rw-r--r--grc/blocks/gr_skiphead.xml65
-rw-r--r--grc/blocks/gr_socket_pdu.xml62
-rw-r--r--grc/blocks/gr_stream_mux.xml75
-rw-r--r--grc/blocks/gr_stream_to_streams.xml67
-rw-r--r--grc/blocks/gr_stream_to_vector.xml66
-rw-r--r--grc/blocks/gr_streams_to_stream.xml67
-rw-r--r--grc/blocks/gr_streams_to_vector.xml67
-rw-r--r--grc/blocks/gr_sub_xx.xml63
-rw-r--r--grc/blocks/gr_tag_debug.xml82
-rw-r--r--grc/blocks/gr_tagged_stream_to_pdu.xml40
-rw-r--r--grc/blocks/gr_threshold_ff.xml40
-rw-r--r--grc/blocks/gr_throttle.xml67
-rw-r--r--grc/blocks/gr_transcendental.xml41
-rw-r--r--grc/blocks/gr_tuntap_pdu.xml34
-rw-r--r--grc/blocks/gr_uchar_to_float.xml20
-rw-r--r--grc/blocks/gr_udp_sink.xml77
-rw-r--r--grc/blocks/gr_udp_source.xml85
-rw-r--r--grc/blocks/gr_unpack_k_bits_bb.xml25
-rw-r--r--grc/blocks/gr_unpacked_to_packed_xx.xml68
-rw-r--r--grc/blocks/gr_vco_f.xml35
-rw-r--r--grc/blocks/gr_vector_insert_x.xml80
-rw-r--r--grc/blocks/gr_vector_sink_x.xml54
-rw-r--r--grc/blocks/gr_vector_source_x.xml79
-rw-r--r--grc/blocks/gr_vector_to_stream.xml66
-rw-r--r--grc/blocks/gr_vector_to_streams.xml67
-rw-r--r--grc/blocks/gr_wavfile_sink.xml43
-rw-r--r--grc/blocks/gr_wavfile_source.xml44
-rw-r--r--grc/blocks/gr_xor_xx.xml48
-rw-r--r--grc/blocks/high_pass_filter.xml127
-rw-r--r--grc/blocks/import.xml26
-rw-r--r--grc/blocks/low_pass_filter.xml127
-rw-r--r--grc/blocks/note.xml17
-rw-r--r--grc/blocks/options.xml190
-rw-r--r--grc/blocks/pad_sink.xml91
-rw-r--r--grc/blocks/pad_source.xml91
-rw-r--r--grc/blocks/parameter.xml99
-rw-r--r--grc/blocks/random_source_x.xml75
-rw-r--r--grc/blocks/root_raised_cosine_filter.xml101
-rw-r--r--grc/blocks/variable.xml23
-rw-r--r--grc/blocks/variable_config.xml88
-rw-r--r--grc/blocks/variable_function_probe.xml70
-rw-r--r--grc/blocks/virtual_sink.xml21
-rw-r--r--grc/blocks/virtual_source.xml21
-rw-r--r--grc/blocks/xmlrpc_client.xml42
-rw-r--r--grc/blocks/xmlrpc_server.xml39
-rw-r--r--grc/cpp/README5
-rw-r--r--grc/examples/CMakeLists.txt37
-rw-r--r--grc/examples/simple/variable_config.grc329
-rw-r--r--grc/examples/xmlrpc/readme.txt18
-rw-r--r--grc/examples/xmlrpc/xmlrpc_client.grc312
-rw-r--r--grc/examples/xmlrpc/xmlrpc_client_script.py23
-rw-r--r--grc/examples/xmlrpc/xmlrpc_server.grc384
-rw-r--r--grc/freedesktop/CMakeLists.txt47
-rw-r--r--grc/freedesktop/README20
-rw-r--r--grc/freedesktop/gnuradio-grc.desktop8
-rw-r--r--grc/freedesktop/gnuradio-grc.xml8
-rw-r--r--grc/freedesktop/grc-icon-128.pngbin0 -> 3570 bytes
-rw-r--r--grc/freedesktop/grc-icon-256.pngbin0 -> 7843 bytes
-rw-r--r--grc/freedesktop/grc-icon-256.svg216
-rw-r--r--grc/freedesktop/grc-icon-32.pngbin0 -> 1060 bytes
-rw-r--r--grc/freedesktop/grc-icon-48.pngbin0 -> 1691 bytes
-rw-r--r--grc/freedesktop/grc-icon-64.pngbin0 -> 1893 bytes
-rw-r--r--grc/freedesktop/grc_setup_freedesktop.in75
-rw-r--r--grc/grc.conf.in7
-rw-r--r--grc/grc_gnuradio/CMakeLists.txt35
-rw-r--r--grc/grc_gnuradio/README11
-rw-r--r--grc/grc_gnuradio/__init__.py1
-rw-r--r--grc/grc_gnuradio/blks2/__init__.py26
-rw-r--r--grc/grc_gnuradio/blks2/error_rate.py137
-rw-r--r--grc/grc_gnuradio/blks2/packet.py242
-rw-r--r--grc/grc_gnuradio/blks2/selector.py128
-rw-r--r--grc/grc_gnuradio/blks2/tcp.py66
-rw-r--r--grc/gui/ActionHandler.py530
-rw-r--r--grc/gui/Actions.py291
-rw-r--r--grc/gui/Bars.py143
-rw-r--r--grc/gui/Block.py201
-rw-r--r--grc/gui/BlockTreeWindow.py201
-rw-r--r--grc/gui/CMakeLists.txt48
-rw-r--r--grc/gui/Colors.py40
-rw-r--r--grc/gui/Connection.py143
-rw-r--r--grc/gui/Constants.py83
-rw-r--r--grc/gui/Dialogs.py118
-rw-r--r--grc/gui/DrawingArea.py133
-rw-r--r--grc/gui/Element.py228
-rw-r--r--grc/gui/FileDialogs.py175
-rw-r--r--grc/gui/FlowGraph.py524
-rw-r--r--grc/gui/MainWindow.py327
-rw-r--r--grc/gui/Messages.py104
-rw-r--r--grc/gui/NotebookPage.py187
-rw-r--r--grc/gui/Param.py189
-rw-r--r--grc/gui/Platform.py23
-rw-r--r--grc/gui/Port.py190
-rw-r--r--grc/gui/Preferences.py86
-rw-r--r--grc/gui/PropsDialog.py170
-rw-r--r--grc/gui/StateCache.py92
-rw-r--r--grc/gui/Utils.py90
-rw-r--r--grc/gui/__init__.py1
-rw-r--r--grc/python/Block.py180
-rw-r--r--grc/python/CMakeLists.txt44
-rw-r--r--grc/python/Connection.py46
-rw-r--r--grc/python/Constants.py95
-rw-r--r--grc/python/FlowGraph.py163
-rw-r--r--grc/python/Generator.py152
-rw-r--r--grc/python/Param.py458
-rw-r--r--grc/python/Platform.py70
-rw-r--r--grc/python/Port.py217
-rw-r--r--grc/python/__init__.py1
-rw-r--r--grc/python/block.dtd57
-rw-r--r--grc/python/convert_hier.py98
-rw-r--r--grc/python/default_flow_graph.grc43
-rw-r--r--grc/python/expr_utils.py153
-rw-r--r--grc/python/extract_docs.py66
-rw-r--r--grc/python/flow_graph.tmpl311
-rw-r--r--grc/scripts/CMakeLists.txt25
-rwxr-xr-xgrc/scripts/gnuradio-companion72
-rw-r--r--grc/todo.txt74
275 files changed, 20857 insertions, 0 deletions
diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt
new file mode 100644
index 000000000..1156f1d76
--- /dev/null
+++ b/grc/CMakeLists.txt
@@ -0,0 +1,128 @@
+# Copyright 2011,2013 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+# Setup dependencies
+########################################################################
+include(GrPython)
+
+GR_PYTHON_CHECK_MODULE("python >= 2.5" sys "sys.version.split()[0] >= '2.5'" PYTHON_MIN_VER_FOUND)
+GR_PYTHON_CHECK_MODULE("Cheetah >= 2.0.0" Cheetah "Cheetah.Version >= '2.0.0'" CHEETAH_FOUND)
+GR_PYTHON_CHECK_MODULE("lxml >= 1.3.6" lxml.etree "lxml.etree.LXML_VERSION >= (1, 3, 6, 0)" LXML_FOUND)
+GR_PYTHON_CHECK_MODULE("pygtk >= 2.10.0" gtk "gtk.pygtk_version >= (2, 10, 0)" PYGTK_FOUND)
+GR_PYTHON_CHECK_MODULE("numpy" numpy True NUMPY_FOUND)
+
+########################################################################
+# Register component
+########################################################################
+include(GrComponent)
+if(NOT CMAKE_CROSSCOMPILING)
+ set(grc_python_deps
+ PYTHON_MIN_VER_FOUND
+ CHEETAH_FOUND
+ LXML_FOUND
+ PYGTK_FOUND
+ NUMPY_FOUND
+ )
+endif(NOT CMAKE_CROSSCOMPILING)
+
+GR_REGISTER_COMPONENT("gnuradio-companion" ENABLE_GRC
+ ENABLE_GR_CORE
+ ENABLE_PYTHON
+ ${grc_python_deps}
+)
+
+########################################################################
+# Begin conditional configuration
+########################################################################
+if(ENABLE_GRC)
+
+########################################################################
+# Setup CPack components
+########################################################################
+include(GrPackage)
+CPACK_COMPONENT("grc"
+ DISPLAY_NAME "GNU Radio Companion"
+ DESCRIPTION "Graphical flow graph designer"
+ DEPENDS "core_python"
+)
+
+########################################################################
+# Create and install the grc conf file
+########################################################################
+file(TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/${GRC_BLOCKS_DIR} blocksdir)
+
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/grc.conf.in
+ ${CMAKE_CURRENT_BINARY_DIR}/grc.conf
+@ONLY)
+
+install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/grc.conf
+ DESTINATION ${GR_PREFSDIR}
+ COMPONENT "grc"
+)
+
+GR_PYTHON_INSTALL(
+ FILES __init__.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc
+ COMPONENT "grc"
+)
+
+########################################################################
+# Appens NSIS commands to set environment variables
+########################################################################
+if(WIN32)
+
+file(TO_NATIVE_PATH ${GR_PKG_DOC_DIR} GR_DOC_DIR)
+string(REPLACE "\\" "\\\\" GR_DOC_DIR ${GR_DOC_DIR})
+
+file(TO_NATIVE_PATH ${GRC_BLOCKS_DIR} GRC_BLOCKS_PATH)
+string(REPLACE "\\" "\\\\" GRC_BLOCKS_PATH ${GRC_BLOCKS_PATH})
+
+file(TO_NATIVE_PATH ${GR_PYTHON_DIR} GR_PYTHON_POSTFIX)
+string(REPLACE "\\" "\\\\" GR_PYTHON_POSTFIX ${GR_PYTHON_POSTFIX})
+
+CPACK_SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}
+ #!include \\\"winmessages.nsh\\\"
+ WriteRegStr HKLM ${HLKM_ENV} \\\"GRC_BLOCKS_PATH\\\" \\\"$INSTDIR\\\\${GRC_BLOCKS_PATH}\\\"
+ SendMessage \\\${HWND_BROADCAST} \\\${WM_WININICHANGE} 0 \\\"STR:Environment\\\" /TIMEOUT=5000
+")
+
+CPACK_SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS}
+ #!include \\\"winmessages.nsh\\\"
+ DeleteRegValue HKLM ${HLKM_ENV} \\\"GRC_BLOCKS_PATH\\\"
+ SendMessage \\\${HWND_BROADCAST} \\\${WM_WININICHANGE} 0 \\\"STR:Environment\\\" /TIMEOUT=5000
+")
+
+endif(WIN32)
+
+########################################################################
+# Add subdirectories
+########################################################################
+add_subdirectory(base)
+add_subdirectory(blocks)
+add_subdirectory(freedesktop)
+add_subdirectory(grc_gnuradio)
+add_subdirectory(gui)
+add_subdirectory(python)
+add_subdirectory(scripts)
+add_subdirectory(examples)
+
+endif(ENABLE_GRC)
diff --git a/grc/__init__.py b/grc/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/grc/__init__.py
diff --git a/grc/base/Block.py b/grc/base/Block.py
new file mode 100644
index 000000000..a20be9db9
--- /dev/null
+++ b/grc/base/Block.py
@@ -0,0 +1,253 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from . import odict
+from Element import Element
+
+from Cheetah.Template import Template
+from UserDict import UserDict
+
+class TemplateArg(UserDict):
+ """
+ A cheetah template argument created from a param.
+ The str of this class evaluates to the param's to code method.
+ The use of this class as a dictionary (enum only) will reveal the enum opts.
+ The __call__ or () method can return the param evaluated to a raw python data type.
+ """
+
+ def __init__(self, param):
+ UserDict.__init__(self)
+ self._param = param
+ if param.is_enum():
+ for key in param.get_opt_keys():
+ self[key] = str(param.get_opt(key))
+
+ def __str__(self):
+ return str(self._param.to_code())
+
+ def __call__(self):
+ return self._param.get_evaluated()
+
+def _get_keys(lst): return [elem.get_key() for elem in lst]
+def _get_elem(lst, key):
+ try: return lst[_get_keys(lst).index(key)]
+ except ValueError: raise ValueError, 'Key "%s" not found in %s.'%(key, _get_keys(lst))
+
+class Block(Element):
+
+ def __init__(self, flow_graph, n):
+ """
+ Make a new block from nested data.
+ @param flow graph the parent element
+ @param n the nested odict
+ @return block a new block
+ """
+ #build the block
+ Element.__init__(self, flow_graph)
+ #grab the data
+ params = n.findall('param')
+ sources = n.findall('source')
+ sinks = n.findall('sink')
+ self._name = n.find('name')
+ self._key = n.find('key')
+ self._category = n.find('category') or ''
+ self._grc_source = n.find('grc_source') or ''
+ self._block_wrapper_path = n.find('block_wrapper_path')
+ #create the param objects
+ self._params = list()
+ #add the id param
+ self.get_params().append(self.get_parent().get_parent().Param(
+ block=self,
+ n=odict({
+ 'name': 'ID',
+ 'key': 'id',
+ 'type': 'id',
+ })
+ ))
+ self.get_params().append(self.get_parent().get_parent().Param(
+ block=self,
+ n=odict({
+ 'name': 'Enabled',
+ 'key': '_enabled',
+ 'type': 'raw',
+ 'value': 'True',
+ 'hide': 'all',
+ })
+ ))
+ for param in map(lambda n: self.get_parent().get_parent().Param(block=self, n=n), params):
+ key = param.get_key()
+ #test against repeated keys
+ if key in self.get_param_keys():
+ raise Exception, 'Key "%s" already exists in params'%key
+ #store the param
+ self.get_params().append(param)
+ #create the source objects
+ self._sources = list()
+ for source in map(lambda n: self.get_parent().get_parent().Port(block=self, n=n, dir='source'), sources):
+ key = source.get_key()
+ #test against repeated keys
+ if key in self.get_source_keys():
+ raise Exception, 'Key "%s" already exists in sources'%key
+ #store the port
+ self.get_sources().append(source)
+ #create the sink objects
+ self._sinks = list()
+ for sink in map(lambda n: self.get_parent().get_parent().Port(block=self, n=n, dir='sink'), sinks):
+ key = sink.get_key()
+ #test against repeated keys
+ if key in self.get_sink_keys():
+ raise Exception, 'Key "%s" already exists in sinks'%key
+ #store the port
+ self.get_sinks().append(sink)
+
+ def get_enabled(self):
+ """
+ Get the enabled state of the block.
+ @return true for enabled
+ """
+ try: return eval(self.get_param('_enabled').get_value())
+ except: return True
+
+ def set_enabled(self, enabled):
+ """
+ Set the enabled state of the block.
+ @param enabled true for enabled
+ """
+ self.get_param('_enabled').set_value(str(enabled))
+
+ def __str__(self): return 'Block - %s - %s(%s)'%(self.get_id(), self.get_name(), self.get_key())
+
+ def get_id(self): return self.get_param('id').get_value()
+ def is_block(self): return True
+ def get_name(self): return self._name
+ def get_key(self): return self._key
+ def get_category(self): return self._category
+ def get_doc(self): return ''
+ def get_ports(self): return self.get_sources() + self.get_sinks()
+ def get_children(self): return self.get_ports() + self.get_params()
+ def get_block_wrapper_path(self): return self._block_wrapper_path
+
+ ##############################################
+ # Access Params
+ ##############################################
+ def get_param_keys(self): return _get_keys(self._params)
+ def get_param(self, key): return _get_elem(self._params, key)
+ def get_params(self): return self._params
+
+ ##############################################
+ # Access Sinks
+ ##############################################
+ def get_sink_keys(self): return _get_keys(self._sinks)
+ def get_sink(self, key): return _get_elem(self._sinks, key)
+ def get_sinks(self): return self._sinks
+
+ ##############################################
+ # Access Sources
+ ##############################################
+ def get_source_keys(self): return _get_keys(self._sources)
+ def get_source(self, key): return _get_elem(self._sources, key)
+ def get_sources(self): return self._sources
+
+ def get_connections(self):
+ return sum([port.get_connections() for port in self.get_ports()], [])
+
+ def resolve_dependencies(self, tmpl):
+ """
+ Resolve a paramater dependency with cheetah templates.
+ @param tmpl the string with dependencies
+ @return the resolved value
+ """
+ tmpl = str(tmpl)
+ if '$' not in tmpl: return tmpl
+ n = dict((p.get_key(), TemplateArg(p)) for p in self.get_params())
+ try: return str(Template(tmpl, n))
+ except Exception, e: return "-------->\n%s: %s\n<--------"%(e, tmpl)
+
+ ##############################################
+ # Controller Modify
+ ##############################################
+ def type_controller_modify(self, direction):
+ """
+ Change the type controller.
+ @param direction +1 or -1
+ @return true for change
+ """
+ changed = False
+ type_param = None
+ for param in filter(lambda p: p.is_enum(), self.get_params()):
+ children = self.get_ports() + self.get_params()
+ #priority to the type controller
+ if param.get_key() in ' '.join(map(lambda p: p._type, children)): type_param = param
+ #use param if type param is unset
+ if not type_param: type_param = param
+ if type_param:
+ #try to increment the enum by direction
+ try:
+ keys = type_param.get_option_keys()
+ old_index = keys.index(type_param.get_value())
+ new_index = (old_index + direction + len(keys))%len(keys)
+ type_param.set_value(keys[new_index])
+ changed = True
+ except: pass
+ return changed
+
+ def port_controller_modify(self, direction):
+ """
+ Change the port controller.
+ @param direction +1 or -1
+ @return true for change
+ """
+ return False
+
+ ##############################################
+ ## Import/Export Methods
+ ##############################################
+ def export_data(self):
+ """
+ Export this block's params to nested data.
+ @return a nested data odict
+ """
+ n = odict()
+ n['key'] = self.get_key()
+ n['param'] = map(lambda p: p.export_data(), self.get_params())
+ return n
+
+ def import_data(self, n):
+ """
+ Import this block's params from nested data.
+ Any param keys that do not exist will be ignored.
+ Since params can be dynamically created based another param,
+ call rewrite, and repeat the load until the params stick.
+ This call to rewrite will also create any dynamic ports
+ that are needed for the connections creation phase.
+ @param n the nested data odict
+ """
+ get_hash = lambda: hash(tuple(map(hash, self.get_params())))
+ my_hash = 0
+ while get_hash() != my_hash:
+ params_n = n.findall('param')
+ for param_n in params_n:
+ key = param_n.find('key')
+ value = param_n.find('value')
+ #the key must exist in this block's params
+ if key in self.get_param_keys():
+ self.get_param(key).set_value(value)
+ #store hash and call rewrite
+ my_hash = get_hash()
+ self.rewrite()
diff --git a/grc/base/CMakeLists.txt b/grc/base/CMakeLists.txt
new file mode 100644
index 000000000..1087e842a
--- /dev/null
+++ b/grc/base/CMakeLists.txt
@@ -0,0 +1,42 @@
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+GR_PYTHON_INSTALL(FILES
+ odict.py
+ ParseXML.py
+ Block.py
+ Connection.py
+ Constants.py
+ Element.py
+ FlowGraph.py
+ Param.py
+ Platform.py
+ Port.py
+ __init__.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/base
+ COMPONENT "grc"
+)
+
+install(FILES
+ block_tree.dtd
+ flow_graph.dtd
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/base
+ COMPONENT "grc"
+)
diff --git a/grc/base/Connection.py b/grc/base/Connection.py
new file mode 100644
index 000000000..3ce7fd07f
--- /dev/null
+++ b/grc/base/Connection.py
@@ -0,0 +1,97 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from Element import Element
+from . import odict
+
+class Connection(Element):
+
+ def __init__(self, flow_graph, porta, portb):
+ """
+ Make a new connection given the parent and 2 ports.
+ @param flow_graph the parent of this element
+ @param porta a port (any direction)
+ @param portb a port (any direction)
+ @throws Error cannot make connection
+ @return a new connection
+ """
+ Element.__init__(self, flow_graph)
+ source = sink = None
+ #separate the source and sink
+ for port in (porta, portb):
+ if port.is_source(): source = port
+ if port.is_sink(): sink = port
+ if not source: raise ValueError('Connection could not isolate source')
+ if not sink: raise ValueError('Connection could not isolate sink')
+ #ensure that this connection (source -> sink) is unique
+ for connection in self.get_parent().get_connections():
+ if connection.get_source() is source and connection.get_sink() is sink:
+ raise Exception('This connection between source and sink is not unique.')
+ self._source = source
+ self._sink = sink
+
+ def __str__(self):
+ return 'Connection (\n\t%s\n\t\t%s\n\t%s\n\t\t%s\n)'%(
+ self.get_source().get_parent(),
+ self.get_source(),
+ self.get_sink().get_parent(),
+ self.get_sink(),
+ )
+
+ def is_connection(self): return True
+
+ def validate(self):
+ """
+ Validate the connections.
+ The ports must match in type.
+ """
+ Element.validate(self)
+ source_type = self.get_source().get_type()
+ sink_type = self.get_sink().get_type()
+ if source_type != sink_type:
+ self.add_error_message('Source type "%s" does not match sink type "%s".'%(source_type, sink_type))
+
+ def get_enabled(self):
+ """
+ Get the enabled state of this connection.
+ @return true if source and sink blocks are enabled
+ """
+ return self.get_source().get_parent().get_enabled() and \
+ self.get_sink().get_parent().get_enabled()
+
+ #############################
+ # Access Ports
+ #############################
+ def get_sink(self): return self._sink
+ def get_source(self): return self._source
+
+ ##############################################
+ ## Import/Export Methods
+ ##############################################
+ def export_data(self):
+ """
+ Export this connection's info.
+ @return a nested data odict
+ """
+ n = odict()
+ n['source_block_id'] = self.get_source().get_parent().get_id()
+ n['sink_block_id'] = self.get_sink().get_parent().get_id()
+ n['source_key'] = self.get_source().get_key()
+ n['sink_key'] = self.get_sink().get_key()
+ return n
diff --git a/grc/base/Constants.py b/grc/base/Constants.py
new file mode 100644
index 000000000..ef45be8df
--- /dev/null
+++ b/grc/base/Constants.py
@@ -0,0 +1,25 @@
+"""
+Copyright 2008, 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import os
+
+#data files
+DATA_DIR = os.path.dirname(__file__)
+FLOW_GRAPH_DTD = os.path.join(DATA_DIR, 'flow_graph.dtd')
+BLOCK_TREE_DTD = os.path.join(DATA_DIR, 'block_tree.dtd')
diff --git a/grc/base/Element.py b/grc/base/Element.py
new file mode 100644
index 000000000..a57090f3b
--- /dev/null
+++ b/grc/base/Element.py
@@ -0,0 +1,89 @@
+"""
+Copyright 2008, 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+class Element(object):
+
+ def __init__(self, parent=None):
+ self._parent = parent
+
+ ##################################################
+ # Element Validation API
+ ##################################################
+ def validate(self):
+ """
+ Validate this element and call validate on all children.
+ Call this base method before adding error messages in the subclass.
+ """
+ self._error_messages = list()
+ for child in self.get_children(): child.validate()
+
+ def is_valid(self):
+ """
+ Is this element valid?
+ @return true when the element is enabled and has no error messages
+ """
+ return not self.get_error_messages() or not self.get_enabled()
+
+ def add_error_message(self, msg):
+ """
+ Add an error message to the list of errors.
+ @param msg the error message string
+ """
+ self._error_messages.append(msg)
+
+ def get_error_messages(self):
+ """
+ Get the list of error messages from this element and all of its children.
+ Do not include the error messages from disabled children.
+ Cleverly indent the children error messages for printing purposes.
+ @return a list of error message strings
+ """
+ error_messages = list(self._error_messages) #make a copy
+ for child in filter(lambda c: c.get_enabled(), self.get_children()):
+ for msg in child.get_error_messages():
+ error_messages.append("%s:\n\t%s"%(child, msg.replace("\n", "\n\t")))
+ return error_messages
+
+ def rewrite(self):
+ """
+ Rewrite this element and call rewrite on all children.
+ Call this base method before rewriting the element.
+ """
+ for child in self.get_children(): child.rewrite()
+
+ def get_enabled(self): return True
+
+ ##############################################
+ ## Tree-like API
+ ##############################################
+ def get_parent(self): return self._parent
+ def get_children(self): return list()
+
+ ##############################################
+ ## Type testing methods
+ ##############################################
+ def is_element(self): return True
+ def is_platform(self): return False
+ def is_flow_graph(self): return False
+ def is_connection(self): return False
+ def is_block(self): return False
+ def is_source(self): return False
+ def is_sink(self): return False
+ def is_port(self): return False
+ def is_param(self): return False
diff --git a/grc/base/FlowGraph.py b/grc/base/FlowGraph.py
new file mode 100644
index 000000000..0ba1f2389
--- /dev/null
+++ b/grc/base/FlowGraph.py
@@ -0,0 +1,219 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from . import odict
+from Element import Element
+from .. gui import Messages
+
+class FlowGraph(Element):
+
+ def __init__(self, platform):
+ """
+ Make a flow graph from the arguments.
+ @param platform a platforms with blocks and contrcutors
+ @return the flow graph object
+ """
+ #initialize
+ Element.__init__(self, platform)
+ #inital blank import
+ self.import_data()
+
+ def _get_unique_id(self, base_id=''):
+ """
+ Get a unique id starting with the base id.
+ @param base_id the id starts with this and appends a count
+ @return a unique id
+ """
+ index = 0
+ while True:
+ id = '%s_%d'%(base_id, index)
+ index = index + 1
+ #make sure that the id is not used by another block
+ if not filter(lambda b: b.get_id() == id, self.get_blocks()): return id
+
+ def __str__(self): return 'FlowGraph - %s(%s)'%(self.get_option('title'), self.get_option('id'))
+
+ def get_option(self, key):
+ """
+ Get the option for a given key.
+ The option comes from the special options block.
+ @param key the param key for the options block
+ @return the value held by that param
+ """
+ return self._options_block.get_param(key).get_evaluated()
+
+ def is_flow_graph(self): return True
+
+ ##############################################
+ ## Access Elements
+ ##############################################
+ def get_block(self, id): return filter(lambda b: b.get_id() == id, self.get_blocks())[0]
+ def get_blocks(self): return filter(lambda e: e.is_block(), self.get_elements())
+ def get_connections(self): return filter(lambda e: e.is_connection(), self.get_elements())
+ def get_children(self): return self.get_elements()
+ def get_elements(self):
+ """
+ Get a list of all the elements.
+ Always ensure that the options block is in the list (only once).
+ @return the element list
+ """
+ options_block_count = self._elements.count(self._options_block)
+ if not options_block_count:
+ self._elements.append(self._options_block)
+ for i in range(options_block_count-1):
+ self._elements.remove(self._options_block)
+ return self._elements
+
+ def get_enabled_blocks(self):
+ """
+ Get a list of all blocks that are enabled.
+ @return a list of blocks
+ """
+ return filter(lambda b: b.get_enabled(), self.get_blocks())
+
+ def get_enabled_connections(self):
+ """
+ Get a list of all connections that are enabled.
+ @return a list of connections
+ """
+ return filter(lambda c: c.get_enabled(), self.get_connections())
+
+ def get_new_block(self, key):
+ """
+ Get a new block of the specified key.
+ Add the block to the list of elements.
+ @param key the block key
+ @return the new block or None if not found
+ """
+ if key not in self.get_parent().get_block_keys(): return None
+ block = self.get_parent().get_new_block(self, key)
+ self.get_elements().append(block)
+ return block
+
+ def connect(self, porta, portb):
+ """
+ Create a connection between porta and portb.
+ @param porta a port
+ @param portb another port
+ @throw Exception bad connection
+ @return the new connection
+ """
+ connection = self.get_parent().Connection(flow_graph=self, porta=porta, portb=portb)
+ self.get_elements().append(connection)
+ return connection
+
+ def remove_element(self, element):
+ """
+ Remove the element from the list of elements.
+ If the element is a port, remove the whole block.
+ If the element is a block, remove its connections.
+ If the element is a connection, just remove the connection.
+ """
+ if element not in self.get_elements(): return
+ #found a port, set to parent signal block
+ if element.is_port():
+ element = element.get_parent()
+ #remove block, remove all involved connections
+ if element.is_block():
+ for port in element.get_ports():
+ map(self.remove_element, port.get_connections())
+ self.get_elements().remove(element)
+
+ def evaluate(self, expr):
+ """
+ Evaluate the expression.
+ @param expr the string expression
+ @throw NotImplementedError
+ """
+ raise NotImplementedError
+
+ ##############################################
+ ## Import/Export Methods
+ ##############################################
+ def export_data(self):
+ """
+ Export this flow graph to nested data.
+ Export all block and connection data.
+ @return a nested data odict
+ """
+ import time
+ n = odict()
+ n['timestamp'] = time.ctime()
+ n['block'] = [block.export_data() for block in self.get_blocks()]
+ n['connection'] = [connection.export_data() for connection in self.get_connections()]
+ return odict({'flow_graph': n})
+
+ def import_data(self, n=None):
+ """
+ Import blocks and connections into this flow graph.
+ Clear this flowgraph of all previous blocks and connections.
+ Any blocks or connections in error will be ignored.
+ @param n the nested data odict
+ """
+ #remove previous elements
+ self._elements = list()
+ #use blank data if none provided
+ fg_n = n and n.find('flow_graph') or odict()
+ blocks_n = fg_n.findall('block')
+ connections_n = fg_n.findall('connection')
+ #create option block
+ self._options_block = self.get_parent().get_new_block(self, 'options')
+ #build the blocks
+ for block_n in blocks_n:
+ key = block_n.find('key')
+ if key == 'options': block = self._options_block
+ else: block = self.get_new_block(key)
+ #only load the block when the block key was valid
+ if block: block.import_data(block_n)
+ else: Messages.send_error_load('Block key "%s" not found in %s'%(key, self.get_parent()))
+ #build the connections
+ for connection_n in connections_n:
+ #try to make the connection
+ try:
+ #get the block ids
+ source_block_id = connection_n.find('source_block_id')
+ sink_block_id = connection_n.find('sink_block_id')
+ #get the port keys
+ source_key = connection_n.find('source_key')
+ sink_key = connection_n.find('sink_key')
+ #verify the blocks
+ block_ids = map(lambda b: b.get_id(), self.get_blocks())
+ if source_block_id not in block_ids:
+ raise LookupError('source block id "%s" not in block ids'%source_block_id)
+ if sink_block_id not in block_ids:
+ raise LookupError('sink block id "%s" not in block ids'%sink_block_id)
+ #get the blocks
+ source_block = self.get_block(source_block_id)
+ sink_block = self.get_block(sink_block_id)
+ #verify the ports
+ if source_key not in source_block.get_source_keys():
+ raise LookupError('source key "%s" not in source block keys'%source_key)
+ if sink_key not in sink_block.get_sink_keys():
+ raise LookupError('sink key "%s" not in sink block keys'%sink_key)
+ #get the ports
+ source = source_block.get_source(source_key)
+ sink = sink_block.get_sink(sink_key)
+ #build the connection
+ self.connect(source, sink)
+ except LookupError, e: Messages.send_error_load(
+ 'Connection between %s(%s) and %s(%s) could not be made.\n\t%s'%(
+ source_block_id, source_key, sink_block_id, sink_key, e
+ )
+ )
+ self.rewrite() #global rewrite
diff --git a/grc/base/Param.py b/grc/base/Param.py
new file mode 100644
index 000000000..c2fa5461a
--- /dev/null
+++ b/grc/base/Param.py
@@ -0,0 +1,181 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from . import odict
+from Element import Element
+
+def _get_keys(lst): return [elem.get_key() for elem in lst]
+def _get_elem(lst, key):
+ try: return lst[_get_keys(lst).index(key)]
+ except ValueError: raise ValueError, 'Key "%s" not found in %s.'%(key, _get_keys(lst))
+
+class Option(Element):
+
+ def __init__(self, param, n):
+ Element.__init__(self, param)
+ self._name = n.find('name')
+ self._key = n.find('key')
+ self._opts = dict()
+ opts = n.findall('opt')
+ #test against opts when non enum
+ if not self.get_parent().is_enum() and opts:
+ raise Exception, 'Options for non-enum types cannot have sub-options'
+ #extract opts
+ for opt in opts:
+ #separate the key:value
+ try: key, value = opt.split(':')
+ except: raise Exception, 'Error separating "%s" into key:value'%opt
+ #test against repeated keys
+ if self._opts.has_key(key):
+ raise Exception, 'Key "%s" already exists in option'%key
+ #store the option
+ self._opts[key] = value
+
+ def __str__(self): return 'Option %s(%s)'%(self.get_name(), self.get_key())
+ def get_name(self): return self._name
+ def get_key(self): return self._key
+
+ ##############################################
+ # Access Opts
+ ##############################################
+ def get_opt_keys(self): return self._opts.keys()
+ def get_opt(self, key): return self._opts[key]
+ def get_opts(self): return self._opts.values()
+
+class Param(Element):
+
+ def __init__(self, block, n):
+ """
+ Make a new param from nested data.
+ @param block the parent element
+ @param n the nested odict
+ """
+ #grab the data
+ self._name = n.find('name')
+ self._key = n.find('key')
+ value = n.find('value') or ''
+ self._type = n.find('type')
+ self._hide = n.find('hide') or ''
+ #build the param
+ Element.__init__(self, block)
+ #create the Option objects from the n data
+ self._options = list()
+ for option in map(lambda o: Option(param=self, n=o), n.findall('option')):
+ key = option.get_key()
+ #test against repeated keys
+ if key in self.get_option_keys():
+ raise Exception, 'Key "%s" already exists in options'%key
+ #store the option
+ self.get_options().append(option)
+ #test the enum options
+ if self.is_enum():
+ #test against options with identical keys
+ if len(set(self.get_option_keys())) != len(self.get_options()):
+ raise Exception, 'Options keys "%s" are not unique.'%self.get_option_keys()
+ #test against inconsistent keys in options
+ opt_keys = self.get_options()[0].get_opt_keys()
+ for option in self.get_options():
+ if set(opt_keys) != set(option.get_opt_keys()):
+ raise Exception, 'Opt keys "%s" are not identical across all options.'%opt_keys
+ #if a value is specified, it must be in the options keys
+ self._value = value if value or value in self.get_option_keys() else self.get_option_keys()[0]
+ if self.get_value() not in self.get_option_keys():
+ raise Exception, 'The value "%s" is not in the possible values of "%s".'%(self.get_value(), self.get_option_keys())
+ else: self._value = value or ''
+
+ def validate(self):
+ """
+ Validate the param.
+ The value must be evaluated and type must a possible type.
+ """
+ Element.validate(self)
+ if self.get_type() not in self.get_types():
+ self.add_error_message('Type "%s" is not a possible type.'%self.get_type())
+
+ def get_evaluated(self): raise NotImplementedError
+
+ def to_code(self):
+ """
+ Convert the value to code.
+ @throw NotImplementedError
+ """
+ raise NotImplementedError
+
+ def get_types(self):
+ """
+ Get a list of all possible param types.
+ @throw NotImplementedError
+ """
+ raise NotImplementedError
+
+ def get_color(self): return '#FFFFFF'
+ def __str__(self): return 'Param - %s(%s)'%(self.get_name(), self.get_key())
+ def is_param(self): return True
+ def get_name(self): return self._name
+ def get_key(self): return self._key
+ def get_hide(self): return self.get_parent().resolve_dependencies(self._hide).strip()
+
+ def get_value(self):
+ value = self._value
+ if self.is_enum() and value not in self.get_option_keys():
+ value = self.get_option_keys()[0]
+ self.set_value(value)
+ return value
+
+ def set_value(self, value): self._value = str(value) #must be a string
+
+ def get_type(self): return self.get_parent().resolve_dependencies(self._type)
+ def is_enum(self): return self._type == 'enum'
+
+ def __repr__(self):
+ """
+ Get the repr (nice string format) for this param.
+ Just return the value (special case enum).
+ Derived classes can handle complex formatting.
+ @return the string representation
+ """
+ if self.is_enum(): return self.get_option(self.get_value()).get_name()
+ return self.get_value()
+
+ ##############################################
+ # Access Options
+ ##############################################
+ def get_option_keys(self): return _get_keys(self.get_options())
+ def get_option(self, key): return _get_elem(self.get_options(), key)
+ def get_options(self): return self._options
+
+ ##############################################
+ # Access Opts
+ ##############################################
+ def get_opt_keys(self): return self.get_option(self.get_value()).get_opt_keys()
+ def get_opt(self, key): return self.get_option(self.get_value()).get_opt(key)
+ def get_opts(self): return self.get_option(self.get_value()).get_opts()
+
+ ##############################################
+ ## Import/Export Methods
+ ##############################################
+ def export_data(self):
+ """
+ Export this param's key/value.
+ @return a nested data odict
+ """
+ n = odict()
+ n['key'] = self.get_key()
+ n['value'] = self.get_value()
+ return n
diff --git a/grc/base/ParseXML.py b/grc/base/ParseXML.py
new file mode 100644
index 000000000..078ebd078
--- /dev/null
+++ b/grc/base/ParseXML.py
@@ -0,0 +1,102 @@
+"""
+Copyright 2008 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from lxml import etree
+from . import odict
+
+class XMLSyntaxError(Exception):
+ def __init__(self, error_log):
+ self._error_log = error_log
+ def __str__(self):
+ return '\n'.join(map(str, self._error_log.filter_from_errors()))
+
+def validate_dtd(xml_file, dtd_file=None):
+ """
+ Validate an xml file against its dtd.
+ @param xml_file the xml file
+ @param dtd_file the optional dtd file
+ @throws Exception validation fails
+ """
+ #perform parsing, use dtd validation if dtd file is not specified
+ parser = etree.XMLParser(dtd_validation=not dtd_file)
+ xml = etree.parse(xml_file, parser=parser)
+ if parser.error_log: raise XMLSyntaxError(parser.error_log)
+ #perform dtd validation if the dtd file is specified
+ if not dtd_file: return
+ dtd = etree.DTD(dtd_file)
+ if not dtd.validate(xml.getroot()): raise XMLSyntaxError(dtd.error_log)
+
+def from_file(xml_file):
+ """
+ Create nested data from an xml file using the from xml helper.
+ @param xml_file the xml file path
+ @return the nested data
+ """
+ xml = etree.parse(xml_file).getroot()
+ return _from_file(xml)
+
+def _from_file(xml):
+ """
+ Recursivly parse the xml tree into nested data format.
+ @param xml the xml tree
+ @return the nested data
+ """
+ tag = xml.tag
+ if not len(xml):
+ return odict({tag: xml.text or ''}) #store empty tags (text is None) as empty string
+ nested_data = odict()
+ for elem in xml:
+ key, value = _from_file(elem).items()[0]
+ if nested_data.has_key(key): nested_data[key].append(value)
+ else: nested_data[key] = [value]
+ #delistify if the length of values is 1
+ for key, values in nested_data.iteritems():
+ if len(values) == 1: nested_data[key] = values[0]
+ return odict({tag: nested_data})
+
+def to_file(nested_data, xml_file):
+ """
+ Write an xml file and use the to xml helper method to load it.
+ @param nested_data the nested data
+ @param xml_file the xml file path
+ """
+ xml = _to_file(nested_data)[0]
+ open(xml_file, 'w').write(etree.tostring(xml, xml_declaration=True, pretty_print=True))
+
+def _to_file(nested_data):
+ """
+ Recursivly parse the nested data into xml tree format.
+ @param nested_data the nested data
+ @return the xml tree filled with child nodes
+ """
+ nodes = list()
+ for key, values in nested_data.iteritems():
+ #listify the values if not a list
+ if not isinstance(values, (list, set, tuple)):
+ values = [values]
+ for value in values:
+ node = etree.Element(key)
+ if isinstance(value, (str, unicode)): node.text = value
+ else: node.extend(_to_file(value))
+ nodes.append(node)
+ return nodes
+
+if __name__ == '__main__':
+ """Use the main method to test parse xml's functions."""
+ pass
diff --git a/grc/base/Platform.py b/grc/base/Platform.py
new file mode 100644
index 000000000..d4b09088b
--- /dev/null
+++ b/grc/base/Platform.py
@@ -0,0 +1,178 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import os
+import sys
+from .. base import ParseXML, odict
+from Element import Element as _Element
+from FlowGraph import FlowGraph as _FlowGraph
+from Connection import Connection as _Connection
+from Block import Block as _Block
+from Port import Port as _Port
+from Param import Param as _Param
+from Constants import BLOCK_TREE_DTD, FLOW_GRAPH_DTD
+
+class Platform(_Element):
+
+ def __init__(self, name, version, key,
+ block_paths, block_dtd, default_flow_graph, generator,
+ license='', website=None, colors=[]):
+ """
+ Make a platform from the arguments.
+ @param name the platform name
+ @param version the version string
+ @param key the unique platform key
+ @param block_paths the file paths to blocks in this platform
+ @param block_dtd the dtd validator for xml block wrappers
+ @param default_flow_graph the default flow graph file path
+ @param generator the generator class for this platform
+ @param colors a list of title, color_spec tuples
+ @param license a multi-line license (first line is copyright)
+ @param website the website url for this platform
+ @return a platform object
+ """
+ _Element.__init__(self)
+ self._name = name
+ self._version = version
+ self._key = key
+ self._license = license
+ self._website = website
+ self._block_paths = block_paths
+ self._block_dtd = block_dtd
+ self._default_flow_graph = default_flow_graph
+ self._generator = generator
+ self._colors = colors
+ #create a dummy flow graph for the blocks
+ self._flow_graph = _Element(self)
+ #search for *.xml files in the given search path
+
+ self.loadblocks();
+
+ def loadblocks(self):
+ xml_files = list()
+ for block_path in self._block_paths:
+ if os.path.isfile(block_path): xml_files.append(block_path)
+ elif os.path.isdir(block_path):
+ for dirpath, dirnames, filenames in os.walk(block_path):
+ for filename in sorted(filter(lambda f: f.endswith('.xml'), filenames)):
+ xml_files.append(os.path.join(dirpath, filename))
+ #load the blocks
+ self._blocks = odict()
+ self._blocks_n = odict()
+ self._block_tree_files = list()
+ for xml_file in xml_files:
+ try: #try to add the xml file as a block wrapper
+ ParseXML.validate_dtd(xml_file, self._block_dtd)
+ n = ParseXML.from_file(xml_file).find('block')
+ #inject block wrapper path
+ n['block_wrapper_path'] = xml_file
+ block = self.Block(self._flow_graph, n)
+ key = block.get_key()
+ #test against repeated keys
+ if key in self.get_block_keys():
+ print >> sys.stderr, 'Warning: Block with key "%s" already exists.\n\tIgnoring: %s'%(key, xml_file)
+ #store the block
+ else:
+ self._blocks[key] = block
+ self._blocks_n[key] = n
+ except ParseXML.XMLSyntaxError, e:
+ try: #try to add the xml file as a block tree
+ ParseXML.validate_dtd(xml_file, BLOCK_TREE_DTD)
+ self._block_tree_files.append(xml_file)
+ except ParseXML.XMLSyntaxError, e:
+ print >> sys.stderr, 'Warning: Block validation failed:\n\t%s\n\tIgnoring: %s'%(e, xml_file)
+ except Exception, e:
+ print >> sys.stderr, 'Warning: Block loading failed:\n\t%s\n\tIgnoring: %s'%(e, xml_file)
+
+ def parse_flow_graph(self, flow_graph_file):
+ """
+ Parse a saved flow graph file.
+ Ensure that the file exists, and passes the dtd check.
+ @param flow_graph_file the flow graph file
+ @return nested data
+ @throws exception if the validation fails
+ """
+ flow_graph_file = flow_graph_file or self._default_flow_graph
+ open(flow_graph_file, 'r') #test open
+ ParseXML.validate_dtd(flow_graph_file, FLOW_GRAPH_DTD)
+ return ParseXML.from_file(flow_graph_file)
+
+ def load_block_tree(self, block_tree):
+ """
+ Load a block tree with categories and blocks.
+ Step 1: Load all blocks from the xml specification.
+ Step 2: Load blocks with builtin category specifications.
+ @param block_tree the block tree object
+ """
+ #recursive function to load categories and blocks
+ def load_category(cat_n, parent=[]):
+ #add this category
+ parent = parent + [cat_n.find('name')]
+ block_tree.add_block(parent)
+ #recursive call to load sub categories
+ map(lambda c: load_category(c, parent), cat_n.findall('cat'))
+ #add blocks in this category
+ for block_key in cat_n.findall('block'):
+ if block_key not in self.get_block_keys():
+ print >> sys.stderr, 'Warning: Block key "%s" not found when loading category tree.'%(block_key)
+ continue
+ block = self.get_block(block_key)
+ #if it exists, the block's category overrides the block tree
+ if not block.get_category(): block_tree.add_block(parent, block)
+ #load the block tree
+ for block_tree_file in self._block_tree_files:
+ #recursivly add all blocks in the tree
+ load_category(ParseXML.from_file(block_tree_file).find('cat'))
+ #add all other blocks, use the catgory tag
+ for block in self.get_blocks():
+ #blocks with empty categories are in the xml block tree or hidden
+ if not block.get_category(): continue
+ block_tree.add_block(block.get_category(), block)
+
+ def __str__(self): return 'Platform - %s(%s)'%(self.get_key(), self.get_name())
+
+ def is_platform(self): return True
+
+ def get_new_flow_graph(self): return self.FlowGraph(platform=self)
+
+ def get_generator(self): return self._generator
+
+ ##############################################
+ # Access Blocks
+ ##############################################
+ def get_block_keys(self): return self._blocks.keys()
+ def get_block(self, key): return self._blocks[key]
+ def get_blocks(self): return self._blocks.values()
+ def get_new_block(self, flow_graph, key): return self.Block(flow_graph, n=self._blocks_n[key])
+
+ def get_name(self): return self._name
+ def get_version(self): return self._version
+ def get_key(self): return self._key
+ def get_license(self): return self._license
+ def get_website(self): return self._website
+ def get_colors(self): return self._colors
+
+ ##############################################
+ # Constructors
+ ##############################################
+ FlowGraph = _FlowGraph
+ Connection = _Connection
+ Block = _Block
+ Port = _Port
+ Param = _Param
diff --git a/grc/base/Port.py b/grc/base/Port.py
new file mode 100644
index 000000000..7a1b5d4e6
--- /dev/null
+++ b/grc/base/Port.py
@@ -0,0 +1,83 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from Element import Element
+
+class Port(Element):
+
+ def __init__(self, block, n, dir):
+ """
+ Make a new port from nested data.
+ @param block the parent element
+ @param n the nested odict
+ @param dir the direction source or sink
+ """
+ #build the port
+ Element.__init__(self, block)
+ #grab the data
+ self._name = n['name']
+ self._key = n['key']
+ self._type = n['type']
+ self._dir = dir
+
+ def validate(self):
+ """
+ Validate the port.
+ The port must be non-empty and type must a possible type.
+ """
+ Element.validate(self)
+ if self.get_type() not in self.get_types():
+ self.add_error_message('Type "%s" is not a possible type.'%self.get_type())
+
+ def __str__(self):
+ if self.is_source():
+ return 'Source - %s(%s)'%(self.get_name(), self.get_key())
+ if self.is_sink():
+ return 'Sink - %s(%s)'%(self.get_name(), self.get_key())
+
+ def get_types(self):
+ """
+ Get a list of all possible port types.
+ @throw NotImplementedError
+ """
+ raise NotImplementedError
+
+ def is_port(self): return True
+ def get_color(self): return '#FFFFFF'
+ def get_name(self): return self._name
+ def get_key(self): return self._key
+ def is_sink(self): return self._dir == 'sink'
+ def is_source(self): return self._dir == 'source'
+ def get_type(self): return self.get_parent().resolve_dependencies(self._type)
+
+ def get_connections(self):
+ """
+ Get all connections that use this port.
+ @return a list of connection objects
+ """
+ connections = self.get_parent().get_parent().get_connections()
+ connections = filter(lambda c: c.get_source() is self or c.get_sink() is self, connections)
+ return connections
+
+ def get_enabled_connections(self):
+ """
+ Get all enabled connections that use this port.
+ @return a list of connection objects
+ """
+ return filter(lambda c: c.get_enabled(), self.get_connections())
diff --git a/grc/base/__init__.py b/grc/base/__init__.py
new file mode 100644
index 000000000..2682db812
--- /dev/null
+++ b/grc/base/__init__.py
@@ -0,0 +1,20 @@
+"""
+Copyright 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from odict import odict
diff --git a/grc/base/block_tree.dtd b/grc/base/block_tree.dtd
new file mode 100644
index 000000000..7d4a13ccc
--- /dev/null
+++ b/grc/base/block_tree.dtd
@@ -0,0 +1,26 @@
+<!--
+Copyright 2008 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+-->
+<!--
+ block_tree.dtd
+ Josh Blum
+ The document type definition for a block tree category listing.
+ -->
+<!ELEMENT cat (name, cat*, block*)>
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT block (#PCDATA)>
diff --git a/grc/base/flow_graph.dtd b/grc/base/flow_graph.dtd
new file mode 100644
index 000000000..74f48f10a
--- /dev/null
+++ b/grc/base/flow_graph.dtd
@@ -0,0 +1,36 @@
+<!--
+Copyright 2008 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+-->
+<!--
+ flow_graph.dtd
+ Josh Blum
+ The document type definition for flow graph xml files.
+ -->
+<!ELEMENT flow_graph (timestamp?, block*, connection*)> <!-- optional timestamp -->
+<!ELEMENT timestamp (#PCDATA)>
+<!-- Block -->
+<!ELEMENT block (key, param*)>
+<!ELEMENT param (key, value)>
+<!ELEMENT key (#PCDATA)>
+<!ELEMENT value (#PCDATA)>
+<!-- Connection -->
+<!ELEMENT connection (source_block_id, sink_block_id, source_key, sink_key)>
+<!ELEMENT source_block_id (#PCDATA)>
+<!ELEMENT sink_block_id (#PCDATA)>
+<!ELEMENT source_key (#PCDATA)>
+<!ELEMENT sink_key (#PCDATA)>
diff --git a/grc/base/odict.py b/grc/base/odict.py
new file mode 100644
index 000000000..044d04ad7
--- /dev/null
+++ b/grc/base/odict.py
@@ -0,0 +1,93 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from UserDict import DictMixin
+
+class odict(DictMixin):
+
+ def __init__(self, d={}):
+ self._keys = list(d.keys())
+ self._data = dict(d.copy())
+
+ def __setitem__(self, key, value):
+ if key not in self._data:
+ self._keys.append(key)
+ self._data[key] = value
+
+ def __getitem__(self, key):
+ return self._data[key]
+
+ def __delitem__(self, key):
+ del self._data[key]
+ self._keys.remove(key)
+
+ def keys(self):
+ return list(self._keys)
+
+ def copy(self):
+ copy_dict = odict()
+ copy_dict._data = self._data.copy()
+ copy_dict._keys = list(self._keys)
+ return copy_dict
+
+ def insert_after(self, pos_key, key, val):
+ """
+ Insert the new key, value entry after the entry given by the position key.
+ If the positional key is None, insert at the end.
+ @param pos_key the positional key
+ @param key the key for the new entry
+ @param val the value for the new entry
+ """
+ index = (pos_key is None) and len(self._keys) or self._keys.index(pos_key)
+ if key in self._keys: raise KeyError('Cannot insert, key "%s" already exists'%str(key))
+ self._keys.insert(index+1, key)
+ self._data[key] = val
+
+ def insert_before(self, pos_key, key, val):
+ """
+ Insert the new key, value entry before the entry given by the position key.
+ If the positional key is None, insert at the begining.
+ @param pos_key the positional key
+ @param key the key for the new entry
+ @param val the value for the new entry
+ """
+ index = (pos_key is not None) and self._keys.index(pos_key) or 0
+ if key in self._keys: raise KeyError('Cannot insert, key "%s" already exists'%str(key))
+ self._keys.insert(index, key)
+ self._data[key] = val
+
+ def find(self, key):
+ """
+ Get the value for this key if exists.
+ @param key the key to search for
+ @return the value or None
+ """
+ if self.has_key(key): return self[key]
+ return None
+
+ def findall(self, key):
+ """
+ Get a list of values for this key.
+ @param key the key to search for
+ @return a list of values or empty list
+ """
+ obj = self.find(key)
+ if obj is None: obj = list()
+ if isinstance(obj, list): return obj
+ return [obj]
diff --git a/grc/blocks/CMakeLists.txt b/grc/blocks/CMakeLists.txt
new file mode 100644
index 000000000..fce4a1907
--- /dev/null
+++ b/grc/blocks/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+file(GLOB xml_files "*.xml")
+install(FILES ${xml_files} DESTINATION ${GRC_BLOCKS_DIR} COMPONENT "grc")
diff --git a/grc/blocks/band_pass_filter.xml b/grc/blocks/band_pass_filter.xml
new file mode 100644
index 000000000..af083473d
--- /dev/null
+++ b/grc/blocks/band_pass_filter.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Band Pass Filter: Custom wrapper
+###################################################
+ -->
+<block>
+ <name>Band Pass Filter</name>
+ <key>band_pass_filter</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>gr.$(type)(#if str($type).startswith('interp') then $interp else $decim#, firdes.$(type.fcn)(
+ $gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, $win, $beta))</make>
+ <callback>set_taps(firdes.$(type.fcn)($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, $win, $beta))</callback>
+ <param>
+ <name>FIR Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <!-- Real Band Pass Taps -->
+ <option>
+ <name>Complex->Complex (Real Taps) (Decim)</name>
+ <key>fir_filter_ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>fcn:band_pass</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Real Taps) (Interp)</name>
+ <key>interp_fir_filter_ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>fcn:band_pass</opt>
+ </option>
+ <option>
+ <name>Float->Float (Real Taps) (Decim)</name>
+ <key>fir_filter_fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ <opt>fcn:band_pass</opt>
+ </option>
+ <option>
+ <name>Float->Float (Real Taps) (Interp)</name>
+ <key>interp_fir_filter_fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ <opt>fcn:band_pass</opt>
+ </option>
+ <!-- Complex Band Pass Taps -->
+ <option>
+ <name>Complex->Complex (Complex Taps) (Decim)</name>
+ <key>fir_filter_ccc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>fcn:complex_band_pass</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Complex Taps) (Interp)</name>
+ <key>interp_fir_filter_ccc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>fcn:complex_band_pass</opt>
+ </option>
+ <option>
+ <name>Float->Complex (Complex Taps) (Decim)</name>
+ <key>fir_filter_fcc</key>
+ <opt>input:float</opt>
+ <opt>output:complex</opt>
+ <opt>fcn:complex_band_pass</opt>
+ </option>
+ <option>
+ <name>Float->Complex (Complex Taps) (Interp)</name>
+ <key>interp_fir_filter_fcc</key>
+ <opt>input:float</opt>
+ <opt>output:complex</opt>
+ <opt>fcn:complex_band_pass</opt>
+ </option>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>#if str($type).startswith('interp') then 'all' else 'none'#</hide>
+ </param>
+ <param>
+ <name>Interpolation</name>
+ <key>interp</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>#if str($type).startswith('interp') then 'none' else 'all'#</hide>
+ </param>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Low Cutoff Freq</name>
+ <key>low_cutoff_freq</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>High Cutoff Freq</name>
+ <key>high_cutoff_freq</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Transition Width</name>
+ <key>width</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Window</name>
+ <key>win</key>
+ <value>firdes.WIN_HAMMING</value>
+ <type>int</type>
+ <option>
+ <name>Hamming</name>
+ <key>firdes.WIN_HAMMING</key>
+ </option>
+ <option>
+ <name>Hann</name>
+ <key>firdes.WIN_HANN</key>
+ </option>
+ <option>
+ <name>Blackman</name>
+ <key>firdes.WIN_BLACKMAN</key>
+ </option>
+ <option>
+ <name>Rectangular</name>
+ <key>firdes.WIN_RECTANGULAR</key>
+ </option>
+ <option>
+ <name>Kaiser</name>
+ <key>firdes.WIN_KAISER</key>
+ </option>
+ </param>
+ <param>
+ <name>Beta</name>
+ <key>beta</key>
+ <value>6.76</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+ <doc>
+This filter is a convenience wrapper for an fir filter and a firdes taps generating function.
+
+Sample rate, cutoff frequency, and transition width are in Hertz.
+
+The beta paramater only applies to the Kaiser window.
+ </doc>
+</block>
diff --git a/grc/blocks/band_reject_filter.xml b/grc/blocks/band_reject_filter.xml
new file mode 100644
index 000000000..dd5e7a9d7
--- /dev/null
+++ b/grc/blocks/band_reject_filter.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Band Reject Filter: Custom wrapper
+###################################################
+ -->
+<block>
+ <name>Band Reject Filter</name>
+ <key>band_reject_filter</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>gr.$(type)(#if str($type).startswith('interp') then $interp else $decim#, firdes.band_reject(
+ $gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, $win, $beta))</make>
+ <callback>set_taps(firdes.band_reject($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, $win, $beta))</callback>
+ <param>
+ <name>FIR Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Decimating)</name>
+ <key>fir_filter_ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Interpolating)</name>
+ <key>interp_fir_filter_ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ </option>
+ <option>
+ <name>Float->Float (Decimating)</name>
+ <key>fir_filter_fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ </option>
+ <option>
+ <name>Float->Float (Interpolating)</name>
+ <key>interp_fir_filter_fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ </option>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>#if str($type).startswith('interp') then 'all' else 'none'#</hide>
+ </param>
+ <param>
+ <name>Interpolation</name>
+ <key>interp</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>#if str($type).startswith('interp') then 'none' else 'all'#</hide>
+ </param>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Low Cutoff Freq</name>
+ <key>low_cutoff_freq</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>High Cutoff Freq</name>
+ <key>high_cutoff_freq</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Transition Width</name>
+ <key>width</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Window</name>
+ <key>win</key>
+ <value>firdes.WIN_HAMMING</value>
+ <type>int</type>
+ <option>
+ <name>Hamming</name>
+ <key>firdes.WIN_HAMMING</key>
+ </option>
+ <option>
+ <name>Hann</name>
+ <key>firdes.WIN_HANN</key>
+ </option>
+ <option>
+ <name>Blackman</name>
+ <key>firdes.WIN_BLACKMAN</key>
+ </option>
+ <option>
+ <name>Rectangular</name>
+ <key>firdes.WIN_RECTANGULAR</key>
+ </option>
+ <option>
+ <name>Kaiser</name>
+ <key>firdes.WIN_KAISER</key>
+ </option>
+ </param>
+ <param>
+ <name>Beta</name>
+ <key>beta</key>
+ <value>6.76</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+ <doc>
+This filter is a convenience wrapper for an fir filter and a firdes taps generating function.
+
+Sample rate, cutoff frequency, and transition width are in Hertz.
+
+The beta paramater only applies to the Kaiser window.
+ </doc>
+</block>
diff --git a/grc/blocks/blks2_am_demod_cf.xml b/grc/blocks/blks2_am_demod_cf.xml
new file mode 100644
index 000000000..898c613be
--- /dev/null
+++ b/grc/blocks/blks2_am_demod_cf.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##AM Demod
+###################################################
+ -->
+<block>
+ <name>AM Demod</name>
+ <key>blks2_am_demod_cf</key>
+ <import>from gnuradio import blks2</import>
+ <make>blks2.am_demod_cf(
+ channel_rate=$chan_rate,
+ audio_decim=$audio_decim,
+ audio_pass=$audio_pass,
+ audio_stop=$audio_stop,
+)</make>
+ <param>
+ <name>Channel Rate</name>
+ <key>chan_rate</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Audio Decimation</name>
+ <key>audio_decim</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Audio Pass</name>
+ <key>audio_pass</key>
+ <value>5000</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Audio Stop</name>
+ <key>audio_stop</key>
+ <value>5500</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_analysis_filterbank.xml b/grc/blocks/blks2_analysis_filterbank.xml
new file mode 100644
index 000000000..93cfa30af
--- /dev/null
+++ b/grc/blocks/blks2_analysis_filterbank.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Analysis Filterbank
+###################################################
+ -->
+<block>
+ <name>Analysis Filterbank</name>
+ <key>blks2_analysis_filterbank</key>
+ <import>from gnuradio import blks2</import>
+ <make>blks2.analysis_filterbank(mpoints=$mpoints, taps=$taps)</make>
+ <param>
+ <name>MPoints</name>
+ <key>mpoints</key>
+ <value>3</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>complex_vector</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ <nports>$mpoints</nports>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_error_rate.xml b/grc/blocks/blks2_error_rate.xml
new file mode 100644
index 000000000..91a303206
--- /dev/null
+++ b/grc/blocks/blks2_error_rate.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Error Rate:
+## Custom blks2 block
+###################################################
+ -->
+<block>
+ <name>Error Rate</name>
+ <key>blks2_error_rate</key>
+ <import>from grc_gnuradio import blks2 as grc_blks2</import>
+ <make>grc_blks2.error_rate(
+ type=$type,
+ win_size=$win_size,
+ bits_per_symbol=$bits_per_symbol,
+)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Bit Error Rate</name>
+ <key>'BER'</key>
+ <opt>hide_bps:</opt>
+ </option>
+ <option>
+ <name>Symbol Error Rate</name>
+ <key>'SER'</key>
+ <opt>hide_bps:all</opt>
+ </option>
+ </param>
+ <param>
+ <name>Window Size</name>
+ <key>win_size</key>
+ <value>1000</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Bits per Symbol</name>
+ <key>bits_per_symbol</key>
+ <value>2</value>
+ <type>int</type>
+ <hide>$type.hide_bps</hide>
+ </param>
+ <sink>
+ <name>ref</name>
+ <type>byte</type>
+ </sink>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+ <doc>
+Calculate the bit error rate (BER) or the symbol error rate (SER) over a number of samples given by the window size. \
+The actual window size will start at size one and grow to the full window size as new samples arrive. \
+Once the window has reached full size, old samples are shifted out of the window and new samples shfited in.
+
+The error block compares the input byte stream to the reference byte stream. \
+For example, the reference byte stream could be the input to a modulator, \
+and the input byte stream could be the output of a modulator.
+
+Each byte in the incoming stream represents one symbol. \
+The bits per symbol parameter is only useful for calculating the BER.
+ </doc>
+</block>
diff --git a/grc/blocks/blks2_fm_deemph.xml b/grc/blocks/blks2_fm_deemph.xml
new file mode 100644
index 000000000..6f38dab6d
--- /dev/null
+++ b/grc/blocks/blks2_fm_deemph.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##FM Deemphasis
+###################################################
+ -->
+<block>
+ <name>FM Deemphasis</name>
+ <key>blks2_fm_deemph</key>
+ <import>from gnuradio import blks2</import>
+ <make>blks2.fm_deemph(fs=$samp_rate, tau=$tau)</make>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Tau</name>
+ <key>tau</key>
+ <value>75e-6</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_fm_demod_cf.xml b/grc/blocks/blks2_fm_demod_cf.xml
new file mode 100644
index 000000000..2ce1fb973
--- /dev/null
+++ b/grc/blocks/blks2_fm_demod_cf.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##FM Demod
+###################################################
+ -->
+<block>
+ <name>FM Demod</name>
+ <key>blks2_fm_demod_cf</key>
+ <import>from gnuradio import blks2</import>
+ <make>blks2.fm_demod_cf(
+ channel_rate=$chan_rate,
+ audio_decim=$audio_decim,
+ deviation=$deviation,
+ audio_pass=$audio_pass,
+ audio_stop=$audio_stop,
+ gain=$gain,
+ tau=$tau,
+)</make>
+ <param>
+ <name>Channel Rate</name>
+ <key>chan_rate</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Audio Decimation</name>
+ <key>audio_decim</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Deviation</name>
+ <key>deviation</key>
+ <value>75000</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Audio Pass</name>
+ <key>audio_pass</key>
+ <value>15000</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Audio Stop</name>
+ <key>audio_stop</key>
+ <value>16000</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Tau</name>
+ <key>tau</key>
+ <value>75e-6</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_fm_preemph.xml b/grc/blocks/blks2_fm_preemph.xml
new file mode 100644
index 000000000..672a7a7b2
--- /dev/null
+++ b/grc/blocks/blks2_fm_preemph.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##FM Preemphasis
+###################################################
+ -->
+<block>
+ <name>FM Preemphasis</name>
+ <key>blks2_fm_preemph</key>
+ <import>from gnuradio import blks2</import>
+ <make>blks2.fm_preemph(fs=$samp_rate, tau=$tau)</make>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Tau</name>
+ <key>tau</key>
+ <value>75e-6</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_logpwrfft_x.xml b/grc/blocks/blks2_logpwrfft_x.xml
new file mode 100644
index 000000000..79a3bfc4b
--- /dev/null
+++ b/grc/blocks/blks2_logpwrfft_x.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Log Power FFT
+###################################################
+ -->
+<block>
+ <name>Log Power FFT</name>
+ <key>blks2_logpwrfft_x</key>
+ <import>from gnuradio import blks2</import>
+ <make>blks2.logpwrfft_$(type.fcn)(
+ sample_rate=$sample_rate,
+ fft_size=$fft_size,
+ ref_scale=$ref_scale,
+ frame_rate=$frame_rate,
+ avg_alpha=$avg_alpha,
+ average=$average,
+)</make>
+ <callback>set_sample_rate($sample_rate)</callback>
+ <callback>set_avg_alpha($avg_alpha)</callback>
+ <callback>set_average($average)</callback>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:c</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:f</opt>
+ </option>
+ </param>
+ <param>
+ <name>Sample Rate</name>
+ <key>sample_rate</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>FFT Size</name>
+ <key>fft_size</key>
+ <value>1024</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Reference Scale</name>
+ <key>ref_scale</key>
+ <value>2</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Frame Rate</name>
+ <key>frame_rate</key>
+ <value>30</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Average</name>
+ <key>average</key>
+ <value>False</value>
+ <type>bool</type>
+ <option>
+ <name>On</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Off</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Average Alpha</name>
+ <key>avg_alpha</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ <vlen>$fft_size</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_nbfm_rx.xml b/grc/blocks/blks2_nbfm_rx.xml
new file mode 100644
index 000000000..d332b9a6b
--- /dev/null
+++ b/grc/blocks/blks2_nbfm_rx.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##NBFM Receive
+###################################################
+ -->
+<block>
+ <name>NBFM Receive</name>
+ <key>blks2_nbfm_rx</key>
+ <import>from gnuradio import blks2</import>
+ <make>blks2.nbfm_rx(
+ audio_rate=$audio_rate,
+ quad_rate=$quad_rate,
+ tau=$tau,
+ max_dev=$max_dev,
+)</make>
+ <param>
+ <name>Audio Rate</name>
+ <key>audio_rate</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Quadrature Rate</name>
+ <key>quad_rate</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Tau</name>
+ <key>tau</key>
+ <value>75e-6</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Max Deviation</name>
+ <key>max_dev</key>
+ <value>5e3</value>
+ <type>real</type>
+ </param>
+ <check>$quad_rate%$audio_rate == 0</check>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_nbfm_tx.xml b/grc/blocks/blks2_nbfm_tx.xml
new file mode 100644
index 000000000..3aa7ede0e
--- /dev/null
+++ b/grc/blocks/blks2_nbfm_tx.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##NBFM Transmit
+###################################################
+ -->
+<block>
+ <name>NBFM Transmit</name>
+ <key>blks2_nbfm_tx</key>
+ <import>from gnuradio import blks2</import>
+ <make>blks2.nbfm_tx(
+ audio_rate=$audio_rate,
+ quad_rate=$quad_rate,
+ tau=$tau,
+ max_dev=$max_dev,
+)</make>
+ <param>
+ <name>Audio Rate</name>
+ <key>audio_rate</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Quadrature Rate</name>
+ <key>quad_rate</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Tau</name>
+ <key>tau</key>
+ <value>75e-6</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Max Deviation</name>
+ <key>max_dev</key>
+ <value>5e3</value>
+ <type>real</type>
+ </param>
+ <check>$quad_rate%$audio_rate == 0</check>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_packet_decoder.xml b/grc/blocks/blks2_packet_decoder.xml
new file mode 100644
index 000000000..07b0d1f2e
--- /dev/null
+++ b/grc/blocks/blks2_packet_decoder.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Packet Decoder
+###################################################
+ -->
+<block>
+ <name>Packet Decoder</name>
+ <key>blks2_packet_decoder</key>
+ <import>from grc_gnuradio import blks2 as grc_blks2</import>
+ <make>grc_blks2.packet_demod_$(type.fcn)(grc_blks2.packet_decoder(
+ access_code=$access_code,
+ threshold=$threshold,
+ callback=lambda ok, payload: self.$(id).recv_pkt(ok, payload),
+ ),
+)</make>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <value>float</value>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:c</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:f</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:i</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:s</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:b</opt>
+ </option>
+ </param>
+ <param>
+ <name>Access Code</name>
+ <key>access_code</key>
+ <value></value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Threshold</name>
+ <key>threshold</key>
+ <value>-1</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+ <doc>
+Packet decoder block, for use with the gnuradio demodulator blocks: gmsk, psk, qam.
+
+Access Code: string of 1's and 0's, leave blank for automatic.
+
+Threshold: -1 for automatic.
+ </doc>
+</block>
diff --git a/grc/blocks/blks2_packet_encoder.xml b/grc/blocks/blks2_packet_encoder.xml
new file mode 100644
index 000000000..b184ebd31
--- /dev/null
+++ b/grc/blocks/blks2_packet_encoder.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Packet Encoder
+###################################################
+ -->
+<block>
+ <name>Packet Encoder</name>
+ <key>blks2_packet_encoder</key>
+ <import>from grc_gnuradio import blks2 as grc_blks2</import>
+ <make>grc_blks2.packet_mod_$(type.fcn)(grc_blks2.packet_encoder(
+ samples_per_symbol=$samples_per_symbol,
+ bits_per_symbol=$bits_per_symbol,
+ access_code=$access_code,
+ pad_for_usrp=$pad_for_usrp,
+ ),
+ payload_length=$payload_length,
+)</make>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <value>float</value>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:c</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:f</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:i</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:s</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:b</opt>
+ </option>
+ </param>
+ <param>
+ <name>Samples/Symbol</name>
+ <key>samples_per_symbol</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Bits/Symbol</name>
+ <key>bits_per_symbol</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Access Code</name>
+ <key>access_code</key>
+ <value></value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Pad for USRP</name>
+ <key>pad_for_usrp</key>
+ <type>enum</type>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Payload Length</name>
+ <key>payload_length</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+ <doc>
+Packet encoder block, for use with the gnuradio modulator blocks: gmsk, dpsk, qam.
+
+Access Code: string of 1's and 0's, leave blank for automatic.
+
+Payload Length: 0 for automatic.
+
+Bits/Symbol should be set accordingly:
+ gmsk -> 1
+ dbpsk -> 1
+ dqpsk -> 2
+ d8psk -> 3
+ qam8 -> 3
+ qam16 -> 4
+ qam64 -> 6
+ qam256 -> 8
+ </doc>
+</block>
diff --git a/grc/blocks/blks2_pfb_arb_resampler.xml b/grc/blocks/blks2_pfb_arb_resampler.xml
new file mode 100644
index 000000000..b58e70f1c
--- /dev/null
+++ b/grc/blocks/blks2_pfb_arb_resampler.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Polyphase Arbitrary Resampler
+###################################################
+ -->
+<block>
+ <name>Polyphase Resampler</name>
+ <key>blks2_pfb_arb_resampler_ccf</key>
+ <import>from gnuradio import blks2</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>blks2.pfb_arb_resampler_ccf(
+ $rate,
+ $taps,
+ $size,
+)</make>
+ <!-- Set taps not implemented yet
+ <callback>set_taps($taps)</callback>
+ -->
+ <callback>set_rate($rate)</callback>
+ <param>
+ <name>Resample Rate</name>
+ <key>rate</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>real_vector</type>
+ </param>
+ <param>
+ <name>Size (# phases)</name>
+ <key>size</key>
+ <value>32</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_pfb_channelizer.xml b/grc/blocks/blks2_pfb_channelizer.xml
new file mode 100644
index 000000000..5a93c0866
--- /dev/null
+++ b/grc/blocks/blks2_pfb_channelizer.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Polyphase Channelizer
+###################################################
+ -->
+<block>
+ <name>Polyphase Channelizer</name>
+ <key>blks2_pfb_channelizer_ccf</key>
+ <import>from gnuradio import blks2</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>blks2.pfb_channelizer_ccf(
+ $nchans,
+ $taps,
+ $osr,
+ $atten)
+self.$(id).set_channel_map($ch_map)
+ </make>
+ <!-- Set taps not implemented yet
+ <callback>set_taps($taps)</callback>
+ -->
+ <callback>set_channel_map($ch_map)</callback>
+
+ <param>
+ <name>Channels</name>
+ <key>nchans</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <value>None</value>
+ <type>real_vector</type>
+ </param>
+ <param>
+ <name>Over Sample Ratio</name>
+ <key>osr</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Attenuation</name>
+ <key>atten</key>
+ <value>100</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Channel Map</name>
+ <key>ch_map</key>
+ <value>[]</value>
+ <type>int_vector</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ <nports>$nchans</nports>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_rational_resampler_xxx.xml b/grc/blocks/blks2_rational_resampler_xxx.xml
new file mode 100644
index 000000000..b92ec8ec2
--- /dev/null
+++ b/grc/blocks/blks2_rational_resampler_xxx.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Rational Resampler
+###################################################
+ -->
+<block>
+ <name>Rational Resampler</name>
+ <key>blks2_rational_resampler_xxx</key>
+ <import>from gnuradio import blks2</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>blks2.rational_resampler_$(type)(
+ interpolation=$interp,
+ decimation=$decim,
+#if $taps()
+ taps=$taps,
+#else
+ taps=None,
+#end if
+#if $fractional_bw() != 0
+ fractional_bw=$fractional_bw,
+#else
+ fractional_bw=None,
+#end if
+)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Complex Taps)</name>
+ <key>ccc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Real Taps)</name>
+ <key>ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Float (Real Taps)</name>
+ <key>fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Interpolation</name>
+ <key>interp</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <value>[]</value>
+ <type>$type.taps</type>
+ </param>
+ <param>
+ <name>Fractional BW</name>
+ <key>fractional_bw</key>
+ <value>0</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+ <doc>
+Leave taps empty for automatic value.
+Leave fractional bandwidth 0 for automatic value.
+ </doc>
+</block>
diff --git a/grc/blocks/blks2_selector.xml b/grc/blocks/blks2_selector.xml
new file mode 100644
index 000000000..2d89df186
--- /dev/null
+++ b/grc/blocks/blks2_selector.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Selector:
+## Custom blks2 block
+###################################################
+ -->
+<block>
+ <name>Selector</name>
+ <key>blks2_selector</key>
+ <import>from grc_gnuradio import blks2 as grc_blks2</import>
+ <make>grc_blks2.selector(
+ item_size=$type.size*$vlen,
+ num_inputs=$num_inputs,
+ num_outputs=$num_outputs,
+ input_index=$input_index,
+ output_index=$output_index,
+)</make>
+ <callback>set_input_index(int($input_index))</callback>
+ <callback>set_output_index(int($output_index))</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Num Outputs</name>
+ <key>num_outputs</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Input Index</name>
+ <key>input_index</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Output Index</name>
+ <key>output_index</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_inputs</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_outputs</nports>
+ </source>
+ <doc>
+Connect the sink at input index to the source at output index. Leave all other ports disconnected.
+ </doc>
+</block>
diff --git a/grc/blocks/blks2_standard_squelch.xml b/grc/blocks/blks2_standard_squelch.xml
new file mode 100644
index 000000000..f0baeb662
--- /dev/null
+++ b/grc/blocks/blks2_standard_squelch.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Standard Squelch
+###################################################
+ -->
+<block>
+ <name>Standard Squelch</name>
+ <key>blks2_standard_squelch</key>
+ <import>from gnuradio import blks2</import>
+ <make>blks2.standard_squelch(audio_rate=$audio_rate)
+self.$(id).set_threshold($threshold)</make>
+ <callback>set_threshold($threshold)</callback>
+ <param>
+ <name>Audio Rate</name>
+ <key>audio_rate</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Threshold</name>
+ <key>threshold</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_stream_to_vector_decimator.xml b/grc/blocks/blks2_stream_to_vector_decimator.xml
new file mode 100644
index 000000000..25f8f7a62
--- /dev/null
+++ b/grc/blocks/blks2_stream_to_vector_decimator.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Stream to Vector Decimator
+###################################################
+ -->
+<block>
+ <name>Stream to Vec Decim</name>
+ <key>blks2_stream_to_vector_decimator</key>
+ <import>from gnuradio import blks2</import>
+ <make>blks2.stream_to_vector_decimator(
+ item_size=$type.size,
+ sample_rate=$sample_rate,
+ vec_rate=$vec_rate,
+ vec_len=$vlen,
+)</make>
+ <callback>set_sample_rate($sample_rate)</callback>
+ <callback>set_vec_rate($vec_rate)</callback>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Sample Rate</name>
+ <key>sample_rate</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Vec Rate</name>
+ <key>vec_rate</key>
+ <value>30</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1024</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt;= 1</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_synthesis_filterbank.xml b/grc/blocks/blks2_synthesis_filterbank.xml
new file mode 100644
index 000000000..5979ed3f7
--- /dev/null
+++ b/grc/blocks/blks2_synthesis_filterbank.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Synthesis Filterbank
+###################################################
+ -->
+<block>
+ <name>Synthesis Filterbank</name>
+ <key>blks2_synthesis_filterbank</key>
+ <import>from gnuradio import blks2</import>
+ <make>blks2.synthesis_filterbank(mpoints=$mpoints, taps=$taps)</make>
+ <param>
+ <name>MPoints</name>
+ <key>mpoints</key>
+ <value>3</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>complex_vector</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ <nports>$mpoints</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_tcp_sink.xml b/grc/blocks/blks2_tcp_sink.xml
new file mode 100644
index 000000000..cfe7b42d8
--- /dev/null
+++ b/grc/blocks/blks2_tcp_sink.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##TCP Sink: Custom blks2 block
+###################################################
+ -->
+<block>
+ <name>TCP Sink</name>
+ <key>blks2_tcp_sink</key>
+ <import>from grc_gnuradio import blks2 as grc_blks2</import>
+ <make>grc_blks2.tcp_sink(
+ itemsize=$type.size*$vlen,
+ addr=$addr,
+ port=$port,
+ server=$server,
+)</make>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Address</name>
+ <key>addr</key>
+ <value>127.0.0.1</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Port</name>
+ <key>port</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Mode</name>
+ <key>server</key>
+ <value>False</value>
+ <type>enum</type>
+ <option>
+ <name>Server</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Client</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <doc>
+In client mode, we attempt to connect to a server at the given address and port. \
+In server mode, we bind a socket to the given address and port and accept the first client.
+ </doc>
+</block>
diff --git a/grc/blocks/blks2_tcp_source.xml b/grc/blocks/blks2_tcp_source.xml
new file mode 100644
index 000000000..6bf742aa0
--- /dev/null
+++ b/grc/blocks/blks2_tcp_source.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##TCP Source: Custom blks2 block
+###################################################
+ -->
+<block>
+ <name>TCP Source</name>
+ <key>blks2_tcp_source</key>
+ <import>from grc_gnuradio import blks2 as grc_blks2</import>
+ <make>grc_blks2.tcp_source(
+ itemsize=$type.size*$vlen,
+ addr=$addr,
+ port=$port,
+ server=$server,
+)</make>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Address</name>
+ <key>addr</key>
+ <value>127.0.0.1</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Port</name>
+ <key>port</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Mode</name>
+ <key>server</key>
+ <value>True</value>
+ <type>enum</type>
+ <option>
+ <name>Server</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Client</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+ <doc>
+In client mode, we attempt to connect to a server at the given address and port. \
+In server mode, we bind a socket to the given address and port and accept the first client.
+ </doc>
+</block>
diff --git a/grc/blocks/blks2_valve.xml b/grc/blocks/blks2_valve.xml
new file mode 100644
index 000000000..47c553523
--- /dev/null
+++ b/grc/blocks/blks2_valve.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Valve:
+## Custom blks2 block
+###################################################
+ -->
+<block>
+ <name>Valve</name>
+ <key>blks2_valve</key>
+ <import>from grc_gnuradio import blks2 as grc_blks2</import>
+ <make>grc_blks2.valve(item_size=$type.size*$vlen, open=bool($open))</make>
+ <callback>set_open(bool($open))</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Open</name>
+ <key>open</key>
+ <value>0</value>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_inputs</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_outputs</nports>
+ </source>
+ <doc>
+Connect output to input when valve is closed (not open).
+ </doc>
+</block>
diff --git a/grc/blocks/blks2_wfm_rcv.xml b/grc/blocks/blks2_wfm_rcv.xml
new file mode 100644
index 000000000..37fb3ba8c
--- /dev/null
+++ b/grc/blocks/blks2_wfm_rcv.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##WBFM Receive
+###################################################
+ -->
+<block>
+ <name>WBFM Receive</name>
+ <key>blks2_wfm_rcv</key>
+ <import>from gnuradio import blks2</import>
+ <make>blks2.wfm_rcv(
+ quad_rate=$quad_rate,
+ audio_decimation=$audio_decimation,
+)</make>
+ <param>
+ <name>Quadrature Rate</name>
+ <key>quad_rate</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Audio Decimation</name>
+ <key>audio_decimation</key>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_wfm_rcv_pll.xml b/grc/blocks/blks2_wfm_rcv_pll.xml
new file mode 100644
index 000000000..2771350cf
--- /dev/null
+++ b/grc/blocks/blks2_wfm_rcv_pll.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##WBFM Receive PLL
+###################################################
+ -->
+<block>
+ <name>WBFM Receive PLL</name>
+ <key>blks2_wfm_rcv_pll</key>
+ <import>from gnuradio import blks2</import>
+ <make>blks2.wfm_rcv_pll(
+ demod_rate=$quad_rate,
+ audio_decimation=$audio_decimation,
+)</make>
+ <param>
+ <name>Quadrature Rate</name>
+ <key>quad_rate</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Audio Decimation</name>
+ <key>audio_decimation</key>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>Lout</name>
+ <type>float</type>
+ </source>
+ <source>
+ <name>Rout</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/blks2_wfm_tx.xml b/grc/blocks/blks2_wfm_tx.xml
new file mode 100644
index 000000000..cff92d819
--- /dev/null
+++ b/grc/blocks/blks2_wfm_tx.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##WBFM Transmit
+###################################################
+ -->
+<block>
+ <name>WBFM Transmit</name>
+ <key>blks2_wfm_tx</key>
+ <import>from gnuradio import blks2</import>
+ <make>blks2.wfm_tx(
+ audio_rate=$audio_rate,
+ quad_rate=$quad_rate,
+ tau=$tau,
+ max_dev=$max_dev,
+)</make>
+ <param>
+ <name>Audio Rate</name>
+ <key>audio_rate</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Quadrature Rate</name>
+ <key>quad_rate</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Tau</name>
+ <key>tau</key>
+ <value>75e-6</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Max Deviation</name>
+ <key>max_dev</key>
+ <value>75e3</value>
+ <type>real</type>
+ </param>
+ <check>$quad_rate%$audio_rate == 0</check>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml
new file mode 100644
index 000000000..dcd6c5448
--- /dev/null
+++ b/grc/blocks/block_tree.xml
@@ -0,0 +1,283 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Block Tree for platform gnuradio python.
+###################################################
+ -->
+<cat>
+ <name></name> <!-- Blank for Root Name -->
+ <cat>
+ <name>Sources</name>
+ <block>const_source_x</block>
+ <block>gr_sig_source_x</block>
+ <block>gr_noise_source_x</block>
+ <block>gr_vector_source_x</block>
+ <block>random_source_x</block>
+ <block>gr_glfsr_source_x</block>
+ <block>gr_null_source</block>
+ <block>gr_file_source</block>
+ <block>blks2_tcp_source</block>
+ <block>gr_udp_source</block>
+ <block>gr_wavfile_source</block>
+ <block>gr_message_source</block>
+ <block>gr_message_burst_source</block>
+ <block>pad_source</block>
+ <block>virtual_source</block>
+ </cat>
+ <cat>
+ <name>Sinks</name>
+ <block>gr_vector_sink_x</block>
+ <block>gr_null_sink</block>
+ <block>gr_file_sink</block>
+ <block>blks2_tcp_sink</block>
+ <block>gr_udp_sink</block>
+ <block>gr_wavfile_sink</block>
+ <block>gr_message_sink</block>
+ <block>pad_sink</block>
+ <block>virtual_sink</block>
+ <block>gr_tag_debug</block>
+ </cat>
+ <cat>
+ <name>Message Tools</name>
+ <block>gr_message_debug</block>
+ <block>gr_message_strobe</block>
+ <block>gr_pdu_to_tagged_stream</block>
+ <block>gr_tagged_stream_to_pdu</block>
+ <block>gr_tuntap_pdu</block>
+ <block>gr_socket_pdu</block>
+ <block>gr_random_pdu</block>
+ </cat>
+ <cat>
+ <name>Operators</name>
+ <block>gr_add_xx</block>
+ <block>gr_sub_xx</block>
+ <block>gr_multiply_xx</block>
+ <block>gr_divide_xx</block>
+ <block>gr_nlog10_ff</block>
+ <block>gr_transcendental</block>
+ <block>gr_add_const_vxx</block>
+ <block>gr_multiply_const_vxx</block>
+ <block>gr_and_const_xx</block>
+
+ <block>gr_not_xx</block>
+ <block>gr_and_xx</block>
+ <block>gr_or_xx</block>
+ <block>gr_xor_xx</block>
+
+ <block>gr_max_xx</block>
+ <block>gr_argmax_xx</block>
+ <block>gr_rms_xx</block>
+ <block>gr_integrate_xx</block>
+
+ <block>gr_conjugate_cc</block>
+
+ <block>gr_fft_vxx</block>
+ <block>blks2_logpwrfft_x</block>
+ <block>gr_vector_insert_x</block>
+
+ <block>gr_endian_swap</block>
+ </cat>
+ <cat>
+ <name>Type Conversions</name>
+ <block>gr_complex_to_arg</block>
+ <block>gr_complex_to_mag</block>
+ <block>gr_complex_to_mag_squared</block>
+ <block>gr_complex_to_real</block>
+ <block>gr_complex_to_imag</block>
+
+ <block>gr_complex_to_float</block>
+ <block>gr_float_to_complex</block>
+
+ <block>gr_float_to_int</block>
+ <block>gr_float_to_short</block>
+ <block>gr_short_to_float</block>
+ <block>gr_short_to_char</block>
+
+ <block>gr_int_to_float</block>
+
+ <block>gr_float_to_char</block>
+ <block>gr_char_to_float</block>
+ <block>gr_char_to_short</block>
+
+ <block>gr_float_to_uchar</block>
+ <block>gr_uchar_to_float</block>
+
+ <block>gr_complex_to_interleaved_short</block>
+ <block>gr_interleaved_short_to_complex</block>
+ </cat>
+ <cat>
+ <name>Stream Conversions</name>
+ <block>gr_interleave</block>
+ <block>gr_deinterleave</block>
+
+ <block>gr_streams_to_stream</block>
+ <block>gr_stream_to_streams</block>
+
+ <block>gr_streams_to_vector</block>
+ <block>gr_vector_to_streams</block>
+
+ <block>gr_stream_to_vector</block>
+ <block>gr_vector_to_stream</block>
+
+ <block>blks2_stream_to_vector_decimator</block>
+
+ <block>gr_stream_mux</block>
+ <block>gr_burst_tagger</block>
+ </cat>
+ <cat>
+ <name>Misc Conversions</name>
+ <block>gr_unpacked_to_packed_xx</block>
+ <block>gr_packed_to_unpacked_xx</block>
+ <block>gr_unpack_k_bits_bb</block>
+ <block>gr_pack_k_bits_bb</block>
+ <block>gr_chunks_to_symbols_xx</block>
+ <block>gr_map_bb</block>
+ </cat>
+ <cat>
+ <name>Synchronizers</name>
+ <block>gr_pfb_clock_sync_xxx</block>
+
+ <block>gr_mpsk_sync_cc</block>
+
+ <block>gr_pll_carriertracking_cc</block>
+ <block>gr_pll_freqdet_cf</block>
+ <block>gr_pll_refout_cc</block>
+
+ <block>gr_pn_correlator_cc</block>
+ <block>gr_simple_correlator</block>
+ <block>gr_simple_framer</block>
+
+ <block>blks2_packet_decoder</block>
+ <block>blks2_packet_encoder</block>
+ </cat>
+ <cat>
+ <name>Level Controls</name>
+ <block>gr_dpll_bb</block>
+ <block>gr_peak_detector_xb</block>
+ <block>gr_peak_detector2_fb</block>
+ <block>gr_sample_and_hold_xx</block>
+
+ <block>gr_agc_xx</block>
+ <block>gr_agc2_xx</block>
+ <block>gr_feedforward_agc_cc</block>
+
+ <block>gr_mute_xx</block>
+ <block>gr_simple_squelch_cc</block>
+ <block>blks2_standard_squelch</block>
+ <block>gr_pwr_squelch_xx</block>
+ <block>gr_ctcss_squelch_ff</block>
+ <block>gr_threshold_ff</block>
+ </cat>
+ <cat>
+ <name>Filters</name>
+ <!-- FIR convenience filters -->
+ <block>low_pass_filter</block>
+ <block>high_pass_filter</block>
+ <block>band_pass_filter</block>
+ <block>band_reject_filter</block>
+ <block>root_raised_cosine_filter</block>
+ <!-- Filters that take taps as arguments -->
+ <block>gr_fir_filter_xxx</block>
+ <block>gr_interp_fir_filter_xxx</block>
+ <block>gr_fft_filter_xxx</block>
+ <block>gr_freq_xlating_fir_filter_xxx</block>
+ <block>gr_iir_filter_ffd</block>
+ <block>gr_filter_delay_fc</block>
+ <block>gr_channel_model</block>
+ <!-- Filter banks -->
+ <block>blks2_synthesis_filterbank</block>
+ <block>blks2_analysis_filterbank</block>
+ <!-- Polyphase filters -->
+ <block>blks2_pfb_arb_resampler_ccf</block>
+ <block>blks2_pfb_channelizer_ccf</block>
+ <block>gr_pfb_synthesizer_ccf</block>
+ <!-- Other filters -->
+ <block>gr_single_pole_iir_filter_xx</block>
+ <block>gr_hilbert_fc</block>
+ <block>gr_goertzel_fc</block>
+ <block>gr_rational_resampler_base_xxx</block>
+ <block>blks2_rational_resampler_xxx</block>
+ <block>gr_fractional_interpolator_xx</block>
+ <block>gr_keep_one_in_n</block>
+ <block>gr_keep_m_in_n</block>
+ <block>gr_moving_average_xx</block>
+ <block>gr_iqcomp_cc</block>
+ <block>gr_dc_blocker</block>
+ </cat>
+ <cat>
+ <name>Modulators</name>
+ <block>gr_vco_f</block>
+ <block>gr_frequency_modulator_fc</block>
+ <block>gr_phase_modulator_fc</block>
+ <block>gr_quadrature_demod_cf</block>
+ <block>gr_cpfsk_bc</block>
+
+ <block>gr_diff_phasor_cc</block>
+
+ <block>gr_diff_encoder_bb</block>
+ <block>gr_diff_decoder_bb</block>
+
+ <block>blks2_wfm_tx</block>
+ <block>blks2_wfm_rcv</block>
+ <block>blks2_wfm_rcv_pll</block>
+
+ <block>blks2_nbfm_tx</block>
+ <block>blks2_nbfm_rx</block>
+
+ <block>blks2_am_demod_cf</block>
+ <block>blks2_fm_demod_cf</block>
+ <block>blks2_fm_deemph</block>
+ <block>blks2_fm_preemph</block>
+ </cat>
+ <cat>
+ <name>Error Correction</name>
+ <cat>
+ <name>Trellis</name>
+ </cat>
+
+ <block>gr_encode_ccsds_27_bb</block>
+ <block>gr_decode_ccsds_27_fb</block>
+ </cat>
+ <cat>
+ <name>Line Coding</name>
+ <block>gr_scrambler_bb</block>
+ <block>gr_descrambler_bb</block>
+ <block>gr_additive_scrambler_bb</block>
+ </cat>
+ <cat>
+ <name>Probes</name>
+ <block>gr_probe_avg_mag_sqrd_x</block>
+ <block>gr_probe_density_b</block>
+ <block>gr_probe_signal_f</block>
+ </cat>
+ <cat>
+ <name>Variables</name>
+ <block>variable</block>
+ <block>variable_config</block>
+ <block>variable_function_probe</block>
+ <block>parameter</block>
+ </cat>
+ <cat>
+ <name>Misc</name>
+ <block>note</block>
+ <block>import</block>
+
+ <block>gr_throttle</block>
+ <block>gr_delay</block>
+ <block>gr_repeat</block>
+
+ <block>blks2_selector</block>
+ <block>blks2_valve</block>
+ <block>blks2_error_rate</block>
+
+ <block>gr_head</block>
+ <block>gr_skiphead</block>
+
+ <block>gr_kludge_copy</block>
+ <block>gr_copy</block>
+ <block>gr_nop</block>
+
+ <block>xmlrpc_server</block>
+ <block>xmlrpc_client</block>
+ </cat>
+</cat>
diff --git a/grc/blocks/const_source_x.xml b/grc/blocks/const_source_x.xml
new file mode 100644
index 000000000..fe8e56ec4
--- /dev/null
+++ b/grc/blocks/const_source_x.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Constant Source: Custom wrapper
+###################################################
+ -->
+<block>
+ <name>Constant Source</name>
+ <key>const_source_x</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.sig_source_$(type.fcn)(0, gr.GR_CONST_WAVE, 0, 0, $const)</make>
+ <callback>set_offset($const)</callback>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:c</opt>
+ <opt>const_type:complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:f</opt>
+ <opt>const_type:real</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:i</opt>
+ <opt>const_type:int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:s</opt>
+ <opt>const_type:int</opt>
+ </option>
+ </param>
+ <param>
+ <name>Constant</name>
+ <key>const</key>
+ <value>0</value>
+ <type>$type.const_type</type>
+ </param>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_add_const_vxx.xml b/grc/blocks/gr_add_const_vxx.xml
new file mode 100644
index 000000000..9f1c545ab
--- /dev/null
+++ b/grc/blocks/gr_add_const_vxx.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Add Const Block:
+## all types, 1 output, 1 input & const
+###################################################
+ -->
+<block>
+ <name>Add Const</name>
+ <key>gr_add_const_vxx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.add_const_v$(type.fcn)($const)</make>
+ <callback>set_k($const)</callback>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>const_type:complex_vector</opt>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>const_type:real_vector</opt>
+ <opt>fcn:ff</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>const_type:int_vector</opt>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>const_type:int_vector</opt>
+ <opt>fcn:ss</opt>
+ </option>
+ </param>
+ <param>
+ <name>Constant</name>
+ <key>const</key>
+ <value>0</value>
+ <type>$type.const_type</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>len($const) == $vlen</check>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_add_xx.xml b/grc/blocks/gr_add_xx.xml
new file mode 100644
index 000000000..97ed9283c
--- /dev/null
+++ b/grc/blocks/gr_add_xx.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Add Block:
+## all types, 1 output, 2 to inf inputs
+###################################################
+ -->
+<block>
+ <name>Add</name>
+ <key>gr_add_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.add_v$(type.fcn)($vlen)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_inputs &gt; 1</check>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_inputs</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_additive_scrambler_bb.xml b/grc/blocks/gr_additive_scrambler_bb.xml
new file mode 100644
index 000000000..a15d6eefb
--- /dev/null
+++ b/grc/blocks/gr_additive_scrambler_bb.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Additive Scrambler
+###################################################
+ -->
+<block>
+ <name>Additive Scrambler</name>
+ <key>gr_additive_scrambler_bb</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.additive_scrambler_bb($mask, $seed, $len, $count)</make>
+ <param>
+ <name>Mask</name>
+ <key>mask</key>
+ <value>0x8A</value>
+ <type>hex</type>
+ </param>
+ <param>
+ <name>Seed</name>
+ <key>seed</key>
+ <value>0x7F</value>
+ <type>hex</type>
+ </param>
+ <param>
+ <name>Length</name>
+ <key>len</key>
+ <value>7</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Count</name>
+ <key>count</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_agc2_xx.xml b/grc/blocks/gr_agc2_xx.xml
new file mode 100644
index 000000000..55b20d4e8
--- /dev/null
+++ b/grc/blocks/gr_agc2_xx.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##AGC2
+###################################################
+ -->
+<block>
+ <name>AGC2</name>
+ <key>gr_agc2_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.agc2_$(type.fcn)($attack_rate, $decay_rate, $reference, $gain, $max_gain)</make>
+ <callback>set_attack_rate($attack_rate)</callback>
+ <callback>set_decay_rate($decay_rate)</callback>
+ <callback>set_reference($reference)</callback>
+ <callback>set_gain($gain)</callback>
+ <callback>set_max_gain($max_gain)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ </param>
+ <param>
+ <name>Attack Rate</name>
+ <key>attack_rate</key>
+ <value>1e-1</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Decay Rate</name>
+ <key>decay_rate</key>
+ <value>1e-2</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Reference</name>
+ <key>reference</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Max Gain</name>
+ <key>max_gain</key>
+ <value>0.0</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_agc_xx.xml b/grc/blocks/gr_agc_xx.xml
new file mode 100644
index 000000000..c87d239ed
--- /dev/null
+++ b/grc/blocks/gr_agc_xx.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##AGC
+###################################################
+ -->
+<block>
+ <name>AGC</name>
+ <key>gr_agc_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.agc_$(type.fcn)($rate, $reference, $gain, $max_gain)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ </param>
+ <param>
+ <name>Rate</name>
+ <key>rate</key>
+ <value>1e-4</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Reference</name>
+ <key>reference</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Max Gain</name>
+ <key>max_gain</key>
+ <value>0.0</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_and_const_xx.xml b/grc/blocks/gr_and_const_xx.xml
new file mode 100644
index 000000000..dc9649311
--- /dev/null
+++ b/grc/blocks/gr_and_const_xx.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## And Const Block:
+## all types, 1 output, 1 input & const
+###################################################
+ -->
+<block>
+ <name>And Const</name>
+ <key>gr_and_const_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.and_const_$(type.fcn)($const)</make>
+ <callback>set_k($const)</callback>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:bb</opt>
+ </option>
+ </param>
+ <param>
+ <name>Constant</name>
+ <key>const</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_and_xx.xml b/grc/blocks/gr_and_xx.xml
new file mode 100644
index 000000000..9ed006090
--- /dev/null
+++ b/grc/blocks/gr_and_xx.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Logical And Block
+###################################################
+ -->
+<block>
+ <name>And</name>
+ <key>gr_and_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.and_$(type.fcn)()</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:bb</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <check>$num_inputs &gt;= 2</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <nports>$num_inputs</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_argmax_xx.xml b/grc/blocks/gr_argmax_xx.xml
new file mode 100644
index 000000000..95269292e
--- /dev/null
+++ b/grc/blocks/gr_argmax_xx.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##ArgMax:
+## 1 output, 2 to inf inputs
+###################################################
+ -->
+<block>
+ <name>Argmax</name>
+ <key>gr_argmax_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.argmax_$(type.fcn)($vlen)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:fs</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:is</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:dd</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_inputs &gt;= 1</check>
+ <check>$vlen &gt;= 1</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_inputs</nports>
+ </sink>
+ <source>
+ <name>max_vec</name>
+ <type>short</type>
+ </source>
+ <source>
+ <name>max_inp</name>
+ <type>short</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_burst_tagger.xml b/grc/blocks/gr_burst_tagger.xml
new file mode 100644
index 000000000..58c909999
--- /dev/null
+++ b/grc/blocks/gr_burst_tagger.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Burst tagger:
+## all types, 1 output, 2 input: stream & trigger (short)
+###################################################
+ -->
+<block>
+ <name>Burst Tagger</name>
+ <key>gr_burst_tagger</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.burst_tagger($type.size)
+self.$(id).set_true_tag($true_key,$true_value)
+self.$(id).set_false_tag($false_key,$false_value)
+ </make>
+ <callback>set_true_tag($true_key,$true_value)</callback>
+ <callback>set_false_tag($false_key,$false_value)</callback>
+ <param>
+ <name>Stream Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>True KeyID</name>
+ <key>true_key</key>
+ <value>burst</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>True Value</name>
+ <key>true_value</key>
+ <value>True</value>
+ <type>bool</type>
+ </param>
+ <param>
+ <name>False KeyID</name>
+ <key>false_key</key>
+ <value>burst</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>False Value</name>
+ <key>false_value</key>
+ <value>False</value>
+ <type>bool</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>1</vlen>
+ </sink>
+ <sink>
+ <name>trigger</name>
+ <type>short</type>
+ <vlen>1</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>1</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_channel_model.xml b/grc/blocks/gr_channel_model.xml
new file mode 100644
index 000000000..d0d178d34
--- /dev/null
+++ b/grc/blocks/gr_channel_model.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Channel Model
+###################################################
+ -->
+<block>
+ <name>Channel Model</name>
+ <key>gr_channel_model</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>gr.channel_model(
+ noise_voltage=$noise_voltage,
+ frequency_offset=$freq_offset,
+ epsilon=$epsilon,
+ taps=$taps,
+ noise_seed=$seed,
+)</make>
+ <callback>set_noise_voltage($noise_voltage)</callback>
+ <callback>set_frequency_offset($freq_offset)</callback>
+ <callback>set_taps($taps)</callback>
+ <callback>set_timing_offset($epsilon)</callback>
+ <param>
+ <name>Noise Voltage</name>
+ <key>noise_voltage</key>
+ <value>0.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Frequency Offset</name>
+ <key>freq_offset</key>
+ <value>0.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Epsilon</name>
+ <key>epsilon</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <value>1.0 + 1.0j</value>
+ <type>complex_vector</type>
+ </param>
+ <param>
+ <name>Seed</name>
+ <key>seed</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_char_to_float.xml b/grc/blocks/gr_char_to_float.xml
new file mode 100644
index 000000000..838b6a203
--- /dev/null
+++ b/grc/blocks/gr_char_to_float.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Char to Float:
+###################################################
+ -->
+<block>
+ <name>Char To Float</name>
+ <key>gr_char_to_float</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.char_to_float($vlen, $scale)</make>
+ <callback>set_scale($scale)</callback>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Scale</name>
+ <key>scale</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_char_to_short.xml b/grc/blocks/gr_char_to_short.xml
new file mode 100644
index 000000000..57261e084
--- /dev/null
+++ b/grc/blocks/gr_char_to_short.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Char to Short:
+###################################################
+ -->
+<block>
+ <name>Char To Short</name>
+ <key>gr_char_to_short</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.char_to_short($vlen)</make>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>short</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_chunks_to_symbols.xml b/grc/blocks/gr_chunks_to_symbols.xml
new file mode 100644
index 000000000..e9da38e9a
--- /dev/null
+++ b/grc/blocks/gr_chunks_to_symbols.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Chunks to Symbols
+###################################################
+ -->
+<block>
+ <name>Chunks to Symbols</name>
+ <key>gr_chunks_to_symbols_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.chunks_to_symbols_$(in_type.fcn)$(out_type.fcn)($symbol_table, $dimension)</make>
+ <param>
+ <name>Input Type</name>
+ <key>in_type</key>
+ <type>enum</type>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:i</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:s</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:b</opt>
+ </option>
+ </param>
+ <param>
+ <name>Output Type</name>
+ <key>out_type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:c</opt>
+ <opt>table:complex_vector</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:f</opt>
+ <opt>table:real_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Symbol Table</name>
+ <key>symbol_table</key>
+ <type>$out_type.table</type>
+ </param>
+ <param>
+ <name>Dimension</name>
+ <key>dimension</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Num Ports</name>
+ <key>num_ports</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_ports &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$in_type</type>
+ <nports>$num_ports</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$out_type</type>
+ <nports>$num_ports</nports>
+ </source>
+</block>
diff --git a/grc/blocks/gr_complex_to_arg.xml b/grc/blocks/gr_complex_to_arg.xml
new file mode 100644
index 000000000..a7bbacd74
--- /dev/null
+++ b/grc/blocks/gr_complex_to_arg.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Complex to Arg
+###################################################
+ -->
+<block>
+ <name>Complex to Arg</name>
+ <key>gr_complex_to_arg</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.complex_to_arg($vlen)</make>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_complex_to_float.xml b/grc/blocks/gr_complex_to_float.xml
new file mode 100644
index 000000000..05681b0b9
--- /dev/null
+++ b/grc/blocks/gr_complex_to_float.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Complex to Float:
+## one or two output streams
+###################################################
+ -->
+<block>
+ <name>Complex To Float</name>
+ <key>gr_complex_to_float</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.complex_to_float($vlen)</make>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>re</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </source>
+ <source>
+ <name>im</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ <optional>1</optional>
+ </source>
+</block>
diff --git a/grc/blocks/gr_complex_to_imag.xml b/grc/blocks/gr_complex_to_imag.xml
new file mode 100644
index 000000000..7c120eedd
--- /dev/null
+++ b/grc/blocks/gr_complex_to_imag.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Complex to Imaginary
+###################################################
+ -->
+<block>
+ <name>Complex to Imag</name>
+ <key>gr_complex_to_imag</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.complex_to_imag($vlen)</make>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_complex_to_interleaved_short.xml b/grc/blocks/gr_complex_to_interleaved_short.xml
new file mode 100644
index 000000000..5e999599a
--- /dev/null
+++ b/grc/blocks/gr_complex_to_interleaved_short.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Complex to Interleaved Short:
+###################################################
+ -->
+<block>
+ <name>Complex To IShort</name>
+ <key>gr_complex_to_interleaved_short</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.complex_to_interleaved_short()</make>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>short</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_complex_to_mag.xml b/grc/blocks/gr_complex_to_mag.xml
new file mode 100644
index 000000000..adc95f207
--- /dev/null
+++ b/grc/blocks/gr_complex_to_mag.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Complex to Magnitude
+###################################################
+ -->
+<block>
+ <name>Complex to Mag</name>
+ <key>gr_complex_to_mag</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.complex_to_mag($vlen)</make>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_complex_to_mag_squared.xml b/grc/blocks/gr_complex_to_mag_squared.xml
new file mode 100644
index 000000000..cd23bfb5c
--- /dev/null
+++ b/grc/blocks/gr_complex_to_mag_squared.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Complex to Magnitude Squared
+###################################################
+ -->
+<block>
+ <name>Complex to Mag^2</name>
+ <key>gr_complex_to_mag_squared</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.complex_to_mag_squared($vlen)</make>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_complex_to_real.xml b/grc/blocks/gr_complex_to_real.xml
new file mode 100644
index 000000000..ae9ec7b14
--- /dev/null
+++ b/grc/blocks/gr_complex_to_real.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Complex to Real
+###################################################
+ -->
+<block>
+ <name>Complex to Real</name>
+ <key>gr_complex_to_real</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.complex_to_real($vlen)</make>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_conjugate_cc.xml b/grc/blocks/gr_conjugate_cc.xml
new file mode 100644
index 000000000..0b4deb347
--- /dev/null
+++ b/grc/blocks/gr_conjugate_cc.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Complex Conjugate
+###################################################
+ -->
+<block>
+ <name>Complex Conjugate</name>
+ <key>gr_conjugate_cc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.conjugate_cc()</make>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_copy.xml b/grc/blocks/gr_copy.xml
new file mode 100644
index 000000000..8b12eaca7
--- /dev/null
+++ b/grc/blocks/gr_copy.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Copy
+###################################################
+ -->
+<block>
+ <name>Copy</name>
+ <key>gr_copy</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.copy($type.size*$vlen)
+self.$(id).set_enabled($enabled)</make>
+ <callback>set_enabled($enabled)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Enabled</name>
+ <key>enabled</key>
+ <value>True</value>
+ <type>bool</type>
+ <option>
+ <name>Enabled</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Disabled</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_cpfsk_bc.xml b/grc/blocks/gr_cpfsk_bc.xml
new file mode 100644
index 000000000..d5549d933
--- /dev/null
+++ b/grc/blocks/gr_cpfsk_bc.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##CPFSK
+###################################################
+ -->
+<block>
+ <name>CPFSK</name>
+ <key>gr_cpfsk_bc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.cpfsk_bc($k, $amplitude, $samples_per_symbol)</make>
+ <callback>set_amplitude($amplitude)</callback>
+ <param>
+ <name>K</name>
+ <key>k</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Amplitude</name>
+ <key>amplitude</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Samples/Symbol</name>
+ <key>samples_per_symbol</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_ctcss_squelch_ff.xml b/grc/blocks/gr_ctcss_squelch_ff.xml
new file mode 100644
index 000000000..a34c75374
--- /dev/null
+++ b/grc/blocks/gr_ctcss_squelch_ff.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<!--
+#
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+-->
+
+<!--
+###################################################
+##CTCSS Squelch
+###################################################
+ -->
+<block>
+ <name>CTCSS Squelch</name>
+ <key>gr_ctcss_squelch_ff</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.ctcss_squelch_ff($rate, $freq, $level, $len, $ramp, $gate)</make>
+ <callback>set_level($level)</callback>
+ <param>
+ <name>Sampling Rate (Hz)</name>
+ <key>rate</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Tone Frequency</name>
+ <key>freq</key>
+ <value>100.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Level</name>
+ <key>level</key>
+ <value>0.01</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Length</name>
+ <key>len</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Ramp</name>
+ <key>ramp</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Gate</name>
+ <key>gate</key>
+ <value>False</value>
+ <type>bool</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_dc_blocker.xml b/grc/blocks/gr_dc_blocker.xml
new file mode 100644
index 000000000..05c342074
--- /dev/null
+++ b/grc/blocks/gr_dc_blocker.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## DC Blocker
+###################################################
+ -->
+<block>
+ <name>DC Blocker</name>
+ <key>gr_dc_blocker</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.dc_blocker_$(type)($length, $long_form)</make>
+ <!-- <callback>set_length($length)</callback> -->
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex</name>
+ <key>cc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ </option>
+ <option>
+ <name>Float->Float</name>
+ <key>ff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ </option>
+ </param>
+ <param>
+ <name>Length</name>
+ <key>length</key>
+ <value>32</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Long Form</name>
+ <key>long_form</key>
+ <value>True</value>
+ <type>bool</type>
+ </param>
+
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_decode_ccsds_27_fb.xml b/grc/blocks/gr_decode_ccsds_27_fb.xml
new file mode 100644
index 000000000..03b31db83
--- /dev/null
+++ b/grc/blocks/gr_decode_ccsds_27_fb.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Decode CCSDS 27
+###################################################
+ -->
+<block>
+ <name>Decode CCSDS 27</name>
+ <key>gr_decode_ccsds_27_fb</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.decode_ccsds_27_fb()</make>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_deinterleave.xml b/grc/blocks/gr_deinterleave.xml
new file mode 100644
index 000000000..a7482978c
--- /dev/null
+++ b/grc/blocks/gr_deinterleave.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Deinterleave
+###################################################
+ -->
+<block>
+ <name>Deinterleave</name>
+ <key>gr_deinterleave</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.deinterleave($type.size*$vlen)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Streams</name>
+ <key>num_streams</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_streams &gt; 0</check>
+ <check>$vlen &gt;= 1</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_streams</nports>
+ </source>
+</block>
diff --git a/grc/blocks/gr_delay.xml b/grc/blocks/gr_delay.xml
new file mode 100644
index 000000000..5cc411a78
--- /dev/null
+++ b/grc/blocks/gr_delay.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Delay
+###################################################
+ -->
+<block>
+ <name>Delay</name>
+ <key>gr_delay</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.delay($type.size*$vlen, $delay)</make>
+ <callback>set_delay($delay)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Delay</name>
+ <key>delay</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Num Ports</name>
+ <key>num_ports</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_ports &gt; 0</check>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_ports</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_ports</nports>
+ </source>
+</block>
diff --git a/grc/blocks/gr_descrambler_bb.xml b/grc/blocks/gr_descrambler_bb.xml
new file mode 100644
index 000000000..5cfbcc203
--- /dev/null
+++ b/grc/blocks/gr_descrambler_bb.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Descrambler
+###################################################
+ -->
+<block>
+ <name>Descrambler</name>
+ <key>gr_descrambler_bb</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.descrambler_bb($mask, $seed, $len)</make>
+ <param>
+ <name>Mask</name>
+ <key>mask</key>
+ <value>0x8A</value>
+ <type>hex</type>
+ </param>
+ <param>
+ <name>Seed</name>
+ <key>seed</key>
+ <value>0x7F</value>
+ <type>hex</type>
+ </param>
+ <param>
+ <name>Length</name>
+ <key>len</key>
+ <value>7</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_diff_decoder_bb.xml b/grc/blocks/gr_diff_decoder_bb.xml
new file mode 100644
index 000000000..ea7cf1734
--- /dev/null
+++ b/grc/blocks/gr_diff_decoder_bb.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Differential Decoder
+###################################################
+ -->
+<block>
+ <name>Differential Decoder</name>
+ <key>gr_diff_decoder_bb</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.diff_decoder_bb($modulus)</make>
+ <param>
+ <name>Modulus</name>
+ <key>modulus</key>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_diff_encoder_bb.xml b/grc/blocks/gr_diff_encoder_bb.xml
new file mode 100644
index 000000000..21241eac2
--- /dev/null
+++ b/grc/blocks/gr_diff_encoder_bb.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Differential Encoder
+###################################################
+ -->
+<block>
+ <name>Differential Encoder</name>
+ <key>gr_diff_encoder_bb</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.diff_encoder_bb($modulus)</make>
+ <param>
+ <name>Modulus</name>
+ <key>modulus</key>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_diff_phasor_cc.xml b/grc/blocks/gr_diff_phasor_cc.xml
new file mode 100644
index 000000000..2b2d7e372
--- /dev/null
+++ b/grc/blocks/gr_diff_phasor_cc.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Differential Phasor
+###################################################
+ -->
+<block>
+ <name>Differential Phasor</name>
+ <key>gr_diff_phasor_cc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.diff_phasor_cc()</make>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_divide_xx.xml b/grc/blocks/gr_divide_xx.xml
new file mode 100644
index 000000000..04667bc2a
--- /dev/null
+++ b/grc/blocks/gr_divide_xx.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Divide Block:
+## all types, 1 output, 2 to inf inputs
+###################################################
+ -->
+<block>
+ <name>Divide</name>
+ <key>gr_divide_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.divide_$(type.fcn)($vlen)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <check>$num_inputs &gt;= 2</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_inputs</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_dpll_bb.xml b/grc/blocks/gr_dpll_bb.xml
new file mode 100644
index 000000000..044d398ff
--- /dev/null
+++ b/grc/blocks/gr_dpll_bb.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Detect Peak
+###################################################
+ -->
+<block>
+ <name>Detect Peak</name>
+ <key>gr_dpll_bb</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.dpll_bb($period, $gain)</make>
+ <param>
+ <name>Period</name>
+ <key>period</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_encode_ccsds_27_bb.xml b/grc/blocks/gr_encode_ccsds_27_bb.xml
new file mode 100644
index 000000000..f31e6b6c8
--- /dev/null
+++ b/grc/blocks/gr_encode_ccsds_27_bb.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Encode CCSDS 27
+###################################################
+ -->
+<block>
+ <name>Encode CCSDS 27</name>
+ <key>gr_encode_ccsds_27_bb</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.encode_ccsds_27_bb()</make>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_endian_swap.xml b/grc/blocks/gr_endian_swap.xml
new file mode 100644
index 000000000..aa564026c
--- /dev/null
+++ b/grc/blocks/gr_endian_swap.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Add Block:
+## all types, 1 output, 2 to inf inputs
+###################################################
+ -->
+<block>
+ <name>Endian Swap</name>
+ <key>gr_endian_swap</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.endian_swap($type.size)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:8</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>s32</key>
+ <opt>size:4</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>s16</key>
+ <opt>size:2</opt>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_feedforward_agc_cc.xml b/grc/blocks/gr_feedforward_agc_cc.xml
new file mode 100644
index 000000000..24e80953f
--- /dev/null
+++ b/grc/blocks/gr_feedforward_agc_cc.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Feed Forward AGC
+###################################################
+ -->
+<block>
+ <name>Feed Forward AGC</name>
+ <key>gr_feedforward_agc_cc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.feedforward_agc_cc($num_samples, $reference)</make>
+ <param>
+ <name>Num Samples</name>
+ <key>num_samples</key>
+ <value>1024</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Reference</name>
+ <key>reference</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_fft_filter_xxx.xml b/grc/blocks/gr_fft_filter_xxx.xml
new file mode 100644
index 000000000..5b4cd83cc
--- /dev/null
+++ b/grc/blocks/gr_fft_filter_xxx.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##FFT Filter
+###################################################
+ -->
+<block>
+ <name>FFT Filter</name>
+ <key>gr_fft_filter_xxx</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>gr.fft_filter_$(type)($decim, $taps, $nthreads)</make>
+ <callback>set_taps($taps)</callback>
+ <callback>set_nthreads($nthreads)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Complex Taps)</name>
+ <key>ccc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Float->Float (Real Taps)</name>
+ <key>fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>$type.taps</type>
+ </param>
+ <param>
+ <name>Num. Threads</name>
+ <key>nthreads</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_fft_vxx.xml b/grc/blocks/gr_fft_vxx.xml
new file mode 100644
index 000000000..565354e41
--- /dev/null
+++ b/grc/blocks/gr_fft_vxx.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##FFT
+###################################################
+ -->
+<block>
+ <name>FFT</name>
+ <key>gr_fft_vxx</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio import window</import>
+ <make>#if $type() == "complex"
+gr.fft_vcc($fft_size, $forward, $window, $shift, $nthreads)
+#else
+gr.fft_vfc($fft_size, $forward, $window, $nthreads)
+#end if</make>
+ <callback>set_nthreads($nthreads)</callback>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>hide_shift:</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>hide_shift:all</opt>
+ </option>
+ </param>
+ <param>
+ <name>FFT Size</name>
+ <key>fft_size</key>
+ <value>1024</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Forward/Reverse</name>
+ <key>forward</key>
+ <type>enum</type>
+ <option>
+ <name>Forward</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Reverse</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Window</name>
+ <key>window</key>
+ <value>window.blackmanharris(1024)</value>
+ <type>real_vector</type>
+ </param>
+ <param>
+ <name>Shift</name>
+ <key>shift</key>
+ <type>enum</type>
+ <hide>$type.hide_shift</hide>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Num. Threads</name>
+ <key>nthreads</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$fft_size</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ <vlen>$fft_size</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_file_sink.xml b/grc/blocks/gr_file_sink.xml
new file mode 100644
index 000000000..d0a693900
--- /dev/null
+++ b/grc/blocks/gr_file_sink.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##File Sink
+###################################################
+ -->
+<block>
+ <name>File Sink</name>
+ <key>gr_file_sink</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.file_sink($type.size*$vlen, $file)
+self.$(id).set_unbuffered($unbuffered)</make>
+ <callback>set_unbuffered($unbuffered)</callback>
+ <callback>open($file)</callback>
+ <param>
+ <name>File</name>
+ <key>file</key>
+ <value></value>
+ <type>file_save</type>
+ </param>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Unbuffered</name>
+ <key>unbuffered</key>
+ <value>False</value>
+ <type>bool</type>
+ <option>
+ <name>Off</name>
+ <key>False</key>
+ </option>
+ <option>
+ <name>On</name>
+ <key>True</key>
+ </option>
+ </param>
+
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+</block>
diff --git a/grc/blocks/gr_file_source.xml b/grc/blocks/gr_file_source.xml
new file mode 100644
index 000000000..5f0e16b27
--- /dev/null
+++ b/grc/blocks/gr_file_source.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##File Source
+###################################################
+ -->
+<block>
+ <name>File Source</name>
+ <key>gr_file_source</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.file_source($type.size*$vlen, $file, $repeat)</make>
+ <callback>open($file, $repeat)</callback>
+ <param>
+ <name>File</name>
+ <key>file</key>
+ <value></value>
+ <type>file_open</type>
+ </param>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Repeat</name>
+ <key>repeat</key>
+ <value>True</value>
+ <type>enum</type>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_filter_delay_fc.xml b/grc/blocks/gr_filter_delay_fc.xml
new file mode 100644
index 000000000..30d65bf82
--- /dev/null
+++ b/grc/blocks/gr_filter_delay_fc.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Filter Delay
+###################################################
+ -->
+<block>
+ <name>Filter Delay</name>
+ <key>gr_filter_delay_fc</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>gr.filter_delay_fc($taps)</make>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>real_vector</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ <optional>1</optional>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_fir_filter_xxx.xml b/grc/blocks/gr_fir_filter_xxx.xml
new file mode 100644
index 000000000..c4de8f539
--- /dev/null
+++ b/grc/blocks/gr_fir_filter_xxx.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Decimating FIR Filter
+###################################################
+ -->
+<block>
+ <name>Decimating FIR Filter</name>
+ <key>gr_fir_filter_xxx</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>gr.fir_filter_$(type)($decim, $taps)</make>
+ <callback>set_taps($taps)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Complex Taps)</name>
+ <key>ccc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Real Taps)</name>
+ <key>ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Complex (Complex Taps)</name>
+ <key>fcc</key>
+ <opt>input:float</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Float->Float (Real Taps)</name>
+ <key>fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Short (Real Taps)</name>
+ <key>fsf</key>
+ <opt>input:float</opt>
+ <opt>output:short</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Short->Complex (Complex Taps)</name>
+ <key>scc</key>
+ <opt>input:short</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>$type.taps</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_float_to_char.xml b/grc/blocks/gr_float_to_char.xml
new file mode 100644
index 000000000..1fa500e3c
--- /dev/null
+++ b/grc/blocks/gr_float_to_char.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Float to Char:
+###################################################
+ -->
+<block>
+ <name>Float To Char</name>
+ <key>gr_float_to_char</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.float_to_char($vlen, $scale)</make>
+ <callback>set_scale($scale)</callback>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Scale</name>
+ <key>scale</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_float_to_complex.xml b/grc/blocks/gr_float_to_complex.xml
new file mode 100644
index 000000000..a42cff358
--- /dev/null
+++ b/grc/blocks/gr_float_to_complex.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Float to Complex:
+## one or two input streams
+###################################################
+ -->
+<block>
+ <name>Float To Complex</name>
+ <key>gr_float_to_complex</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.float_to_complex($vlen)</make>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>re</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <sink>
+ <name>im</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ <optional>1</optional>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_float_to_int.xml b/grc/blocks/gr_float_to_int.xml
new file mode 100644
index 000000000..b43c208a5
--- /dev/null
+++ b/grc/blocks/gr_float_to_int.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Float to Int:
+###################################################
+ -->
+<block>
+ <name>Float To Int</name>
+ <key>gr_float_to_int</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.float_to_int($vlen, $scale)</make>
+ <callback>set_scale($scale)</callback>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Scale</name>
+ <key>scale</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>int</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_float_to_short.xml b/grc/blocks/gr_float_to_short.xml
new file mode 100644
index 000000000..4f76b8f58
--- /dev/null
+++ b/grc/blocks/gr_float_to_short.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Float to Short:
+###################################################
+ -->
+<block>
+ <name>Float To Short</name>
+ <key>gr_float_to_short</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.float_to_short($vlen, $scale)</make>
+ <callback>set_scale($scale)</callback>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Scale</name>
+ <key>scale</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>short</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_float_to_uchar.xml b/grc/blocks/gr_float_to_uchar.xml
new file mode 100644
index 000000000..aa804d7d9
--- /dev/null
+++ b/grc/blocks/gr_float_to_uchar.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Float to Unsigned Char:
+###################################################
+ -->
+<block>
+ <name>Float To UChar</name>
+ <key>gr_float_to_uchar</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.float_to_uchar()</make>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_fractional_interpolator_xx.xml b/grc/blocks/gr_fractional_interpolator_xx.xml
new file mode 100644
index 000000000..8d65ff8bf
--- /dev/null
+++ b/grc/blocks/gr_fractional_interpolator_xx.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Fractional Interpolator
+###################################################
+ -->
+<block>
+ <name>Fractional Interpolator</name>
+ <key>gr_fractional_interpolator_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.fractional_interpolator_$(type.fcn)($phase_shift, $interp_ratio)</make>
+ <callback>set_interp_ratio($interp_ratio)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ </param>
+ <param>
+ <name>Phase Shift</name>
+ <key>phase_shift</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Interpolation Ratio</name>
+ <key>interp_ratio</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_freq_xlating_fir_filter_xxx.xml b/grc/blocks/gr_freq_xlating_fir_filter_xxx.xml
new file mode 100644
index 000000000..e3ee66977
--- /dev/null
+++ b/grc/blocks/gr_freq_xlating_fir_filter_xxx.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Frequency Xlating Filter
+###################################################
+ -->
+<block>
+ <name>Frequency Xlating FIR Filter</name>
+ <key>gr_freq_xlating_fir_filter_xxx</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>gr.freq_xlating_fir_filter_$(type)($decim, $taps, $center_freq, $samp_rate)</make>
+ <callback>set_taps($taps)</callback>
+ <callback>set_center_freq($center_freq)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Complex Taps)</name>
+ <key>ccc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Real Taps)</name>
+ <key>ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Complex (Complex Taps)</name>
+ <key>fcc</key>
+ <opt>input:float</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Float->Complex (Real Taps)</name>
+ <key>fcf</key>
+ <opt>input:float</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Short->Complex (Complex Taps)</name>
+ <key>scc</key>
+ <opt>input:short</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Short->Complex (Real Taps)</name>
+ <key>scf</key>
+ <opt>input:short</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>$type.taps</type>
+ </param>
+ <param>
+ <name>Center Frequency</name>
+ <key>center_freq</key>
+ <value>0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_frequency_modulator_fc.xml b/grc/blocks/gr_frequency_modulator_fc.xml
new file mode 100644
index 000000000..d5f8fcfe3
--- /dev/null
+++ b/grc/blocks/gr_frequency_modulator_fc.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Frequency Modulator
+###################################################
+ -->
+<block>
+ <name>Frequency Mod</name>
+ <key>gr_frequency_modulator_fc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.frequency_modulator_fc($sensitivity)</make>
+ <callback>set_sensitivity($sensitivity)</callback>
+ <param>
+ <name>Sensitivity</name>
+ <key>sensitivity</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_glfsr_source_x.xml b/grc/blocks/gr_glfsr_source_x.xml
new file mode 100644
index 000000000..88fb66797
--- /dev/null
+++ b/grc/blocks/gr_glfsr_source_x.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##GLFSR Source
+###################################################
+ -->
+<block>
+ <name>GLFSR Source</name>
+ <key>gr_glfsr_source_x</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.glfsr_source_$(type.fcn)($degree, $repeat, $mask, $seed)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:f</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:b</opt>
+ </option>
+ </param>
+ <param>
+ <name>Degree</name>
+ <key>degree</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Repeat</name>
+ <key>repeat</key>
+ <type>enum</type>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Mask</name>
+ <key>mask</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Seed</name>
+ <key>seed</key>
+ <type>int</type>
+ </param>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_goertzel_fc.xml b/grc/blocks/gr_goertzel_fc.xml
new file mode 100644
index 000000000..f27d9582e
--- /dev/null
+++ b/grc/blocks/gr_goertzel_fc.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Goertzel
+###################################################
+ -->
+<block>
+ <name>Goertzel</name>
+ <key>gr_goertzel_fc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.goertzel_fc($rate, $len, $freq)</make>
+ <callback>set_freq($freq)</callback>
+ <callback>set_rate($rate)</callback>
+ <param>
+ <name>Rate</name>
+ <key>rate</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Length</name>
+ <key>len</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Frequency</name>
+ <key>freq</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_head.xml b/grc/blocks/gr_head.xml
new file mode 100644
index 000000000..e5ff7f6aa
--- /dev/null
+++ b/grc/blocks/gr_head.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Head
+###################################################
+ -->
+<block>
+ <name>Head</name>
+ <key>gr_head</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.head($type.size*$vlen, $num_items)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Items</name>
+ <key>num_items</key>
+ <value>1024</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_hilbert_fc.xml b/grc/blocks/gr_hilbert_fc.xml
new file mode 100644
index 000000000..165e8da23
--- /dev/null
+++ b/grc/blocks/gr_hilbert_fc.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Hilbert
+###################################################
+ -->
+<block>
+ <name>Hilbert</name>
+ <key>gr_hilbert_fc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.hilbert_fc($num_taps)</make>
+ <param>
+ <name>Num Taps</name>
+ <key>num_taps</key>
+ <value>64</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_iir_filter_ffd.xml b/grc/blocks/gr_iir_filter_ffd.xml
new file mode 100644
index 000000000..9799150e8
--- /dev/null
+++ b/grc/blocks/gr_iir_filter_ffd.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##IIR Filter
+###################################################
+ -->
+<block>
+ <name>IIR Filter</name>
+ <key>gr_iir_filter_ffd</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.iir_filter_ffd($fftaps, $fbtaps)</make>
+ <callback>set_taps($fftaps, $fbtaps)</callback>
+ <param>
+ <name>Feed-forward Taps</name>
+ <key>fftaps</key>
+ <type>real_vector</type>
+ </param>
+ <param>
+ <name>Feedback Taps</name>
+ <key>fbtaps</key>
+ <type>real_vector</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_int_to_float.xml b/grc/blocks/gr_int_to_float.xml
new file mode 100644
index 000000000..7430fec72
--- /dev/null
+++ b/grc/blocks/gr_int_to_float.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Int to Float:
+###################################################
+ -->
+<block>
+ <name>Int To Float</name>
+ <key>gr_int_to_float</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.int_to_float($vlen, $scale)</make>
+ <callback>set_scale($scale)</callback>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Scale</name>
+ <key>scale</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>int</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_integrate_xx.xml b/grc/blocks/gr_integrate_xx.xml
new file mode 100644
index 000000000..d0ebd42e2
--- /dev/null
+++ b/grc/blocks/gr_integrate_xx.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Integrate
+###################################################
+ -->
+<block>
+ <name>Integrate</name>
+ <key>gr_integrate_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.integrate_$(type.fcn)($decim)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_interleave.xml b/grc/blocks/gr_interleave.xml
new file mode 100644
index 000000000..3db16ab55
--- /dev/null
+++ b/grc/blocks/gr_interleave.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Interleave
+###################################################
+ -->
+<block>
+ <name>Interleave</name>
+ <key>gr_interleave</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.interleave($type.size*$vlen)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Streams</name>
+ <key>num_streams</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_streams &gt; 0</check>
+ <check>$vlen &gt;= 1</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_streams</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_interleaved_short_to_complex.xml b/grc/blocks/gr_interleaved_short_to_complex.xml
new file mode 100644
index 000000000..e3023e499
--- /dev/null
+++ b/grc/blocks/gr_interleaved_short_to_complex.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Interleaved Short to Complex:
+###################################################
+ -->
+<block>
+ <name>IShort To Complex</name>
+ <key>gr_interleaved_short_to_complex</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.interleaved_short_to_complex()</make>
+ <sink>
+ <name>in</name>
+ <type>short</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_interp_fir_filter_xxx.xml b/grc/blocks/gr_interp_fir_filter_xxx.xml
new file mode 100644
index 000000000..55375ae02
--- /dev/null
+++ b/grc/blocks/gr_interp_fir_filter_xxx.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Interpolating FIR Filter
+###################################################
+ -->
+<block>
+ <name>Interpolating FIR Filter</name>
+ <key>gr_interp_fir_filter_xxx</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>gr.interp_fir_filter_$(type)($interp, $taps)</make>
+ <callback>set_taps($taps)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Complex Taps)</name>
+ <key>ccc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Real Taps)</name>
+ <key>ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Complex (Complex Taps)</name>
+ <key>fcc</key>
+ <opt>input:float</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Float->Float (Real Taps)</name>
+ <key>fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Short (Real Taps)</name>
+ <key>fsf</key>
+ <opt>input:float</opt>
+ <opt>output:short</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Short->Complex (Complex Taps)</name>
+ <key>scc</key>
+ <opt>input:short</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Interpolation</name>
+ <key>interp</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>$type.taps</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_iqcomp_cc.xml b/grc/blocks/gr_iqcomp_cc.xml
new file mode 100644
index 000000000..1603bdc42
--- /dev/null
+++ b/grc/blocks/gr_iqcomp_cc.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##IQ Comp
+###################################################
+ -->
+<block>
+ <name>IQ Comp</name>
+ <key>gr_iqcomp_cc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.iqcomp_cc($mu)</make>
+ <param>
+ <name>Mu</name>
+ <key>mu</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_keep_m_in_n.xml b/grc/blocks/gr_keep_m_in_n.xml
new file mode 100644
index 000000000..35a156176
--- /dev/null
+++ b/grc/blocks/gr_keep_m_in_n.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Keep M in N
+###################################################
+ -->
+<block>
+ <name>Keep M in N</name>
+ <key>gr_keep_m_in_n</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.keep_m_in_n($type.size, $m, $n, $offset)</make>
+ <callback>set_offset($offset)</callback>
+ <callback>set_m($m)</callback>
+ <callback>set_n($n)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>M</name>
+ <key>m</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>N</name>
+ <key>n</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>initial offset</name>
+ <key>offset</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <check>$n &gt; 0</check>
+ <check>$m &gt; 0</check>
+ <check>$m &lt; $n</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>1</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>1</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_keep_one_in_n.xml b/grc/blocks/gr_keep_one_in_n.xml
new file mode 100644
index 000000000..21595b755
--- /dev/null
+++ b/grc/blocks/gr_keep_one_in_n.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Keep 1 in N
+###################################################
+ -->
+<block>
+ <name>Keep 1 in N</name>
+ <key>gr_keep_one_in_n</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.keep_one_in_n($type.size*$vlen, $n)</make>
+ <callback>set_n($n)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>N</name>
+ <key>n</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$n &gt; 0</check>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_kludge_copy.xml b/grc/blocks/gr_kludge_copy.xml
new file mode 100644
index 000000000..8058b082d
--- /dev/null
+++ b/grc/blocks/gr_kludge_copy.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Kludge Copy
+###################################################
+ -->
+<block>
+ <name>Kludge Copy</name>
+ <key>gr_kludge_copy</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.kludge_copy($type.size*$vlen)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Ports</name>
+ <key>num_ports</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_ports &gt; 0</check>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_ports</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_ports</nports>
+ </source>
+</block>
diff --git a/grc/blocks/gr_map_bb.xml b/grc/blocks/gr_map_bb.xml
new file mode 100644
index 000000000..20d6bd2b4
--- /dev/null
+++ b/grc/blocks/gr_map_bb.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Map
+###################################################
+ -->
+<block>
+ <name>Map</name>
+ <key>gr_map_bb</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.map_bb($map)</make>
+ <param>
+ <name>Map</name>
+ <key>map</key>
+ <type>int_vector</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_max_xx.xml b/grc/blocks/gr_max_xx.xml
new file mode 100644
index 000000000..9dbbe60e5
--- /dev/null
+++ b/grc/blocks/gr_max_xx.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Max:
+## 1 output, 2 to inf inputs
+###################################################
+ -->
+<block>
+ <name>Max</name>
+ <key>gr_max_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.max_$(type.fcn)($vlen)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:dd</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_inputs &gt;= 2</check>
+ <check>$vlen &gt;= 1</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_inputs</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_message_burst_source.xml b/grc/blocks/gr_message_burst_source.xml
new file mode 100644
index 000000000..e835d2a2c
--- /dev/null
+++ b/grc/blocks/gr_message_burst_source.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Message Burst Source (the sink port is a message)
+###################################################
+ -->
+<block>
+ <name>Message Burst Source</name>
+ <key>gr_message_burst_source</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.message_burst_source($type.size*$vlen, $(id)_msgq_in)</make>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>msg</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_message_debug.xml b/grc/blocks/gr_message_debug.xml
new file mode 100644
index 000000000..964f95756
--- /dev/null
+++ b/grc/blocks/gr_message_debug.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Message Debug
+###################################################
+ -->
+<block>
+ <name>Message Debug</name>
+ <key>gr_message_debug</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.message_debug()</make>
+ <sink>
+ <name>print</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+ <sink>
+ <name>store</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+ <sink>
+ <name>print_pdu</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+</block>
diff --git a/grc/blocks/gr_message_sink.xml b/grc/blocks/gr_message_sink.xml
new file mode 100644
index 000000000..18e92adb9
--- /dev/null
+++ b/grc/blocks/gr_message_sink.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Message Sink (the source port is a message)
+###################################################
+ -->
+<block>
+ <name>Message Sink</name>
+ <key>gr_message_sink</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.message_sink($type.size*$vlen, $(id)_msgq_out, $dont_block)</make>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Don't Block</name>
+ <key>dont_block</key>
+ <value>False</value>
+ <type>enum</type>
+ <option>
+ <name>Don't Block</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Block</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>msg</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_message_source.xml b/grc/blocks/gr_message_source.xml
new file mode 100644
index 000000000..72367b21b
--- /dev/null
+++ b/grc/blocks/gr_message_source.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Message Source (the sink port is a message)
+###################################################
+ -->
+<block>
+ <name>Message Source</name>
+ <key>gr_message_source</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.message_source($type.size*$vlen, $(id)_msgq_in)</make>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>msg</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_message_strobe.xml b/grc/blocks/gr_message_strobe.xml
new file mode 100644
index 000000000..60a7724df
--- /dev/null
+++ b/grc/blocks/gr_message_strobe.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Message Strobe
+###################################################
+ -->
+<block>
+ <name>Message Strobe</name>
+ <key>gr_message_strobe</key>
+ <import>from gnuradio import gr</import>
+ <import>from gruel import pmt</import>
+ <make>gr.message_strobe($msg, $period)</make>
+ <param>
+ <name>Message PMT</name>
+ <key>msg</key>
+ <value>pmt.pmt_intern("TEST")</value>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Period (ms)</name>
+ <key>period</key>
+ <value>1000</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>set_msg</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+ <source>
+ <name>strobe</name>
+ <type>message</type>
+ <optional>1</optional>
+ </source>
+</block>
diff --git a/grc/blocks/gr_moving_average_xx.xml b/grc/blocks/gr_moving_average_xx.xml
new file mode 100644
index 000000000..b70943c78
--- /dev/null
+++ b/grc/blocks/gr_moving_average_xx.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Moving Average
+###################################################
+ -->
+<block>
+ <name>Moving Average</name>
+ <key>gr_moving_average_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.moving_average_$(type.fcn)($length, $scale, $max_iter)</make>
+ <callback>set_length_and_scale($length, $scale)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ <opt>scale:complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ <opt>scale:real</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ <opt>scale:int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ <opt>scale:int</opt>
+ </option>
+ </param>
+ <param>
+ <name>Length</name>
+ <key>length</key>
+ <value>1000</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Scale</name>
+ <key>scale</key>
+ <value>1</value>
+ <type>$type.scale</type>
+ </param>
+ <param>
+ <name>Max Iter</name>
+ <key>max_iter</key>
+ <value>4000</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_mpsk_sync_cc.xml b/grc/blocks/gr_mpsk_sync_cc.xml
new file mode 100644
index 000000000..fd08f8340
--- /dev/null
+++ b/grc/blocks/gr_mpsk_sync_cc.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##MPSK Sync
+###################################################
+ -->
+<block>
+ <name>MPSK Sync</name>
+ <key>gr_mpsk_sync_cc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.mpsk_sync_cc($alpha, $beta, $max_freq, $min_freq, $ref_phase, $omega, $gain_omega, $mu, $gain_mu)</make>
+ <callback>set_mu($mu)</callback>
+ <callback>set_gain_mu($gain_mu)</callback>
+ <callback>set_omega($omega)</callback>
+ <callback>set_gain_omega($gain_omega)</callback>
+ <param>
+ <name>Alpha</name>
+ <key>alpha</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Beta</name>
+ <key>beta</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Max Freq</name>
+ <key>max_freq</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Min Freq</name>
+ <key>min_freq</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Reference Phase</name>
+ <key>ref_phase</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Omega</name>
+ <key>omega</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Gain Omega</name>
+ <key>gain_omega</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Mu</name>
+ <key>mu</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Gain Mu</name>
+ <key>gain_mu</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_multiply_const_vxx.xml b/grc/blocks/gr_multiply_const_vxx.xml
new file mode 100644
index 000000000..1309d75cd
--- /dev/null
+++ b/grc/blocks/gr_multiply_const_vxx.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Multiply Const Block:
+## all types, 1 output, 1 input & const
+###################################################
+ -->
+<block>
+ <name>Multiply Const</name>
+ <key>gr_multiply_const_vxx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.multiply_const_v$(type.fcn)($const)</make>
+ <callback>set_k($const)</callback>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>const_type:complex_vector</opt>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>const_type:real_vector</opt>
+ <opt>fcn:ff</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>const_type:int_vector</opt>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>const_type:int_vector</opt>
+ <opt>fcn:ss</opt>
+ </option>
+ </param>
+ <param>
+ <name>Constant</name>
+ <key>const</key>
+ <value>0</value>
+ <type>$type.const_type</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>len($const) == $vlen</check>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_multiply_xx.xml b/grc/blocks/gr_multiply_xx.xml
new file mode 100644
index 000000000..60f65c274
--- /dev/null
+++ b/grc/blocks/gr_multiply_xx.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Multiply Block:
+## all types, 1 output, 2 to inf inputs
+###################################################
+ -->
+<block>
+ <name>Multiply</name>
+ <key>gr_multiply_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.multiply_v$(type.fcn)($vlen)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_inputs &gt; 1</check>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_inputs</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_mute_xx.xml b/grc/blocks/gr_mute_xx.xml
new file mode 100644
index 000000000..a9a857c6a
--- /dev/null
+++ b/grc/blocks/gr_mute_xx.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Mute Block:
+## Cast input to bool.
+###################################################
+ -->
+<block>
+ <name>Mute</name>
+ <key>gr_mute_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.mute_$(type.fcn)(bool($mute))</make>
+ <callback>set_mute(bool($mute))</callback>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ </param>
+ <param>
+ <name>Mute</name>
+ <key>mute</key>
+ <value>False</value>
+ <type>raw</type>
+ <option>
+ <name>True</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>False</name>
+ <key>False</key>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_nlog10_ff.xml b/grc/blocks/gr_nlog10_ff.xml
new file mode 100644
index 000000000..935078236
--- /dev/null
+++ b/grc/blocks/gr_nlog10_ff.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Log10 Block:
+## float in/ float out
+###################################################
+ -->
+<block>
+ <name>Log10</name>
+ <key>gr_nlog10_ff</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.nlog10_ff($n, $vlen, $k)</make>
+ <param>
+ <name>n</name>
+ <key>n</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>k</name>
+ <key>k</key>
+ <value>0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen >= 1</check>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_noise_source_x.xml b/grc/blocks/gr_noise_source_x.xml
new file mode 100644
index 000000000..72daaaa20
--- /dev/null
+++ b/grc/blocks/gr_noise_source_x.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Noise Source
+###################################################
+ -->
+<block>
+ <name>Noise Source</name>
+ <key>gr_noise_source_x</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.noise_source_$(type.fcn)($noise_type, $amp, $seed)</make>
+ <callback>set_type($noise_type)</callback>
+ <callback>set_amplitude($amp)</callback>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:c</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:f</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:i</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:s</opt>
+ </option>
+ </param>
+ <param>
+ <name>Noise Type</name>
+ <key>noise_type</key>
+ <value>gr.GR_GAUSSIAN</value>
+ <type>int</type>
+ <option>
+ <name>Uniform</name>
+ <key>gr.GR_UNIFORM</key>
+ </option>
+ <option>
+ <name>Gaussian</name>
+ <key>gr.GR_GAUSSIAN</key>
+ </option>
+ <option>
+ <name>Laplacian</name>
+ <key>gr.GR_LAPLACIAN</key>
+ </option>
+ <option>
+ <name>Impulse</name>
+ <key>gr.GR_IMPULSE</key>
+ </option>
+ </param>
+ <param>
+ <name>Amplitude</name>
+ <key>amp</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Seed</name>
+ <key>seed</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_nop.xml b/grc/blocks/gr_nop.xml
new file mode 100644
index 000000000..bd884d6b8
--- /dev/null
+++ b/grc/blocks/gr_nop.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Nop
+###################################################
+ -->
+<block>
+ <name>Nop</name>
+ <key>gr_nop</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.nop($type.size*$vlen)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Ports</name>
+ <key>num_ports</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_ports &gt; 0</check>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_ports</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_ports</nports>
+ </source>
+</block>
diff --git a/grc/blocks/gr_not_xx.xml b/grc/blocks/gr_not_xx.xml
new file mode 100644
index 000000000..1c2bb8709
--- /dev/null
+++ b/grc/blocks/gr_not_xx.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Logical Not Block
+###################################################
+ -->
+<block>
+ <name>Not</name>
+ <key>gr_not_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.not_$(type.fcn)()</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:bb</opt>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_null_sink.xml b/grc/blocks/gr_null_sink.xml
new file mode 100644
index 000000000..ed106b495
--- /dev/null
+++ b/grc/blocks/gr_null_sink.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Null Sink
+###################################################
+ -->
+<block>
+ <name>Null Sink</name>
+ <key>gr_null_sink</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.null_sink($type.size*$vlen)</make>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+</block>
diff --git a/grc/blocks/gr_null_source.xml b/grc/blocks/gr_null_source.xml
new file mode 100644
index 000000000..6132eae3c
--- /dev/null
+++ b/grc/blocks/gr_null_source.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Null Source
+###################################################
+ -->
+<block>
+ <name>Null Source</name>
+ <key>gr_null_source</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.null_source($type.size*$vlen)</make>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_or_xx.xml b/grc/blocks/gr_or_xx.xml
new file mode 100644
index 000000000..b374aa22a
--- /dev/null
+++ b/grc/blocks/gr_or_xx.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Logical Or Block
+###################################################
+ -->
+<block>
+ <name>Or</name>
+ <key>gr_or_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.or_$(type.fcn)()</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:bb</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <check>$num_inputs &gt;= 2</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <nports>$num_inputs</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_pack_k_bits_bb.xml b/grc/blocks/gr_pack_k_bits_bb.xml
new file mode 100644
index 000000000..34e64a5d9
--- /dev/null
+++ b/grc/blocks/gr_pack_k_bits_bb.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Pack K Bits
+###################################################
+ -->
+<block>
+ <name>Pack K Bits</name>
+ <key>gr_pack_k_bits_bb</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.pack_k_bits_bb($k)</make>
+ <param>
+ <name>K</name>
+ <key>k</key>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+
+ <doc>
+ Pack K unpacked bits (one bit per byte) into a single packed byte containing k bits and 8 - k zeros.
+ </doc>
+
+</block>
diff --git a/grc/blocks/gr_packed_to_unpacked_xx.xml b/grc/blocks/gr_packed_to_unpacked_xx.xml
new file mode 100644
index 000000000..c1477dd9c
--- /dev/null
+++ b/grc/blocks/gr_packed_to_unpacked_xx.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Packed to Unpacked
+###################################################
+ -->
+<block>
+ <name>Packed to Unpacked</name>
+ <key>gr_packed_to_unpacked_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.packed_to_unpacked_$(type.fcn)($bits_per_chunk, $endianness)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:bb</opt>
+ </option>
+ </param>
+ <param>
+ <name>Bits per Chunk</name>
+ <key>bits_per_chunk</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Endianness</name>
+ <key>endianness</key>
+ <type>int</type>
+ <option>
+ <name>MSB</name>
+ <key>gr.GR_MSB_FIRST</key>
+ </option>
+ <option>
+ <name>LSB</name>
+ <key>gr.GR_LSB_FIRST</key>
+ </option>
+ </param>
+ <param>
+ <name>Num Ports</name>
+ <key>num_ports</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_ports &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <nports>$num_ports</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <nports>$num_ports</nports>
+ </source>
+</block>
diff --git a/grc/blocks/gr_pdu_to_tagged_stream.xml b/grc/blocks/gr_pdu_to_tagged_stream.xml
new file mode 100644
index 000000000..6d2fea97e
--- /dev/null
+++ b/grc/blocks/gr_pdu_to_tagged_stream.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## PDU Message to Tagged Stream
+###################################################
+ -->
+<block>
+ <name>PDU to Tagged Stream</name>
+ <key>gr_pdu_to_tagged_stream</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.pdu_to_tagged_stream($type.tv)</make>
+ <param>
+ <name>Item Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>tv:gr.pdu_byte</opt>
+ </option>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>tv:gr.pdu_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>tv:gr.pdu_float</opt>
+ </option>
+ </param>
+ <sink>
+ <name>pdus</name>
+ <type>message</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_peak_detector2_fb.xml b/grc/blocks/gr_peak_detector2_fb.xml
new file mode 100644
index 000000000..128c6244f
--- /dev/null
+++ b/grc/blocks/gr_peak_detector2_fb.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Peak Detector2
+###################################################
+ -->
+<block>
+ <name>Peak Detector2</name>
+ <key>gr_peak_detector2_fb</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.peak_detector2_fb($threshold_factor_rise, $look_ahead, $alpha)</make>
+ <callback>set_threshold_factor_rise($threshold_factor_rise)</callback>
+ <callback>set_look_ahead($look_ahead)</callback>
+ <callback>set_alpha($alpha)</callback>
+ <param>
+ <name>TH Factor Rise</name>
+ <key>threshold_factor_rise</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Look Ahead</name>
+ <key>look_ahead</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Alpha</name>
+ <key>alpha</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_peak_detector_xb.xml b/grc/blocks/gr_peak_detector_xb.xml
new file mode 100644
index 000000000..394b0697f
--- /dev/null
+++ b/grc/blocks/gr_peak_detector_xb.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Peak Detector
+###################################################
+ -->
+<block>
+ <name>Peak Detector</name>
+ <key>gr_peak_detector_xb</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.peak_detector_$(type.fcn)b($threshold_factor_rise, $threshold_factor_fall, $look_ahead, $alpha)</make>
+ <callback>set_threshold_factor_rise($threshold_factor_rise)</callback>
+ <callback>set_threshold_factor_fall($threshold_factor_fall)</callback>
+ <callback>set_look_ahead($look_ahead)</callback>
+ <callback>set_alpha($alpha)</callback>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:f</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:i</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:s</opt>
+ </option>
+ </param>
+ <param>
+ <name>TH Factor Rise</name>
+ <key>threshold_factor_rise</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>TH Factor Fall</name>
+ <key>threshold_factor_fall</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Look Ahead</name>
+ <key>look_ahead</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Alpha</name>
+ <key>alpha</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_pfb_clock_sync.xml b/grc/blocks/gr_pfb_clock_sync.xml
new file mode 100644
index 000000000..3e5e65d12
--- /dev/null
+++ b/grc/blocks/gr_pfb_clock_sync.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Polyphase Filter based Clock Sync
+###################################################
+ -->
+<block>
+ <name>Polyphase Clock Sync</name>
+ <key>gr_pfb_clock_sync_xxx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.pfb_clock_sync_$(type)($sps, $alpha, $taps, $filter_size, $init_phase, $max_dev, $osps)
+self.$(id).set_beta($beta)</make>
+ <callback>set_taps($taps)</callback>
+ <callback>set_alpha($alpha)</callback>
+ <callback>set_beta($beta)</callback>
+
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Real Taps)</name>
+ <key>ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Float (Real Taps)</name>
+ <key>fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ </param>
+
+ <param>
+ <name>Samples/Symbol</name>
+ <key>sps</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Alpha</name>
+ <key>alpha</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Beta</name>
+ <key>beta</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>real_vector</type>
+ </param>
+ <param>
+ <name>Filter Size</name>
+ <key>filter_size</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Initial Phase</name>
+ <key>init_phase</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Maximum Rate Deviation</name>
+ <key>max_dev</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Output SPS</name>
+ <key>osps</key>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+ <source>
+ <name>err</name>
+ <type>float</type>
+ <optional>1</optional>
+ </source>
+ <source>
+ <name>rate</name>
+ <type>float</type>
+ <optional>1</optional>
+ </source>
+ <source>
+ <name>phase</name>
+ <type>float</type>
+ <optional>1</optional>
+ </source>
+</block>
diff --git a/grc/blocks/gr_pfb_synthesizer.xml b/grc/blocks/gr_pfb_synthesizer.xml
new file mode 100644
index 000000000..49e5cb032
--- /dev/null
+++ b/grc/blocks/gr_pfb_synthesizer.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Polyphase Synthesis Filterbank
+###################################################
+ -->
+<block>
+ <name>Polyphase Synthesizer</name>
+ <key>gr_pfb_synthesizer_ccf</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>gr.pfb_synthesizer_ccf(
+ $numchans, $taps, $twox)
+self.$(id).set_channel_map($ch_map)
+ </make>
+ <callback>set_taps($taps)</callback>
+ <callback>set_channel_map($ch_map)</callback>
+
+ <param>
+ <name>Channels</name>
+ <key>numchans</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Connections</name>
+ <key>connections</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>real_vector</type>
+ </param>
+ <param>
+ <name>2x Sample Rate</name>
+ <key>twox</key>
+ <value>False</value>
+ <type>bool</type>
+ </param>
+ <param>
+ <name>Channel Map</name>
+ <key>ch_map</key>
+ <value>[]</value>
+ <type>int_vector</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ <nports>$connections</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_phase_modulator_fc.xml b/grc/blocks/gr_phase_modulator_fc.xml
new file mode 100644
index 000000000..758c50863
--- /dev/null
+++ b/grc/blocks/gr_phase_modulator_fc.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Phase Modulator
+###################################################
+ -->
+<block>
+ <name>Phase Mod</name>
+ <key>gr_phase_modulator_fc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.phase_modulator_fc($sensitivity)</make>
+ <param>
+ <name>Sensitivity</name>
+ <key>sensitivity</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_pll_carriertracking_cc.xml b/grc/blocks/gr_pll_carriertracking_cc.xml
new file mode 100644
index 000000000..27e673248
--- /dev/null
+++ b/grc/blocks/gr_pll_carriertracking_cc.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##PLL Carrier Tracking
+###################################################
+ -->
+<block>
+ <name>PLL Carrier Tracking</name>
+ <key>gr_pll_carriertracking_cc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.pll_carriertracking_cc($w, $max_freq, $min_freq)</make>
+ <callback>set_loop_bandwidth($w)</callback>
+ <param>
+ <name>Loop Bandwidth</name>
+ <key>w</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Max Freq</name>
+ <key>max_freq</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Min Freq</name>
+ <key>min_freq</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_pll_freqdet_cf.xml b/grc/blocks/gr_pll_freqdet_cf.xml
new file mode 100644
index 000000000..d6e4694f0
--- /dev/null
+++ b/grc/blocks/gr_pll_freqdet_cf.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##PLL Frequency Det
+###################################################
+ -->
+<block>
+ <name>PLL Freq Det</name>
+ <key>gr_pll_freqdet_cf</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.pll_freqdet_cf($w, $max_freq, $min_freq)</make>
+ <callback>set_loop_bandwidth($w)</callback>
+ <param>
+ <name>Loop Bandwidth</name>
+ <key>w</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Max Freq</name>
+ <key>max_freq</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Min Freq</name>
+ <key>min_freq</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_pll_refout_cc.xml b/grc/blocks/gr_pll_refout_cc.xml
new file mode 100644
index 000000000..b231ddd19
--- /dev/null
+++ b/grc/blocks/gr_pll_refout_cc.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##PLL Reference Out
+###################################################
+ -->
+<block>
+ <name>PLL Ref Out</name>
+ <key>gr_pll_refout_cc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.pll_refout_cc($w, $max_freq, $min_freq)</make>
+ <callback>set_loop_bandwidth($w)</callback>
+ <param>
+ <name>Loop Bandwidth</name>
+ <key>w</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Max Freq</name>
+ <key>max_freq</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Min Freq</name>
+ <key>min_freq</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_pn_correlator_cc.xml b/grc/blocks/gr_pn_correlator_cc.xml
new file mode 100644
index 000000000..094f46cdf
--- /dev/null
+++ b/grc/blocks/gr_pn_correlator_cc.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##PN Correlator
+###################################################
+ -->
+<block>
+ <name>PN Correlator</name>
+ <key>gr_pn_correlator_cc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.pn_correlator_cc($degree, $mask, $seed)</make>
+ <param>
+ <name>Degree</name>
+ <key>degree</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Mask</name>
+ <key>mask</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Seed</name>
+ <key>seed</key>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_probe_avg_mag_sqrd_x.xml b/grc/blocks/gr_probe_avg_mag_sqrd_x.xml
new file mode 100644
index 000000000..6bf706ae1
--- /dev/null
+++ b/grc/blocks/gr_probe_avg_mag_sqrd_x.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Probe Average Magnitude Squared
+###################################################
+ -->
+<block>
+ <name>Probe Avg Mag^2</name>
+ <key>gr_probe_avg_mag_sqrd_x</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.probe_avg_mag_sqrd_$(type)($threshold, $alpha)</make>
+ <callback>set_alpha($alpha)</callback>
+ <callback>set_threshold($threshold)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>c</key>
+ <opt>input:complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>f</key>
+ <opt>input:float</opt>
+ </option>
+ </param>
+ <param>
+ <name>Threshold (dB)</name>
+ <key>threshold</key>
+ <value>0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Alpha</name>
+ <key>alpha</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <doc>
+Available functions to probe: level()
+
+Use with the function probe block.
+ </doc>
+</block>
diff --git a/grc/blocks/gr_probe_density_b.xml b/grc/blocks/gr_probe_density_b.xml
new file mode 100644
index 000000000..3a91256aa
--- /dev/null
+++ b/grc/blocks/gr_probe_density_b.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Probe Density
+###################################################
+ -->
+<block>
+ <name>Probe Density</name>
+ <key>gr_probe_density_b</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.probe_density_b($alpha)</make>
+ <callback>set_alpha($alpha)</callback>
+ <param>
+ <name>Alpha</name>
+ <key>alpha</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Probe Rate</name>
+ <key>probe_rate</key>
+ <value>10</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <doc>
+Available functions to probe: density()
+
+Use with the function probe block.
+ </doc>
+</block>
diff --git a/grc/blocks/gr_probe_signal_f.xml b/grc/blocks/gr_probe_signal_f.xml
new file mode 100644
index 000000000..5c38e816f
--- /dev/null
+++ b/grc/blocks/gr_probe_signal_f.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Probe Signal
+###################################################
+ -->
+<block>
+ <name>Probe Signal</name>
+ <key>gr_probe_signal_f</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.probe_signal_f()</make>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <doc>
+Available functions to probe: level()
+
+Use with the function probe block.
+ </doc>
+</block>
diff --git a/grc/blocks/gr_pwr_squelch_xx.xml b/grc/blocks/gr_pwr_squelch_xx.xml
new file mode 100644
index 000000000..08d621177
--- /dev/null
+++ b/grc/blocks/gr_pwr_squelch_xx.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Power Squelch
+###################################################
+ -->
+<block>
+ <name>Power Squelch</name>
+ <key>gr_pwr_squelch_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.pwr_squelch_$(type.fcn)($threshold, $alpha, $ramp, $gate)</make>
+ <callback>set_threshold($threshold)</callback>
+ <callback>set_alpha($alpha)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ </param>
+ <param>
+ <name>Threshold (dB)</name>
+ <key>threshold</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Alpha</name>
+ <key>alpha</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Ramp</name>
+ <key>ramp</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Gate</name>
+ <key>gate</key>
+ <type>enum</type>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_quadrature_demod_cf.xml b/grc/blocks/gr_quadrature_demod_cf.xml
new file mode 100644
index 000000000..fad0b3879
--- /dev/null
+++ b/grc/blocks/gr_quadrature_demod_cf.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Quadrature Demodulator
+###################################################
+ -->
+<block>
+ <name>Quadrature Demod</name>
+ <key>gr_quadrature_demod_cf</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.quadrature_demod_cf($gain)</make>
+ <callback>set_gain($gain)</callback>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_random_pdu.xml b/grc/blocks/gr_random_pdu.xml
new file mode 100644
index 000000000..ed5a79a92
--- /dev/null
+++ b/grc/blocks/gr_random_pdu.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Random PDU
+###################################################
+ -->
+<block>
+ <name>Random PDU Generator</name>
+ <key>gr_random_pdu</key>
+ <import>from gnuradio import gr</import>
+ <import>from gruel import pmt</import>
+ <make>gr.random_pdu($minsize, $maxsize)</make>
+ <param>
+ <name>Min Bytes</name>
+ <key>minsize</key>
+ <value>50</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Max Bytes</name>
+ <key>maxsize</key>
+ <value>2000</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>generate</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+ <source>
+ <name>pdus</name>
+ <type>message</type>
+ <optional>1</optional>
+ </source>
+</block>
diff --git a/grc/blocks/gr_rational_resampler_base_xxx.xml b/grc/blocks/gr_rational_resampler_base_xxx.xml
new file mode 100644
index 000000000..4b7720173
--- /dev/null
+++ b/grc/blocks/gr_rational_resampler_base_xxx.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Rational Resampler Base
+###################################################
+ -->
+<block>
+ <name>Rational Resampler Base</name>
+ <key>gr_rational_resampler_base_xxx</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>gr.rational_resampler_base_$(type)($interp, $decim, $taps)</make>
+ <callback>set_taps($taps)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Complex Taps)</name>
+ <key>ccc</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Real Taps)</name>
+ <key>ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Complex (Complex Taps)</name>
+ <key>fcc</key>
+ <opt>input:float</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ <option>
+ <name>Float->Float (Real Taps)</name>
+ <key>fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Short (Real Taps)</name>
+ <key>fsf</key>
+ <opt>input:float</opt>
+ <opt>output:short</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Short->Complex (Complex Taps)</name>
+ <key>scc</key>
+ <opt>input:short</opt>
+ <opt>output:complex</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Interpolation</name>
+ <key>interp</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>$type.taps</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_repeat.xml b/grc/blocks/gr_repeat.xml
new file mode 100644
index 000000000..ba652a4d7
--- /dev/null
+++ b/grc/blocks/gr_repeat.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Repeat
+###################################################
+ -->
+<block>
+ <name>Repeat</name>
+ <key>gr_repeat</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.repeat($type.size*$vlen, $interp)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Interpolation</name>
+ <key>interp</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_rms_xx.xml b/grc/blocks/gr_rms_xx.xml
new file mode 100644
index 000000000..1e0947192
--- /dev/null
+++ b/grc/blocks/gr_rms_xx.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##RMS
+###################################################
+ -->
+<block>
+ <name>RMS</name>
+ <key>gr_rms_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.rms_$(type.fcn)f($alpha)</make>
+ <callback>set_alpha($alpha)</callback>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:c</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:f</opt>
+ </option>
+ </param>
+ <param>
+ <name>Alpha</name>
+ <key>alpha</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_sample_and_hold_xx.xml b/grc/blocks/gr_sample_and_hold_xx.xml
new file mode 100644
index 000000000..2a036c3fd
--- /dev/null
+++ b/grc/blocks/gr_sample_and_hold_xx.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Sample and Hold
+###################################################
+ -->
+<block>
+ <name>Sample and Hold</name>
+ <key>gr_sample_and_hold_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.sample_and_hold_$(type.fcn)()</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:bb</opt>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <sink>
+ <name>ctrl</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_scrambler_bb.xml b/grc/blocks/gr_scrambler_bb.xml
new file mode 100644
index 000000000..d079c4015
--- /dev/null
+++ b/grc/blocks/gr_scrambler_bb.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Descrambler
+###################################################
+ -->
+<block>
+ <name>Scrambler</name>
+ <key>gr_scrambler_bb</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.scrambler_bb($mask, $seed, $len)</make>
+ <param>
+ <name>Mask</name>
+ <key>mask</key>
+ <value>0x8A</value>
+ <type>hex</type>
+ </param>
+ <param>
+ <name>Seed</name>
+ <key>seed</key>
+ <value>0x7F</value>
+ <type>hex</type>
+ </param>
+ <param>
+ <name>Length</name>
+ <key>len</key>
+ <value>7</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_short_to_char.xml b/grc/blocks/gr_short_to_char.xml
new file mode 100644
index 000000000..9c41da84e
--- /dev/null
+++ b/grc/blocks/gr_short_to_char.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Short to char:
+###################################################
+ -->
+<block>
+ <name>Short To Char</name>
+ <key>gr_short_to_char</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.short_to_char($vlen)</make>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>short</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_short_to_float.xml b/grc/blocks/gr_short_to_float.xml
new file mode 100644
index 000000000..529f8c78c
--- /dev/null
+++ b/grc/blocks/gr_short_to_float.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Short to Float:
+###################################################
+ -->
+<block>
+ <name>Short To Float</name>
+ <key>gr_short_to_float</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.short_to_float($vlen, $scale)</make>
+ <callback>set_scale($scale)</callback>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Scale</name>
+ <key>scale</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>short</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_sig_source_x.xml b/grc/blocks/gr_sig_source_x.xml
new file mode 100644
index 000000000..644cf52d0
--- /dev/null
+++ b/grc/blocks/gr_sig_source_x.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Signal Source
+###################################################
+ -->
+<block>
+ <name>Signal Source</name>
+ <key>gr_sig_source_x</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.sig_source_$(type.fcn)($samp_rate, $waveform, $freq, $amp, $offset)</make>
+ <callback>set_sampling_freq($samp_rate)</callback>
+ <callback>set_waveform($waveform)</callback>
+ <callback>set_frequency($freq)</callback>
+ <callback>set_amplitude($amp)</callback>
+ <callback>set_offset($offset)</callback>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:c</opt>
+ <opt>offset_type:complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:f</opt>
+ <opt>offset_type:real</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:i</opt>
+ <opt>offset_type:int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:s</opt>
+ <opt>offset_type:int</opt>
+ </option>
+ </param>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Waveform</name>
+ <key>waveform</key>
+ <value>gr.GR_COS_WAVE</value>
+ <type>int</type>
+ <option>
+ <name>Constant</name>
+ <key>gr.GR_CONST_WAVE</key>
+ </option>
+ <option>
+ <name>Sine</name>
+ <key>gr.GR_SIN_WAVE</key>
+ </option>
+ <option>
+ <name>Cosine</name>
+ <key>gr.GR_COS_WAVE</key>
+ </option>
+ <option>
+ <name>Square</name>
+ <key>gr.GR_SQR_WAVE</key>
+ </option>
+ <option>
+ <name>Triangle</name>
+ <key>gr.GR_TRI_WAVE</key>
+ </option>
+ <option>
+ <name>Saw Tooth</name>
+ <key>gr.GR_SAW_WAVE</key>
+ </option>
+ </param>
+ <param>
+ <name>Frequency</name>
+ <key>freq</key>
+ <value>1000</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Amplitude</name>
+ <key>amp</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Offset</name>
+ <key>offset</key>
+ <value>0</value>
+ <type>$type.offset_type</type>
+ </param>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_simple_correlator.xml b/grc/blocks/gr_simple_correlator.xml
new file mode 100644
index 000000000..820523a64
--- /dev/null
+++ b/grc/blocks/gr_simple_correlator.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Simple Correlator
+###################################################
+ -->
+<block>
+ <name>Simple Correlator</name>
+ <key>gr_simple_correlator</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.simple_correlator($payload_bytesize)</make>
+ <param>
+ <name>Payload Byte Size</name>
+ <key>payload_bytesize</key>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_simple_framer.xml b/grc/blocks/gr_simple_framer.xml
new file mode 100644
index 000000000..2a0295c41
--- /dev/null
+++ b/grc/blocks/gr_simple_framer.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Simple Framer
+###################################################
+ -->
+<block>
+ <name>Simple Framer</name>
+ <key>gr_simple_framer</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.simple_framer($payload_bytesize)</make>
+ <param>
+ <name>Payload Byte Size</name>
+ <key>payload_bytesize</key>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_simple_squelch_cc.xml b/grc/blocks/gr_simple_squelch_cc.xml
new file mode 100644
index 000000000..5c0727f5f
--- /dev/null
+++ b/grc/blocks/gr_simple_squelch_cc.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Simple Squelch
+###################################################
+ -->
+<block>
+ <name>Simple Squelch</name>
+ <key>gr_simple_squelch_cc</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.simple_squelch_cc($threshold, $alpha)</make>
+ <callback>set_threshold($threshold)</callback>
+ <callback>set_alpha($alpha)</callback>
+ <param>
+ <name>Threshold (dB)</name>
+ <key>threshold</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Alpha</name>
+ <key>alpha</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_single_pole_iir_filter_xx.xml b/grc/blocks/gr_single_pole_iir_filter_xx.xml
new file mode 100644
index 000000000..50cf4a82d
--- /dev/null
+++ b/grc/blocks/gr_single_pole_iir_filter_xx.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Single Pole IIR Filter
+###################################################
+ -->
+<block>
+ <name>Single Pole IIR Filter</name>
+ <key>gr_single_pole_iir_filter_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.single_pole_iir_filter_$(type.fcn)($alpha, $vlen)</make>
+ <callback>set_taps($alpha)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ </param>
+ <param>
+ <name>Alpha</name>
+ <key>alpha</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_skiphead.xml b/grc/blocks/gr_skiphead.xml
new file mode 100644
index 000000000..0849ad298
--- /dev/null
+++ b/grc/blocks/gr_skiphead.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Skip Head
+###################################################
+ -->
+<block>
+ <name>Skip Head</name>
+ <key>gr_skiphead</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.skiphead($type.size*$vlen, $num_items)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Items</name>
+ <key>num_items</key>
+ <value>1024</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_socket_pdu.xml b/grc/blocks/gr_socket_pdu.xml
new file mode 100644
index 000000000..a175c3699
--- /dev/null
+++ b/grc/blocks/gr_socket_pdu.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Socket PDU Message source/sink
+###################################################
+ -->
+<block>
+ <name>Socket PDU</name>
+ <key>gr_socket_pdu</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.socket_pdu($type, $host, $port, $mtu)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <value>TCP_SERVER</value>
+ <type>enum</type>
+ <option>
+ <name>TCP Server</name>
+ <key>"TCP_SERVER"</key>
+ </option>
+ <option>
+ <name>TCP Client</name>
+ <key>"TCP_CLIENT"</key>
+ </option>
+ <option>
+ <name>UDP Server</name>
+ <key>"UDP_SERVER"</key>
+ </option>
+ <option>
+ <name>UDP Client</name>
+ <key>"UDP_CLIENT"</key>
+ </option>
+ </param>
+ <param>
+ <name>Host</name>
+ <key>host</key>
+ <value></value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Port</name>
+ <key>port</key>
+ <value>52001</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>MTU</name>
+ <key>mtu</key>
+ <value>10000</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>pdus</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+ <source>
+ <name>pdus</name>
+ <type>message</type>
+ <optional>1</optional>
+ </source>
+</block>
diff --git a/grc/blocks/gr_stream_mux.xml b/grc/blocks/gr_stream_mux.xml
new file mode 100644
index 000000000..8efe7b655
--- /dev/null
+++ b/grc/blocks/gr_stream_mux.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Stream Mux:
+## all types, many inputs, only one output
+###################################################
+ -->
+<block>
+ <name>Stream Mux</name>
+ <key>gr_stream_mux</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.stream_mux($type.size*$vlen, $lengths)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Lengths</name>
+ <key>lengths</key>
+ <value>1, 1</value>
+ <type>int_vector</type>
+ </param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_inputs &gt; 0</check>
+ <check>$num_inputs == len($lengths)</check>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_inputs</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_stream_to_streams.xml b/grc/blocks/gr_stream_to_streams.xml
new file mode 100644
index 000000000..82542b8d4
--- /dev/null
+++ b/grc/blocks/gr_stream_to_streams.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Stream to Streams
+###################################################
+ -->
+<block>
+ <name>Stream to Streams</name>
+ <key>gr_stream_to_streams</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.stream_to_streams($type.size*$vlen, $num_streams)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Streams</name>
+ <key>num_streams</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_streams &gt; 0</check>
+ <check>$vlen &gt;= 1</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_streams</nports>
+ </source>
+</block>
diff --git a/grc/blocks/gr_stream_to_vector.xml b/grc/blocks/gr_stream_to_vector.xml
new file mode 100644
index 000000000..296d786f8
--- /dev/null
+++ b/grc/blocks/gr_stream_to_vector.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Stream to Vector
+###################################################
+ -->
+<block>
+ <name>Stream to Vector</name>
+ <key>gr_stream_to_vector</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.stream_to_vector($type.size*$vlen, $num_items)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Items</name>
+ <key>num_items</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_items &gt; 0</check>
+ <check>$vlen &gt;= 1</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen*$num_items</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_streams_to_stream.xml b/grc/blocks/gr_streams_to_stream.xml
new file mode 100644
index 000000000..7aadd7eef
--- /dev/null
+++ b/grc/blocks/gr_streams_to_stream.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Streams to Stream
+###################################################
+ -->
+<block>
+ <name>Streams to Stream</name>
+ <key>gr_streams_to_stream</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.streams_to_stream($type.size*$vlen, $num_streams)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Streams</name>
+ <key>num_streams</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_streams &gt; 0</check>
+ <check>$vlen &gt;= 1</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_streams</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_streams_to_vector.xml b/grc/blocks/gr_streams_to_vector.xml
new file mode 100644
index 000000000..4ecdcb2d4
--- /dev/null
+++ b/grc/blocks/gr_streams_to_vector.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Streams to Vector
+###################################################
+ -->
+<block>
+ <name>Streams to Vector</name>
+ <key>gr_streams_to_vector</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.streams_to_vector($type.size*$vlen, $num_streams)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Streams</name>
+ <key>num_streams</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_streams &gt; 0</check>
+ <check>$vlen &gt;= 1</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_streams</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen*$num_streams</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_sub_xx.xml b/grc/blocks/gr_sub_xx.xml
new file mode 100644
index 000000000..c677747da
--- /dev/null
+++ b/grc/blocks/gr_sub_xx.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Subtract Block:
+## all types, 1 output, 2 to inf inputs
+###################################################
+ -->
+<block>
+ <name>Subtract</name>
+ <key>gr_sub_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.sub_$(type.fcn)($vlen)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <check>$num_inputs &gt;= 1</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_inputs</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_tag_debug.xml b/grc/blocks/gr_tag_debug.xml
new file mode 100644
index 000000000..4af7729be
--- /dev/null
+++ b/grc/blocks/gr_tag_debug.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Tag Debug
+###################################################
+ -->
+<block>
+ <name>Tag Debug</name>
+ <key>gr_tag_debug</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.tag_debug($type.size*$vlen, $name)</make>
+ <callback>set_display($display)</callback>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Name</name>
+ <key>name</key>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Display</name>
+ <key>display</key>
+ <value>True</value>
+ <type>bool</type>
+ <option>
+ <name>On</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Off</name>
+ <key>False</key>
+ </option>
+ </param>
+ <check>$num_inputs &gt;= 1</check>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_inputs</nports>
+ </sink>
+</block>
diff --git a/grc/blocks/gr_tagged_stream_to_pdu.xml b/grc/blocks/gr_tagged_stream_to_pdu.xml
new file mode 100644
index 000000000..e2f754c9e
--- /dev/null
+++ b/grc/blocks/gr_tagged_stream_to_pdu.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Tagged Stream to PDU Message
+###################################################
+ -->
+<block>
+ <name>Tagged Stream to PDU</name>
+ <key>gr_tagged_stream_to_pdu</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.tagged_stream_to_pdu($type.tv)</make>
+ <param>
+ <name>Item Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>tv:gr.pdu_byte</opt>
+ </option>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>tv:gr.pdu_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>tv:gr.pdu_float</opt>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>pdus</name>
+ <type>message</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_threshold_ff.xml b/grc/blocks/gr_threshold_ff.xml
new file mode 100644
index 000000000..740ce5794
--- /dev/null
+++ b/grc/blocks/gr_threshold_ff.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Threshold
+###################################################
+ -->
+<block>
+ <name>Threshold</name>
+ <key>gr_threshold_ff</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.threshold_ff($low, $high, $init)</make>
+ <callback>set_hi($high)</callback>
+ <callback>set_lo($low)</callback>
+ <param>
+ <name>Low</name>
+ <key>low</key>
+ <value>-100</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>High</name>
+ <key>high</key>
+ <value>100</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Initial State</name>
+ <key>init</key>
+ <value>0</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_throttle.xml b/grc/blocks/gr_throttle.xml
new file mode 100644
index 000000000..e3a5a2ba1
--- /dev/null
+++ b/grc/blocks/gr_throttle.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Throttle
+###################################################
+ -->
+<block>
+ <name>Throttle</name>
+ <key>gr_throttle</key>
+ <throttle>1</throttle>
+ <import>from gnuradio import gr</import>
+ <make>gr.throttle($type.size*$vlen, $samples_per_second)</make>
+ <callback>set_sample_rate($samples_per_second)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Sample Rate</name>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_transcendental.xml b/grc/blocks/gr_transcendental.xml
new file mode 100644
index 000000000..eede447f9
--- /dev/null
+++ b/grc/blocks/gr_transcendental.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##transcendental functions
+###################################################
+ -->
+<block>
+ <name>Transcendental</name>
+ <key>gr_transcendental</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.transcendental($name, "$type")</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex_double</key>
+ <opt>type:complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>type:float</opt>
+ </option>
+ </param>
+ <param>
+ <name>Function Name</name>
+ <key>name</key>
+ <value>cos</value>
+ <type>string</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.type</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_tuntap_pdu.xml b/grc/blocks/gr_tuntap_pdu.xml
new file mode 100644
index 000000000..f169345af
--- /dev/null
+++ b/grc/blocks/gr_tuntap_pdu.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Tuntap PDU Message source/sink
+###################################################
+ -->
+<block>
+ <name>TunTap PDU</name>
+ <key>gr_tuntap_pdu</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.tuntap_pdu($ifn, $mtu)</make>
+ <param>
+ <name>Interface Name</name>
+ <key>ifn</key>
+ <value>tun0</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>MTU</name>
+ <key>mtu</key>
+ <value>10000</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>pdus</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+ <source>
+ <name>pdus</name>
+ <type>message</type>
+ <optional>1</optional>
+ </source>
+</block>
diff --git a/grc/blocks/gr_uchar_to_float.xml b/grc/blocks/gr_uchar_to_float.xml
new file mode 100644
index 000000000..0a5f7f96a
--- /dev/null
+++ b/grc/blocks/gr_uchar_to_float.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Unsigned Char to Float:
+###################################################
+ -->
+<block>
+ <name>UChar To Float</name>
+ <key>gr_uchar_to_float</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.uchar_to_float()</make>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_udp_sink.xml b/grc/blocks/gr_udp_sink.xml
new file mode 100644
index 000000000..45f81075f
--- /dev/null
+++ b/grc/blocks/gr_udp_sink.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##UDP Sink
+###################################################
+ -->
+<block>
+ <name>UDP Sink</name>
+ <key>gr_udp_sink</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.udp_sink($type.size*$vlen, $ipaddr, $port, $psize, $eof)</make>
+ <callback>set_mtu($mtu)</callback>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Destination IP Address</name>
+ <key>ipaddr</key>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Destination Port</name>
+ <key>port</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Payload Size</name>
+ <key>psize</key>
+ <value>1472</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Send Null Pkt as EOF</name>
+ <key>eof</key>
+ <value>True</value>
+ <type>bool</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+</block>
diff --git a/grc/blocks/gr_udp_source.xml b/grc/blocks/gr_udp_source.xml
new file mode 100644
index 000000000..a1b961651
--- /dev/null
+++ b/grc/blocks/gr_udp_source.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##UDP Source
+###################################################
+ -->
+<block>
+ <name>UDP Source</name>
+ <key>gr_udp_source</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.udp_source($type.size*$vlen, $ipaddr, $port, $psize, $eof, $wait)</make>
+ <callback>set_mtu($mtu)</callback>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>IP Address</name>
+ <key>ipaddr</key>
+ <value>127.0.0.1</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Port</name>
+ <key>port</key>
+ <value>1234</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Payload Size</name>
+ <key>psize</key>
+ <value>1472</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Null Pkt is EOF</name>
+ <key>eof</key>
+ <value>True</value>
+ <type>bool</type>
+ </param>
+ <param>
+ <name>Wait for Data</name>
+ <key>wait</key>
+ <value>True</value>
+ <type>bool</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_unpack_k_bits_bb.xml b/grc/blocks/gr_unpack_k_bits_bb.xml
new file mode 100644
index 000000000..9917644ab
--- /dev/null
+++ b/grc/blocks/gr_unpack_k_bits_bb.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Unpack K Bits
+###################################################
+ -->
+<block>
+ <name>Unpack K Bits</name>
+ <key>gr_unpack_k_bits_bb</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.unpack_k_bits_bb($k)</make>
+ <param>
+ <name>K</name>
+ <key>k</key>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_unpacked_to_packed_xx.xml b/grc/blocks/gr_unpacked_to_packed_xx.xml
new file mode 100644
index 000000000..427c80082
--- /dev/null
+++ b/grc/blocks/gr_unpacked_to_packed_xx.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Unpacked to Packed
+###################################################
+ -->
+<block>
+ <name>Unpacked to Packed</name>
+ <key>gr_unpacked_to_packed_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.unpacked_to_packed_$(type.fcn)($bits_per_chunk, $endianness)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:bb</opt>
+ </option>
+ </param>
+ <param>
+ <name>Bits per Chunk</name>
+ <key>bits_per_chunk</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Endianness</name>
+ <key>endianness</key>
+ <type>int</type>
+ <option>
+ <name>MSB</name>
+ <key>gr.GR_MSB_FIRST</key>
+ </option>
+ <option>
+ <name>LSB</name>
+ <key>gr.GR_LSB_FIRST</key>
+ </option>
+ </param>
+ <param>
+ <name>Num Ports</name>
+ <key>num_ports</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_ports &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <nports>$num_ports</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <nports>$num_ports</nports>
+ </source>
+</block>
diff --git a/grc/blocks/gr_vco_f.xml b/grc/blocks/gr_vco_f.xml
new file mode 100644
index 000000000..e49c53965
--- /dev/null
+++ b/grc/blocks/gr_vco_f.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##VCO
+###################################################
+ -->
+<block>
+ <name>VCO</name>
+ <key>gr_vco_f</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.vco_f($samp_rate, $sensitivity, $amplitude)</make>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Sensitivity</name>
+ <key>sensitivity</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Amplitude</name>
+ <key>amplitude</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/grc/blocks/gr_vector_insert_x.xml b/grc/blocks/gr_vector_insert_x.xml
new file mode 100644
index 000000000..f9ce1f654
--- /dev/null
+++ b/grc/blocks/gr_vector_insert_x.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Vector Source
+###################################################
+ -->
+<block>
+ <name>Vector Insert</name>
+ <key>gr_vector_insert_x</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.vector_insert_$(type.fcn)($vector, $period, $offset)</make>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:b</opt>
+ <opt>vec_type:int_vector</opt>
+ </option>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:c</opt>
+ <opt>vec_type:complex_vector</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:f</opt>
+ <opt>vec_type:real_vector</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:i</opt>
+ <opt>vec_type:int_vector</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:s</opt>
+ <opt>vec_type:int_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vector</name>
+ <key>vector</key>
+ <value>0, 0, 0</value>
+ <type>$type.vec_type</type>
+ </param>
+ <param>
+ <name>Periodicity</name>
+ <key>period</key>
+ <value>100</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Offset</name>
+ <key>offset</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+
+ <doc>
+ Periodicity, the length of the periodicity at which the vector should be inserted at the output.
+ (i.e. one vector for every N output items)
+
+ Offset sepcifies where in the cycle period we should begin at.
+ </doc>
+</block>
diff --git a/grc/blocks/gr_vector_sink_x.xml b/grc/blocks/gr_vector_sink_x.xml
new file mode 100644
index 000000000..3bd998698
--- /dev/null
+++ b/grc/blocks/gr_vector_sink_x.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Vector sink
+###################################################
+ -->
+<block>
+ <name>Vector Sink</name>
+ <key>gr_vector_sink_x</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.vector_sink_$(type.fcn)($vlen)</make>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:c</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:f</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:i</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:s</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:b</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+</block>
diff --git a/grc/blocks/gr_vector_source_x.xml b/grc/blocks/gr_vector_source_x.xml
new file mode 100644
index 000000000..7a6a3aeff
--- /dev/null
+++ b/grc/blocks/gr_vector_source_x.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Vector Source
+###################################################
+ -->
+<block>
+ <name>Vector Source</name>
+ <key>gr_vector_source_x</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.vector_source_$(type.fcn)($vector, $repeat, $vlen)</make>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:c</opt>
+ <opt>vec_type:complex_vector</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:f</opt>
+ <opt>vec_type:real_vector</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:i</opt>
+ <opt>vec_type:int_vector</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:s</opt>
+ <opt>vec_type:int_vector</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:b</opt>
+ <opt>vec_type:int_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vector</name>
+ <key>vector</key>
+ <value>0, 0, 0</value>
+ <type>$type.vec_type</type>
+ </param>
+ <param>
+ <name>Repeat</name>
+ <key>repeat</key>
+ <value>True</value>
+ <type>enum</type>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_vector_to_stream.xml b/grc/blocks/gr_vector_to_stream.xml
new file mode 100644
index 000000000..d56d34067
--- /dev/null
+++ b/grc/blocks/gr_vector_to_stream.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Vector to Stream
+###################################################
+ -->
+<block>
+ <name>Vector to Stream</name>
+ <key>gr_vector_to_stream</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.vector_to_stream($type.size*$vlen, $num_items)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Items</name>
+ <key>num_items</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_items &gt; 0</check>
+ <check>$vlen &gt;= 1</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen*$num_items</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/grc/blocks/gr_vector_to_streams.xml b/grc/blocks/gr_vector_to_streams.xml
new file mode 100644
index 000000000..86cb56813
--- /dev/null
+++ b/grc/blocks/gr_vector_to_streams.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Vector to Streams
+###################################################
+ -->
+<block>
+ <name>Vector to Streams</name>
+ <key>gr_vector_to_streams</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.vector_to_streams($type.size*$vlen, $num_streams)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Streams</name>
+ <key>num_streams</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$num_streams &gt; 0</check>
+ <check>$vlen &gt;= 1</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen*$num_streams</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$num_streams</nports>
+ </source>
+</block>
diff --git a/grc/blocks/gr_wavfile_sink.xml b/grc/blocks/gr_wavfile_sink.xml
new file mode 100644
index 000000000..651e16cb6
--- /dev/null
+++ b/grc/blocks/gr_wavfile_sink.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Wav File Sink
+###################################################
+ -->
+<block>
+ <name>Wav File Sink</name>
+ <key>gr_wavfile_sink</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.wavfile_sink($file, $nchan, $samp_rate, $bits_per_sample)</make>
+ <callback>open($file)</callback>
+ <param>
+ <name>File</name>
+ <key>file</key>
+ <value></value>
+ <type>file_save</type>
+ </param>
+ <param>
+ <name>N Channels</name>
+ <key>nchan</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Bits per Sample</name>
+ <key>bits_per_sample</key>
+ <value>8</value>
+ <type>int</type>
+ </param>
+ <check>1 &lt;= $nchan</check>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ <nports>$nchan</nports>
+ </sink>
+</block>
diff --git a/grc/blocks/gr_wavfile_source.xml b/grc/blocks/gr_wavfile_source.xml
new file mode 100644
index 000000000..433bb0af2
--- /dev/null
+++ b/grc/blocks/gr_wavfile_source.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Wav File Source
+###################################################
+ -->
+<block>
+ <name>Wav File Source</name>
+ <key>gr_wavfile_source</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.wavfile_source($file, $repeat)</make>
+ <param>
+ <name>File</name>
+ <key>file</key>
+ <value></value>
+ <type>file_open</type>
+ </param>
+ <param>
+ <name>Repeat</name>
+ <key>repeat</key>
+ <value>True</value>
+ <type>enum</type>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>N Channels</name>
+ <key>nchan</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>1 &lt;= $nchan</check>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ <nports>$nchan</nports>
+ </source>
+</block>
diff --git a/grc/blocks/gr_xor_xx.xml b/grc/blocks/gr_xor_xx.xml
new file mode 100644
index 000000000..c014cbe57
--- /dev/null
+++ b/grc/blocks/gr_xor_xx.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Logical Xor Block
+###################################################
+ -->
+<block>
+ <name>Xor</name>
+ <key>gr_xor_xx</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.xor_$(type.fcn)()</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:ii</opt>
+ </option>
+ <option>
+ <name>Shxort</name>
+ <key>short</key>
+ <opt>fcn:ss</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:bb</opt>
+ </option>
+ </param>
+ <param>
+ <name>Num Inputs</name>
+ <key>num_inputs</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <check>$num_inputs &gt;= 2</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <nports>$num_inputs</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/grc/blocks/high_pass_filter.xml b/grc/blocks/high_pass_filter.xml
new file mode 100644
index 000000000..0e29cbb36
--- /dev/null
+++ b/grc/blocks/high_pass_filter.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##High Pass Filter: Custom wrapper
+###################################################
+ -->
+<block>
+ <name>High Pass Filter</name>
+ <key>high_pass_filter</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>gr.$(type)(#if str($type).startswith('interp') then $interp else $decim#, firdes.high_pass(
+ $gain, $samp_rate, $cutoff_freq, $width, $win, $beta))</make>
+ <callback>set_taps(firdes.high_pass($gain, $samp_rate, $cutoff_freq, $width, $win, $beta))</callback>
+ <param>
+ <name>FIR Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Decimating)</name>
+ <key>fir_filter_ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Interpolating)</name>
+ <key>interp_fir_filter_ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ </option>
+ <option>
+ <name>Float->Float (Decimating)</name>
+ <key>fir_filter_fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ </option>
+ <option>
+ <name>Float->Float (Interpolating)</name>
+ <key>interp_fir_filter_fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ </option>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>#if str($type).startswith('interp') then 'all' else 'none'#</hide>
+ </param>
+ <param>
+ <name>Interpolation</name>
+ <key>interp</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>#if str($type).startswith('interp') then 'none' else 'all'#</hide>
+ </param>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Cutoff Freq</name>
+ <key>cutoff_freq</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Transition Width</name>
+ <key>width</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Window</name>
+ <key>win</key>
+ <value>firdes.WIN_HAMMING</value>
+ <type>int</type>
+ <option>
+ <name>Hamming</name>
+ <key>firdes.WIN_HAMMING</key>
+ </option>
+ <option>
+ <name>Hann</name>
+ <key>firdes.WIN_HANN</key>
+ </option>
+ <option>
+ <name>Blackman</name>
+ <key>firdes.WIN_BLACKMAN</key>
+ </option>
+ <option>
+ <name>Rectangular</name>
+ <key>firdes.WIN_RECTANGULAR</key>
+ </option>
+ <option>
+ <name>Kaiser</name>
+ <key>firdes.WIN_KAISER</key>
+ </option>
+ </param>
+ <param>
+ <name>Beta</name>
+ <key>beta</key>
+ <value>6.76</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+ <doc>
+This filter is a convenience wrapper for an fir filter and a firdes taps generating function.
+
+Sample rate, cutoff frequency, and transition width are in Hertz.
+
+The beta paramater only applies to the Kaiser window.
+ </doc>
+</block>
diff --git a/grc/blocks/import.xml b/grc/blocks/import.xml
new file mode 100644
index 000000000..feea052d3
--- /dev/null
+++ b/grc/blocks/import.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Import python modules into the namespace
+###################################################
+ -->
+<block>
+ <name>Import</name>
+ <key>import</key>
+ <import>$import</import>
+ <make></make>
+ <param>
+ <name>Import</name>
+ <key>import</key>
+ <value></value>
+ <type>import</type>
+ </param>
+ <doc>
+Import additional python modules into the namespace.
+
+Examples:
+from gnuradio.gr import firdes
+import math,cmath
+from math import pi
+ </doc>
+</block>
diff --git a/grc/blocks/low_pass_filter.xml b/grc/blocks/low_pass_filter.xml
new file mode 100644
index 000000000..26435fd4d
--- /dev/null
+++ b/grc/blocks/low_pass_filter.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Low Pass Filter: Custom wrapper
+###################################################
+ -->
+<block>
+ <name>Low Pass Filter</name>
+ <key>low_pass_filter</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>gr.$(type)(#if str($type).startswith('interp') then $interp else $decim#, firdes.low_pass(
+ $gain, $samp_rate, $cutoff_freq, $width, $win, $beta))</make>
+ <callback>set_taps(firdes.low_pass($gain, $samp_rate, $cutoff_freq, $width, $win, $beta))</callback>
+ <param>
+ <name>FIR Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Decimating)</name>
+ <key>fir_filter_ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Interpolating)</name>
+ <key>interp_fir_filter_ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ </option>
+ <option>
+ <name>Float->Float (Decimating)</name>
+ <key>fir_filter_fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ </option>
+ <option>
+ <name>Float->Float (Interpolating)</name>
+ <key>interp_fir_filter_fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ </option>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>#if str($type).startswith('interp') then 'all' else 'none'#</hide>
+ </param>
+ <param>
+ <name>Interpolation</name>
+ <key>interp</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>#if str($type).startswith('interp') then 'none' else 'all'#</hide>
+ </param>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Cutoff Freq</name>
+ <key>cutoff_freq</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Transition Width</name>
+ <key>width</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Window</name>
+ <key>win</key>
+ <value>firdes.WIN_HAMMING</value>
+ <type>int</type>
+ <option>
+ <name>Hamming</name>
+ <key>firdes.WIN_HAMMING</key>
+ </option>
+ <option>
+ <name>Hann</name>
+ <key>firdes.WIN_HANN</key>
+ </option>
+ <option>
+ <name>Blackman</name>
+ <key>firdes.WIN_BLACKMAN</key>
+ </option>
+ <option>
+ <name>Rectangular</name>
+ <key>firdes.WIN_RECTANGULAR</key>
+ </option>
+ <option>
+ <name>Kaiser</name>
+ <key>firdes.WIN_KAISER</key>
+ </option>
+ </param>
+ <param>
+ <name>Beta</name>
+ <key>beta</key>
+ <value>6.76</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+ <doc>
+This filter is a convenience wrapper for an fir filter and a firdes taps generating function.
+
+Sample rate, cutoff frequency, and transition width are in Hertz.
+
+The beta paramater only applies to the Kaiser window.
+ </doc>
+</block>
diff --git a/grc/blocks/note.xml b/grc/blocks/note.xml
new file mode 100644
index 000000000..db6687c03
--- /dev/null
+++ b/grc/blocks/note.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Note Block (dummy)
+###################################################
+ -->
+<block>
+ <name>Note</name>
+ <key>note</key>
+ <make></make>
+ <param>
+ <name>Note</name>
+ <key>note</key>
+ <value></value>
+ <type>string</type>
+ </param>
+</block>
diff --git a/grc/blocks/options.xml b/grc/blocks/options.xml
new file mode 100644
index 000000000..1cf0b7707
--- /dev/null
+++ b/grc/blocks/options.xml
@@ -0,0 +1,190 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Options Block:
+## options for window size,
+## and flow graph building.
+###################################################
+ -->
+<block>
+ <name>Options</name>
+ <key>options</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio.gr import firdes</import>
+ <import>#if $generate_options() == 'wx_gui'
+from grc_gnuradio import wxgui as grc_wxgui
+import wx
+#end if
+#if $generate_options() == 'qt_gui'
+from PyQt4 import Qt
+import sys
+#end if
+#if $generate_options() != 'hb'
+from optparse import OptionParser
+from gnuradio.eng_option import eng_option
+from gnuradio import eng_notation
+#end if</import>
+ <make></make>
+ <callback>if $run: self.start()
+else: self.stop(); self.wait()</callback>
+ <param>
+ <name>Title</name>
+ <key>title</key>
+ <value></value>
+ <type>string</type>
+ <hide>#if $title() then 'none' else 'part'#</hide>
+ </param>
+ <param>
+ <name>Author</name>
+ <key>author</key>
+ <value></value>
+ <type>string</type>
+ <hide>#if $author() then 'none' else 'part'#</hide>
+ </param>
+ <param>
+ <name>Description</name>
+ <key>description</key>
+ <value></value>
+ <type>string</type>
+ <hide>#if $description() then 'none' else 'part'#</hide>
+ </param>
+ <param>
+ <name>Window Size</name>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ <type>int_vector</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>Generate Options</name>
+ <key>generate_options</key>
+ <value>wx_gui</value>
+ <type>enum</type>
+ <option>
+ <name>WX GUI</name>
+ <key>wx_gui</key>
+ </option>
+ <option>
+ <name>QT GUI</name>
+ <key>qt_gui</key>
+ </option>
+ <option>
+ <name>No GUI</name>
+ <key>no_gui</key>
+ </option>
+ <option>
+ <name>Hier Block</name>
+ <key>hb</key>
+ </option>
+ </param>
+ <param>
+ <name>Category</name>
+ <key>category</key>
+ <value>Custom</value>
+ <type>string</type>
+ <hide>#if $generate_options() == 'hb' then 'none' else 'all'#</hide>
+ </param>
+ <param>
+ <name>Run Options</name>
+ <key>run_options</key>
+ <value>prompt</value>
+ <type>enum</type>
+ <hide>#if $generate_options() == 'no_gui' then 'none' else 'all'#</hide>
+ <option>
+ <name>Run to Completion</name>
+ <key>run</key>
+ </option>
+ <option>
+ <name>Prompt for Exit</name>
+ <key>prompt</key>
+ </option>
+ </param>
+ <param>
+ <name>Run</name>
+ <key>run</key>
+ <value>True</value>
+ <type>bool</type>
+ <hide>
+#if $generate_options() in ('qt_gui', 'wx_gui')
+ #if $run()
+ part
+ #else
+ none
+ #end if
+#else
+ all
+#end if
+ </hide>
+ <option>
+ <name>Autostart</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Off</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Max Number of Output</name>
+ <key>max_nouts</key>
+ <value>0</value>
+ <type>int</type>
+ <hide>#if $generate_options() == 'hb'
+all#slurp
+#elif $max_nouts()
+none#slurp
+#else
+part#slurp
+#end if</hide>
+ </param>
+ <param>
+ <name>Realtime Scheduling</name>
+ <key>realtime_scheduling</key>
+ <value></value>
+ <type>enum</type>
+ <hide>#if $generate_options() == 'hb'
+all#slurp
+#elif $realtime_scheduling()
+none#slurp
+#else
+part#slurp
+#end if</hide>
+ <option>
+ <name>Off</name>
+ <key></key>
+ </option>
+ <option>
+ <name>On</name>
+ <key>1</key>
+ </option>
+ </param>
+ <check>len($window_size) == 2</check>
+ <check>300 &lt;= $(window_size)[0] &lt;= 4096</check>
+ <check>300 &lt;= $(window_size)[1] &lt;= 4096</check>
+ <doc>
+The options block sets special parameters for the flow graph. \
+Only one option block is allowed per flow graph.
+
+Title, author, and description parameters are for identification purposes.
+
+The window size controls the dimensions of the flow graph editor. \
+The window size (width, height) must be between (300, 300) and (4096, 4096).
+
+The generate options controls the type of code generated. \
+Non-graphical flow graphs should avoid using graphical sinks or graphical variable controls.
+
+In a graphical application, \
+run can be controlled by a variable to start and stop the flowgraph at runtime.
+
+The id of this block determines the name of the generated file and the name of the class. \
+For example, an id of my_block will generate the file my_block.py and class my_block(gr....
+
+The category parameter determines the placement of the block in the block selection window. \
+The category only applies when creating hier blocks. \
+To put hier blocks into the root category, enter / for the category.
+
+The Max Number of Output is the maximum number of output items allowed for any block \
+in the flowgraph; to disable this set the max_nouts equal to 0.\
+Use this to adjust the maximum latency a flowgraph can exhibit.
+ </doc>
+</block>
diff --git a/grc/blocks/pad_sink.xml b/grc/blocks/pad_sink.xml
new file mode 100644
index 000000000..f0e10a339
--- /dev/null
+++ b/grc/blocks/pad_sink.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Pad Sink: IO Pads
+###################################################
+ -->
+<block>
+ <name>Pad Sink</name>
+ <key>pad_sink</key>
+ <make>#if str($type) == "message"
+None;self.message_port_register_hier_in($label)
+#end if</make>
+ <param>
+ <name>Label</name>
+ <key>label</key>
+ <value>out</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ <option>
+ <name>Message</name>
+ <key>message</key>
+ <opt>size:0</opt>
+ </option>
+ <option>
+ <name>Wildcard</name>
+ <key></key>
+ <opt>size:0</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Optional</name>
+ <key>optional</key>
+ <value>False</value>
+ <type>bool</type>
+ <hide>part</hide>
+ <option>
+ <name>Optional</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Required</name>
+ <key>False</key>
+ </option>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <doc>
+The inputs of this block will become the outputs to this flow graph when it is instantiated as a hierarchical block.
+
+Pad sink will be ordered alphabetically by their ids. The first pad sink will have an index of 0.
+ </doc>
+</block>
diff --git a/grc/blocks/pad_source.xml b/grc/blocks/pad_source.xml
new file mode 100644
index 000000000..a56a65dcc
--- /dev/null
+++ b/grc/blocks/pad_source.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Pad Source: IO Pads
+###################################################
+ -->
+<block>
+ <name>Pad Source</name>
+ <key>pad_source</key>
+ <make>#if str($type) == "message"
+None;self.message_port_register_hier_out($label)
+#end if</make>
+ <param>
+ <name>Label</name>
+ <key>label</key>
+ <value>in</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ <option>
+ <name>Message</name>
+ <key>message</key>
+ <opt>size:0</opt>
+ </option>
+ <option>
+ <name>Wildcard</name>
+ <key></key>
+ <opt>size:0</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Optional</name>
+ <key>optional</key>
+ <value>False</value>
+ <type>bool</type>
+ <hide>part</hide>
+ <option>
+ <name>Optional</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Required</name>
+ <key>False</key>
+ </option>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+ <doc>
+The outputs of this block will become the inputs to this flow graph when it is instantiated as a hierarchical block.
+
+Pad sources will be ordered alphabetically by their ids. The first pad source will have an index of 0.
+ </doc>
+</block>
diff --git a/grc/blocks/parameter.xml b/grc/blocks/parameter.xml
new file mode 100644
index 000000000..e35b8f4d1
--- /dev/null
+++ b/grc/blocks/parameter.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Parameter block: a grc variable with key, value
+###################################################
+ -->
+<block>
+ <name>Parameter</name>
+ <key>parameter</key>
+ <var_make>self.$(id) = $(id)</var_make>
+ <make>$value</make>
+ <param>
+ <name>Label</name>
+ <key>label</key>
+ <value></value>
+ <type>string</type>
+ <hide>#if $label() then 'none' else 'part'#</hide>
+ </param>
+ <param>
+ <name>Value</name>
+ <key>value</key>
+ <value>0</value>
+ <type>$type.type</type>
+ </param>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <value></value>
+ <type>enum</type>
+ <hide>#if $type() then 'none' else 'part'#</hide>
+ <option>
+ <name>None</name>
+ <key></key>
+ <opt>type:raw</opt>
+ </option>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>type:complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>eng_float</key>
+ <opt>type:real</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>intx</key>
+ <opt>type:int</opt>
+ </option>
+ <option>
+ <name>Long</name>
+ <key>long</key>
+ <opt>type:int</opt>
+ </option>
+ <option>
+ <name>String</name>
+ <key>string</key>
+ <opt>type:string</opt>
+ </option>
+ <!-- not supported yet in tmpl
+ <option>
+ <name>Boolean</name>
+ <key>bool</key>
+ <opt>type:bool</opt>
+ </option>
+ -->
+ </param>
+ <param>
+ <name>Short ID</name>
+ <key>short_id</key>
+ <value></value>
+ <type>string</type>
+ <hide>#if not $type()
+all#slurp
+#elif $short_id()
+none#slurp
+#else
+part#slurp
+#end if</hide>
+ </param>
+ <check>len($short_id) in (0, 1)</check>
+ <check>$short_id == '' or $(short_id).isalpha()</check>
+ <doc>
+This block represents a parameter to the flow graph. \
+A parameter can be used to pass command line arguments into a top block. \
+Or, parameters can pass arguments into an instantiated hierarchical block.
+
+The paramater value cannot depend on any variables.
+
+Leave the label blank to use the parameter id as the label.
+
+When type is not None, this parameter also becomes a command line option of the form:
+
+-[short_id] --[id] [value]
+
+The Short ID field may be left blank.
+ </doc>
+</block>
diff --git a/grc/blocks/random_source_x.xml b/grc/blocks/random_source_x.xml
new file mode 100644
index 000000000..800bae716
--- /dev/null
+++ b/grc/blocks/random_source_x.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Random Source:
+## Custom block
+###################################################
+ -->
+<block>
+ <name>Random Source</name>
+ <key>random_source_x</key>
+ <import>from gnuradio import gr</import>
+ <import>import numpy</import>
+ <make>gr.vector_source_$(type.fcn)(map(int, numpy.random.randint($min, $max, $num_samps)), $repeat)</make>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>fcn:i</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>fcn:s</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>fcn:b</opt>
+ </option>
+ </param>
+ <param>
+ <name>Minimum</name>
+ <key>min</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Maximum</name>
+ <key>max</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Num Samples</name>
+ <key>num_samps</key>
+ <value>1000</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Repeat</name>
+ <key>repeat</key>
+ <value>True</value>
+ <type>enum</type>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ </param>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+ <doc>
+Generate num samples of random numbers of [min, max). Repeat samples if specified.
+
+Ex: With min=0 and max=2, the sequence 01110101... will be generated.
+ </doc>
+</block>
diff --git a/grc/blocks/root_raised_cosine_filter.xml b/grc/blocks/root_raised_cosine_filter.xml
new file mode 100644
index 000000000..81688d297
--- /dev/null
+++ b/grc/blocks/root_raised_cosine_filter.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Root Raised Cosine Filter: Custom wrapper
+###################################################
+ -->
+<block>
+ <name>Root Raised Cosine Filter</name>
+ <key>root_raised_cosine_filter</key>
+ <import>from gnuradio import gr</import>
+ <import>from gnuradio.gr import firdes</import>
+ <make>gr.$(type)(#if str($type).startswith('interp') then $interp else $decim#, firdes.root_raised_cosine(
+ $gain, $samp_rate, $sym_rate, $alpha, $ntaps))</make>
+ <callback>set_taps(firdes.root_raised_cosine($gain, $samp_rate, $sym_rate, $alpha, $ntaps))</callback>
+ <param>
+ <name>FIR Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Decimating)</name>
+ <key>fir_filter_ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ </option>
+ <option>
+ <name>Complex->Complex (Interpolating)</name>
+ <key>interp_fir_filter_ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ </option>
+ <option>
+ <name>Float->Float (Decimating)</name>
+ <key>fir_filter_fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ </option>
+ <option>
+ <name>Float->Float (Interpolating)</name>
+ <key>interp_fir_filter_fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ </option>
+ </param>
+ <param>
+ <name>Decimation</name>
+ <key>decim</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>#if str($type).startswith('interp') then 'all' else 'none'#</hide>
+ </param>
+ <param>
+ <name>Interpolation</name>
+ <key>interp</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>#if str($type).startswith('interp') then 'none' else 'all'#</hide>
+ </param>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <value>1</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Sample Rate</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Symbol Rate</name>
+ <key>sym_rate</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Alpha</name>
+ <key>alpha</key>
+ <value>0.35</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Num Taps</name>
+ <key>ntaps</key>
+ <value>11*samp_rate</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type.input</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type.output</type>
+ </source>
+ <doc>
+This filter is a convenience wrapper for an fir filter and a firdes taps generating function.
+
+Sample rate in Hertz.
+ </doc>
+</block>
diff --git a/grc/blocks/variable.xml b/grc/blocks/variable.xml
new file mode 100644
index 000000000..afee0f5d4
--- /dev/null
+++ b/grc/blocks/variable.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Variable block: a grc variable with key, value
+###################################################
+ -->
+<block>
+ <name>Variable</name>
+ <key>variable</key>
+ <var_make>self.$(id) = $(id) = $value</var_make>
+ <make></make>
+ <callback>self.set_$(id)($value)</callback>
+ <param>
+ <name>Value</name>
+ <key>value</key>
+ <value>0</value>
+ <type>raw</type>
+ </param>
+ <doc>
+This block maps a value to a unique variable. \
+This variable block has no graphical representation.
+ </doc>
+</block>
diff --git a/grc/blocks/variable_config.xml b/grc/blocks/variable_config.xml
new file mode 100644
index 000000000..11bff9edc
--- /dev/null
+++ b/grc/blocks/variable_config.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Variable Config block:
+## a variable that reads and writes to a config file
+###################################################
+ -->
+<block>
+ <name>Variable Config</name>
+ <key>variable_config</key>
+ <import>import ConfigParser</import>
+ <var_make>self._$(id)_config = ConfigParser.ConfigParser()
+self._$(id)_config.read($config_file)
+try: $(id) = self._$(id)_config.$(type.get)($section, $option)
+except: $(id) = $value
+self.$(id) = $(id)</var_make>
+ <make></make>
+ <callback>self.set_$(id)($value)</callback>
+ <callback>self._$(id)_config = ConfigParser.ConfigParser()
+self._$(id)_config.read($config_file)
+if not self._$(id)_config.has_section($section):
+ self._$(id)_config.add_section($section)
+self._$(id)_config.set($section, $option, str($writeback))
+self._$(id)_config.write(open($config_file, 'w'))</callback>
+ <param>
+ <name>Default Value</name>
+ <key>value</key>
+ <value>0</value>
+ <type>$type</type>
+ </param>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <value>real</value>
+ <type>enum</type>
+ <option>
+ <name>Float</name>
+ <key>real</key>
+ <opt>get:getfloat</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>get:getint</opt>
+ </option>
+ <option>
+ <name>Bool</name>
+ <key>bool</key>
+ <opt>get:getboolean</opt>
+ </option>
+ <option>
+ <name>String</name>
+ <key>string</key>
+ <opt>get:get</opt>
+ </option>
+ </param>
+ <param>
+ <name>Config File</name>
+ <key>config_file</key>
+ <value>default</value>
+ <type>file_open</type>
+ </param>
+ <param>
+ <name>Section</name>
+ <key>section</key>
+ <value>main</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Option</name>
+ <key>option</key>
+ <value>key</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>WriteBack</name>
+ <key>writeback</key>
+ <value>None</value>
+ <type>raw</type>
+ </param>
+ <doc>
+This block represents a variable that can be read from a config file.
+
+To save the value back into the config file: \
+enter the name of another variable into the writeback param. \
+When the other variable is changed at runtime, the config file will be re-written.
+ </doc>
+</block>
diff --git a/grc/blocks/variable_function_probe.xml b/grc/blocks/variable_function_probe.xml
new file mode 100644
index 000000000..269966c70
--- /dev/null
+++ b/grc/blocks/variable_function_probe.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Variable function probe
+###################################################
+ -->
+<block>
+ <name>Function Probe</name>
+ <key>variable_function_probe</key>
+ <import>import time</import>
+ <import>import threading</import>
+ <var_make>self.$(id) = $(id) = $value</var_make>
+ <make>#slurp
+def _$(id)_probe():
+ while True:
+ val = self.$(block_id()).$(function_name())($(function_args()))
+ try: self.set_$(id)(val)
+ except AttributeError, e: pass
+ time.sleep(1.0/($poll_rate))
+_$(id)_thread = threading.Thread(target=_$(id)_probe)
+_$(id)_thread.daemon = True
+_$(id)_thread.start()</make>
+ <callback>self.set_$(id)($value)</callback>
+ <param>
+ <name>Value</name>
+ <key>value</key>
+ <value>0</value>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Block ID</name>
+ <key>block_id</key>
+ <value>my_block_0</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Function Name</name>
+ <key>function_name</key>
+ <value>get_number</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Function Args</name>
+ <key>function_args</key>
+ <value></value>
+ <type>string</type>
+ <hide>#if $function_args() then 'none' else 'part'#</hide>
+ </param>
+ <param>
+ <name>Poll Rate (Hz)</name>
+ <key>poll_rate</key>
+ <value>10</value>
+ <type>real</type>
+ </param>
+ <doc>
+Periodically probe a function and set its value to this variable.
+
+Set the values for block ID, function name, and function args appropriately: \
+Block ID should be the ID of another block in this flow graph. \
+Function name should be the name of a class method on that block. \
+Function args are the parameters passed into that function. \
+For a function with no arguments, leave function args blank. \
+When passing a string for the function arguments, quote the string literal: '"arg"'.
+
+The values will used literally, and generated into the following form:
+self.block_id.function_name(function_args)
+
+To poll a stream for a level, use this with the probe signal block.
+ </doc>
+</block>
diff --git a/grc/blocks/virtual_sink.xml b/grc/blocks/virtual_sink.xml
new file mode 100644
index 000000000..35fb27e67
--- /dev/null
+++ b/grc/blocks/virtual_sink.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Virtual Sink
+###################################################
+ -->
+<block>
+ <name>Virtual Sink</name>
+ <key>virtual_sink</key>
+ <make></make>
+ <param>
+ <name>Stream ID</name>
+ <key>stream_id</key>
+ <value></value>
+ <type>stream_id</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type></type>
+ </sink>
+</block>
diff --git a/grc/blocks/virtual_source.xml b/grc/blocks/virtual_source.xml
new file mode 100644
index 000000000..e0c775449
--- /dev/null
+++ b/grc/blocks/virtual_source.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Virtual Source
+###################################################
+ -->
+<block>
+ <name>Virtual Source</name>
+ <key>virtual_source</key>
+ <make></make>
+ <param>
+ <name>Stream ID</name>
+ <key>stream_id</key>
+ <value></value>
+ <type>stream_id</type>
+ </param>
+ <source>
+ <name>out</name>
+ <type></type>
+ </source>
+</block>
diff --git a/grc/blocks/xmlrpc_client.xml b/grc/blocks/xmlrpc_client.xml
new file mode 100644
index 000000000..dc4d154d1
--- /dev/null
+++ b/grc/blocks/xmlrpc_client.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Simple XMLRPC Client
+###################################################
+ -->
+<block>
+ <name>XMLRPC Client</name>
+ <key>xmlrpc_client</key>
+ <import>import xmlrpclib</import>
+ <make>xmlrpclib.Server('http://$(addr()):$(port)')</make>
+ <callback>$(callback())($variable)</callback>
+ <param>
+ <name>Address</name>
+ <key>addr</key>
+ <value>localhost</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Port</name>
+ <key>port</key>
+ <value>8080</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Callback</name>
+ <key>callback</key>
+ <value>set_</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Variable</name>
+ <key>variable</key>
+ <type>raw</type>
+ </param>
+ <doc>
+This block will create an XMLRPC client. \
+The client will execute the callback on the server when the variable is changed. \
+The callback should be a the name of a function registered on the server. \
+The variable should be an expression containing a the name of a variable in flow graph.
+ </doc>
+</block>
diff --git a/grc/blocks/xmlrpc_server.xml b/grc/blocks/xmlrpc_server.xml
new file mode 100644
index 000000000..6c31bd1a9
--- /dev/null
+++ b/grc/blocks/xmlrpc_server.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Simple XMLRPC Server
+###################################################
+ -->
+<block>
+ <name>XMLRPC Server</name>
+ <key>xmlrpc_server</key>
+ <import>import SimpleXMLRPCServer</import>
+ <import>import threading</import>
+ <make>SimpleXMLRPCServer.SimpleXMLRPCServer(($addr, $port), allow_none=True)
+self.$(id).register_instance(self)
+threading.Thread(target=self.$(id).serve_forever).start()</make>
+ <param>
+ <name>Address</name>
+ <key>addr</key>
+ <value>localhost</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Port</name>
+ <key>port</key>
+ <value>8080</value>
+ <type>int</type>
+ </param>
+ <doc>
+This block will start an XMLRPC server. \
+The server provides access to the run, start, stop, wait functions of the flow graph. \
+The server also provides access to the variable callbacks in the flow graph. \
+Ex: If the variable is called freq, the function provided by the server will be called set_freq(new_freq).
+
+Example client in python:
+
+import xmlrpclib
+s = xmlrpclib.Server('http://localhost:8080')
+s.set_freq(5000)
+ </doc>
+</block>
diff --git a/grc/cpp/README b/grc/cpp/README
new file mode 100644
index 000000000..3eccc5dbf
--- /dev/null
+++ b/grc/cpp/README
@@ -0,0 +1,5 @@
+GRC could be used to generate c++ based flowgraphs:
+
+* A few base and gui classes would be overridden.
+* Block info could be extracted from the doxygen xml.
+* New flowgraph templates would be designed.
diff --git a/grc/examples/CMakeLists.txt b/grc/examples/CMakeLists.txt
new file mode 100644
index 000000000..a218dbe50
--- /dev/null
+++ b/grc/examples/CMakeLists.txt
@@ -0,0 +1,37 @@
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+# SIMPLE
+install(
+ FILES
+ simple/variable_config.grc
+ DESTINATION ${GR_PKG_DATA_DIR}/examples/grc/simple
+ COMPONENT "grc"
+)
+
+# XMLRPC
+install(
+ FILES
+ xmlrpc/readme.txt
+ xmlrpc/xmlrpc_client.grc
+ xmlrpc/xmlrpc_client_script.py
+ xmlrpc/xmlrpc_server.grc
+ DESTINATION ${GR_PKG_DATA_DIR}/examples/grc/xmlrpc
+ COMPONENT "grc"
+)
diff --git a/grc/examples/simple/variable_config.grc b/grc/examples/simple/variable_config.grc
new file mode 100644
index 000000000..95c287cce
--- /dev/null
+++ b/grc/examples/simple/variable_config.grc
@@ -0,0 +1,329 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Thu Jun 25 10:56:04 2009</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>variable_config_demo</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>Variable Config Block Demonstration</value>
+ </param>
+ <param>
+ <key>author</key>
+ <value>Example</value>
+ </param>
+ <param>
+ <key>description</key>
+ <value>Save/Load freq from a config file.</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>autostart</key>
+ <value>True</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>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>32000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 170)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_config</key>
+ <param>
+ <key>id</key>
+ <value>freq_init</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>1000</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>real</value>
+ </param>
+ <param>
+ <key>config_file</key>
+ <value>config.conf</value>
+ </param>
+ <param>
+ <key>section</key>
+ <value>main</value>
+ </param>
+ <param>
+ <key>option</key>
+ <value>freq</value>
+ </param>
+ <param>
+ <key>writeback</key>
+ <value>freq</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(255, 17)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_slider</key>
+ <param>
+ <key>id</key>
+ <value>freq</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Frequency (Hz)</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>freq_init</value>
+ </param>
+ <param>
+ <key>min</key>
+ <value>-samp_rate/2</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>samp_rate/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>_coordinate</key>
+ <value>(429, 24)</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>complex</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>(392, 233)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_sig_source_x</key>
+ <param>
+ <key>id</key>
+ <value>gr_sig_source_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>waveform</key>
+ <value>gr.GR_COS_WAVE</value>
+ </param>
+ <param>
+ <key>freq</key>
+ <value>freq</value>
+ </param>
+ <param>
+ <key>amp</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>offset</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(148, 233)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_fftsink2</key>
+ <param>
+ <key>id</key>
+ <value>wxgui_fftsink2_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>FFT Plot</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>baseband_freq</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>y_per_div</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>y_divs</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ref_level</key>
+ <value>50</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>fft_rate</key>
+ <value>30</value>
+ </param>
+ <param>
+ <key>peak_hold</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>average</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>avg_alpha</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(671, 233)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>gr_sig_source_x_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>wxgui_fftsink2_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/grc/examples/xmlrpc/readme.txt b/grc/examples/xmlrpc/readme.txt
new file mode 100644
index 000000000..056ad1e82
--- /dev/null
+++ b/grc/examples/xmlrpc/readme.txt
@@ -0,0 +1,18 @@
+##################################################
+# XMLRPC example
+##################################################
+
+XMLRPC allows software to make remote function calls over http.
+In the case of GRC, one can use XMLRPC to modify variables in a running flow graph.
+See http://www.xmlrpc.com/
+
+--- Server Example ---
+Place an "XMLRPC Server" block inside of any flow graph.
+The server will provide set functions for every variable in the flow graph.
+If a variable is called "freq", the server will provide a function set_freq(new_freq).
+Run the server example and experiment with the example client script.
+
+-- Client Example --
+The "XMLRPC Client" block will give a variable control over one remove function.
+In the example client, there is one client block and gui control per variable.
+This technique can be used to remotely control a flow graph, perhaps running on a non-gui machine.
diff --git a/grc/examples/xmlrpc/xmlrpc_client.grc b/grc/examples/xmlrpc/xmlrpc_client.grc
new file mode 100644
index 000000000..3bb4e7ed3
--- /dev/null
+++ b/grc/examples/xmlrpc/xmlrpc_client.grc
@@ -0,0 +1,312 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Thu Jul 24 14:27:44 2008</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>client_block</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>XMLRPC Client</value>
+ </param>
+ <param>
+ <key>author</key>
+ <value>Example</value>
+ </param>
+ <param>
+ <key>description</key>
+ <value>example flow graph</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>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>xmlrpc_client</key>
+ <param>
+ <key>id</key>
+ <value>xmlrpc_client0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>addr</key>
+ <value>localhost</value>
+ </param>
+ <param>
+ <key>port</key>
+ <value>1234</value>
+ </param>
+ <param>
+ <key>callback</key>
+ <value>set_ampl</value>
+ </param>
+ <param>
+ <key>variable</key>
+ <value>ampl</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(409, 35)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>xmlrpc_client</key>
+ <param>
+ <key>id</key>
+ <value>xmlrpc_client</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>addr</key>
+ <value>localhost</value>
+ </param>
+ <param>
+ <key>port</key>
+ <value>1234</value>
+ </param>
+ <param>
+ <key>callback</key>
+ <value>set_freq</value>
+ </param>
+ <param>
+ <key>variable</key>
+ <value>freq</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(222, 34)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_slider</key>
+ <param>
+ <key>id</key>
+ <value>freq</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Frequency (Hz)</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>1000</value>
+ </param>
+ <param>
+ <key>min</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>5000</value>
+ </param>
+ <param>
+ <key>num_steps</key>
+ <value>100</value>
+ </param>
+ <param>
+ <key>slider_type</key>
+ <value>horizontal</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value>0, 0, 1, 2</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(207, 162)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_slider</key>
+ <param>
+ <key>id</key>
+ <value>ampl</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Amplitude</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>1</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>slider_type</key>
+ <value>horizontal</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value>1, 0, 1, 2</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(397, 167)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_chooser</key>
+ <param>
+ <key>id</key>
+ <value>offset</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Offset</value>
+ </param>
+ <param>
+ <key>value_index</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>choices</key>
+ <value>[-1, 0, 1]</value>
+ </param>
+ <param>
+ <key>labels</key>
+ <value>["neg", "zero", "pos"]</value>
+ </param>
+ <param>
+ <key>chooser_type</key>
+ <value>radio_buttons_horizontal</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value>2, 0, 1, 2</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(596, 177)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>xmlrpc_client</key>
+ <param>
+ <key>id</key>
+ <value>xmlrpc_client1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>addr</key>
+ <value>localhost</value>
+ </param>
+ <param>
+ <key>port</key>
+ <value>1234</value>
+ </param>
+ <param>
+ <key>callback</key>
+ <value>set_offset</value>
+ </param>
+ <param>
+ <key>variable</key>
+ <value>offset*ampl</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(608, 39)</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>32000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(13, 172)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+</flow_graph> \ No newline at end of file
diff --git a/grc/examples/xmlrpc/xmlrpc_client_script.py b/grc/examples/xmlrpc/xmlrpc_client_script.py
new file mode 100644
index 000000000..8f00fa55d
--- /dev/null
+++ b/grc/examples/xmlrpc/xmlrpc_client_script.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+import time
+import random
+import xmlrpclib
+
+#create server object
+s = xmlrpclib.Server("http://localhost:1234")
+
+#randomly change parameters of the sinusoid
+for i in range(10):
+ #generate random values
+ new_freq = random.uniform(0, 5000)
+ new_ampl = random.uniform(0, 2)
+ new_offset = random.uniform(-1, 1)
+ #set new values
+ time.sleep(1)
+ s.set_freq(new_freq)
+ time.sleep(1)
+ s.set_ampl(new_ampl)
+ time.sleep(1)
+ s.set_offset(new_offset)
+
diff --git a/grc/examples/xmlrpc/xmlrpc_server.grc b/grc/examples/xmlrpc/xmlrpc_server.grc
new file mode 100644
index 000000000..dc539ef1b
--- /dev/null
+++ b/grc/examples/xmlrpc/xmlrpc_server.grc
@@ -0,0 +1,384 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Thu Jul 24 14:27:42 2008</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>server_block</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>XMLRPC Server</value>
+ </param>
+ <param>
+ <key>author</key>
+ <value>Example</value>
+ </param>
+ <param>
+ <key>description</key>
+ <value>example flow graph</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>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_sig_source_x</key>
+ <param>
+ <key>id</key>
+ <value>gr_sig_source_x</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>waveform</key>
+ <value>gr.GR_COS_WAVE</value>
+ </param>
+ <param>
+ <key>freq</key>
+ <value>freq</value>
+ </param>
+ <param>
+ <key>amp</key>
+ <value>ampl</value>
+ </param>
+ <param>
+ <key>offset</key>
+ <value>offset</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(162, 200)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>offset</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(12, 390)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>xmlrpc_server</key>
+ <param>
+ <key>id</key>
+ <value>xmlrpc_server</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>addr</key>
+ <value>localhost</value>
+ </param>
+ <param>
+ <key>port</key>
+ <value>1234</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(395, 240)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_throttle</key>
+ <param>
+ <key>id</key>
+ <value>gr_throttle</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</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>(386, 93)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_scopesink2</key>
+ <param>
+ <key>id</key>
+ <value>wxgui_scopesink2</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>Scope Plot</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>frame_decim</key>
+ <value>15</value>
+ </param>
+ <param>
+ <key>v_scale</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>t_scale</key>
+ <value>.001</value>
+ </param>
+ <param>
+ <key>marker</key>
+ <value>set_format_line</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value>0, 0, 2, 4</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(623, 28)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_fftsink2</key>
+ <param>
+ <key>id</key>
+ <value>wxgui_fftsink2</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>FFT Plot</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>baseband_freq</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>y_per_div</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>y_divs</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>ref_level</key>
+ <value>50</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>512</value>
+ </param>
+ <param>
+ <key>fft_rate</key>
+ <value>15</value>
+ </param>
+ <param>
+ <key>avg_alpha</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>average</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>peak_hold</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value>2, 0, 2, 4</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(630, 233)</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>32000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(11, 160)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>freq</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>1000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(11, 237)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>ampl</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(13, 315)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>gr_sig_source_x</source_block_id>
+ <sink_block_id>gr_throttle</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_throttle</source_block_id>
+ <sink_block_id>wxgui_scopesink2</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>gr_throttle</source_block_id>
+ <sink_block_id>wxgui_fftsink2</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph> \ No newline at end of file
diff --git a/grc/freedesktop/CMakeLists.txt b/grc/freedesktop/CMakeLists.txt
new file mode 100644
index 000000000..d95fe04ac
--- /dev/null
+++ b/grc/freedesktop/CMakeLists.txt
@@ -0,0 +1,47 @@
+# Copyright 2011-2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+set(grc_freedesktop_path ${GR_PKG_DATA_DIR}/grc/freedesktop)
+
+install(FILES
+ grc-icon-256.png
+ grc-icon-128.png
+ grc-icon-64.png
+ grc-icon-48.png
+ grc-icon-32.png
+ gnuradio-grc.xml
+ gnuradio-grc.desktop
+ DESTINATION ${grc_freedesktop_path}
+ COMPONENT "grc"
+)
+
+find_program(HAVE_XDG_UTILS xdg-desktop-menu)
+
+if(UNIX AND HAVE_XDG_UTILS)
+ set(SRCDIR ${CMAKE_INSTALL_PREFIX}/${grc_freedesktop_path})
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/grc_setup_freedesktop.in
+ ${CMAKE_CURRENT_BINARY_DIR}/grc_setup_freedesktop
+ @ONLY)
+ install(
+ PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/grc_setup_freedesktop
+ DESTINATION ${GR_PKG_LIBEXEC_DIR} COMPONENT "grc"
+ )
+endif(UNIX AND HAVE_XDG_UTILS)
diff --git a/grc/freedesktop/README b/grc/freedesktop/README
new file mode 100644
index 000000000..0857ecc22
--- /dev/null
+++ b/grc/freedesktop/README
@@ -0,0 +1,20 @@
+##################################################
+# Freedesktop Notes
+##################################################
+
+This directory contains icons, a mime type, and menu files for grc.
+Installation of these files requires a set of tools called xdg-utils.
+xdg-utils will install files in a standard way according to the freedesktop.org standards.
+
+Desktop enviroments that implement these standards are gnome, kde, xfce, and others.
+If you have one of these desktop enviroments, xdg-utils should come installed.
+If xdg-utils is not installed, then this directory will be ignored by the build.
+
+The gtk IconTheme module locates the installed icons for use inside the grc app.
+On recent versions of gtk, IconTheme ignores the icons installed into the default theme.
+This presents a problem for the gnome file system browser, nautilus, and the grc app.
+As a solution, icons are also installed under the gnome theme.
+
+*.png files - these are the icons of various sizes
+*.desktop files - these are the menu items for grc executables
+*.xml file - this is the mime type for the saved flow graphs
diff --git a/grc/freedesktop/gnuradio-grc.desktop b/grc/freedesktop/gnuradio-grc.desktop
new file mode 100644
index 000000000..5fd049780
--- /dev/null
+++ b/grc/freedesktop/gnuradio-grc.desktop
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=GRC
+Exec=gnuradio-companion %F
+Categories=Development;
+MimeType=application/gnuradio-grc;
+Icon=gnuradio-grc
diff --git a/grc/freedesktop/gnuradio-grc.xml b/grc/freedesktop/gnuradio-grc.xml
new file mode 100644
index 000000000..a5cb95d9f
--- /dev/null
+++ b/grc/freedesktop/gnuradio-grc.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
+ <mime-type type="application/gnuradio-grc">
+ <sub-class-of type="application/xml"/>
+ <glob pattern="*.grc"/>
+ <glob pattern="*.grc.xml"/>
+ </mime-type>
+</mime-info>
diff --git a/grc/freedesktop/grc-icon-128.png b/grc/freedesktop/grc-icon-128.png
new file mode 100644
index 000000000..d94ef35dc
--- /dev/null
+++ b/grc/freedesktop/grc-icon-128.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-256.png b/grc/freedesktop/grc-icon-256.png
new file mode 100644
index 000000000..e4e8e54ae
--- /dev/null
+++ b/grc/freedesktop/grc-icon-256.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-256.svg b/grc/freedesktop/grc-icon-256.svg
new file mode 100644
index 000000000..87526d46c
--- /dev/null
+++ b/grc/freedesktop/grc-icon-256.svg
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="256"
+ height="256"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ version="1.0"
+ sodipodi:docbase="/home/past/src"
+ sodipodi:docname="grc-icon-v3.svg"
+ inkscape:export-filename="/home/past/src/grc-icon-v3.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient3661">
+ <stop
+ style="stop-color:#0012dc;stop-opacity:1;"
+ offset="0"
+ id="stop3663" />
+ <stop
+ style="stop-color:#8b92ff;stop-opacity:0.55371898;"
+ offset="1"
+ id="stop3665" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3661"
+ id="linearGradient2801"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-162.6648,798.0997)"
+ x1="17.664845"
+ y1="132.0565"
+ x2="157.82524"
+ y2="132.0565" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.7382812"
+ inkscape:cx="126.48791"
+ inkscape:cy="128.00013"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ gridoriginx="1px"
+ gridoriginy="1px"
+ gridspacingx="2px"
+ gridspacingy="2px"
+ guidecolor="#00ff0a"
+ guideopacity="0.49803922"
+ inkscape:grid-points="true"
+ inkscape:window-width="1098"
+ inkscape:window-height="904"
+ inkscape:window-x="149"
+ inkscape:window-y="42"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:object-points="true"
+ inkscape:object-nodes="true"
+ inkscape:object-bbox="true">
+ <sodipodi:guide
+ orientation="vertical"
+ position="224"
+ id="guide10639" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="227.64729"
+ id="guide10641" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="220"
+ id="guide10643" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="268.4015"
+ id="guide10645" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" />
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Patrick Strasser &lt;patrick.strasser@tugraz.at&gt;</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:description>Icon/Symbol for the GNURadio Companion</dc:description>
+ <dc:title>grc-icon.svg</dc:title>
+ <dc:date>2007-02-23</dc:date>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/by-sa/2.5/">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Notice" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Attribution" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Ebene 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-796.3622)">
+ <g
+ id="g7451"
+ transform="matrix(1.025628,0,0,1.030546,-0.101723,-32.00742)">
+ <path
+ id="rect2760"
+ d="M 4.1981031,916.37787 L 160.00074,916.37787 L 160.00074,1048.3467 L 4.1981031,1048.3467 L 4.1981031,916.37787 z "
+ style="fill:white;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:7.78145933;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <g
+ transform="matrix(0.995753,0,0,1.003897,164.8198,-8.972397)"
+ id="g2789"
+ style="stroke-width:8;stroke-miterlimit:4;stroke-dasharray:none">
+ <rect
+ style="fill:url(#linearGradient2801);fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:7.78288651;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect9020"
+ width="140.1604"
+ height="16.796082"
+ x="-145"
+ y="921.75818" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:7.78288651;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M -161.50649,938.55428 L -4.8395996,938.55428"
+ id="path9005" />
+ </g>
+ </g>
+ <g
+ id="g5503"
+ transform="matrix(1.028571,0,0,1.172413,-5.14284,-137.9928)">
+ <rect
+ y="800.36212"
+ x="40"
+ height="116.00005"
+ width="140"
+ id="rect4562"
+ style="fill:#f3c690;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:7.28504848;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <g
+ transform="matrix(0.921053,0,0,1,26.93956,1.859948)"
+ id="g3694">
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:7.59084845;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 44,820.3622 L 136.35974,820.3622"
+ id="path4564" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:7.59084749;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 80,811.74976 L 80,828.3622"
+ id="path5451" />
+ </g>
+ <g
+ id="g5499">
+ <rect
+ style="fill:white;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:7.28504944;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect7223"
+ width="140"
+ height="68.000015"
+ x="40"
+ y="848.36218" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:7.28505039;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 57.001362,905.90132 C 88.923615,905.8552 86.182775,867.89142 95.399136,867.52563 C 104.60967,867.16008 113.73233,867.60291 124.38688,868.00066 C 137.23411,868.48027 130.39915,906.48027 162.99863,906.48027"
+ id="path7225"
+ sodipodi:nodetypes="czss" />
+ </g>
+ </g>
+ <rect
+ style="fill:#b890f3;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:7.99999952;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect14319"
+ width="79.999992"
+ height="64.000023"
+ x="27.999992"
+ y="960.36249" />
+ <rect
+ style="fill:#f3c690;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:7.99999905;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect15206"
+ width="24.000004"
+ height="24.000004"
+ x="108"
+ y="980.36218" />
+ <path
+ id="path13320"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:7.99999666;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 220.97574,800.36203 L 220.97574,865.80513 C 236.42474,865.93437 248.49884,861.19996 248.96304,854.45866 C 249.42721,847.71737 237.26568,843.20829 221.81667,846.27676 C 206.36767,849.34522 193.45938,858.02071 192.98843,867.61976 C 192.53101,876.94268 204.68583,884.63729 220.13479,885.43882 C 235.58379,885.69443 248.49884,880.72833 248.96304,873.98703 C 249.42721,867.24575 237.26567,862.73666 221.81666,865.80513 C 206.36766,868.8736 193.45939,877.54909 192.98843,887.14813 C 192.53101,896.47106 204.68582,904.16566 220.13479,904.86701 C 235.5838,905.02246 248.49885,900.05636 248.96305,893.31506 C 249.42722,886.57378 237.26568,882.06469 221.81667,885.13316 C 206.36767,888.20162 193.45939,896.87711 192.98844,906.47616 C 192.53102,915.79909 204.68583,923.49369 220.13479,923.98015 C 235.58379,923.92069 248.49884,918.95459 248.96304,912.21329 C 249.42721,905.47201 237.26567,900.96293 221.81666,904.0314 C 206.36766,907.09986 193.45939,915.77535 192.98843,925.37439 C 192.53101,934.69732 207.20989,943.06708 221.81667,943.00644 L 221.81667,967.97713 C 221.63716,982.45754 209.62079,992.36197 195.88792,992.36199 L 132.42659,992.36199"
+ sodipodi:nodetypes="cccssscssscssscssccc" />
+ </g>
+</svg>
diff --git a/grc/freedesktop/grc-icon-32.png b/grc/freedesktop/grc-icon-32.png
new file mode 100644
index 000000000..1e4f4f6c5
--- /dev/null
+++ b/grc/freedesktop/grc-icon-32.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-48.png b/grc/freedesktop/grc-icon-48.png
new file mode 100644
index 000000000..caddc92ad
--- /dev/null
+++ b/grc/freedesktop/grc-icon-48.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-64.png b/grc/freedesktop/grc-icon-64.png
new file mode 100644
index 000000000..fa8e06e28
--- /dev/null
+++ b/grc/freedesktop/grc-icon-64.png
Binary files differ
diff --git a/grc/freedesktop/grc_setup_freedesktop.in b/grc/freedesktop/grc_setup_freedesktop.in
new file mode 100644
index 000000000..1e3546197
--- /dev/null
+++ b/grc/freedesktop/grc_setup_freedesktop.in
@@ -0,0 +1,75 @@
+#!/bin/bash
+#
+# Copyright 2008-2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+##################################################
+# setup grc on a freedesktop platform
+# $1 should be install or uninstall
+# $2 is the optional path to the files
+# when $2 is unspecified, the path is:
+# @SRCDIR@
+##################################################
+
+ICON_SIZES="32 48 64 128 256"
+if [ -n "$2" ]; then
+ SRCDIR="$2"
+else
+ SRCDIR="@SRCDIR@"
+fi
+
+case "$1" in
+'install')
+ echo "Begin freedesktop install..."
+ for size in ${ICON_SIZES}; do \
+ echo "Install icon: ${size}x${size}"
+ xdg-icon-resource install --noupdate --context mimetypes --theme gnome --size ${size} ${SRCDIR}/grc-icon-${size}.png application-gnuradio-grc; \
+ xdg-icon-resource install --noupdate --context mimetypes --size ${size} ${SRCDIR}/grc-icon-${size}.png application-gnuradio-grc; \
+ xdg-icon-resource install --noupdate --context apps --theme gnome --size ${size} ${SRCDIR}/grc-icon-${size}.png gnuradio-grc; \
+ xdg-icon-resource install --noupdate --context apps --size ${size} ${SRCDIR}/grc-icon-${size}.png gnuradio-grc; \
+ done
+ xdg-icon-resource forceupdate
+ echo "Install mime type"
+ xdg-mime install ${SRCDIR}/gnuradio-grc.xml
+ echo "Install menu items"
+ xdg-desktop-menu install ${SRCDIR}/*.desktop
+ echo "Done!"
+ echo ""
+ ;;
+'uninstall')
+ echo "Begin freedesktop uninstall..."
+ for size in ${ICON_SIZES}; do \
+ echo "Uninstall icon: ${size}x${size}"
+ xdg-icon-resource uninstall --noupdate --context mimetypes --theme gnome --size ${size} application-gnuradio-grc; \
+ xdg-icon-resource uninstall --noupdate --context mimetypes --size ${size} application-gnuradio-grc; \
+ xdg-icon-resource uninstall --noupdate --context apps --theme gnome --size ${size} gnuradio-grc; \
+ xdg-icon-resource uninstall --noupdate --context apps --size ${size} gnuradio-grc; \
+ done
+ xdg-icon-resource forceupdate
+ echo "Uninstall mime type"
+ xdg-mime uninstall ${SRCDIR}/gnuradio-grc.xml
+ echo "Uninstall menu items"
+ xdg-desktop-menu uninstall `ls ${SRCDIR}/*.desktop | xargs -n1 basename`
+ echo "Done!"
+ echo ""
+ ;;
+*)
+ echo "Usage: $0 [install|uninstall]"
+ ;;
+esac
diff --git a/grc/grc.conf.in b/grc/grc.conf.in
new file mode 100644
index 000000000..ace604ace
--- /dev/null
+++ b/grc/grc.conf.in
@@ -0,0 +1,7 @@
+# This file contains system wide configuration data for GNU Radio.
+# You may override any setting on a per-user basis by editing
+# ~/.gnuradio/config.conf
+
+[grc]
+global_blocks_path = @blocksdir@
+local_blocks_path =
diff --git a/grc/grc_gnuradio/CMakeLists.txt b/grc/grc_gnuradio/CMakeLists.txt
new file mode 100644
index 000000000..e992a60a3
--- /dev/null
+++ b/grc/grc_gnuradio/CMakeLists.txt
@@ -0,0 +1,35 @@
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+GR_PYTHON_INSTALL(
+ FILES __init__.py
+ DESTINATION ${GR_PYTHON_DIR}/grc_gnuradio
+ COMPONENT "grc"
+)
+
+GR_PYTHON_INSTALL(FILES
+ blks2/__init__.py
+ blks2/error_rate.py
+ blks2/packet.py
+ blks2/selector.py
+ blks2/tcp.py
+ DESTINATION ${GR_PYTHON_DIR}/grc_gnuradio/blks2
+ COMPONENT "grc"
+)
diff --git a/grc/grc_gnuradio/README b/grc/grc_gnuradio/README
new file mode 100644
index 000000000..897eed65c
--- /dev/null
+++ b/grc/grc_gnuradio/README
@@ -0,0 +1,11 @@
+This is the grc_gnuradio module.
+It contains supplemental python modules that grc uses at runtime.
+The supplemental modules are meant to mimic modules in gnuradio.
+These will be phased-out as new functionaility is merged into gnuradio.
+
+The blk2s module wraps many blocks in blks2 and gives them streaming outputs.
+Will be phased-out by new message passing implementations.
+Other blks2 blocks will hopefully make their way into blks2impl.
+
+The wxgui module contains a top_block + wxgui frame.
+Will be phased-out by gui.py in wxgui and a new top block template.
diff --git a/grc/grc_gnuradio/__init__.py b/grc/grc_gnuradio/__init__.py
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/grc/grc_gnuradio/__init__.py
@@ -0,0 +1 @@
+
diff --git a/grc/grc_gnuradio/blks2/__init__.py b/grc/grc_gnuradio/blks2/__init__.py
new file mode 100644
index 000000000..fde76f256
--- /dev/null
+++ b/grc/grc_gnuradio/blks2/__init__.py
@@ -0,0 +1,26 @@
+# Copyright 2008-2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from selector import selector, valve
+from packet import options, packet_encoder, packet_decoder, \
+ packet_mod_b, packet_mod_s, packet_mod_i, packet_mod_f, packet_mod_c, \
+ packet_demod_b, packet_demod_s, packet_demod_i, packet_demod_f, packet_demod_c
+from error_rate import error_rate
+from tcp import tcp_source, tcp_sink
diff --git a/grc/grc_gnuradio/blks2/error_rate.py b/grc/grc_gnuradio/blks2/error_rate.py
new file mode 100644
index 000000000..9b2df58ef
--- /dev/null
+++ b/grc/grc_gnuradio/blks2/error_rate.py
@@ -0,0 +1,137 @@
+# Copyright 2008 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+default_win_size = 1000
+
+from gnuradio import gr
+import gnuradio.gr.gr_threading as _threading
+import numpy
+
+#generate 1s counts array
+_1s_counts = [sum([1&(i>>j) for j in range(8)]) for i in range(2**8)]
+
+class input_watcher(_threading.Thread):
+ """
+ Read samples from the message queue and hand them to the callback.
+ """
+
+ def __init__(self, msgq, callback):
+ self._msgq = msgq
+ self._callback = callback
+ _threading.Thread.__init__(self)
+ self.setDaemon(1)
+ self.keep_running = True
+ self.start()
+
+ def run(self):
+ r = ''
+ while True:
+ msg = self._msgq.delete_head()
+ itemsize = int(msg.arg1())
+ nitems = int(msg.arg2())
+ s = r + msg.to_string()
+ i = (nitems-nitems%2)*itemsize
+ r = s[i:]
+ s = s[:i]
+ samples = numpy.fromstring(s, numpy.int8)
+ self._callback(samples)
+
+class error_rate(gr.hier_block2):
+ """
+ Sample the incoming data streams (byte) and calculate the bit or symbol error rate.
+ Write the running rate to the output data stream (float).
+ """
+
+ def __init__(self, type='BER', win_size=default_win_size, bits_per_symbol=2):
+ """
+ Error rate constructor.
+ @param type a string 'BER' or 'SER'
+ @param win_size the number of samples to calculate over
+ @param bits_per_symbol the number of information bits per symbol (BER only)
+ """
+ #init
+ gr.hier_block2.__init__(
+ self, 'error_rate',
+ gr.io_signature(2, 2, gr.sizeof_char),
+ gr.io_signature(1, 1, gr.sizeof_float),
+ )
+ assert type in ('BER', 'SER')
+ self._max_samples = win_size
+ self._bits_per_symbol = bits_per_symbol
+ #setup message queue
+ msg_source = gr.message_source(gr.sizeof_float, 1)
+ self._msgq_source = msg_source.msgq()
+ msgq_sink = gr.msg_queue(2)
+ msg_sink = gr.message_sink(gr.sizeof_char, msgq_sink, False) #False -> blocking
+ inter = gr.interleave(gr.sizeof_char)
+ #start thread
+ self._num_errs = 0
+ self._err_index = 0
+ self._num_samps = 0
+ self._err_array = numpy.zeros(self._max_samples, numpy.int8)
+ if type == 'BER':
+ input_watcher(msgq_sink, self._handler_ber)
+ elif type == 'SER':
+ input_watcher(msgq_sink, self._handler_ser)
+ #connect
+ self.connect(msg_source, self)
+ self.connect((self, 0), (inter, 0))
+ self.connect((self, 1), (inter, 1))
+ self.connect(inter, msg_sink)
+
+ def _handler_ber(self, samples):
+ num = len(samples)/2
+ arr = numpy.zeros(num, numpy.float32)
+ for i in range(num):
+ old_err = self._err_array[self._err_index]
+ #record error
+ self._err_array[self._err_index] = _1s_counts[samples[i*2] ^ samples[i*2 + 1]]
+ self._num_errs = self._num_errs + self._err_array[self._err_index] - old_err
+ #increment index
+ self._err_index = (self._err_index + 1)%self._max_samples
+ self._num_samps = min(self._num_samps + 1, self._max_samples)
+ #write sample
+ arr[i] = float(self._num_errs)/float(self._num_samps*self._bits_per_symbol)
+ #write message
+ msg = gr.message_from_string(arr.tostring(), 0, gr.sizeof_float, num)
+ self._msgq_source.insert_tail(msg)
+
+ def _handler_ser(self, samples):
+ num = len(samples)/2
+ arr = numpy.zeros(num, numpy.float32)
+ for i in range(num):
+ old_err = self._err_array[self._err_index]
+ #record error
+ ref = samples[i*2]
+ res = samples[i*2 + 1]
+ if ref == res:
+ self._err_array[self._err_index] = 0
+ else:
+ self._err_array[self._err_index] = 1
+ #update number of errors
+ self._num_errs = self._num_errs + self._err_array[self._err_index] - old_err
+ #increment index
+ self._err_index = (self._err_index + 1)%self._max_samples
+ self._num_samps = min(self._num_samps + 1, self._max_samples)
+ #write sample
+ arr[i] = float(self._num_errs)/float(self._num_samps)
+ #write message
+ msg = gr.message_from_string(arr.tostring(), 0, gr.sizeof_float, num)
+ self._msgq_source.insert_tail(msg)
diff --git a/grc/grc_gnuradio/blks2/packet.py b/grc/grc_gnuradio/blks2/packet.py
new file mode 100644
index 000000000..e39f55c84
--- /dev/null
+++ b/grc/grc_gnuradio/blks2/packet.py
@@ -0,0 +1,242 @@
+# Copyright 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, digital
+from gnuradio.digital import packet_utils
+import gnuradio.gr.gr_threading as _threading
+
+##payload length in bytes
+DEFAULT_PAYLOAD_LEN = 512
+
+##how many messages in a queue
+DEFAULT_MSGQ_LIMIT = 2
+
+##threshold for unmaking packets
+DEFAULT_THRESHOLD = 12
+
+##################################################
+## Options Class for OFDM
+##################################################
+class options(object):
+ def __init__(self, **kwargs):
+ for key, value in kwargs.iteritems(): setattr(self, key, value)
+
+##################################################
+## Packet Encoder
+##################################################
+class _packet_encoder_thread(_threading.Thread):
+
+ def __init__(self, msgq, payload_length, send):
+ self._msgq = msgq
+ self._payload_length = payload_length
+ self._send = send
+ _threading.Thread.__init__(self)
+ self.setDaemon(1)
+ self.keep_running = True
+ self.start()
+
+ def run(self):
+ sample = '' #residual sample
+ while self.keep_running:
+ msg = self._msgq.delete_head() #blocking read of message queue
+ sample = sample + msg.to_string() #get the body of the msg as a string
+ while len(sample) >= self._payload_length:
+ payload = sample[:self._payload_length]
+ sample = sample[self._payload_length:]
+ self._send(payload)
+
+class packet_encoder(gr.hier_block2):
+ """
+ Hierarchical block for wrapping packet-based modulators.
+ """
+
+ def __init__(self, samples_per_symbol, bits_per_symbol, access_code='', pad_for_usrp=True):
+ """
+ packet_mod constructor.
+ @param samples_per_symbol number of samples per symbol
+ @param bits_per_symbol number of bits per symbol
+ @param access_code AKA sync vector
+ @param pad_for_usrp If true, packets are padded such that they end up a multiple of 128 samples
+ @param payload_length number of bytes in a data-stream slice
+ """
+ #setup parameters
+ self._samples_per_symbol = samples_per_symbol
+ self._bits_per_symbol = bits_per_symbol
+ self._pad_for_usrp = pad_for_usrp
+ if not access_code: #get access code
+ access_code = packet_utils.default_access_code
+ if not packet_utils.is_1_0_string(access_code):
+ raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
+ self._access_code = access_code
+ self._pad_for_usrp = pad_for_usrp
+ #create blocks
+ msg_source = gr.message_source(gr.sizeof_char, DEFAULT_MSGQ_LIMIT)
+ self._msgq_out = msg_source.msgq()
+ #initialize hier2
+ gr.hier_block2.__init__(
+ self,
+ "packet_encoder",
+ gr.io_signature(0, 0, 0), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_char) # Output signature
+ )
+ #connect
+ self.connect(msg_source, self)
+
+ def send_pkt(self, payload):
+ """
+ Wrap the payload in a packet and push onto the message queue.
+ @param payload string, data to send
+ """
+ packet = packet_utils.make_packet(
+ payload,
+ self._samples_per_symbol,
+ self._bits_per_symbol,
+ self._access_code,
+ self._pad_for_usrp
+ )
+ msg = gr.message_from_string(packet)
+ self._msgq_out.insert_tail(msg)
+
+##################################################
+## Packet Decoder
+##################################################
+class _packet_decoder_thread(_threading.Thread):
+
+ def __init__(self, msgq, callback):
+ _threading.Thread.__init__(self)
+ self.setDaemon(1)
+ self._msgq = msgq
+ self.callback = callback
+ self.keep_running = True
+ self.start()
+
+ def run(self):
+ while self.keep_running:
+ msg = self._msgq.delete_head()
+ ok, payload = packet_utils.unmake_packet(msg.to_string(), int(msg.arg1()))
+ if self.callback:
+ self.callback(ok, payload)
+
+class packet_decoder(gr.hier_block2):
+ """
+ Hierarchical block for wrapping packet-based demodulators.
+ """
+
+ def __init__(self, access_code='', threshold=-1, callback=None):
+ """
+ packet_demod constructor.
+ @param access_code AKA sync vector
+ @param threshold detect access_code with up to threshold bits wrong (0 -> use default)
+ @param callback a function of args: ok, payload
+ """
+ #access code
+ if not access_code: #get access code
+ access_code = packet_utils.default_access_code
+ if not packet_utils.is_1_0_string(access_code):
+ raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
+ self._access_code = access_code
+ #threshold
+ if threshold < 0: threshold = DEFAULT_THRESHOLD
+ self._threshold = threshold
+ #blocks
+ msgq = gr.msg_queue(DEFAULT_MSGQ_LIMIT) #holds packets from the PHY
+ correlator = digital.correlate_access_code_bb(self._access_code, self._threshold)
+ framer_sink = gr.framer_sink_1(msgq)
+ #initialize hier2
+ gr.hier_block2.__init__(
+ self,
+ "packet_decoder",
+ gr.io_signature(1, 1, gr.sizeof_char), # Input signature
+ gr.io_signature(0, 0, 0) # Output signature
+ )
+ #connect
+ self.connect(self, correlator, framer_sink)
+ #start thread
+ _packet_decoder_thread(msgq, callback)
+
+##################################################
+## Packet Mod for OFDM Mod and Packet Encoder
+##################################################
+class packet_mod_base(gr.hier_block2):
+ """
+ Hierarchical block for wrapping packet source block.
+ """
+
+ def __init__(self, packet_source=None, payload_length=0):
+ if not payload_length: #get payload length
+ payload_length = DEFAULT_PAYLOAD_LEN
+ if payload_length%self._item_size_in != 0: #verify that packet length is a multiple of the stream size
+ raise ValueError, 'The payload length: "%d" is not a mutiple of the stream size: "%d".'%(payload_length, self._item_size_in)
+ #initialize hier2
+ gr.hier_block2.__init__(
+ self,
+ "ofdm_mod",
+ gr.io_signature(1, 1, self._item_size_in), # Input signature
+ gr.io_signature(1, 1, packet_source._hb.output_signature().sizeof_stream_item(0)) # Output signature
+ )
+ #create blocks
+ msgq = gr.msg_queue(DEFAULT_MSGQ_LIMIT)
+ msg_sink = gr.message_sink(self._item_size_in, msgq, False) #False -> blocking
+ #connect
+ self.connect(self, msg_sink)
+ self.connect(packet_source, self)
+ #start thread
+ _packet_encoder_thread(msgq, payload_length, packet_source.send_pkt)
+
+class packet_mod_b(packet_mod_base): _item_size_in = gr.sizeof_char
+class packet_mod_s(packet_mod_base): _item_size_in = gr.sizeof_short
+class packet_mod_i(packet_mod_base): _item_size_in = gr.sizeof_int
+class packet_mod_f(packet_mod_base): _item_size_in = gr.sizeof_float
+class packet_mod_c(packet_mod_base): _item_size_in = gr.sizeof_gr_complex
+
+##################################################
+## Packet Demod for OFDM Demod and Packet Decoder
+##################################################
+class packet_demod_base(gr.hier_block2):
+ """
+ Hierarchical block for wrapping packet sink block.
+ """
+
+ def __init__(self, packet_sink=None):
+ #initialize hier2
+ gr.hier_block2.__init__(
+ self,
+ "ofdm_mod",
+ gr.io_signature(1, 1, packet_sink._hb.input_signature().sizeof_stream_item(0)), # Input signature
+ gr.io_signature(1, 1, self._item_size_out) # Output signature
+ )
+ #create blocks
+ msg_source = gr.message_source(self._item_size_out, DEFAULT_MSGQ_LIMIT)
+ self._msgq_out = msg_source.msgq()
+ #connect
+ self.connect(self, packet_sink)
+ self.connect(msg_source, self)
+ if packet_sink._hb.output_signature().sizeof_stream_item(0):
+ self.connect(packet_sink, gr.null_sink(packet_sink._hb.output_signature().sizeof_stream_item(0)))
+
+ def recv_pkt(self, ok, payload):
+ msg = gr.message_from_string(payload, 0, self._item_size_out, len(payload)/self._item_size_out)
+ if ok: self._msgq_out.insert_tail(msg)
+
+class packet_demod_b(packet_demod_base): _item_size_out = gr.sizeof_char
+class packet_demod_s(packet_demod_base): _item_size_out = gr.sizeof_short
+class packet_demod_i(packet_demod_base): _item_size_out = gr.sizeof_int
+class packet_demod_f(packet_demod_base): _item_size_out = gr.sizeof_float
+class packet_demod_c(packet_demod_base): _item_size_out = gr.sizeof_gr_complex
diff --git a/grc/grc_gnuradio/blks2/selector.py b/grc/grc_gnuradio/blks2/selector.py
new file mode 100644
index 000000000..f0f6d5dd7
--- /dev/null
+++ b/grc/grc_gnuradio/blks2/selector.py
@@ -0,0 +1,128 @@
+#
+# Copyright 2008 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr
+
+class selector(gr.hier_block2):
+ """A hier2 block with N inputs and M outputs, where data is only forwarded through input n to output m."""
+ def __init__(self, item_size, num_inputs, num_outputs, input_index, output_index):
+ """
+ Selector constructor.
+ @param item_size the size of the gr data stream in bytes
+ @param num_inputs the number of inputs (integer)
+ @param num_outputs the number of outputs (integer)
+ @param input_index the index for the source data
+ @param output_index the index for the destination data
+ """
+ gr.hier_block2.__init__(
+ self, 'selector',
+ gr.io_signature(num_inputs, num_inputs, item_size),
+ gr.io_signature(num_outputs, num_outputs, item_size),
+ )
+ #terminator blocks for unused inputs and outputs
+ self.input_terminators = [gr.null_sink(item_size) for i in range(num_inputs)]
+ self.output_terminators = [gr.head(item_size, 0) for i in range(num_outputs)]
+ self.copy = gr.kludge_copy(item_size)
+ #connections
+ for i in range(num_inputs): self.connect((self, i), self.input_terminators[i])
+ for i in range(num_outputs): self.connect(gr.null_source(item_size), self.output_terminators[i], (self, i))
+ self.item_size = item_size
+ self.input_index = input_index
+ self.output_index = output_index
+ self.num_inputs = num_inputs
+ self.num_outputs = num_outputs
+ self._connect_current()
+
+ def _indexes_valid(self):
+ """
+ Are the input and output indexes within range of the number of inputs and outputs?
+ @return true if input index and output index are in range
+ """
+ return self.input_index in range(self.num_inputs) and self.output_index in range(self.num_outputs)
+
+ def _connect_current(self):
+ """If the input and output indexes are valid:
+ disconnect the blocks at the input and output index from their terminators,
+ and connect them to one another. Then connect the terminators to one another."""
+ if self._indexes_valid():
+ self.disconnect((self, self.input_index), self.input_terminators[self.input_index])
+ self.disconnect(self.output_terminators[self.output_index], (self, self.output_index))
+ self.connect((self, self.input_index), self.copy)
+ self.connect(self.copy, (self, self.output_index))
+ self.connect(self.output_terminators[self.output_index], self.input_terminators[self.input_index])
+
+ def _disconnect_current(self):
+ """If the input and output indexes are valid:
+ disconnect the blocks at the input and output index from one another,
+ and the terminators at the input and output index from one another.
+ Reconnect the blocks to the terminators."""
+ if self._indexes_valid():
+ self.disconnect((self, self.input_index), self.copy)
+ self.disconnect(self.copy, (self, self.output_index))
+ self.disconnect(self.output_terminators[self.output_index], self.input_terminators[self.input_index])
+ self.connect((self, self.input_index), self.input_terminators[self.input_index])
+ self.connect(self.output_terminators[self.output_index], (self, self.output_index))
+
+ def set_input_index(self, input_index):
+ """
+ Change the block to the new input index if the index changed.
+ @param input_index the new input index
+ """
+ if self.input_index != input_index:
+ self.lock()
+ self._disconnect_current()
+ self.input_index = input_index
+ self._connect_current()
+ self.unlock()
+
+ def set_output_index(self, output_index):
+ """
+ Change the block to the new output index if the index changed.
+ @param output_index the new output index
+ """
+ if self.output_index != output_index:
+ self.lock()
+ self._disconnect_current()
+ self.output_index = output_index
+ self._connect_current()
+ self.unlock()
+
+class valve(selector):
+ """Wrapper for selector with 1 input and 1 output."""
+
+ def __init__(self, item_size, open):
+ """
+ Constructor for valve.
+ @param item_size the size of the gr data stream in bytes
+ @param open true if initial valve state is open
+ """
+ if open: output_index = -1
+ else: output_index = 0
+ selector.__init__(self, item_size, 1, 1, 0, output_index)
+
+ def set_open(self, open):
+ """
+ Callback to set open state.
+ @param open true to set valve state to open
+ """
+ if open: output_index = -1
+ else: output_index = 0
+ self.set_output_index(output_index)
diff --git a/grc/grc_gnuradio/blks2/tcp.py b/grc/grc_gnuradio/blks2/tcp.py
new file mode 100644
index 000000000..c6739b711
--- /dev/null
+++ b/grc/grc_gnuradio/blks2/tcp.py
@@ -0,0 +1,66 @@
+#
+# Copyright 2009 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr
+import socket
+import os
+
+def _get_sock_fd(addr, port, server):
+ """
+ Get the file descriptor for the socket.
+ As a client, block on connect, dup the socket descriptor.
+ As a server, block on accept, dup the client descriptor.
+ @param addr the ip address string
+ @param port the tcp port number
+ @param server true for server mode, false for client mode
+ @return the file descriptor number
+ """
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ if server:
+ sock.bind((addr, port))
+ sock.listen(1)
+ clientsock, address = sock.accept()
+ return os.dup(clientsock.fileno())
+ else:
+ sock.connect((addr, port))
+ return os.dup(sock.fileno())
+
+class tcp_source(gr.hier_block2):
+ def __init__(self, itemsize, addr, port, server=True):
+ #init hier block
+ gr.hier_block2.__init__(
+ self, 'tcp_source',
+ gr.io_signature(0, 0, 0),
+ gr.io_signature(1, 1, itemsize),
+ )
+ fd = _get_sock_fd(addr, port, server)
+ self.connect(gr.file_descriptor_source(itemsize, fd), self)
+
+class tcp_sink(gr.hier_block2):
+ def __init__(self, itemsize, addr, port, server=False):
+ #init hier block
+ gr.hier_block2.__init__(
+ self, 'tcp_sink',
+ gr.io_signature(1, 1, itemsize),
+ gr.io_signature(0, 0, 0),
+ )
+ fd = _get_sock_fd(addr, port, server)
+ self.connect(self, gr.file_descriptor_sink(itemsize, fd))
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
new file mode 100644
index 000000000..9fb5e4ebf
--- /dev/null
+++ b/grc/gui/ActionHandler.py
@@ -0,0 +1,530 @@
+"""
+Copyright 2007-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import os
+import signal
+from Constants import IMAGE_FILE_EXTENSION
+import Actions
+import pygtk
+pygtk.require('2.0')
+import gtk
+import gobject
+import Preferences
+from threading import Thread
+import Messages
+from .. base import ParseXML
+from MainWindow import MainWindow
+from PropsDialog import PropsDialog
+import Dialogs
+from FileDialogs import OpenFlowGraphFileDialog, SaveFlowGraphFileDialog, SaveImageFileDialog
+
+gobject.threads_init()
+
+class ActionHandler:
+ """
+ The action handler will setup all the major window components,
+ and handle button presses and flow graph operations from the GUI.
+ """
+
+ def __init__(self, file_paths, platform):
+ """
+ ActionHandler constructor.
+ Create the main window, setup the message handler, import the preferences,
+ and connect all of the action handlers. Finally, enter the gtk main loop and block.
+ @param file_paths a list of flow graph file passed from command line
+ @param platform platform module
+ """
+ self.clipboard = None
+ for action in Actions.get_all_actions(): action.connect('activate', self._handle_action)
+ #setup the main window
+ self.platform = platform;
+ self.main_window = MainWindow(platform)
+ self.main_window.connect('delete-event', self._quit)
+ self.main_window.connect('key-press-event', self._handle_key_press)
+ self.get_page = self.main_window.get_page
+ self.get_flow_graph = self.main_window.get_flow_graph
+ self.get_focus_flag = self.main_window.get_focus_flag
+ #setup the messages
+ Messages.register_messenger(self.main_window.add_report_line)
+ Messages.send_init(platform)
+ #initialize
+ self.init_file_paths = file_paths
+ Actions.APPLICATION_INITIALIZE()
+ #enter the mainloop
+ gtk.main()
+
+ def _handle_key_press(self, widget, event):
+ """
+ Handle key presses from the keyboard and translate key combinations into actions.
+ This key press handler is called prior to the gtk key press handler.
+ This handler bypasses built in accelerator key handling when in focus because
+ * some keys are ignored by the accelerators like the direction keys,
+ * some keys are not registered to any accelerators but are still used.
+ When not in focus, gtk and the accelerators handle the the key press.
+ @return false to let gtk handle the key action
+ """
+ if not self.get_focus_flag(): return False
+ return Actions.handle_key_press(event)
+
+ def _quit(self, window, event):
+ """
+ Handle the delete event from the main window.
+ Generated by pressing X to close, alt+f4, or right click+close.
+ This method in turns calls the state handler to quit.
+ @return true
+ """
+ Actions.APPLICATION_QUIT()
+ return True
+
+ def _handle_action(self, action):
+ #print action
+ ##################################################
+ # Initalize/Quit
+ ##################################################
+ if action == Actions.APPLICATION_INITIALIZE:
+ for action in Actions.get_all_actions(): action.set_sensitive(False) #set all actions disabled
+ #enable a select few actions
+ for action in (
+ Actions.APPLICATION_QUIT, Actions.FLOW_GRAPH_NEW,
+ Actions.FLOW_GRAPH_OPEN, Actions.FLOW_GRAPH_SAVE_AS,
+ Actions.FLOW_GRAPH_CLOSE, Actions.ABOUT_WINDOW_DISPLAY,
+ Actions.FLOW_GRAPH_SCREEN_CAPTURE, Actions.HELP_WINDOW_DISPLAY,
+ Actions.TYPES_WINDOW_DISPLAY,
+ ): action.set_sensitive(True)
+ if not self.init_file_paths:
+ self.init_file_paths = Preferences.files_open()
+ if not self.init_file_paths: self.init_file_paths = ['']
+ for file_path in self.init_file_paths:
+ if file_path: self.main_window.new_page(file_path) #load pages from file paths
+ if Preferences.file_open() in self.init_file_paths:
+ self.main_window.new_page(Preferences.file_open(), show=True)
+ if not self.get_page(): self.main_window.new_page() #ensure that at least a blank page exists
+ elif action == Actions.APPLICATION_QUIT:
+ if self.main_window.close_pages():
+ gtk.main_quit()
+ exit(0)
+ ##################################################
+ # Selections
+ ##################################################
+ elif action == Actions.ELEMENT_SELECT:
+ pass #do nothing, update routines below
+ elif action == Actions.NOTHING_SELECT:
+ self.get_flow_graph().unselect()
+ ##################################################
+ # Enable/Disable
+ ##################################################
+ elif action == Actions.BLOCK_ENABLE:
+ if self.get_flow_graph().enable_selected(True):
+ self.get_flow_graph().update()
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ self.get_page().set_saved(False)
+ elif action == Actions.BLOCK_DISABLE:
+ if self.get_flow_graph().enable_selected(False):
+ self.get_flow_graph().update()
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ self.get_page().set_saved(False)
+ ##################################################
+ # Cut/Copy/Paste
+ ##################################################
+ elif action == Actions.BLOCK_CUT:
+ Actions.BLOCK_COPY()
+ Actions.ELEMENT_DELETE()
+ elif action == Actions.BLOCK_COPY:
+ self.clipboard = self.get_flow_graph().copy_to_clipboard()
+ elif action == Actions.BLOCK_PASTE:
+ if self.clipboard:
+ self.get_flow_graph().paste_from_clipboard(self.clipboard)
+ self.get_flow_graph().update()
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ self.get_page().set_saved(False)
+ ##################################################
+ # Create heir block
+ ##################################################
+ elif action == Actions.BLOCK_CREATE_HIER:
+
+ # keeping track of coordinates for pasting later
+ coords = self.get_flow_graph().get_selected_blocks()[0].get_coordinate()
+ x,y = coords
+ x_min = x
+ y_min = y
+
+ pads = [];
+ params = [];
+
+ # Save the state of the leaf blocks
+ for block in self.get_flow_graph().get_selected_blocks():
+
+ # Check for string variables within the blocks
+ for param in block.get_params():
+ for variable in self.get_flow_graph().get_variables():
+ # If a block parameter exists that is a variable, create a parameter for it
+ if param.get_value() == variable.get_id():
+ params.append(param.get_value())
+ for flow_param in self.get_flow_graph().get_parameters():
+ # If a block parameter exists that is a parameter, create a parameter for it
+ if param.get_value() == flow_param.get_id():
+ params.append(param.get_value())
+
+
+ # keep track of x,y mins for pasting later
+ (x,y) = block.get_coordinate()
+ if x < x_min:
+ x_min = x
+ if y < y_min:
+ y_min = y
+
+ for connection in block.get_connections():
+
+ # Get id of connected blocks
+ source_id = connection.get_source().get_parent().get_id()
+ sink_id = connection.get_sink().get_parent().get_id()
+
+ # If connected block is not in the list of selected blocks create a pad for it
+ if self.get_flow_graph().get_block(source_id) not in self.get_flow_graph().get_selected_blocks():
+ pads.append({'key': connection.get_sink().get_key(), 'coord': connection.get_source().get_coordinate(), 'block_id' : block.get_id(), 'direction': 'source'})
+
+ if self.get_flow_graph().get_block(sink_id) not in self.get_flow_graph().get_selected_blocks():
+ pads.append({'key': connection.get_source().get_key(), 'coord': connection.get_sink().get_coordinate(), 'block_id' : block.get_id(), 'direction': 'sink'})
+
+
+ # Copy the selected blocks and paste them into a new page
+ # then move the flowgraph to a reasonable position
+ Actions.BLOCK_COPY()
+ self.main_window.new_page()
+ Actions.BLOCK_PASTE()
+ coords = (x_min,y_min)
+ self.get_flow_graph().move_selected(coords)
+
+
+ # Set flow graph to heir block type
+ top_block = self.get_flow_graph().get_block("top_block")
+ top_block.get_param('generate_options').set_value('hb')
+
+ # this needs to be a unique name
+ top_block.get_param('id').set_value('new_heir')
+
+ # Remove the default samp_rate variable block that is created
+ remove_me = self.get_flow_graph().get_block("samp_rate")
+ self.get_flow_graph().remove_element(remove_me)
+
+
+ # Add the param blocks along the top of the window
+ x_pos = 150
+ for param in params:
+ param_id = self.get_flow_graph().add_new_block('parameter',(x_pos,10))
+ param_block = self.get_flow_graph().get_block(param_id)
+ param_block.get_param('id').set_value(param)
+ x_pos = x_pos + 100
+
+ for pad in pads:
+ # Add the pad sources and sinks within the new heir block
+ if pad['direction'] == 'sink':
+
+ # Add new PAD_SINK block to the canvas
+ pad_id = self.get_flow_graph().add_new_block('pad_sink', pad['coord'])
+
+ # setup the references to the sink and source
+ pad_block = self.get_flow_graph().get_block(pad_id)
+ pad_sink = pad_block.get_sinks()[0]
+
+ source_block = self.get_flow_graph().get_block(pad['block_id'])
+ source = source_block.get_source(pad['key'])
+
+ # Ensure the port types match
+ while pad_sink.get_type() != source.get_type():
+
+ # Special case for some blocks that have non-standard type names, e.g. uhd
+ if pad_sink.get_type() == 'complex' and source.get_type() == 'fc32':
+ break;
+ pad_block.type_controller_modify(1)
+
+ # Connect the pad to the proper sinks
+ new_connection = self.get_flow_graph().connect(source,pad_sink)
+
+ elif pad['direction'] == 'source':
+ pad_id = self.get_flow_graph().add_new_block('pad_source', pad['coord'])
+
+ # setup the references to the sink and source
+ pad_block = self.get_flow_graph().get_block(pad_id)
+ pad_source = pad_block.get_sources()[0]
+
+ sink_block = self.get_flow_graph().get_block(pad['block_id'])
+ sink = sink_block.get_sink(pad['key'])
+
+ # Ensure the port types match
+ while sink.get_type() != pad_source.get_type():
+ # Special case for some blocks that have non-standard type names, e.g. uhd
+ if pad_source.get_type() == 'complex' and sink.get_type() == 'fc32':
+ break;
+ pad_block.type_controller_modify(1)
+
+ # Connect the pad to the proper sinks
+ new_connection = self.get_flow_graph().connect(pad_source,sink)
+
+ # update the new heir block flow graph
+ self.get_flow_graph().update()
+
+
+ ##################################################
+ # Move/Rotate/Delete/Create
+ ##################################################
+ elif action == Actions.BLOCK_MOVE:
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ self.get_page().set_saved(False)
+ elif action == Actions.BLOCK_ROTATE_CCW:
+ if self.get_flow_graph().rotate_selected(90):
+ self.get_flow_graph().update()
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ self.get_page().set_saved(False)
+ elif action == Actions.BLOCK_ROTATE_CW:
+ if self.get_flow_graph().rotate_selected(-90):
+ self.get_flow_graph().update()
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ self.get_page().set_saved(False)
+ elif action == Actions.ELEMENT_DELETE:
+ if self.get_flow_graph().remove_selected():
+ self.get_flow_graph().update()
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ Actions.NOTHING_SELECT()
+ self.get_page().set_saved(False)
+ elif action == Actions.ELEMENT_CREATE:
+ self.get_flow_graph().update()
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ Actions.NOTHING_SELECT()
+ self.get_page().set_saved(False)
+ elif action == Actions.BLOCK_INC_TYPE:
+ if self.get_flow_graph().type_controller_modify_selected(1):
+ self.get_flow_graph().update()
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ self.get_page().set_saved(False)
+ elif action == Actions.BLOCK_DEC_TYPE:
+ if self.get_flow_graph().type_controller_modify_selected(-1):
+ self.get_flow_graph().update()
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ self.get_page().set_saved(False)
+ elif action == Actions.PORT_CONTROLLER_INC:
+ if self.get_flow_graph().port_controller_modify_selected(1):
+ self.get_flow_graph().update()
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ self.get_page().set_saved(False)
+ elif action == Actions.PORT_CONTROLLER_DEC:
+ if self.get_flow_graph().port_controller_modify_selected(-1):
+ self.get_flow_graph().update()
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ self.get_page().set_saved(False)
+ ##################################################
+ # Window stuff
+ ##################################################
+ elif action == Actions.ABOUT_WINDOW_DISPLAY:
+ Dialogs.AboutDialog(self.get_flow_graph().get_parent())
+ elif action == Actions.HELP_WINDOW_DISPLAY:
+ Dialogs.HelpDialog()
+ elif action == Actions.TYPES_WINDOW_DISPLAY:
+ Dialogs.TypesDialog(self.get_flow_graph().get_parent())
+ elif action == Actions.ERRORS_WINDOW_DISPLAY:
+ Dialogs.ErrorsDialog(self.get_flow_graph())
+ ##################################################
+ # Param Modifications
+ ##################################################
+ elif action == Actions.BLOCK_PARAM_MODIFY:
+ selected_block = self.get_flow_graph().get_selected_block()
+ if selected_block:
+ if PropsDialog(selected_block).run():
+ #save the new state
+ self.get_flow_graph().update()
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ self.get_page().set_saved(False)
+ else:
+ #restore the current state
+ n = self.get_page().get_state_cache().get_current_state()
+ self.get_flow_graph().import_data(n)
+ self.get_flow_graph().update()
+ ##################################################
+ # Undo/Redo
+ ##################################################
+ elif action == Actions.FLOW_GRAPH_UNDO:
+ n = self.get_page().get_state_cache().get_prev_state()
+ if n:
+ self.get_flow_graph().unselect()
+ self.get_flow_graph().import_data(n)
+ self.get_flow_graph().update()
+ self.get_page().set_saved(False)
+ elif action == Actions.FLOW_GRAPH_REDO:
+ n = self.get_page().get_state_cache().get_next_state()
+ if n:
+ self.get_flow_graph().unselect()
+ self.get_flow_graph().import_data(n)
+ self.get_flow_graph().update()
+ self.get_page().set_saved(False)
+ ##################################################
+ # New/Open/Save/Close
+ ##################################################
+ elif action == Actions.FLOW_GRAPH_NEW:
+ self.main_window.new_page()
+ elif action == Actions.FLOW_GRAPH_OPEN:
+ file_paths = OpenFlowGraphFileDialog(self.get_page().get_file_path()).run()
+ if file_paths: #open a new page for each file, show only the first
+ for i,file_path in enumerate(file_paths):
+ self.main_window.new_page(file_path, show=(i==0))
+ elif action == Actions.FLOW_GRAPH_CLOSE:
+ self.main_window.close_page()
+ elif action == Actions.FLOW_GRAPH_SAVE:
+ #read-only or undefined file path, do save-as
+ if self.get_page().get_read_only() or not self.get_page().get_file_path():
+ Actions.FLOW_GRAPH_SAVE_AS()
+ #otherwise try to save
+ else:
+ try:
+ ParseXML.to_file(self.get_flow_graph().export_data(), self.get_page().get_file_path())
+ self.get_flow_graph().grc_file_path = self.get_page().get_file_path()
+ self.get_page().set_saved(True)
+ except IOError:
+ Messages.send_fail_save(self.get_page().get_file_path())
+ self.get_page().set_saved(False)
+ elif action == Actions.FLOW_GRAPH_SAVE_AS:
+ file_path = SaveFlowGraphFileDialog(self.get_page().get_file_path()).run()
+ if file_path is not None:
+ self.get_page().set_file_path(file_path)
+ Actions.FLOW_GRAPH_SAVE()
+ elif action == Actions.FLOW_GRAPH_SCREEN_CAPTURE:
+ file_path = SaveImageFileDialog(self.get_page().get_file_path()).run()
+ if file_path is not None:
+ pixbuf = self.get_flow_graph().get_drawing_area().get_pixbuf()
+ pixbuf.save(file_path, IMAGE_FILE_EXTENSION[1:])
+ ##################################################
+ # Gen/Exec/Stop
+ ##################################################
+ elif action == Actions.FLOW_GRAPH_GEN:
+ if not self.get_page().get_proc():
+ if not self.get_page().get_saved() or not self.get_page().get_file_path():
+ Actions.FLOW_GRAPH_SAVE() #only save if file path missing or not saved
+ if self.get_page().get_saved() and self.get_page().get_file_path():
+ generator = self.get_page().get_generator()
+ try:
+ Messages.send_start_gen(generator.get_file_path())
+ generator.write()
+ except Exception,e: Messages.send_fail_gen(e)
+ else: self.generator = None
+ elif action == Actions.FLOW_GRAPH_EXEC:
+ if not self.get_page().get_proc():
+ Actions.FLOW_GRAPH_GEN()
+ if self.get_page().get_saved() and self.get_page().get_file_path():
+ ExecFlowGraphThread(self)
+ elif action == Actions.FLOW_GRAPH_KILL:
+ if self.get_page().get_proc():
+ try: self.get_page().get_proc().kill()
+ except: print "could not kill process: %d"%self.get_page().get_proc().pid
+ elif action == Actions.PAGE_CHANGE: #pass and run the global actions
+ pass
+ elif action == Actions.RELOAD_BLOCKS:
+ self.platform.loadblocks()
+ self.main_window.btwin.clear();
+ self.platform.load_block_tree(self.main_window.btwin);
+ elif action == Actions.OPEN_HIER:
+ bn = [];
+ for b in self.get_flow_graph().get_selected_blocks():
+ if b._grc_source:
+ self.main_window.new_page(b._grc_source, show=True);
+ else: print '!!! Action "%s" not handled !!!'%action
+ ##################################################
+ # Global Actions for all States
+ ##################################################
+ #update general buttons
+ Actions.ERRORS_WINDOW_DISPLAY.set_sensitive(not self.get_flow_graph().is_valid())
+ Actions.ELEMENT_DELETE.set_sensitive(bool(self.get_flow_graph().get_selected_elements()))
+ Actions.BLOCK_PARAM_MODIFY.set_sensitive(bool(self.get_flow_graph().get_selected_block()))
+ Actions.BLOCK_ROTATE_CCW.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.BLOCK_ROTATE_CW.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ #update cut/copy/paste
+ Actions.BLOCK_CUT.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.BLOCK_COPY.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.BLOCK_PASTE.set_sensitive(bool(self.clipboard))
+ #update enable/disable
+ Actions.BLOCK_ENABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.BLOCK_DISABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.BLOCK_CREATE_HIER.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.OPEN_HIER.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.RELOAD_BLOCKS.set_sensitive(True)
+ #set the exec and stop buttons
+ self.update_exec_stop()
+ #saved status
+ Actions.FLOW_GRAPH_SAVE.set_sensitive(not self.get_page().get_saved())
+ self.main_window.update()
+ try: #set the size of the flow graph area (if changed)
+ new_size = self.get_flow_graph().get_option('window_size')
+ if self.get_flow_graph().get_size() != tuple(new_size):
+ self.get_flow_graph().set_size(*new_size)
+ except: pass
+ #draw the flow graph
+ self.get_flow_graph().update_selected()
+ self.get_flow_graph().queue_draw()
+ return True #action was handled
+
+ def update_exec_stop(self):
+ """
+ Update the exec and stop buttons.
+ Lock and unlock the mutex for race conditions with exec flow graph threads.
+ """
+ sensitive = self.get_flow_graph().is_valid() and not self.get_page().get_proc()
+ Actions.FLOW_GRAPH_GEN.set_sensitive(sensitive)
+ Actions.FLOW_GRAPH_EXEC.set_sensitive(sensitive)
+ Actions.FLOW_GRAPH_KILL.set_sensitive(self.get_page().get_proc() != None)
+
+class ExecFlowGraphThread(Thread):
+ """Execute the flow graph as a new process and wait on it to finish."""
+
+ def __init__ (self, action_handler):
+ """
+ ExecFlowGraphThread constructor.
+ @param action_handler an instance of an ActionHandler
+ """
+ Thread.__init__(self)
+ self.update_exec_stop = action_handler.update_exec_stop
+ self.flow_graph = action_handler.get_flow_graph()
+ #store page and dont use main window calls in run
+ self.page = action_handler.get_page()
+ Messages.send_start_exec(self.page.get_generator().get_file_path())
+ #get the popen
+ try:
+ self.p = self.page.get_generator().get_popen()
+ self.page.set_proc(self.p)
+ #update
+ self.update_exec_stop()
+ self.start()
+ except Exception, e:
+ Messages.send_verbose_exec(str(e))
+ Messages.send_end_exec()
+
+ def run(self):
+ """
+ Wait on the executing process by reading from its stdout.
+ Use gobject.idle_add when calling functions that modify gtk objects.
+ """
+ #handle completion
+ r = "\n"
+ while(r):
+ gobject.idle_add(Messages.send_verbose_exec, r)
+ r = os.read(self.p.stdout.fileno(), 1024)
+ gobject.idle_add(self.done)
+
+ def done(self):
+ """Perform end of execution tasks."""
+ Messages.send_end_exec()
+ self.page.set_proc(None)
+ self.update_exec_stop()
diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py
new file mode 100644
index 000000000..fab026c5e
--- /dev/null
+++ b/grc/gui/Actions.py
@@ -0,0 +1,291 @@
+"""
+Copyright 2007-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+
+NO_MODS_MASK = 0
+
+########################################################################
+# Actions API
+########################################################################
+_actions_keypress_dict = dict()
+_keymap = gtk.gdk.keymap_get_default()
+_used_mods_mask = NO_MODS_MASK
+def handle_key_press(event):
+ """
+ Call the action associated with the key press event.
+ Both the key value and the mask must have a match.
+ @param event a gtk key press event
+ @return true if handled
+ """
+ _used_mods_mask = reduce(lambda x, y: x | y, [mod_mask for keyval, mod_mask in _actions_keypress_dict], NO_MODS_MASK)
+ #extract the key value and the consumed modifiers
+ keyval, egroup, level, consumed = _keymap.translate_keyboard_state(
+ event.hardware_keycode, event.state, event.group)
+ #get the modifier mask and ignore irrelevant modifiers
+ mod_mask = event.state & ~consumed & _used_mods_mask
+ #look up the keypress and call the action
+ try: _actions_keypress_dict[(keyval, mod_mask)]()
+ except KeyError: return False #not handled
+ return True #handled here
+
+_all_actions_list = list()
+def get_all_actions(): return _all_actions_list
+
+_accel_group = gtk.AccelGroup()
+def get_accel_group(): return _accel_group
+
+class Action(gtk.Action):
+ """
+ A custom Action class based on gtk.Action.
+ Pass additional arguments such as keypresses.
+ Register actions and keypresses with this module.
+ """
+
+ def __init__(self, keypresses=(), name=None, label=None, tooltip=None, stock_id=None):
+ """
+ Create a new Action instance.
+ @param key_presses a tuple of (keyval1, mod_mask1, keyval2, mod_mask2, ...)
+ @param the regular gtk.Action parameters (defaults to None)
+ """
+ if name is None: name = label
+ gtk.Action.__init__(self,
+ name=name, label=label,
+ tooltip=tooltip, stock_id=stock_id,
+ )
+ #register this action
+ _all_actions_list.append(self)
+ for i in range(len(keypresses)/2):
+ keyval, mod_mask = keypresses[i*2:(i+1)*2]
+ #register this keypress
+ if _actions_keypress_dict.has_key((keyval, mod_mask)):
+ raise KeyError('keyval/mod_mask pair already registered "%s"'%str((keyval, mod_mask)))
+ _actions_keypress_dict[(keyval, mod_mask)] = self
+ #set the accelerator group, and accelerator path
+ #register the key name and mod mask with the accelerator path
+ if label is None: continue #dont register accel
+ accel_path = '<main>/'+self.get_name()
+ self.set_accel_group(get_accel_group())
+ self.set_accel_path(accel_path)
+ gtk.accel_map_add_entry(accel_path, keyval, mod_mask)
+
+ def __str__(self):
+ """
+ The string representation should be the name of the action id.
+ Try to find the action id for this action by searching this module.
+ """
+ try:
+ import Actions
+ return filter(lambda attr: getattr(Actions, attr) == self, dir(Actions))[0]
+ except: return self.get_name()
+
+ def __repr__(self): return str(self)
+
+ def __call__(self):
+ """
+ Emit the activate signal when called with ().
+ """
+ self.emit('activate')
+
+########################################################################
+# Actions
+########################################################################
+PAGE_CHANGE = Action()
+FLOW_GRAPH_NEW = Action(
+ label='_New',
+ tooltip='Create a new flow graph',
+ stock_id=gtk.STOCK_NEW,
+ keypresses=(gtk.keysyms.n, gtk.gdk.CONTROL_MASK),
+)
+FLOW_GRAPH_OPEN = Action(
+ label='_Open',
+ tooltip='Open an existing flow graph',
+ stock_id=gtk.STOCK_OPEN,
+ keypresses=(gtk.keysyms.o, gtk.gdk.CONTROL_MASK),
+)
+FLOW_GRAPH_SAVE = Action(
+ label='_Save',
+ tooltip='Save the current flow graph',
+ stock_id=gtk.STOCK_SAVE,
+ keypresses=(gtk.keysyms.s, gtk.gdk.CONTROL_MASK),
+)
+FLOW_GRAPH_SAVE_AS = Action(
+ label='Save _As',
+ tooltip='Save the current flow graph as...',
+ stock_id=gtk.STOCK_SAVE_AS,
+ keypresses=(gtk.keysyms.s, gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK),
+)
+FLOW_GRAPH_CLOSE = Action(
+ label='_Close',
+ tooltip='Close the current flow graph',
+ stock_id=gtk.STOCK_CLOSE,
+ keypresses=(gtk.keysyms.w, gtk.gdk.CONTROL_MASK),
+)
+APPLICATION_INITIALIZE = Action()
+APPLICATION_QUIT = Action(
+ label='_Quit',
+ tooltip='Quit program',
+ stock_id=gtk.STOCK_QUIT,
+ keypresses=(gtk.keysyms.q, gtk.gdk.CONTROL_MASK),
+)
+FLOW_GRAPH_UNDO = Action(
+ label='_Undo',
+ tooltip='Undo a change to the flow graph',
+ stock_id=gtk.STOCK_UNDO,
+ keypresses=(gtk.keysyms.z, gtk.gdk.CONTROL_MASK),
+)
+FLOW_GRAPH_REDO = Action(
+ label='_Redo',
+ tooltip='Redo a change to the flow graph',
+ stock_id=gtk.STOCK_REDO,
+ keypresses=(gtk.keysyms.y, gtk.gdk.CONTROL_MASK),
+)
+NOTHING_SELECT = Action()
+ELEMENT_SELECT = Action()
+ELEMENT_CREATE = Action()
+ELEMENT_DELETE = Action(
+ label='_Delete',
+ tooltip='Delete the selected blocks',
+ stock_id=gtk.STOCK_DELETE,
+ keypresses=(gtk.keysyms.Delete, NO_MODS_MASK),
+)
+BLOCK_MOVE = Action()
+BLOCK_ROTATE_CCW = Action(
+ label='Rotate Counterclockwise',
+ tooltip='Rotate the selected blocks 90 degrees to the left',
+ stock_id=gtk.STOCK_GO_BACK,
+ keypresses=(gtk.keysyms.Left, NO_MODS_MASK),
+)
+BLOCK_ROTATE_CW = Action(
+ label='Rotate Clockwise',
+ tooltip='Rotate the selected blocks 90 degrees to the right',
+ stock_id=gtk.STOCK_GO_FORWARD,
+ keypresses=(gtk.keysyms.Right, NO_MODS_MASK),
+)
+BLOCK_PARAM_MODIFY = Action(
+ label='_Properties',
+ tooltip='Modify params for the selected block',
+ stock_id=gtk.STOCK_PROPERTIES,
+ keypresses=(gtk.keysyms.Return, NO_MODS_MASK),
+)
+BLOCK_ENABLE = Action(
+ label='E_nable',
+ tooltip='Enable the selected blocks',
+ stock_id=gtk.STOCK_CONNECT,
+ keypresses=(gtk.keysyms.e, NO_MODS_MASK),
+)
+BLOCK_DISABLE = Action(
+ label='D_isable',
+ tooltip='Disable the selected blocks',
+ stock_id=gtk.STOCK_DISCONNECT,
+ keypresses=(gtk.keysyms.d, NO_MODS_MASK),
+)
+BLOCK_CREATE_HIER = Action(
+ label='C_reate Hier',
+ tooltip='Create hier block from selected blocks',
+ stock_id=gtk.STOCK_CONNECT,
+# keypresses=(gtk.keysyms.c, NO_MODS_MASK),
+)
+BLOCK_CUT = Action(
+ label='Cu_t',
+ tooltip='Cut',
+ stock_id=gtk.STOCK_CUT,
+ keypresses=(gtk.keysyms.x, gtk.gdk.CONTROL_MASK),
+)
+BLOCK_COPY = Action(
+ label='_Copy',
+ tooltip='Copy',
+ stock_id=gtk.STOCK_COPY,
+ keypresses=(gtk.keysyms.c, gtk.gdk.CONTROL_MASK),
+)
+BLOCK_PASTE = Action(
+ label='_Paste',
+ tooltip='Paste',
+ stock_id=gtk.STOCK_PASTE,
+ keypresses=(gtk.keysyms.v, gtk.gdk.CONTROL_MASK),
+)
+ERRORS_WINDOW_DISPLAY = Action(
+ label='_Errors',
+ tooltip='View flow graph errors',
+ stock_id=gtk.STOCK_DIALOG_ERROR,
+)
+ABOUT_WINDOW_DISPLAY = Action(
+ label='_About',
+ tooltip='About this program',
+ stock_id=gtk.STOCK_ABOUT,
+)
+HELP_WINDOW_DISPLAY = Action(
+ label='_Help',
+ tooltip='Usage tips',
+ stock_id=gtk.STOCK_HELP,
+ keypresses=(gtk.keysyms.F1, NO_MODS_MASK),
+)
+TYPES_WINDOW_DISPLAY = Action(
+ label='_Types',
+ tooltip='Types color mapping',
+ stock_id=gtk.STOCK_DIALOG_INFO,
+)
+FLOW_GRAPH_GEN = Action(
+ label='_Generate',
+ tooltip='Generate the flow graph',
+ stock_id=gtk.STOCK_CONVERT,
+ keypresses=(gtk.keysyms.F5, NO_MODS_MASK),
+)
+FLOW_GRAPH_EXEC = Action(
+ label='_Execute',
+ tooltip='Execute the flow graph',
+ stock_id=gtk.STOCK_EXECUTE,
+ keypresses=(gtk.keysyms.F6, NO_MODS_MASK),
+)
+FLOW_GRAPH_KILL = Action(
+ label='_Kill',
+ tooltip='Kill the flow graph',
+ stock_id=gtk.STOCK_STOP,
+ keypresses=(gtk.keysyms.F7, NO_MODS_MASK),
+)
+FLOW_GRAPH_SCREEN_CAPTURE = Action(
+ label='S_creen Capture',
+ tooltip='Create a screen capture of the flow graph',
+ stock_id=gtk.STOCK_PRINT,
+ keypresses=(gtk.keysyms.Print, NO_MODS_MASK),
+)
+PORT_CONTROLLER_DEC = Action(
+ keypresses=(gtk.keysyms.minus, NO_MODS_MASK, gtk.keysyms.KP_Subtract, NO_MODS_MASK),
+)
+PORT_CONTROLLER_INC = Action(
+ keypresses=(gtk.keysyms.plus, NO_MODS_MASK, gtk.keysyms.KP_Add, NO_MODS_MASK),
+)
+BLOCK_INC_TYPE = Action(
+ keypresses=(gtk.keysyms.Down, NO_MODS_MASK),
+)
+BLOCK_DEC_TYPE = Action(
+ keypresses=(gtk.keysyms.Up, NO_MODS_MASK),
+)
+RELOAD_BLOCKS = Action(
+ label='Reload _Blocks',
+ tooltip='Reload Blocks',
+ stock_id=gtk.STOCK_REFRESH
+)
+OPEN_HIER = Action(
+ label='Open H_ier',
+ tooltip='Open the source of the selected hierarchical block',
+ stock_id=gtk.STOCK_JUMP_TO,
+)
diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py
new file mode 100644
index 000000000..d95d23f1f
--- /dev/null
+++ b/grc/gui/Bars.py
@@ -0,0 +1,143 @@
+"""
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import Actions
+import pygtk
+pygtk.require('2.0')
+import gtk
+
+##The list of actions for the toolbar.
+TOOLBAR_LIST = (
+ Actions.FLOW_GRAPH_NEW,
+ Actions.FLOW_GRAPH_OPEN,
+ Actions.FLOW_GRAPH_SAVE,
+ Actions.FLOW_GRAPH_CLOSE,
+ None,
+ Actions.FLOW_GRAPH_SCREEN_CAPTURE,
+ None,
+ Actions.BLOCK_CUT,
+ Actions.BLOCK_COPY,
+ Actions.BLOCK_PASTE,
+ Actions.ELEMENT_DELETE,
+ None,
+ Actions.FLOW_GRAPH_UNDO,
+ Actions.FLOW_GRAPH_REDO,
+ None,
+ Actions.ERRORS_WINDOW_DISPLAY,
+ Actions.FLOW_GRAPH_GEN,
+ Actions.FLOW_GRAPH_EXEC,
+ Actions.FLOW_GRAPH_KILL,
+ None,
+ Actions.BLOCK_ROTATE_CCW,
+ Actions.BLOCK_ROTATE_CW,
+ None,
+ Actions.BLOCK_ENABLE,
+ Actions.BLOCK_DISABLE,
+ None,
+ Actions.RELOAD_BLOCKS,
+ Actions.OPEN_HIER,
+)
+
+##The list of actions and categories for the menu bar.
+MENU_BAR_LIST = (
+ (gtk.Action('File', '_File', None, None), [
+ Actions.FLOW_GRAPH_NEW,
+ Actions.FLOW_GRAPH_OPEN,
+ None,
+ Actions.FLOW_GRAPH_SAVE,
+ Actions.FLOW_GRAPH_SAVE_AS,
+ None,
+ Actions.FLOW_GRAPH_SCREEN_CAPTURE,
+ None,
+ Actions.FLOW_GRAPH_CLOSE,
+ Actions.APPLICATION_QUIT,
+ ]),
+ (gtk.Action('Edit', '_Edit', None, None), [
+ Actions.FLOW_GRAPH_UNDO,
+ Actions.FLOW_GRAPH_REDO,
+ None,
+ Actions.BLOCK_CUT,
+ Actions.BLOCK_COPY,
+ Actions.BLOCK_PASTE,
+ Actions.ELEMENT_DELETE,
+ None,
+ Actions.BLOCK_ROTATE_CCW,
+ Actions.BLOCK_ROTATE_CW,
+ None,
+ Actions.BLOCK_ENABLE,
+ Actions.BLOCK_DISABLE,
+ None,
+ Actions.BLOCK_PARAM_MODIFY,
+ ]),
+ (gtk.Action('View', '_View', None, None), [
+ Actions.ERRORS_WINDOW_DISPLAY,
+ ]),
+ (gtk.Action('Build', '_Build', None, None), [
+ Actions.FLOW_GRAPH_GEN,
+ Actions.FLOW_GRAPH_EXEC,
+ Actions.FLOW_GRAPH_KILL,
+ ]),
+ (gtk.Action('Help', '_Help', None, None), [
+ Actions.HELP_WINDOW_DISPLAY,
+ Actions.TYPES_WINDOW_DISPLAY,
+ None,
+ Actions.ABOUT_WINDOW_DISPLAY,
+ ]),
+)
+
+class Toolbar(gtk.Toolbar):
+ """The gtk toolbar with actions added from the toolbar list."""
+
+ def __init__(self):
+ """
+ Parse the list of action names in the toolbar list.
+ Look up the action for each name in the action list and add it to the toolbar.
+ """
+ gtk.Toolbar.__init__(self)
+ self.set_style(gtk.TOOLBAR_ICONS)
+ for action in TOOLBAR_LIST:
+ if action: #add a tool item
+ self.add(action.create_tool_item())
+ #this reset of the tooltip property is required (after creating the tool item) for the tooltip to show
+ action.set_property('tooltip', action.get_property('tooltip'))
+ else: self.add(gtk.SeparatorToolItem())
+
+class MenuBar(gtk.MenuBar):
+ """The gtk menu bar with actions added from the menu bar list."""
+
+ def __init__(self):
+ """
+ Parse the list of submenus from the menubar list.
+ For each submenu, get a list of action names.
+ Look up the action for each name in the action list and add it to the submenu.
+ Add the submenu to the menu bar.
+ """
+ gtk.MenuBar.__init__(self)
+ for main_action, actions in MENU_BAR_LIST:
+ #create the main menu item
+ main_menu_item = main_action.create_menu_item()
+ self.append(main_menu_item)
+ #create the menu
+ main_menu = gtk.Menu()
+ main_menu_item.set_submenu(main_menu)
+ for action in actions:
+ if action: #append a menu item
+ main_menu.append(action.create_menu_item())
+ else: main_menu.append(gtk.SeparatorMenuItem())
+ main_menu.show_all() #this show all is required for the separators to show
diff --git a/grc/gui/Block.py b/grc/gui/Block.py
new file mode 100644
index 000000000..27143e070
--- /dev/null
+++ b/grc/gui/Block.py
@@ -0,0 +1,201 @@
+"""
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from Element import Element
+import Utils
+import Colors
+from .. base import odict
+from Constants import BORDER_PROXIMITY_SENSITIVITY
+from Constants import \
+ BLOCK_LABEL_PADDING, \
+ PORT_SEPARATION, LABEL_SEPARATION, \
+ PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS
+import pygtk
+pygtk.require('2.0')
+import gtk
+import pango
+
+BLOCK_MARKUP_TMPL="""\
+#set $foreground = $block.is_valid() and 'black' or 'red'
+<span foreground="$foreground" font_desc="Sans 8"><b>$encode($block.get_name())</b></span>"""
+
+class Block(Element):
+ """The graphical signal block."""
+
+ def __init__(self):
+ """
+ Block contructor.
+ Add graphics related params to the block.
+ """
+ #add the position param
+ self.get_params().append(self.get_parent().get_parent().Param(
+ block=self,
+ n=odict({
+ 'name': 'GUI Coordinate',
+ 'key': '_coordinate',
+ 'type': 'raw',
+ 'value': '(0, 0)',
+ 'hide': 'all',
+ })
+ ))
+ self.get_params().append(self.get_parent().get_parent().Param(
+ block=self,
+ n=odict({
+ 'name': 'GUI Rotation',
+ 'key': '_rotation',
+ 'type': 'raw',
+ 'value': '0',
+ 'hide': 'all',
+ })
+ ))
+ Element.__init__(self)
+
+ def get_coordinate(self):
+ """
+ Get the coordinate from the position param.
+ @return the coordinate tuple (x, y) or (0, 0) if failure
+ """
+ try: #should evaluate to tuple
+ coor = eval(self.get_param('_coordinate').get_value())
+ x, y = map(int, coor)
+ fgW,fgH = self.get_parent().get_size()
+ if x <= 0:
+ x = 0
+ elif x >= fgW - BORDER_PROXIMITY_SENSITIVITY:
+ x = fgW - BORDER_PROXIMITY_SENSITIVITY
+ if y <= 0:
+ y = 0
+ elif y >= fgH - BORDER_PROXIMITY_SENSITIVITY:
+ y = fgH - BORDER_PROXIMITY_SENSITIVITY
+ return (x, y)
+ except:
+ self.set_coordinate((0, 0))
+ return (0, 0)
+
+ def set_coordinate(self, coor):
+ """
+ Set the coordinate into the position param.
+ @param coor the coordinate tuple (x, y)
+ """
+ self.get_param('_coordinate').set_value(str(coor))
+
+ def get_rotation(self):
+ """
+ Get the rotation from the position param.
+ @return the rotation in degrees or 0 if failure
+ """
+ try: #should evaluate to dict
+ rotation = eval(self.get_param('_rotation').get_value())
+ return int(rotation)
+ except:
+ self.set_rotation(POSSIBLE_ROTATIONS[0])
+ return POSSIBLE_ROTATIONS[0]
+
+ def set_rotation(self, rot):
+ """
+ Set the rotation into the position param.
+ @param rot the rotation in degrees
+ """
+ self.get_param('_rotation').set_value(str(rot))
+
+ def create_shapes(self):
+ """Update the block, parameters, and ports when a change occurs."""
+ Element.create_shapes(self)
+ if self.is_horizontal(): self.add_area((0, 0), (self.W, self.H))
+ elif self.is_vertical(): self.add_area((0, 0), (self.H, self.W))
+
+ def create_labels(self):
+ """Create the labels for the signal block."""
+ Element.create_labels(self)
+ self._bg_color = self.get_enabled() and Colors.BLOCK_ENABLED_COLOR or Colors.BLOCK_DISABLED_COLOR
+ layouts = list()
+ #create the main layout
+ layout = gtk.DrawingArea().create_pango_layout('')
+ layouts.append(layout)
+ layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self))
+ self.label_width, self.label_height = layout.get_pixel_size()
+ #display the params
+ markups = [param.get_markup() for param in self.get_params() if param.get_hide() not in ('all', 'part')]
+ if markups:
+ layout = gtk.DrawingArea().create_pango_layout('')
+ layout.set_spacing(LABEL_SEPARATION*pango.SCALE)
+ layout.set_markup('\n'.join(markups))
+ layouts.append(layout)
+ w,h = layout.get_pixel_size()
+ self.label_width = max(w, self.label_width)
+ self.label_height += h + LABEL_SEPARATION
+ width = self.label_width
+ height = self.label_height
+ #setup the pixmap
+ pixmap = self.get_parent().new_pixmap(width, height)
+ gc = pixmap.new_gc()
+ gc.set_foreground(self._bg_color)
+ pixmap.draw_rectangle(gc, True, 0, 0, width, height)
+ #draw the layouts
+ h_off = 0
+ for i,layout in enumerate(layouts):
+ w,h = layout.get_pixel_size()
+ if i == 0: w_off = (width-w)/2
+ else: w_off = 0
+ pixmap.draw_layout(gc, w_off, h_off, layout)
+ h_off = h + h_off + LABEL_SEPARATION
+ #create vertical and horizontal pixmaps
+ self.horizontal_label = pixmap
+ if self.is_vertical():
+ self.vertical_label = self.get_parent().new_pixmap(height, width)
+ Utils.rotate_pixmap(gc, self.horizontal_label, self.vertical_label)
+ #calculate width and height needed
+ self.W = self.label_width + 2*BLOCK_LABEL_PADDING
+ self.H = max(*(
+ [self.label_height+2*BLOCK_LABEL_PADDING] + [2*PORT_BORDER_SEPARATION + \
+ sum([port.H + PORT_SEPARATION for port in ports]) - PORT_SEPARATION
+ for ports in (self.get_sources(), self.get_sinks())]
+ ))
+
+ def draw(self, gc, window):
+ """
+ Draw the signal block with label and inputs/outputs.
+ @param gc the graphics context
+ @param window the gtk window to draw on
+ """
+ x, y = self.get_coordinate()
+ #draw main block
+ Element.draw(
+ self, gc, window, bg_color=self._bg_color,
+ border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or Colors.BORDER_COLOR,
+ )
+ #draw label image
+ if self.is_horizontal():
+ window.draw_drawable(gc, self.horizontal_label, 0, 0, x+BLOCK_LABEL_PADDING, y+(self.H-self.label_height)/2, -1, -1)
+ elif self.is_vertical():
+ window.draw_drawable(gc, self.vertical_label, 0, 0, x+(self.H-self.label_height)/2, y+BLOCK_LABEL_PADDING, -1, -1)
+ #draw ports
+ for port in self.get_ports(): port.draw(gc, window)
+
+ def what_is_selected(self, coor, coor_m=None):
+ """
+ Get the element that is selected.
+ @param coor the (x,y) tuple
+ @param coor_m the (x_m, y_m) tuple
+ @return this block, a port, or None
+ """
+ for port in self.get_ports():
+ port_selected = port.what_is_selected(coor, coor_m)
+ if port_selected: return port_selected
+ return Element.what_is_selected(self, coor, coor_m)
diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py
new file mode 100644
index 000000000..62afb6205
--- /dev/null
+++ b/grc/gui/BlockTreeWindow.py
@@ -0,0 +1,201 @@
+"""
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from Constants import DEFAULT_BLOCKS_WINDOW_WIDTH, DND_TARGETS
+import Utils
+import pygtk
+pygtk.require('2.0')
+import gtk
+import gobject
+
+NAME_INDEX = 0
+KEY_INDEX = 1
+DOC_INDEX = 2
+
+DOC_MARKUP_TMPL="""\
+#if $doc
+$encode($doc)#slurp
+#else
+undocumented#slurp
+#end if"""
+
+CAT_MARKUP_TMPL="""Category: $cat"""
+
+class BlockTreeWindow(gtk.VBox):
+ """The block selection panel."""
+
+ def __init__(self, platform, get_flow_graph):
+ """
+ BlockTreeWindow constructor.
+ Create a tree view of the possible blocks in the platform.
+ The tree view nodes will be category names, the leaves will be block names.
+ A mouse double click or button press action will trigger the add block event.
+ @param platform the particular platform will all block prototypes
+ @param get_flow_graph get the selected flow graph
+ """
+ gtk.VBox.__init__(self)
+ self.platform = platform
+ self.get_flow_graph = get_flow_graph
+ #make the tree model for holding blocks
+ self.treestore = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
+ self.treeview = gtk.TreeView(self.treestore)
+ self.treeview.set_enable_search(False) #disable pop up search box
+ self.treeview.add_events(gtk.gdk.BUTTON_PRESS_MASK)
+ self.treeview.connect('button-press-event', self._handle_mouse_button_press)
+ selection = self.treeview.get_selection()
+ selection.set_mode('single')
+ selection.connect('changed', self._handle_selection_change)
+ renderer = gtk.CellRendererText()
+ column = gtk.TreeViewColumn('Blocks', renderer, text=NAME_INDEX)
+ self.treeview.append_column(column)
+ #setup the search
+ self.treeview.set_enable_search(True)
+ self.treeview.set_search_equal_func(self._handle_search)
+ #try to enable the tooltips (available in pygtk 2.12 and above)
+ try: self.treeview.set_tooltip_column(DOC_INDEX)
+ except: pass
+ #setup drag and drop
+ self.treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, DND_TARGETS, gtk.gdk.ACTION_COPY)
+ self.treeview.connect('drag-data-get', self._handle_drag_get_data)
+ #make the scrolled window to hold the tree view
+ scrolled_window = gtk.ScrolledWindow()
+ scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ scrolled_window.add_with_viewport(self.treeview)
+ scrolled_window.set_size_request(DEFAULT_BLOCKS_WINDOW_WIDTH, -1)
+ self.pack_start(scrolled_window)
+ #add button
+ self.add_button = gtk.Button(None, gtk.STOCK_ADD)
+ self.add_button.connect('clicked', self._handle_add_button)
+ self.pack_start(self.add_button, False)
+ #map categories to iters, automatic mapping for root
+ self._categories = {tuple(): None}
+ #add blocks and categories
+ self.platform.load_block_tree(self)
+ #initialize
+ self._update_add_button()
+
+ def clear(self):
+ self.treestore.clear();
+ self._categories = {tuple(): None}
+
+
+ ############################################################
+ ## Block Tree Methods
+ ############################################################
+ def add_block(self, category, block=None):
+ """
+ Add a block with category to this selection window.
+ Add only the category when block is None.
+ @param category the category list or path string
+ @param block the block object or None
+ """
+ if isinstance(category, str): category = category.split('/')
+ category = tuple(filter(lambda x: x, category)) #tuple is hashable
+ #add category and all sub categories
+ for i, cat_name in enumerate(category):
+ sub_category = category[:i+1]
+ if sub_category not in self._categories:
+ iter = self.treestore.insert_before(self._categories[sub_category[:-1]], None)
+ self.treestore.set_value(iter, NAME_INDEX, '[ %s ]'%cat_name)
+ self.treestore.set_value(iter, KEY_INDEX, '')
+ self.treestore.set_value(iter, DOC_INDEX, Utils.parse_template(CAT_MARKUP_TMPL, cat=cat_name))
+ self._categories[sub_category] = iter
+ #add block
+ if block is None: return
+ iter = self.treestore.insert_before(self._categories[category], None)
+ self.treestore.set_value(iter, NAME_INDEX, block.get_name())
+ self.treestore.set_value(iter, KEY_INDEX, block.get_key())
+ self.treestore.set_value(iter, DOC_INDEX, Utils.parse_template(DOC_MARKUP_TMPL, doc=block.get_doc()))
+
+ ############################################################
+ ## Helper Methods
+ ############################################################
+ def _get_selected_block_key(self):
+ """
+ Get the currently selected block key.
+ @return the key of the selected block or a empty string
+ """
+ selection = self.treeview.get_selection()
+ treestore, iter = selection.get_selected()
+ return iter and treestore.get_value(iter, KEY_INDEX) or ''
+
+ def _update_add_button(self):
+ """
+ Update the add button's sensitivity.
+ The button should be active only if a block is selected.
+ """
+ key = self._get_selected_block_key()
+ self.add_button.set_sensitive(bool(key))
+
+ def _add_selected_block(self):
+ """
+ Add the selected block with the given key to the flow graph.
+ """
+ key = self._get_selected_block_key()
+ if key: self.get_flow_graph().add_new_block(key)
+
+ ############################################################
+ ## Event Handlers
+ ############################################################
+ def _handle_search(self, model, column, key, iter):
+ #determine which blocks match the search key
+ blocks = self.get_flow_graph().get_parent().get_blocks()
+ matching_blocks = filter(lambda b: key in b.get_key() or key in b.get_name().lower(), blocks)
+ #remove the old search category
+ try: self.treestore.remove(self._categories.pop((self._search_category, )))
+ except (KeyError, AttributeError): pass #nothing to remove
+ #create a search category
+ if not matching_blocks: return
+ self._search_category = 'Search: %s'%key
+ for block in matching_blocks: self.add_block(self._search_category, block)
+ #expand the search category
+ path = self.treestore.get_path(self._categories[(self._search_category, )])
+ self.treeview.collapse_all()
+ self.treeview.expand_row(path, open_all=False)
+
+ def _handle_drag_get_data(self, widget, drag_context, selection_data, info, time):
+ """
+ Handle a drag and drop by setting the key to the selection object.
+ This will call the destination handler for drag and drop.
+ Only call set when the key is valid to ignore DND from categories.
+ """
+ key = self._get_selected_block_key()
+ if key: selection_data.set(selection_data.target, 8, key)
+
+ def _handle_mouse_button_press(self, widget, event):
+ """
+ Handle the mouse button press.
+ If a left double click is detected, call add selected block.
+ """
+ if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
+ self._add_selected_block()
+
+ def _handle_selection_change(self, selection):
+ """
+ Handle a selection change in the tree view.
+ If a selection changes, set the add button sensitive.
+ """
+ self._update_add_button()
+
+ def _handle_add_button(self, widget):
+ """
+ Handle the add button clicked signal.
+ Call add selected block.
+ """
+ self._add_selected_block()
diff --git a/grc/gui/CMakeLists.txt b/grc/gui/CMakeLists.txt
new file mode 100644
index 000000000..c2eb16e9f
--- /dev/null
+++ b/grc/gui/CMakeLists.txt
@@ -0,0 +1,48 @@
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+GR_PYTHON_INSTALL(FILES
+ Block.py
+ Colors.py
+ Constants.py
+ Connection.py
+ Element.py
+ FlowGraph.py
+ Param.py
+ Platform.py
+ Port.py
+ Utils.py
+ ActionHandler.py
+ Actions.py
+ Bars.py
+ BlockTreeWindow.py
+ Dialogs.py
+ DrawingArea.py
+ FileDialogs.py
+ MainWindow.py
+ Messages.py
+ NotebookPage.py
+ PropsDialog.py
+ Preferences.py
+ StateCache.py
+ __init__.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/gui
+ COMPONENT "grc"
+)
diff --git a/grc/gui/Colors.py b/grc/gui/Colors.py
new file mode 100644
index 000000000..c79dadee3
--- /dev/null
+++ b/grc/gui/Colors.py
@@ -0,0 +1,40 @@
+"""
+Copyright 2008 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+
+_COLORMAP = gtk.gdk.colormap_get_system() #create all of the colors
+def get_color(color_code): return _COLORMAP.alloc_color(color_code, True, True)
+
+HIGHLIGHT_COLOR = get_color('#00FFFF')
+BORDER_COLOR = get_color('black')
+#param entry boxes
+PARAM_ENTRY_TEXT_COLOR = get_color('black')
+ENTRYENUM_CUSTOM_COLOR = get_color('#EEEEEE')
+#flow graph color constants
+FLOWGRAPH_BACKGROUND_COLOR = get_color('#FFF9FF')
+#block color constants
+BLOCK_ENABLED_COLOR = get_color('#F1ECFF')
+BLOCK_DISABLED_COLOR = get_color('#CCCCCC')
+#connection color constants
+CONNECTION_ENABLED_COLOR = get_color('black')
+CONNECTION_DISABLED_COLOR = get_color('#999999')
+CONNECTION_ERROR_COLOR = get_color('red')
diff --git a/grc/gui/Connection.py b/grc/gui/Connection.py
new file mode 100644
index 000000000..fabf34ee7
--- /dev/null
+++ b/grc/gui/Connection.py
@@ -0,0 +1,143 @@
+"""
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import Utils
+from Element import Element
+import Colors
+from Constants import CONNECTOR_ARROW_BASE, CONNECTOR_ARROW_HEIGHT
+
+class Connection(Element):
+ """
+ A graphical connection for ports.
+ The connection has 2 parts, the arrow and the wire.
+ The coloring of the arrow and wire exposes the status of 3 states:
+ enabled/disabled, valid/invalid, highlighted/non-highlighted.
+ The wire coloring exposes the enabled and highlighted states.
+ The arrow coloring exposes the enabled and valid states.
+ """
+
+ def __init__(self): Element.__init__(self)
+
+ def get_coordinate(self):
+ """
+ Get the 0,0 coordinate.
+ Coordinates are irrelevant in connection.
+ @return 0, 0
+ """
+ return (0, 0)
+
+ def get_rotation(self):
+ """
+ Get the 0 degree rotation.
+ Rotations are irrelevant in connection.
+ @return 0
+ """
+ return 0
+
+ def create_shapes(self):
+ """Precalculate relative coordinates."""
+ Element.create_shapes(self)
+ self._sink_rot = None
+ self._source_rot = None
+ self._sink_coor = None
+ self._source_coor = None
+ #get the source coordinate
+ connector_length = self.get_source().get_connector_length()
+ self.x1, self.y1 = Utils.get_rotated_coordinate((connector_length, 0), self.get_source().get_rotation())
+ #get the sink coordinate
+ connector_length = self.get_sink().get_connector_length() + CONNECTOR_ARROW_HEIGHT
+ self.x2, self.y2 = Utils.get_rotated_coordinate((-connector_length, 0), self.get_sink().get_rotation())
+ #build the arrow
+ self.arrow = [(0, 0),
+ Utils.get_rotated_coordinate((-CONNECTOR_ARROW_HEIGHT, -CONNECTOR_ARROW_BASE/2), self.get_sink().get_rotation()),
+ Utils.get_rotated_coordinate((-CONNECTOR_ARROW_HEIGHT, CONNECTOR_ARROW_BASE/2), self.get_sink().get_rotation()),
+ ]
+ self._update_after_move()
+ if not self.get_enabled(): self._arrow_color = Colors.CONNECTION_DISABLED_COLOR
+ elif not self.is_valid(): self._arrow_color = Colors.CONNECTION_ERROR_COLOR
+ else: self._arrow_color = Colors.CONNECTION_ENABLED_COLOR
+
+ def _update_after_move(self):
+ """Calculate coordinates."""
+ self.clear() #FIXME do i want this here?
+ #source connector
+ source = self.get_source()
+ X, Y = source.get_connector_coordinate()
+ x1, y1 = self.x1 + X, self.y1 + Y
+ self.add_line((x1, y1), (X, Y))
+ #sink connector
+ sink = self.get_sink()
+ X, Y = sink.get_connector_coordinate()
+ x2, y2 = self.x2 + X, self.y2 + Y
+ self.add_line((x2, y2), (X, Y))
+ #adjust arrow
+ self._arrow = [(x+X, y+Y) for x,y in self.arrow]
+ #add the horizontal and vertical lines in this connection
+ if abs(source.get_connector_direction() - sink.get_connector_direction()) == 180:
+ #2 possible point sets to create a 3-line connector
+ mid_x, mid_y = (x1 + x2)/2.0, (y1 + y2)/2.0
+ points = [((mid_x, y1), (mid_x, y2)), ((x1, mid_y), (x2, mid_y))]
+ #source connector -> points[0][0] should be in the direction of source (if possible)
+ if Utils.get_angle_from_coordinates((x1, y1), points[0][0]) != source.get_connector_direction(): points.reverse()
+ #points[0][0] -> sink connector should not be in the direction of sink
+ if Utils.get_angle_from_coordinates(points[0][0], (x2, y2)) == sink.get_connector_direction(): points.reverse()
+ #points[0][0] -> source connector should not be in the direction of source
+ if Utils.get_angle_from_coordinates(points[0][0], (x1, y1)) == source.get_connector_direction(): points.reverse()
+ #create 3-line connector
+ p1, p2 = map(int, points[0][0]), map(int, points[0][1])
+ self.add_line((x1, y1), p1)
+ self.add_line(p1, p2)
+ self.add_line((x2, y2), p2)
+ else:
+ #2 possible points to create a right-angled connector
+ points = [(x1, y2), (x2, y1)]
+ #source connector -> points[0] should be in the direction of source (if possible)
+ if Utils.get_angle_from_coordinates((x1, y1), points[0]) != source.get_connector_direction(): points.reverse()
+ #points[0] -> sink connector should not be in the direction of sink
+ if Utils.get_angle_from_coordinates(points[0], (x2, y2)) == sink.get_connector_direction(): points.reverse()
+ #points[0] -> source connector should not be in the direction of source
+ if Utils.get_angle_from_coordinates(points[0], (x1, y1)) == source.get_connector_direction(): points.reverse()
+ #create right-angled connector
+ self.add_line((x1, y1), points[0])
+ self.add_line((x2, y2), points[0])
+
+ def draw(self, gc, window):
+ """
+ Draw the connection.
+ @param gc the graphics context
+ @param window the gtk window to draw on
+ """
+ sink = self.get_sink()
+ source = self.get_source()
+ #check for changes
+ if self._sink_rot != sink.get_rotation() or self._source_rot != source.get_rotation(): self.create_shapes()
+ elif self._sink_coor != sink.get_coordinate() or self._source_coor != source.get_coordinate(): self._update_after_move()
+ #cache values
+ self._sink_rot = sink.get_rotation()
+ self._source_rot = source.get_rotation()
+ self._sink_coor = sink.get_coordinate()
+ self._source_coor = source.get_coordinate()
+ #draw
+ if self.is_highlighted(): border_color = Colors.HIGHLIGHT_COLOR
+ elif self.get_enabled(): border_color = Colors.CONNECTION_ENABLED_COLOR
+ else: border_color = Colors.CONNECTION_DISABLED_COLOR
+ Element.draw(self, gc, window, bg_color=None, border_color=border_color)
+ #draw arrow on sink port
+ gc.set_foreground(self._arrow_color)
+ window.draw_polygon(gc, True, self._arrow)
diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py
new file mode 100644
index 000000000..7fabcfc0a
--- /dev/null
+++ b/grc/gui/Constants.py
@@ -0,0 +1,83 @@
+"""
+Copyright 2008, 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+import os
+
+##default path for the open/save dialogs
+DEFAULT_FILE_PATH = os.getcwd()
+
+##file extensions
+IMAGE_FILE_EXTENSION = '.png'
+
+##name for new/unsaved flow graphs
+NEW_FLOGRAPH_TITLE = 'untitled'
+
+##main window constraints
+MIN_WINDOW_WIDTH = 600
+MIN_WINDOW_HEIGHT = 400
+##dialog constraints
+MIN_DIALOG_WIDTH = 500
+MIN_DIALOG_HEIGHT = 500
+##default sizes
+DEFAULT_BLOCKS_WINDOW_WIDTH = 100
+DEFAULT_REPORTS_WINDOW_WIDTH = 100
+
+##The size of the state saving cache in the flow graph (for undo/redo functionality)
+STATE_CACHE_SIZE = 42
+
+##Shared targets for drag and drop of blocks
+DND_TARGETS = [('STRING', gtk.TARGET_SAME_APP, 0)]
+
+#label constraint dimensions
+LABEL_SEPARATION = 3
+BLOCK_LABEL_PADDING = 7
+PORT_LABEL_PADDING = 2
+
+#port constraint dimensions
+PORT_SEPARATION = 17
+PORT_BORDER_SEPARATION = 9
+PORT_MIN_WIDTH = 20
+
+#minimal length of connector
+CONNECTOR_EXTENSION_MINIMAL = 11
+
+#increment length for connector
+CONNECTOR_EXTENSION_INCREMENT = 11
+
+#connection arrow dimensions
+CONNECTOR_ARROW_BASE = 13
+CONNECTOR_ARROW_HEIGHT = 17
+
+#possible rotations in degrees
+POSSIBLE_ROTATIONS = (0, 90, 180, 270)
+
+#How close can the mouse get to the window border before mouse events are ignored.
+BORDER_PROXIMITY_SENSITIVITY = 50
+
+#How close the mouse can get to the edge of the visible window before scrolling is invoked.
+SCROLL_PROXIMITY_SENSITIVITY = 30
+
+#When the window has to be scrolled, move it this distance in the required direction.
+SCROLL_DISTANCE = 15
+
+#How close the mouse click can be to a line and register a connection select.
+LINE_SELECT_SENSITIVITY = 5
diff --git a/grc/gui/Dialogs.py b/grc/gui/Dialogs.py
new file mode 100644
index 000000000..473c796af
--- /dev/null
+++ b/grc/gui/Dialogs.py
@@ -0,0 +1,118 @@
+"""
+Copyright 2008, 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+import Utils
+
+class TextDisplay(gtk.TextView):
+ """A non editable gtk text view."""
+
+ def __init__(self, text=''):
+ """
+ TextDisplay constructor.
+ @param text the text to display (string)
+ """
+ text_buffer = gtk.TextBuffer()
+ text_buffer.set_text(text)
+ self.set_text = text_buffer.set_text
+ self.insert = lambda line: text_buffer.insert(text_buffer.get_end_iter(), line)
+ gtk.TextView.__init__(self, text_buffer)
+ self.set_editable(False)
+ self.set_cursor_visible(False)
+ self.set_wrap_mode(gtk.WRAP_WORD_CHAR)
+
+def MessageDialogHelper(type, buttons, title=None, markup=None):
+ """
+ Create a modal message dialog and run it.
+ @param type the type of message: gtk.MESSAGE_INFO, gtk.MESSAGE_WARNING, gtk.MESSAGE_QUESTION or gtk.MESSAGE_ERROR
+ @param buttons the predefined set of buttons to use:
+ gtk.BUTTONS_NONE, gtk.BUTTONS_OK, gtk.BUTTONS_CLOSE, gtk.BUTTONS_CANCEL, gtk.BUTTONS_YES_NO, gtk.BUTTONS_OK_CANCEL
+ @param tittle the title of the window (string)
+ @param markup the message text with pango markup
+ @return the gtk response from run()
+ """
+ message_dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, type, buttons)
+ if title: message_dialog.set_title(title)
+ if markup: message_dialog.set_markup(markup)
+ response = message_dialog.run()
+ message_dialog.destroy()
+ return response
+
+
+ERRORS_MARKUP_TMPL="""\
+#for $i, $err_msg in enumerate($errors)
+<b>Error $i:</b>
+$encode($err_msg.replace('\t', ' '))
+
+#end for"""
+def ErrorsDialog(flowgraph): MessageDialogHelper(
+ type=gtk.MESSAGE_ERROR,
+ buttons=gtk.BUTTONS_CLOSE,
+ title='Flow Graph Errors',
+ markup=Utils.parse_template(ERRORS_MARKUP_TMPL, errors=flowgraph.get_error_messages()),
+)
+
+class AboutDialog(gtk.AboutDialog):
+ """A cute little about dialog."""
+
+ def __init__(self, platform):
+ """AboutDialog constructor."""
+ gtk.AboutDialog.__init__(self)
+ self.set_name(platform.get_name())
+ self.set_version(platform.get_version())
+ self.set_license(platform.get_license())
+ self.set_copyright(platform.get_license().splitlines()[0])
+ self.set_website(platform.get_website())
+ self.run()
+ self.destroy()
+
+def HelpDialog(): MessageDialogHelper(
+ type=gtk.MESSAGE_INFO,
+ buttons=gtk.BUTTONS_CLOSE,
+ title='Help',
+ markup="""\
+<b>Usage Tips</b>
+
+<u>Add block</u>: drag and drop or double click a block in the block selection window.
+<u>Rotate block</u>: Select a block, press left/right on the keyboard.
+<u>Change type</u>: Select a block, press up/down on the keyboard.
+<u>Edit parameters</u>: double click on a block in the flow graph.
+<u>Make connection</u>: click on the source port of one block, then click on the sink port of another block.
+<u>Remove connection</u>: select the connection and press delete, or drag the connection.
+
+* See the menu for other keyboard shortcuts.""")
+
+COLORS_DIALOG_MARKUP_TMPL = """\
+<b>Color Mapping</b>
+
+#if $colors
+ #set $max_len = max([len(color[0]) for color in $colors]) + 10
+ #for $title, $color_spec in $colors
+<span background="$color_spec"><tt>$($encode($title).center($max_len))</tt></span>
+ #end for
+#end if
+"""
+
+def TypesDialog(platform): MessageDialogHelper(
+ type=gtk.MESSAGE_INFO,
+ buttons=gtk.BUTTONS_CLOSE,
+ title='Types',
+ markup=Utils.parse_template(COLORS_DIALOG_MARKUP_TMPL, colors=platform.get_colors()))
diff --git a/grc/gui/DrawingArea.py b/grc/gui/DrawingArea.py
new file mode 100644
index 000000000..790df7c3f
--- /dev/null
+++ b/grc/gui/DrawingArea.py
@@ -0,0 +1,133 @@
+"""
+Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT, DND_TARGETS
+
+class DrawingArea(gtk.DrawingArea):
+ """
+ DrawingArea is the gtk pixel map that graphical elements may draw themselves on.
+ The drawing area also responds to mouse and key events.
+ """
+
+ def __init__(self, flow_graph):
+ """
+ DrawingArea contructor.
+ Connect event handlers.
+ @param main_window the main_window containing all flow graphs
+ """
+ self.ctrl_mask = False
+ self._flow_graph = flow_graph
+ gtk.DrawingArea.__init__(self)
+ self.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT)
+ self.connect('realize', self._handle_window_realize)
+ self.connect('configure-event', self._handle_window_configure)
+ self.connect('expose-event', self._handle_window_expose)
+ self.connect('motion-notify-event', self._handle_mouse_motion)
+ self.connect('button-press-event', self._handle_mouse_button_press)
+ self.connect('button-release-event', self._handle_mouse_button_release)
+ self.add_events(
+ gtk.gdk.BUTTON_PRESS_MASK | \
+ gtk.gdk.POINTER_MOTION_MASK | \
+ gtk.gdk.BUTTON_RELEASE_MASK | \
+ gtk.gdk.LEAVE_NOTIFY_MASK | \
+ gtk.gdk.ENTER_NOTIFY_MASK
+ )
+ #setup drag and drop
+ self.drag_dest_set(gtk.DEST_DEFAULT_ALL, DND_TARGETS, gtk.gdk.ACTION_COPY)
+ self.connect('drag-data-received', self._handle_drag_data_received)
+ #setup the focus flag
+ self._focus_flag = False
+ self.get_focus_flag = lambda: self._focus_flag
+ def _handle_focus_event(widget, event, focus_flag): self._focus_flag = focus_flag
+ self.connect('leave-notify-event', _handle_focus_event, False)
+ self.connect('enter-notify-event', _handle_focus_event, True)
+
+ def new_pixmap(self, width, height): return gtk.gdk.Pixmap(self.window, width, height, -1)
+ def get_pixbuf(self):
+ width, height = self._pixmap.get_size()
+ pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, width, height)
+ pixbuf.get_from_drawable(self._pixmap, self._pixmap.get_colormap(), 0, 0, 0, 0, width, height)
+ return pixbuf
+
+ ##########################################################################
+ ## Handlers
+ ##########################################################################
+ def _handle_drag_data_received(self, widget, drag_context, x, y, selection_data, info, time):
+ """
+ Handle a drag and drop by adding a block at the given coordinate.
+ """
+ self._flow_graph.add_new_block(selection_data.data, (x, y))
+
+ def _handle_mouse_button_press(self, widget, event):
+ """
+ Forward button click information to the flow graph.
+ """
+ self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK
+ if event.button == 1: self._flow_graph.handle_mouse_selector_press(
+ double_click=(event.type == gtk.gdk._2BUTTON_PRESS),
+ coordinate=(event.x, event.y),
+ )
+ if event.button == 3: self._flow_graph.handle_mouse_context_press(
+ coordinate=(event.x, event.y),
+ event=event,
+ )
+
+ def _handle_mouse_button_release(self, widget, event):
+ """
+ Forward button release information to the flow graph.
+ """
+ self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK
+ if event.button == 1: self._flow_graph.handle_mouse_selector_release(
+ coordinate=(event.x, event.y),
+ )
+
+ def _handle_mouse_motion(self, widget, event):
+ """
+ Forward mouse motion information to the flow graph.
+ """
+ self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK
+ self._flow_graph.handle_mouse_motion(
+ coordinate=(event.x, event.y),
+ )
+
+ def _handle_window_realize(self, widget):
+ """
+ Called when the window is realized.
+ Update the flowgraph, which calls new pixmap.
+ """
+ self._flow_graph.update()
+
+ def _handle_window_configure(self, widget, event):
+ """
+ Called when the window is resized.
+ Create a new pixmap for background buffer.
+ """
+ self._pixmap = self.new_pixmap(*self.get_size_request())
+
+ def _handle_window_expose(self, widget, event):
+ """
+ Called when window is exposed, or queue_draw is called.
+ Double buffering: draw to pixmap, then draw pixmap to window.
+ """
+ gc = self.window.new_gc()
+ self._flow_graph.draw(gc, self._pixmap)
+ self.window.draw_drawable(gc, self._pixmap, 0, 0, 0, 0, -1, -1)
diff --git a/grc/gui/Element.py b/grc/gui/Element.py
new file mode 100644
index 000000000..e020c5caa
--- /dev/null
+++ b/grc/gui/Element.py
@@ -0,0 +1,228 @@
+"""
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from Constants import LINE_SELECT_SENSITIVITY
+from Constants import POSSIBLE_ROTATIONS
+
+class Element(object):
+ """
+ GraphicalElement is the base class for all graphical elements.
+ It contains an X,Y coordinate, a list of rectangular areas that the element occupies,
+ and methods to detect selection of those areas.
+ """
+
+ def __init__(self):
+ """
+ Make a new list of rectangular areas and lines, and set the coordinate and the rotation.
+ """
+ self.set_rotation(POSSIBLE_ROTATIONS[0])
+ self.set_coordinate((0, 0))
+ self.clear()
+ self.set_highlighted(False)
+
+ def is_horizontal(self, rotation=None):
+ """
+ Is this element horizontal?
+ If rotation is None, use this element's rotation.
+ @param rotation the optional rotation
+ @return true if rotation is horizontal
+ """
+ rotation = rotation or self.get_rotation()
+ return rotation in (0, 180)
+
+ def is_vertical(self, rotation=None):
+ """
+ Is this element vertical?
+ If rotation is None, use this element's rotation.
+ @param rotation the optional rotation
+ @return true if rotation is vertical
+ """
+ rotation = rotation or self.get_rotation()
+ return rotation in (90, 270)
+
+ def create_labels(self):
+ """
+ Create labels (if applicable) and call on all children.
+ Call this base method before creating labels in the element.
+ """
+ for child in self.get_children(): child.create_labels()
+
+ def create_shapes(self):
+ """
+ Create shapes (if applicable) and call on all children.
+ Call this base method before creating shapes in the element.
+ """
+ self.clear()
+ for child in self.get_children(): child.create_shapes()
+
+ def draw(self, gc, window, border_color, bg_color):
+ """
+ Draw in the given window.
+ @param gc the graphics context
+ @param window the gtk window to draw on
+ @param border_color the color for lines and rectangle borders
+ @param bg_color the color for the inside of the rectangle
+ """
+ X,Y = self.get_coordinate()
+ for (rX,rY),(W,H) in self._areas_list:
+ aX = X + rX
+ aY = Y + rY
+ gc.set_foreground(bg_color)
+ window.draw_rectangle(gc, True, aX, aY, W, H)
+ gc.set_foreground(border_color)
+ window.draw_rectangle(gc, False, aX, aY, W, H)
+ for (x1, y1),(x2, y2) in self._lines_list:
+ gc.set_foreground(border_color)
+ window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2)
+
+ def rotate(self, rotation):
+ """
+ Rotate all of the areas by 90 degrees.
+ @param rotation multiple of 90 degrees
+ """
+ self.set_rotation((self.get_rotation() + rotation)%360)
+
+ def clear(self):
+ """Empty the lines and areas."""
+ self._areas_list = list()
+ self._lines_list = list()
+
+ def set_coordinate(self, coor):
+ """
+ Set the reference coordinate.
+ @param coor the coordinate tuple (x,y)
+ """
+ self.coor = coor
+
+ def get_parent(self):
+ """
+ Get the parent of this element.
+ @return the parent
+ """
+ return self.parent
+
+ def set_highlighted(self, highlighted):
+ """
+ Set the highlight status.
+ @param highlighted true to enable highlighting
+ """
+ self.highlighted = highlighted
+
+ def is_highlighted(self):
+ """
+ Get the highlight status.
+ @return true if highlighted
+ """
+ return self.highlighted
+
+ def get_coordinate(self):
+ """Get the coordinate.
+ @return the coordinate tuple (x,y)
+ """
+ return self.coor
+
+ def move(self, delta_coor):
+ """
+ Move the element by adding the delta_coor to the current coordinate.
+ @param delta_coor (delta_x,delta_y) tuple
+ """
+ deltaX, deltaY = delta_coor
+ X, Y = self.get_coordinate()
+ self.set_coordinate((X+deltaX, Y+deltaY))
+
+ def add_area(self, rel_coor, area):
+ """
+ Add an area to the area list.
+ An area is actually a coordinate relative to the main coordinate
+ with a width/height pair relative to the area coordinate.
+ A positive width is to the right of the coordinate.
+ A positive height is above the coordinate.
+ The area is associated with a rotation.
+ @param rel_coor (x,y) offset from this element's coordinate
+ @param area (width,height) tuple
+ """
+ self._areas_list.append((rel_coor, area))
+
+ def add_line(self, rel_coor1, rel_coor2):
+ """
+ Add a line to the line list.
+ A line is defined by 2 relative coordinates.
+ Lines must be horizontal or vertical.
+ The line is associated with a rotation.
+ @param rel_coor1 relative (x1,y1) tuple
+ @param rel_coor2 relative (x2,y2) tuple
+ """
+ self._lines_list.append((rel_coor1, rel_coor2))
+
+ def what_is_selected(self, coor, coor_m=None):
+ """
+ One coordinate specified:
+ Is this element selected at given coordinate?
+ ie: is the coordinate encompassed by one of the areas or lines?
+ Both coordinates specified:
+ Is this element within the rectangular region defined by both coordinates?
+ ie: do any area corners or line endpoints fall within the region?
+ @param coor the selection coordinate, tuple x, y
+ @param coor_m an additional selection coordinate.
+ @return self if one of the areas/lines encompasses coor, else None.
+ """
+ #function to test if p is between a and b (inclusive)
+ in_between = lambda p, a, b: p >= min(a, b) and p <= max(a, b)
+ #relative coordinate
+ x, y = [a-b for a,b in zip(coor, self.get_coordinate())]
+ if coor_m:
+ x_m, y_m = [a-b for a,b in zip(coor_m, self.get_coordinate())]
+ #handle rectangular areas
+ for (x1,y1), (w,h) in self._areas_list:
+ if in_between(x1, x, x_m) and in_between(y1, y, y_m) or \
+ in_between(x1+w, x, x_m) and in_between(y1, y, y_m) or \
+ in_between(x1, x, x_m) and in_between(y1+h, y, y_m) or \
+ in_between(x1+w, x, x_m) and in_between(y1+h, y, y_m):
+ return self
+ #handle horizontal or vertical lines
+ for (x1, y1), (x2, y2) in self._lines_list:
+ if in_between(x1, x, x_m) and in_between(y1, y, y_m) or \
+ in_between(x2, x, x_m) and in_between(y2, y, y_m):
+ return self
+ return None
+ else:
+ #handle rectangular areas
+ for (x1,y1), (w,h) in self._areas_list:
+ if in_between(x, x1, x1+w) and in_between(y, y1, y1+h): return self
+ #handle horizontal or vertical lines
+ for (x1, y1), (x2, y2) in self._lines_list:
+ if x1 == x2: x1, x2 = x1-LINE_SELECT_SENSITIVITY, x2+LINE_SELECT_SENSITIVITY
+ if y1 == y2: y1, y2 = y1-LINE_SELECT_SENSITIVITY, y2+LINE_SELECT_SENSITIVITY
+ if in_between(x, x1, x2) and in_between(y, y1, y2): return self
+ return None
+
+ def get_rotation(self):
+ """
+ Get the rotation in degrees.
+ @return the rotation
+ """
+ return self.rotation
+
+ def set_rotation(self, rotation):
+ """
+ Set the rotation in degrees.
+ @param rotation the rotation"""
+ if rotation not in POSSIBLE_ROTATIONS:
+ raise Exception('"%s" is not one of the possible rotations: (%s)'%(rotation, POSSIBLE_ROTATIONS))
+ self.rotation = rotation
diff --git a/grc/gui/FileDialogs.py b/grc/gui/FileDialogs.py
new file mode 100644
index 000000000..3b210c33f
--- /dev/null
+++ b/grc/gui/FileDialogs.py
@@ -0,0 +1,175 @@
+"""
+Copyright 2007 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+from Dialogs import MessageDialogHelper
+from Constants import \
+ DEFAULT_FILE_PATH, IMAGE_FILE_EXTENSION, \
+ NEW_FLOGRAPH_TITLE
+import Preferences
+from os import path
+import Utils
+
+##################################################
+# Constants
+##################################################
+OPEN_FLOW_GRAPH = 'open flow graph'
+SAVE_FLOW_GRAPH = 'save flow graph'
+SAVE_IMAGE = 'save image'
+
+FILE_OVERWRITE_MARKUP_TMPL="""\
+File <b>$encode($filename)</b> Exists!\nWould you like to overwrite the existing file?"""
+
+FILE_DNE_MARKUP_TMPL="""\
+File <b>$encode($filename)</b> Does not Exist!"""
+
+##################################################
+# File Filters
+##################################################
+##the filter for flow graph files
+def get_flow_graph_files_filter():
+ filter = gtk.FileFilter()
+ filter.set_name('Flow Graph Files')
+ filter.add_pattern('*'+Preferences.file_extension())
+ return filter
+
+##the filter for image files
+def get_image_files_filter():
+ filter = gtk.FileFilter()
+ filter.set_name('Image Files')
+ filter.add_pattern('*'+IMAGE_FILE_EXTENSION)
+ return filter
+
+##the filter for all files
+def get_all_files_filter():
+ filter = gtk.FileFilter()
+ filter.set_name('All Files')
+ filter.add_pattern('*')
+ return filter
+
+##################################################
+# File Dialogs
+##################################################
+class FileDialogHelper(gtk.FileChooserDialog):
+ """
+ A wrapper class for the gtk file chooser dialog.
+ Implement a file chooser dialog with only necessary parameters.
+ """
+
+ def __init__(self, action, title):
+ """
+ FileDialogHelper contructor.
+ Create a save or open dialog with cancel and ok buttons.
+ Use standard settings: no multiple selection, local files only, and the * filter.
+ @param action gtk.FILE_CHOOSER_ACTION_OPEN or gtk.FILE_CHOOSER_ACTION_SAVE
+ @param title the title of the dialog (string)
+ """
+ ok_stock = {gtk.FILE_CHOOSER_ACTION_OPEN : 'gtk-open', gtk.FILE_CHOOSER_ACTION_SAVE : 'gtk-save'}[action]
+ gtk.FileChooserDialog.__init__(self, title, None, action, ('gtk-cancel', gtk.RESPONSE_CANCEL, ok_stock, gtk.RESPONSE_OK))
+ self.set_select_multiple(False)
+ self.set_local_only(True)
+ self.add_filter(get_all_files_filter())
+
+class FileDialog(FileDialogHelper):
+ """A dialog box to save or open flow graph files. This is a base class, do not use."""
+
+ def __init__(self, current_file_path=''):
+ """
+ FileDialog constructor.
+ @param current_file_path the current directory or path to the open flow graph
+ """
+ if not current_file_path: current_file_path = path.join(DEFAULT_FILE_PATH, NEW_FLOGRAPH_TITLE + Preferences.file_extension())
+ if self.type == OPEN_FLOW_GRAPH:
+ FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_OPEN, 'Open a Flow Graph from a File...')
+ self.add_and_set_filter(get_flow_graph_files_filter())
+ self.set_select_multiple(True)
+ elif self.type == SAVE_FLOW_GRAPH:
+ FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save a Flow Graph to a File...')
+ self.add_and_set_filter(get_flow_graph_files_filter())
+ self.set_current_name(path.basename(current_file_path)) #show the current filename
+ elif self.type == SAVE_IMAGE:
+ FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save a Flow Graph Screen Shot...')
+ self.add_and_set_filter(get_image_files_filter())
+ current_file_path = current_file_path + IMAGE_FILE_EXTENSION
+ self.set_current_name(path.basename(current_file_path)) #show the current filename
+ self.set_current_folder(path.dirname(current_file_path)) #current directory
+
+ def add_and_set_filter(self, filter):
+ """
+ Add the gtk file filter to the list of filters and set it as the default file filter.
+ @param filter a gtk file filter.
+ """
+ self.add_filter(filter)
+ self.set_filter(filter)
+
+ def get_rectified_filename(self):
+ """
+ Run the dialog and get the filename.
+ If this is a save dialog and the file name is missing the extension, append the file extension.
+ If the file name with the extension already exists, show a overwrite dialog.
+ If this is an open dialog, return a list of filenames.
+ @return the complete file path
+ """
+ if gtk.FileChooserDialog.run(self) != gtk.RESPONSE_OK: return None #response was cancel
+ #############################################
+ # Handle Save Dialogs
+ #############################################
+ if self.type in (SAVE_FLOW_GRAPH, SAVE_IMAGE):
+ filename = self.get_filename()
+ extension = {
+ SAVE_FLOW_GRAPH: Preferences.file_extension(),
+ SAVE_IMAGE: IMAGE_FILE_EXTENSION,
+ }[self.type]
+ #append the missing file extension if the filter matches
+ if path.splitext(filename)[1].lower() != extension: filename += extension
+ self.set_current_name(path.basename(filename)) #show the filename with extension
+ if path.exists(filename): #ask the user to confirm overwrite
+ if MessageDialogHelper(
+ gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, 'Confirm Overwrite!',
+ Utils.parse_template(FILE_OVERWRITE_MARKUP_TMPL, filename=filename),
+ ) == gtk.RESPONSE_NO: return self.get_rectified_filename()
+ return filename
+ #############################################
+ # Handle Open Dialogs
+ #############################################
+ elif self.type in (OPEN_FLOW_GRAPH,):
+ filenames = self.get_filenames()
+ for filename in filenames:
+ if not path.exists(filename): #show a warning and re-run
+ MessageDialogHelper(
+ gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, 'Cannot Open!',
+ Utils.parse_template(FILE_DNE_MARKUP_TMPL, filename=filename),
+ )
+ return self.get_rectified_filename()
+ return filenames
+
+ def run(self):
+ """
+ Get the filename and destroy the dialog.
+ @return the filename or None if a close/cancel occured.
+ """
+ filename = self.get_rectified_filename()
+ self.destroy()
+ return filename
+
+class OpenFlowGraphFileDialog(FileDialog): type = OPEN_FLOW_GRAPH
+class SaveFlowGraphFileDialog(FileDialog): type = SAVE_FLOW_GRAPH
+class SaveImageFileDialog(FileDialog): type = SAVE_IMAGE
diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py
new file mode 100644
index 000000000..6af4bcb62
--- /dev/null
+++ b/grc/gui/FlowGraph.py
@@ -0,0 +1,524 @@
+"""
+Copyright 2007-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from Constants import SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE
+import Actions
+import Colors
+import Utils
+from Element import Element
+import pygtk
+pygtk.require('2.0')
+import gtk
+import random
+import Messages
+
+class FlowGraph(Element):
+ """
+ FlowGraph is the data structure to store graphical signal blocks,
+ graphical inputs and outputs,
+ and the connections between inputs and outputs.
+ """
+
+ def __init__(self):
+ """
+ FlowGraph contructor.
+ Create a list for signal blocks and connections. Connect mouse handlers.
+ """
+ Element.__init__(self)
+ #when is the flow graph selected? (used by keyboard event handler)
+ self.is_selected = lambda: bool(self.get_selected_elements())
+ #important vars dealing with mouse event tracking
+ self.element_moved = False
+ self.mouse_pressed = False
+ self.unselect()
+ self.press_coor = (0, 0)
+ #selected ports
+ self._old_selected_port = None
+ self._new_selected_port = None
+ #context menu
+ self._context_menu = gtk.Menu()
+ for action in [
+ Actions.BLOCK_CUT,
+ Actions.BLOCK_COPY,
+ Actions.BLOCK_PASTE,
+ Actions.ELEMENT_DELETE,
+ Actions.BLOCK_ROTATE_CCW,
+ Actions.BLOCK_ROTATE_CW,
+ Actions.BLOCK_ENABLE,
+ Actions.BLOCK_DISABLE,
+ Actions.BLOCK_PARAM_MODIFY,
+ Actions.BLOCK_CREATE_HIER,
+ Actions.OPEN_HIER,
+ ]: self._context_menu.append(action.create_menu_item())
+
+ ###########################################################################
+ # Access Drawing Area
+ ###########################################################################
+ def get_drawing_area(self): return self.drawing_area
+ def queue_draw(self): self.get_drawing_area().queue_draw()
+ def get_size(self): return self.get_drawing_area().get_size_request()
+ def set_size(self, *args): self.get_drawing_area().set_size_request(*args)
+ def get_scroll_pane(self): return self.drawing_area.get_parent()
+ def get_ctrl_mask(self): return self.drawing_area.ctrl_mask
+ def new_pixmap(self, *args): return self.get_drawing_area().new_pixmap(*args)
+
+ def add_new_block(self, key, coor=None):
+ """
+ Add a block of the given key to this flow graph.
+ @param key the block key
+ @param coor an optional coordinate or None for random
+ """
+ id = self._get_unique_id(key)
+ #calculate the position coordinate
+ h_adj = self.get_scroll_pane().get_hadjustment()
+ v_adj = self.get_scroll_pane().get_vadjustment()
+ if coor is None: coor = (
+ int(random.uniform(.25, .75)*h_adj.page_size + h_adj.get_value()),
+ int(random.uniform(.25, .75)*v_adj.page_size + v_adj.get_value()),
+ )
+ #get the new block
+ block = self.get_new_block(key)
+ block.set_coordinate(coor)
+ block.set_rotation(0)
+ block.get_param('id').set_value(id)
+ Actions.ELEMENT_CREATE()
+
+ return id
+
+ ###########################################################################
+ # Copy Paste
+ ###########################################################################
+ def copy_to_clipboard(self):
+ """
+ Copy the selected blocks and connections into the clipboard.
+ @return the clipboard
+ """
+ #get selected blocks
+ blocks = self.get_selected_blocks()
+ if not blocks: return None
+ #calc x and y min
+ x_min, y_min = blocks[0].get_coordinate()
+ for block in blocks:
+ x, y = block.get_coordinate()
+ x_min = min(x, x_min)
+ y_min = min(y, y_min)
+ #get connections between selected blocks
+ connections = filter(
+ lambda c: c.get_source().get_parent() in blocks and c.get_sink().get_parent() in blocks,
+ self.get_connections(),
+ )
+ clipboard = (
+ (x_min, y_min),
+ [block.export_data() for block in blocks],
+ [connection.export_data() for connection in connections],
+ )
+ return clipboard
+
+ def paste_from_clipboard(self, clipboard):
+ """
+ Paste the blocks and connections from the clipboard.
+ @param clipboard the nested data of blocks, connections
+ """
+ selected = set()
+ (x_min, y_min), blocks_n, connections_n = clipboard
+ old_id2block = dict()
+ #recalc the position
+ h_adj = self.get_scroll_pane().get_hadjustment()
+ v_adj = self.get_scroll_pane().get_vadjustment()
+ x_off = h_adj.get_value() - x_min + h_adj.page_size/4
+ y_off = v_adj.get_value() - y_min + v_adj.page_size/4
+ #create blocks
+ for block_n in blocks_n:
+ block_key = block_n.find('key')
+ if block_key == 'options': continue
+ block = self.get_new_block(block_key)
+ selected.add(block)
+ #set params
+ params_n = block_n.findall('param')
+ for param_n in params_n:
+ param_key = param_n.find('key')
+ param_value = param_n.find('value')
+ #setup id parameter
+ if param_key == 'id':
+ old_id2block[param_value] = block
+ #if the block id is not unique, get a new block id
+ if param_value in [block.get_id() for block in self.get_blocks()]:
+ param_value = self._get_unique_id(param_value)
+ #set value to key
+ block.get_param(param_key).set_value(param_value)
+ #move block to offset coordinate
+ block.move((x_off, y_off))
+ #update before creating connections
+ self.update()
+ #create connections
+ for connection_n in connections_n:
+ source = old_id2block[connection_n.find('source_block_id')].get_source(connection_n.find('source_key'))
+ sink = old_id2block[connection_n.find('sink_block_id')].get_sink(connection_n.find('sink_key'))
+ self.connect(source, sink)
+ #set all pasted elements selected
+ for block in selected: selected = selected.union(set(block.get_connections()))
+ self._selected_elements = list(selected)
+
+ ###########################################################################
+ # Modify Selected
+ ###########################################################################
+ def type_controller_modify_selected(self, direction):
+ """
+ Change the registered type controller for the selected signal blocks.
+ @param direction +1 or -1
+ @return true for change
+ """
+ return any([sb.type_controller_modify(direction) for sb in self.get_selected_blocks()])
+
+ def port_controller_modify_selected(self, direction):
+ """
+ Change port controller for the selected signal blocks.
+ @param direction +1 or -1
+ @return true for changed
+ """
+ return any([sb.port_controller_modify(direction) for sb in self.get_selected_blocks()])
+
+ def enable_selected(self, enable):
+ """
+ Enable/disable the selected blocks.
+ @param enable true to enable
+ @return true if changed
+ """
+ changed = False
+ for selected_block in self.get_selected_blocks():
+ if selected_block.get_enabled() != enable:
+ selected_block.set_enabled(enable)
+ changed = True
+ return changed
+
+ def move_selected(self, delta_coordinate):
+ """
+ Move the element and by the change in coordinates.
+ @param delta_coordinate the change in coordinates
+ """
+ for selected_block in self.get_selected_blocks():
+ selected_block.move(delta_coordinate)
+ self.element_moved = True
+
+ def rotate_selected(self, rotation):
+ """
+ Rotate the selected blocks by multiples of 90 degrees.
+ @param rotation the rotation in degrees
+ @return true if changed, otherwise false.
+ """
+ if not self.get_selected_blocks(): return False
+ #initialize min and max coordinates
+ min_x, min_y = self.get_selected_block().get_coordinate()
+ max_x, max_y = self.get_selected_block().get_coordinate()
+ #rotate each selected block, and find min/max coordinate
+ for selected_block in self.get_selected_blocks():
+ selected_block.rotate(rotation)
+ #update the min/max coordinate
+ x, y = selected_block.get_coordinate()
+ min_x, min_y = min(min_x, x), min(min_y, y)
+ max_x, max_y = max(max_x, x), max(max_y, y)
+ #calculate center point of slected blocks
+ ctr_x, ctr_y = (max_x + min_x)/2, (max_y + min_y)/2
+ #rotate the blocks around the center point
+ for selected_block in self.get_selected_blocks():
+ x, y = selected_block.get_coordinate()
+ x, y = Utils.get_rotated_coordinate((x - ctr_x, y - ctr_y), rotation)
+ selected_block.set_coordinate((x + ctr_x, y + ctr_y))
+ return True
+
+ def remove_selected(self):
+ """
+ Remove selected elements
+ @return true if changed.
+ """
+ changed = False
+ for selected_element in self.get_selected_elements():
+ self.remove_element(selected_element)
+ changed = True
+ return changed
+
+ def draw(self, gc, window):
+ """
+ Draw the background and grid if enabled.
+ Draw all of the elements in this flow graph onto the pixmap.
+ Draw the pixmap to the drawable window of this flow graph.
+ """
+ W,H = self.get_size()
+ #draw the background
+ gc.set_foreground(Colors.FLOWGRAPH_BACKGROUND_COLOR)
+ window.draw_rectangle(gc, True, 0, 0, W, H)
+ #draw multi select rectangle
+ if self.mouse_pressed and (not self.get_selected_elements() or self.get_ctrl_mask()):
+ #coordinates
+ x1, y1 = self.press_coor
+ x2, y2 = self.get_coordinate()
+ #calculate top-left coordinate and width/height
+ x, y = int(min(x1, x2)), int(min(y1, y2))
+ w, h = int(abs(x1 - x2)), int(abs(y1 - y2))
+ #draw
+ gc.set_foreground(Colors.HIGHLIGHT_COLOR)
+ window.draw_rectangle(gc, True, x, y, w, h)
+ gc.set_foreground(Colors.BORDER_COLOR)
+ window.draw_rectangle(gc, False, x, y, w, h)
+ #draw blocks on top of connections
+ for element in self.get_connections() + self.get_blocks():
+ element.draw(gc, window)
+ #draw selected blocks on top of selected connections
+ for selected_element in self.get_selected_connections() + self.get_selected_blocks():
+ selected_element.draw(gc, window)
+
+ def update_selected(self):
+ """
+ Remove deleted elements from the selected elements list.
+ Update highlighting so only the selected are highlighted.
+ """
+ selected_elements = self.get_selected_elements()
+ elements = self.get_elements()
+ #remove deleted elements
+ for selected in selected_elements:
+ if selected in elements: continue
+ selected_elements.remove(selected)
+ if self._old_selected_port and self._old_selected_port.get_parent() not in elements:
+ self._old_selected_port = None
+ if self._new_selected_port and self._new_selected_port.get_parent() not in elements:
+ self._new_selected_port = None
+ #update highlighting
+ for element in elements:
+ element.set_highlighted(element in selected_elements)
+
+ def update(self):
+ """
+ Call the top level rewrite and validate.
+ Call the top level create labels and shapes.
+ """
+ self.rewrite()
+ self.validate()
+ self.create_labels()
+ self.create_shapes()
+
+ ##########################################################################
+ ## Get Selected
+ ##########################################################################
+ def unselect(self):
+ """
+ Set selected elements to an empty set.
+ """
+ self._selected_elements = []
+
+ def what_is_selected(self, coor, coor_m=None):
+ """
+ What is selected?
+ At the given coordinate, return the elements found to be selected.
+ If coor_m is unspecified, return a list of only the first element found to be selected:
+ Iterate though the elements backwards since top elements are at the end of the list.
+ If an element is selected, place it at the end of the list so that is is drawn last,
+ and hence on top. Update the selected port information.
+ @param coor the coordinate of the mouse click
+ @param coor_m the coordinate for multi select
+ @return the selected blocks and connections or an empty list
+ """
+ selected_port = None
+ selected = set()
+ #check the elements
+ for element in reversed(self.get_elements()):
+ selected_element = element.what_is_selected(coor, coor_m)
+ if not selected_element: continue
+ #update the selected port information
+ if selected_element.is_port():
+ if not coor_m: selected_port = selected_element
+ selected_element = selected_element.get_parent()
+ selected.add(selected_element)
+ #place at the end of the list
+ self.get_elements().remove(element)
+ self.get_elements().append(element)
+ #single select mode, break
+ if not coor_m: break
+ #update selected ports
+ self._old_selected_port = self._new_selected_port
+ self._new_selected_port = selected_port
+ return list(selected)
+
+ def get_selected_connections(self):
+ """
+ Get a group of selected connections.
+ @return sub set of connections in this flow graph
+ """
+ selected = set()
+ for selected_element in self.get_selected_elements():
+ if selected_element.is_connection(): selected.add(selected_element)
+ return list(selected)
+
+ def get_selected_blocks(self):
+ """
+ Get a group of selected blocks.
+ @return sub set of blocks in this flow graph
+ """
+ selected = set()
+ for selected_element in self.get_selected_elements():
+ if selected_element.is_block(): selected.add(selected_element)
+ return list(selected)
+
+ def get_selected_block(self):
+ """
+ Get the selected block when a block or port is selected.
+ @return a block or None
+ """
+ return self.get_selected_blocks() and self.get_selected_blocks()[0] or None
+
+ def get_selected_elements(self):
+ """
+ Get the group of selected elements.
+ @return sub set of elements in this flow graph
+ """
+ return self._selected_elements
+
+ def get_selected_element(self):
+ """
+ Get the selected element.
+ @return a block, port, or connection or None
+ """
+ return self.get_selected_elements() and self.get_selected_elements()[0] or None
+
+ def update_selected_elements(self):
+ """
+ Update the selected elements.
+ The update behavior depends on the state of the mouse button.
+ When the mouse button pressed the selection will change when
+ the control mask is set or the new selection is not in the current group.
+ When the mouse button is released the selection will change when
+ the mouse has moved and the control mask is set or the current group is empty.
+ Attempt to make a new connection if the old and ports are filled.
+ If the control mask is set, merge with the current elements.
+ """
+ selected_elements = None
+ if self.mouse_pressed:
+ new_selections = self.what_is_selected(self.get_coordinate())
+ #update the selections if the new selection is not in the current selections
+ #allows us to move entire selected groups of elements
+ if self.get_ctrl_mask() or not (
+ new_selections and new_selections[0] in self.get_selected_elements()
+ ): selected_elements = new_selections
+ else: #called from a mouse release
+ if not self.element_moved and (not self.get_selected_elements() or self.get_ctrl_mask()):
+ selected_elements = self.what_is_selected(self.get_coordinate(), self.press_coor)
+ #this selection and the last were ports, try to connect them
+ if self._old_selected_port and self._new_selected_port and \
+ self._old_selected_port is not self._new_selected_port:
+ try:
+ self.connect(self._old_selected_port, self._new_selected_port)
+ Actions.ELEMENT_CREATE()
+ except: Messages.send_fail_connection()
+ self._old_selected_port = None
+ self._new_selected_port = None
+ return
+ #update selected elements
+ if selected_elements is None: return
+ old_elements = set(self.get_selected_elements())
+ self._selected_elements = list(set(selected_elements))
+ new_elements = set(self.get_selected_elements())
+ #if ctrl, set the selected elements to the union - intersection of old and new
+ if self.get_ctrl_mask():
+ self._selected_elements = list(
+ set.union(old_elements, new_elements) - set.intersection(old_elements, new_elements)
+ )
+ Actions.ELEMENT_SELECT()
+
+ ##########################################################################
+ ## Event Handlers
+ ##########################################################################
+ def handle_mouse_context_press(self, coordinate, event):
+ """
+ The context mouse button was pressed:
+ If no elements were selected, perform re-selection at this coordinate.
+ Then, show the context menu at the mouse click location.
+ """
+ selections = self.what_is_selected(coordinate)
+ if not set(selections).intersection(self.get_selected_elements()):
+ self.set_coordinate(coordinate)
+ self.mouse_pressed = True
+ self.update_selected_elements()
+ self.mouse_pressed = False
+ self._context_menu.popup(None, None, None, event.button, event.time)
+
+ def handle_mouse_selector_press(self, double_click, coordinate):
+ """
+ The selector mouse button was pressed:
+ Find the selected element. Attempt a new connection if possible.
+ Open the block params window on a double click.
+ Update the selection state of the flow graph.
+ """
+ self.press_coor = coordinate
+ self.set_coordinate(coordinate)
+ self.time = 0
+ self.mouse_pressed = True
+ if double_click: self.unselect()
+ self.update_selected_elements()
+ #double click detected, bring up params dialog if possible
+ if double_click and self.get_selected_block():
+ self.mouse_pressed = False
+ Actions.BLOCK_PARAM_MODIFY()
+
+ def handle_mouse_selector_release(self, coordinate):
+ """
+ The selector mouse button was released:
+ Update the state, handle motion (dragging).
+ And update the selected flowgraph elements.
+ """
+ self.set_coordinate(coordinate)
+ self.time = 0
+ self.mouse_pressed = False
+ if self.element_moved:
+ Actions.BLOCK_MOVE()
+ self.element_moved = False
+ self.update_selected_elements()
+
+ def handle_mouse_motion(self, coordinate):
+ """
+ The mouse has moved, respond to mouse dragging.
+ Move a selected element to the new coordinate.
+ Auto-scroll the scroll bars at the boundaries.
+ """
+ #to perform a movement, the mouse must be pressed
+ # (no longer checking pending events via gtk.events_pending() - always true in Windows)
+ if not self.mouse_pressed: return
+ #perform autoscrolling
+ width, height = self.get_size()
+ x, y = coordinate
+ h_adj = self.get_scroll_pane().get_hadjustment()
+ v_adj = self.get_scroll_pane().get_vadjustment()
+ for pos, length, adj, adj_val, adj_len in (
+ (x, width, h_adj, h_adj.get_value(), h_adj.page_size),
+ (y, height, v_adj, v_adj.get_value(), v_adj.page_size),
+ ):
+ #scroll if we moved near the border
+ if pos-adj_val > adj_len-SCROLL_PROXIMITY_SENSITIVITY and adj_val+SCROLL_DISTANCE < length-adj_len:
+ adj.set_value(adj_val+SCROLL_DISTANCE)
+ adj.emit('changed')
+ elif pos-adj_val < SCROLL_PROXIMITY_SENSITIVITY:
+ adj.set_value(adj_val-SCROLL_DISTANCE)
+ adj.emit('changed')
+ #remove the connection if selected in drag event
+ if len(self.get_selected_elements()) == 1 and self.get_selected_element().is_connection():
+ Actions.ELEMENT_DELETE()
+ #move the selected elements and record the new coordinate
+ X, Y = self.get_coordinate()
+ if not self.get_ctrl_mask(): self.move_selected((int(x - X), int(y - Y)))
+ self.set_coordinate((x, y))
+ #queue draw for animation
+ self.queue_draw()
diff --git a/grc/gui/MainWindow.py b/grc/gui/MainWindow.py
new file mode 100644
index 000000000..1dc02dabb
--- /dev/null
+++ b/grc/gui/MainWindow.py
@@ -0,0 +1,327 @@
+"""
+Copyright 2008, 2009, 2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from Constants import \
+ NEW_FLOGRAPH_TITLE, DEFAULT_REPORTS_WINDOW_WIDTH
+import Actions
+import pygtk
+pygtk.require('2.0')
+import gtk
+import Bars
+from BlockTreeWindow import BlockTreeWindow
+from Dialogs import TextDisplay, MessageDialogHelper
+from NotebookPage import NotebookPage
+import Preferences
+import Messages
+import Utils
+import os
+
+MAIN_WINDOW_TITLE_TMPL = """\
+#if not $saved
+*#slurp
+#end if
+#if $basename
+$basename#slurp
+#else
+$new_flowgraph_title#slurp
+#end if
+#if $read_only
+ (read only)#slurp
+#end if
+#if $dirname
+ - $dirname#slurp
+#end if
+ - $platform_name#slurp
+"""
+
+PAGE_TITLE_MARKUP_TMPL = """\
+#set $foreground = $saved and 'black' or 'red'
+<span foreground="$foreground">$encode($title or $new_flowgraph_title)</span>#slurp
+#if $read_only
+ (ro)#slurp
+#end if
+"""
+
+############################################################
+# Main window
+############################################################
+
+class MainWindow(gtk.Window):
+ """The topmost window with menus, the tool bar, and other major windows."""
+
+ def __init__(self, platform):
+ """
+ MainWindow contructor
+ Setup the menu, toolbar, flowgraph editor notebook, block selection window...
+ """
+ self._platform = platform
+ #setup window
+ gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
+ vbox = gtk.VBox()
+ self.hpaned = gtk.HPaned()
+ self.add(vbox)
+ #create the menu bar and toolbar
+ self.add_accel_group(Actions.get_accel_group())
+ vbox.pack_start(Bars.MenuBar(), False)
+ vbox.pack_start(Bars.Toolbar(), False)
+ vbox.pack_start(self.hpaned)
+ #create the notebook
+ self.notebook = gtk.Notebook()
+ self.page_to_be_closed = None
+ self.current_page = None
+ self.notebook.set_show_border(False)
+ self.notebook.set_scrollable(True) #scroll arrows for page tabs
+ self.notebook.connect('switch-page', self._handle_page_change)
+ #setup containers
+ self.flow_graph_vpaned = gtk.VPaned()
+ #flow_graph_box.pack_start(self.scrolled_window)
+ self.flow_graph_vpaned.pack1(self.notebook)
+ self.hpaned.pack1(self.flow_graph_vpaned)
+ self.btwin = BlockTreeWindow(platform, self.get_flow_graph);
+ self.hpaned.pack2(self.btwin, False) #dont allow resize
+ #create the reports window
+ self.text_display = TextDisplay()
+ #house the reports in a scrolled window
+ self.reports_scrolled_window = gtk.ScrolledWindow()
+ self.reports_scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ self.reports_scrolled_window.add_with_viewport(self.text_display)
+ self.reports_scrolled_window.set_size_request(-1, DEFAULT_REPORTS_WINDOW_WIDTH)
+ self.flow_graph_vpaned.pack2(self.reports_scrolled_window, False) #dont allow resize
+ #load preferences and show the main window
+ Preferences.load(platform)
+ self.resize(*Preferences.main_window_size())
+ self.flow_graph_vpaned.set_position(Preferences.reports_window_position())
+ self.hpaned.set_position(Preferences.blocks_window_position())
+ self.show_all()
+
+ ############################################################
+ # Event Handlers
+ ############################################################
+
+ def _quit(self, window, event):
+ """
+ Handle the delete event from the main window.
+ Generated by pressing X to close, alt+f4, or right click+close.
+ This method in turns calls the state handler to quit.
+ @return true
+ """
+ Actions.APPLICATION_QUIT()
+ return True
+
+ def _handle_page_change(self, notebook, page, page_num):
+ """
+ Handle a page change. When the user clicks on a new tab,
+ reload the flow graph to update the vars window and
+ call handle states (select nothing) to update the buttons.
+ @param notebook the notebook
+ @param page new page
+ @param page_num new page number
+ """
+ self.current_page = self.notebook.get_nth_page(page_num)
+ Messages.send_page_switch(self.current_page.get_file_path())
+ Actions.PAGE_CHANGE()
+
+ ############################################################
+ # Report Window
+ ############################################################
+
+ def add_report_line(self, line):
+ """
+ Place line at the end of the text buffer, then scroll its window all the way down.
+ @param line the new text
+ """
+ self.text_display.insert(line)
+ vadj = self.reports_scrolled_window.get_vadjustment()
+ vadj.set_value(vadj.upper)
+ vadj.emit('changed')
+
+ ############################################################
+ # Pages: create and close
+ ############################################################
+
+ def new_page(self, file_path='', show=False):
+ """
+ Create a new notebook page.
+ Set the tab to be selected.
+ @param file_path optional file to load into the flow graph
+ @param show true if the page should be shown after loading
+ """
+ #if the file is already open, show the open page and return
+ if file_path and file_path in self._get_files(): #already open
+ page = self.notebook.get_nth_page(self._get_files().index(file_path))
+ self._set_page(page)
+ return
+ try: #try to load from file
+ if file_path: Messages.send_start_load(file_path)
+ flow_graph = self._platform.get_new_flow_graph()
+ flow_graph.grc_file_path = file_path;
+ #print flow_graph
+ page = NotebookPage(
+ self,
+ flow_graph=flow_graph,
+ file_path=file_path,
+ )
+ if file_path: Messages.send_end_load()
+ except Exception, e: #return on failure
+ Messages.send_fail_load(e)
+ if isinstance(e, KeyError) and str(e) == "'options'":
+ # This error is unrecoverable, so crash gracefully
+ exit(-1)
+ return
+ #add this page to the notebook
+ self.notebook.append_page(page, page.get_tab())
+ try: self.notebook.set_tab_reorderable(page, True)
+ except: pass #gtk too old
+ self.notebook.set_tab_label_packing(page, False, False, gtk.PACK_START)
+ #only show if blank or manual
+ if not file_path or show: self._set_page(page)
+
+ def close_pages(self):
+ """
+ Close all the pages in this notebook.
+ @return true if all closed
+ """
+ open_files = filter(lambda file: file, self._get_files()) #filter blank files
+ open_file = self.get_page().get_file_path()
+ #close each page
+ for page in self._get_pages():
+ self.page_to_be_closed = page
+ self.close_page(False)
+ if self.notebook.get_n_pages(): return False
+ #save state before closing
+ Preferences.files_open(open_files)
+ Preferences.file_open(open_file)
+ Preferences.main_window_size(self.get_size())
+ Preferences.reports_window_position(self.flow_graph_vpaned.get_position())
+ Preferences.blocks_window_position(self.hpaned.get_position())
+ Preferences.save()
+ return True
+
+ def close_page(self, ensure=True):
+ """
+ Close the current page.
+ If the notebook becomes empty, and ensure is true,
+ call new page upon exit to ensure that at least one page exists.
+ @param ensure boolean
+ """
+ if not self.page_to_be_closed: self.page_to_be_closed = self.get_page()
+ #show the page if it has an executing flow graph or is unsaved
+ if self.page_to_be_closed.get_proc() or not self.page_to_be_closed.get_saved():
+ self._set_page(self.page_to_be_closed)
+ #unsaved? ask the user
+ if not self.page_to_be_closed.get_saved() and self._save_changes():
+ Actions.FLOW_GRAPH_SAVE() #try to save
+ if not self.page_to_be_closed.get_saved(): #still unsaved?
+ self.page_to_be_closed = None #set the page to be closed back to None
+ return
+ #stop the flow graph if executing
+ if self.page_to_be_closed.get_proc(): Actions.FLOW_GRAPH_KILL()
+ #remove the page
+ self.notebook.remove_page(self.notebook.page_num(self.page_to_be_closed))
+ if ensure and self.notebook.get_n_pages() == 0: self.new_page() #no pages, make a new one
+ self.page_to_be_closed = None #set the page to be closed back to None
+
+ ############################################################
+ # Misc
+ ############################################################
+
+ def update(self):
+ """
+ Set the title of the main window.
+ Set the titles on the page tabs.
+ Show/hide the reports window.
+ @param title the window title
+ """
+ gtk.Window.set_title(self, Utils.parse_template(MAIN_WINDOW_TITLE_TMPL,
+ basename=os.path.basename(self.get_page().get_file_path()),
+ dirname=os.path.dirname(self.get_page().get_file_path()),
+ new_flowgraph_title=NEW_FLOGRAPH_TITLE,
+ read_only=self.get_page().get_read_only(),
+ saved=self.get_page().get_saved(),
+ platform_name=self._platform.get_name(),
+ )
+ )
+ #set tab titles
+ for page in self._get_pages(): page.set_markup(
+ Utils.parse_template(PAGE_TITLE_MARKUP_TMPL,
+ #get filename and strip out file extension
+ title=os.path.splitext(os.path.basename(page.get_file_path()))[0],
+ read_only=page.get_read_only(), saved=page.get_saved(),
+ new_flowgraph_title=NEW_FLOGRAPH_TITLE,
+ )
+ )
+ #show/hide notebook tabs
+ self.notebook.set_show_tabs(len(self._get_pages()) > 1)
+
+ def get_page(self):
+ """
+ Get the selected page.
+ @return the selected page
+ """
+ return self.current_page
+
+ def get_flow_graph(self):
+ """
+ Get the selected flow graph.
+ @return the selected flow graph
+ """
+ return self.get_page().get_flow_graph()
+
+ def get_focus_flag(self):
+ """
+ Get the focus flag from the current page.
+ @return the focus flag
+ """
+ return self.get_page().get_drawing_area().get_focus_flag()
+
+ ############################################################
+ # Helpers
+ ############################################################
+
+ def _set_page(self, page):
+ """
+ Set the current page.
+ @param page the page widget
+ """
+ self.current_page = page
+ self.notebook.set_current_page(self.notebook.page_num(self.current_page))
+
+ def _save_changes(self):
+ """
+ Save changes to flow graph?
+ @return true if yes
+ """
+ return MessageDialogHelper(
+ gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, 'Unsaved Changes!',
+ 'Would you like to save changes before closing?'
+ ) == gtk.RESPONSE_YES
+
+ def _get_files(self):
+ """
+ Get the file names for all the pages, in order.
+ @return list of file paths
+ """
+ return map(lambda page: page.get_file_path(), self._get_pages())
+
+ def _get_pages(self):
+ """
+ Get a list of all pages in the notebook.
+ @return list of pages
+ """
+ return [self.notebook.get_nth_page(page_num) for page_num in range(self.notebook.get_n_pages())]
diff --git a/grc/gui/Messages.py b/grc/gui/Messages.py
new file mode 100644
index 000000000..e98e897aa
--- /dev/null
+++ b/grc/gui/Messages.py
@@ -0,0 +1,104 @@
+"""
+Copyright 2007 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import traceback
+import sys
+
+## A list of functions that can receive a message.
+MESSENGERS_LIST = list()
+
+def register_messenger(messenger):
+ """
+ Append the given messenger to the list of messengers.
+ @param messenger a method thats takes a string
+ """
+ MESSENGERS_LIST.append(messenger)
+
+def send(message):
+ """
+ Give the message to each of the messengers.
+ @param message a message string
+ """
+ for messenger in MESSENGERS_LIST: messenger(message)
+
+#register stdout by default
+register_messenger(sys.stdout.write)
+
+###########################################################################
+# Special functions for specific program functionalities
+###########################################################################
+def send_init(platform):
+ send("""<<< Welcome to %s %s >>>\n"""%(platform.get_name(), platform.get_version()))
+
+def send_page_switch(file_path):
+ send('\nShowing: "%s"\n'%file_path)
+
+################# functions for loading flow graphs ########################################
+def send_start_load(file_path):
+ send('\nLoading: "%s"'%file_path + '\n')
+
+def send_error_load(error):
+ send('>>> Error: %s\n'%error)
+ traceback.print_exc()
+
+def send_end_load():
+ send('>>> Done\n')
+
+def send_fail_load(error):
+ send('Error: %s\n'%error)
+ send('>>> Failure\n')
+ traceback.print_exc()
+
+################# functions for generating flow graphs ########################################
+def send_start_gen(file_path):
+ send('\nGenerating: "%s"'%file_path + '\n')
+
+def send_fail_gen(error):
+ send('Generate Error: %s\n'%error)
+ send('>>> Failure\n')
+ traceback.print_exc()
+
+################# functions for executing flow graphs ########################################
+def send_start_exec(file_path):
+ send('\nExecuting: "%s"'%file_path + '\n')
+
+def send_verbose_exec(verbose):
+ send(verbose)
+
+def send_end_exec():
+ send('\n>>> Done\n')
+
+################# functions for saving flow graphs ########################################
+def send_fail_save(file_path):
+ send('>>> Error: Cannot save: %s\n'%file_path)
+
+################# functions for connections ########################################
+def send_fail_connection():
+ send('>>> Error: Cannot create connection.\n')
+
+################# functions for preferences ########################################
+def send_fail_load_preferences(prefs_file_path):
+ send('>>> Error: Cannot load preferences file: "%s"\n'%prefs_file_path)
+
+def send_fail_save_preferences(prefs_file_path):
+ send('>>> Error: Cannot save preferences file: "%s"\n'%prefs_file_path)
+
+################# functions for warning ########################################
+def send_warning(warning):
+ send('>>> Warning: %s\n'%warning)
diff --git a/grc/gui/NotebookPage.py b/grc/gui/NotebookPage.py
new file mode 100644
index 000000000..86b6f1513
--- /dev/null
+++ b/grc/gui/NotebookPage.py
@@ -0,0 +1,187 @@
+"""
+Copyright 2008, 2009, 2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+import Actions
+from StateCache import StateCache
+from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT
+from DrawingArea import DrawingArea
+import os
+
+############################################################
+## Notebook Page
+############################################################
+
+class NotebookPage(gtk.HBox):
+ """A page in the notebook."""
+
+ def __init__(self, main_window, flow_graph, file_path=''):
+ """
+ Page constructor.
+ @param main_window main window
+ @param file_path path to a flow graph file
+ """
+ self._flow_graph = flow_graph
+ self.set_proc(None)
+ #import the file
+ self.main_window = main_window
+ self.set_file_path(file_path)
+ initial_state = flow_graph.get_parent().parse_flow_graph(file_path)
+ self.state_cache = StateCache(initial_state)
+ self.set_saved(True)
+ #import the data to the flow graph
+ self.get_flow_graph().import_data(initial_state)
+ #initialize page gui
+ gtk.HBox.__init__(self, False, 0)
+ self.show()
+ #tab box to hold label and close button
+ self.tab = gtk.HBox(False, 0)
+ #setup tab label
+ self.label = gtk.Label()
+ self.tab.pack_start(self.label, False)
+ #setup button image
+ image = gtk.Image()
+ image.set_from_stock('gtk-close', gtk.ICON_SIZE_MENU)
+ #setup image box
+ image_box = gtk.HBox(False, 0)
+ image_box.pack_start(image, True, False, 0)
+ #setup the button
+ button = gtk.Button()
+ button.connect("clicked", self._handle_button)
+ button.set_relief(gtk.RELIEF_NONE)
+ button.add(image_box)
+ #button size
+ w, h = gtk.icon_size_lookup_for_settings(button.get_settings(), gtk.ICON_SIZE_MENU)
+ button.set_size_request(w+6, h+6)
+ self.tab.pack_start(button, False)
+ self.tab.show_all()
+ #setup scroll window and drawing area
+ self.scrolled_window = gtk.ScrolledWindow()
+ self.scrolled_window.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT)
+ self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ self.drawing_area = DrawingArea(self.get_flow_graph())
+ self.scrolled_window.add_with_viewport(self.get_drawing_area())
+ self.pack_start(self.scrolled_window)
+ #inject drawing area into flow graph
+ self.get_flow_graph().drawing_area = self.get_drawing_area()
+ self.show_all()
+
+ def get_drawing_area(self): return self.drawing_area
+
+ def get_generator(self):
+ """
+ Get the generator object for this flow graph.
+ @return generator
+ """
+ return self.get_flow_graph().get_parent().get_generator()(
+ self.get_flow_graph(),
+ self.get_file_path(),
+ )
+
+ def _handle_button(self, button):
+ """
+ The button was clicked.
+ Make the current page selected, then close.
+ @param the button
+ """
+ self.main_window.page_to_be_closed = self
+ Actions.FLOW_GRAPH_CLOSE()
+
+ def set_markup(self, markup):
+ """
+ Set the markup in this label.
+ @param markup the new markup text
+ """
+ self.label.set_markup(markup)
+
+ def get_tab(self):
+ """
+ Get the gtk widget for this page's tab.
+ @return gtk widget
+ """
+ return self.tab
+
+ def get_proc(self):
+ """
+ Get the subprocess for the flow graph.
+ @return the subprocess object
+ """
+ return self.process
+
+ def set_proc(self, process):
+ """
+ Set the subprocess object.
+ @param process the new subprocess
+ """
+ self.process = process
+
+ def get_flow_graph(self):
+ """
+ Get the flow graph.
+ @return the flow graph
+ """
+ return self._flow_graph
+
+ def get_read_only(self):
+ """
+ Get the read-only state of the file.
+ Always false for empty path.
+ @return true for read-only
+ """
+ if not self.get_file_path(): return False
+ return os.path.exists(self.get_file_path()) and \
+ not os.access(self.get_file_path(), os.W_OK)
+
+ def get_file_path(self):
+ """
+ Get the file path for the flow graph.
+ @return the file path or ''
+ """
+ return self.file_path
+
+ def set_file_path(self, file_path=''):
+ """
+ Set the file path, '' for no file path.
+ @param file_path file path string
+ """
+ if file_path: self.file_path = os.path.abspath(file_path)
+ else: self.file_path = ''
+
+ def get_saved(self):
+ """
+ Get the saved status for the flow graph.
+ @return true if saved
+ """
+ return self.saved
+
+ def set_saved(self, saved=True):
+ """
+ Set the saved status.
+ @param saved boolean status
+ """
+ self.saved = saved
+
+ def get_state_cache(self):
+ """
+ Get the state cache for the flow graph.
+ @return the state cache
+ """
+ return self.state_cache
diff --git a/grc/gui/Param.py b/grc/gui/Param.py
new file mode 100644
index 000000000..cb6c663e3
--- /dev/null
+++ b/grc/gui/Param.py
@@ -0,0 +1,189 @@
+"""
+Copyright 2007-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import Utils
+from Element import Element
+import pygtk
+pygtk.require('2.0')
+import gtk
+import Colors
+
+class InputParam(gtk.HBox):
+ """The base class for an input parameter inside the input parameters dialog."""
+
+ def __init__(self, param, callback=None):
+ gtk.HBox.__init__(self)
+ self.param = param
+ self._callback = callback
+ self.label = gtk.Label() #no label, markup is added by set_markup
+ self.label.set_size_request(150, -1)
+ self.pack_start(self.label, False)
+ self.set_markup = lambda m: self.label.set_markup(m)
+ self.tp = None
+ #connect events
+ self.connect('show', self._update_gui)
+ def set_color(self, color): pass
+ def set_tooltip_text(self, text): pass
+
+ def _update_gui(self, *args):
+ """
+ Set the markup, color, tooltip, show/hide.
+ """
+ #set the markup
+ has_cb = \
+ hasattr(self.param.get_parent(), 'get_callbacks') and \
+ filter(lambda c: self.param.get_key() in c, self.param.get_parent()._callbacks)
+ self.set_markup(Utils.parse_template(PARAM_LABEL_MARKUP_TMPL, param=self.param, has_cb=has_cb))
+ #set the color
+ self.set_color(self.param.get_color())
+ #set the tooltip
+ self.set_tooltip_text(
+ Utils.parse_template(TIP_MARKUP_TMPL, param=self.param).strip(),
+ )
+ #show/hide
+ if self.param.get_hide() == 'all': self.hide_all()
+ else: self.show_all()
+
+ def _handle_changed(self, *args):
+ """
+ Handle a gui change by setting the new param value,
+ calling the callback (if applicable), and updating.
+ """
+ #set the new value
+ self.param.set_value(self.get_text())
+ #call the callback
+ if self._callback: self._callback(*args)
+ else: self.param.validate()
+ #gui update
+ self._update_gui()
+
+class EntryParam(InputParam):
+ """Provide an entry box for strings and numbers."""
+
+ def __init__(self, *args, **kwargs):
+ InputParam.__init__(self, *args, **kwargs)
+ self._input = gtk.Entry()
+ self._input.set_text(self.param.get_value())
+ self._input.connect('changed', self._handle_changed)
+ self.pack_start(self._input, True)
+ def get_text(self): return self._input.get_text()
+ def set_color(self, color):
+ self._input.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
+ self._input.modify_text(gtk.STATE_NORMAL, Colors.PARAM_ENTRY_TEXT_COLOR)
+ def set_tooltip_text(self, text): self._input.set_tooltip_text(text)
+
+class EnumParam(InputParam):
+ """Provide an entry box for Enum types with a drop down menu."""
+
+ def __init__(self, *args, **kwargs):
+ InputParam.__init__(self, *args, **kwargs)
+ self._input = gtk.combo_box_new_text()
+ for option in self.param.get_options(): self._input.append_text(option.get_name())
+ self._input.set_active(self.param.get_option_keys().index(self.param.get_value()))
+ self._input.connect('changed', self._handle_changed)
+ self.pack_start(self._input, False)
+ def get_text(self): return self.param.get_option_keys()[self._input.get_active()]
+ def set_tooltip_text(self, text): self._input.set_tooltip_text(text)
+
+class EnumEntryParam(InputParam):
+ """Provide an entry box and drop down menu for Raw Enum types."""
+
+ def __init__(self, *args, **kwargs):
+ InputParam.__init__(self, *args, **kwargs)
+ self._input = gtk.combo_box_entry_new_text()
+ for option in self.param.get_options(): self._input.append_text(option.get_name())
+ try: self._input.set_active(self.param.get_option_keys().index(self.param.get_value()))
+ except:
+ self._input.set_active(-1)
+ self._input.get_child().set_text(self.param.get_value())
+ self._input.connect('changed', self._handle_changed)
+ self._input.get_child().connect('changed', self._handle_changed)
+ self.pack_start(self._input, False)
+ def get_text(self):
+ if self._input.get_active() == -1: return self._input.get_child().get_text()
+ return self.param.get_option_keys()[self._input.get_active()]
+ def set_tooltip_text(self, text):
+ if self._input.get_active() == -1: #custom entry
+ self._input.get_child().set_tooltip_text(text)
+ else: self._input.set_tooltip_text(text)
+ def set_color(self, color):
+ if self._input.get_active() == -1: #custom entry, use color
+ self._input.get_child().modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
+ self._input.get_child().modify_text(gtk.STATE_NORMAL, Colors.PARAM_ENTRY_TEXT_COLOR)
+ else: #from enum, make pale background
+ self._input.get_child().modify_base(gtk.STATE_NORMAL, Colors.ENTRYENUM_CUSTOM_COLOR)
+ self._input.get_child().modify_text(gtk.STATE_NORMAL, Colors.PARAM_ENTRY_TEXT_COLOR)
+
+PARAM_MARKUP_TMPL="""\
+#set $foreground = $param.is_valid() and 'black' or 'red'
+<span foreground="$foreground" font_desc="Sans 7.5"><b>$encode($param.get_name()): </b>$encode(repr($param))</span>"""
+
+PARAM_LABEL_MARKUP_TMPL="""\
+#set $foreground = $param.is_valid() and 'black' or 'red'
+#set $underline = $has_cb and 'low' or 'none'
+<span underline="$underline" foreground="$foreground" font_desc="Sans 9">$encode($param.get_name())</span>"""
+
+TIP_MARKUP_TMPL="""\
+########################################
+#def truncate(string)
+ #set $max_len = 100
+ #set $string = str($string)
+ #if len($string) > $max_len
+$('%s...%s'%($string[:$max_len/2], $string[-$max_len/2:]))#slurp
+ #else
+$string#slurp
+ #end if
+#end def
+########################################
+Key: $param.get_key()
+Type: $param.get_type()
+#if $param.is_valid()
+Value: $truncate($param.get_evaluated())
+#elif len($param.get_error_messages()) == 1
+Error: $(param.get_error_messages()[0])
+#else
+Error:
+ #for $error_msg in $param.get_error_messages()
+ * $error_msg
+ #end for
+#end if"""
+
+class Param(Element):
+ """The graphical parameter."""
+
+ def __init__(self): Element.__init__(self)
+
+ def get_input(self, *args, **kwargs):
+ """
+ Get the graphical gtk class to represent this parameter.
+ An enum requires and combo parameter.
+ A non-enum with options gets a combined entry/combo parameter.
+ All others get a standard entry parameter.
+ @return gtk input class
+ """
+ if self.is_enum(): return EnumParam(self, *args, **kwargs)
+ if self.get_options(): return EnumEntryParam(self, *args, **kwargs)
+ return EntryParam(self, *args, **kwargs)
+
+ def get_markup(self):
+ """
+ Get the markup for this param.
+ @return a pango markup string
+ """
+ return Utils.parse_template(PARAM_MARKUP_TMPL, param=self)
diff --git a/grc/gui/Platform.py b/grc/gui/Platform.py
new file mode 100644
index 000000000..8bbfaca23
--- /dev/null
+++ b/grc/gui/Platform.py
@@ -0,0 +1,23 @@
+"""
+Copyright 2008, 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from Element import Element
+
+class Platform(Element):
+ def __init__(self): Element.__init__(self)
diff --git a/grc/gui/Port.py b/grc/gui/Port.py
new file mode 100644
index 000000000..2896d04c1
--- /dev/null
+++ b/grc/gui/Port.py
@@ -0,0 +1,190 @@
+"""
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from Element import Element
+from Constants import \
+ PORT_SEPARATION, CONNECTOR_EXTENSION_MINIMAL, \
+ CONNECTOR_EXTENSION_INCREMENT, \
+ PORT_LABEL_PADDING, PORT_MIN_WIDTH
+import Utils
+import Colors
+import pygtk
+pygtk.require('2.0')
+import gtk
+
+PORT_MARKUP_TMPL="""\
+<span foreground="black" font_desc="Sans 7.5">$encode($port.get_name())</span>"""
+
+class Port(Element):
+ """The graphical port."""
+
+ def __init__(self):
+ """
+ Port contructor.
+ Create list of connector coordinates.
+ """
+ Element.__init__(self)
+ self.connector_coordinates = dict()
+
+ def create_shapes(self):
+ """Create new areas and labels for the port."""
+ Element.create_shapes(self)
+ #get current rotation
+ rotation = self.get_rotation()
+ #get all sibling ports
+ if self.is_source(): ports = self.get_parent().get_sources()
+ elif self.is_sink(): ports = self.get_parent().get_sinks()
+ #get the max width
+ self.W = max([port.W for port in ports] + [PORT_MIN_WIDTH])
+ #get a numeric index for this port relative to its sibling ports
+ index = ports.index(self)
+ length = len(ports)
+ #reverse the order of ports for these rotations
+ if rotation in (180, 270): index = length-index-1
+ offset = (self.get_parent().H - length*self.H - (length-1)*PORT_SEPARATION)/2
+ #create areas and connector coordinates
+ if (self.is_sink() and rotation == 0) or (self.is_source() and rotation == 180):
+ x = -1*self.W
+ y = (PORT_SEPARATION+self.H)*index+offset
+ self.add_area((x, y), (self.W, self.H))
+ self._connector_coordinate = (x-1, y+self.H/2)
+ elif (self.is_source() and rotation == 0) or (self.is_sink() and rotation == 180):
+ x = self.get_parent().W
+ y = (PORT_SEPARATION+self.H)*index+offset
+ self.add_area((x, y), (self.W, self.H))
+ self._connector_coordinate = (x+1+self.W, y+self.H/2)
+ elif (self.is_source() and rotation == 90) or (self.is_sink() and rotation == 270):
+ y = -1*self.W
+ x = (PORT_SEPARATION+self.H)*index+offset
+ self.add_area((x, y), (self.H, self.W))
+ self._connector_coordinate = (x+self.H/2, y-1)
+ elif (self.is_sink() and rotation == 90) or (self.is_source() and rotation == 270):
+ y = self.get_parent().W
+ x = (PORT_SEPARATION+self.H)*index+offset
+ self.add_area((x, y), (self.H, self.W))
+ self._connector_coordinate = (x+self.H/2, y+1+self.W)
+ #the connector length
+ self._connector_length = CONNECTOR_EXTENSION_MINIMAL + CONNECTOR_EXTENSION_INCREMENT*index
+
+ def create_labels(self):
+ """Create the labels for the socket."""
+ Element.create_labels(self)
+ self._bg_color = Colors.get_color(self.get_color())
+ #create the layout
+ layout = gtk.DrawingArea().create_pango_layout('')
+ layout.set_markup(Utils.parse_template(PORT_MARKUP_TMPL, port=self))
+ self.w, self.h = layout.get_pixel_size()
+ self.W, self.H = 2*PORT_LABEL_PADDING+self.w, 2*PORT_LABEL_PADDING+self.h
+ #create the pixmap
+ pixmap = self.get_parent().get_parent().new_pixmap(self.w, self.h)
+ gc = pixmap.new_gc()
+ gc.set_foreground(self._bg_color)
+ pixmap.draw_rectangle(gc, True, 0, 0, self.w, self.h)
+ pixmap.draw_layout(gc, 0, 0, layout)
+ #create vertical and horizontal pixmaps
+ self.horizontal_label = pixmap
+ if self.is_vertical():
+ self.vertical_label = self.get_parent().get_parent().new_pixmap(self.h, self.w)
+ Utils.rotate_pixmap(gc, self.horizontal_label, self.vertical_label)
+
+ def draw(self, gc, window):
+ """
+ Draw the socket with a label.
+ @param gc the graphics context
+ @param window the gtk window to draw on
+ """
+ Element.draw(
+ self, gc, window, bg_color=self._bg_color,
+ border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or Colors.BORDER_COLOR,
+ )
+ X,Y = self.get_coordinate()
+ (x,y),(w,h) = self._areas_list[0] #use the first area's sizes to place the labels
+ if self.is_horizontal():
+ window.draw_drawable(gc, self.horizontal_label, 0, 0, x+X+(self.W-self.w)/2, y+Y+(self.H-self.h)/2, -1, -1)
+ elif self.is_vertical():
+ window.draw_drawable(gc, self.vertical_label, 0, 0, x+X+(self.H-self.h)/2, y+Y+(self.W-self.w)/2, -1, -1)
+
+ def get_connector_coordinate(self):
+ """
+ Get the coordinate where connections may attach to.
+ @return the connector coordinate (x, y) tuple
+ """
+ x,y = self._connector_coordinate
+ X,Y = self.get_coordinate()
+ return (x+X, y+Y)
+
+ def get_connector_direction(self):
+ """
+ Get the direction that the socket points: 0,90,180,270.
+ This is the rotation degree if the socket is an output or
+ the rotation degree + 180 if the socket is an input.
+ @return the direction in degrees
+ """
+ if self.is_source(): return self.get_rotation()
+ elif self.is_sink(): return (self.get_rotation() + 180)%360
+
+ def get_connector_length(self):
+ """
+ Get the length of the connector.
+ The connector length increases as the port index changes.
+ @return the length in pixels
+ """
+ return self._connector_length
+
+ def get_rotation(self):
+ """
+ Get the parent's rotation rather than self.
+ @return the parent's rotation
+ """
+ return self.get_parent().get_rotation()
+
+ def move(self, delta_coor):
+ """
+ Move the parent rather than self.
+ @param delta_corr the (delta_x, delta_y) tuple
+ """
+ self.get_parent().move(delta_coor)
+
+ def rotate(self, direction):
+ """
+ Rotate the parent rather than self.
+ @param direction degrees to rotate
+ """
+ self.get_parent().rotate(direction)
+
+ def get_coordinate(self):
+ """
+ Get the parent's coordinate rather than self.
+ @return the parents coordinate
+ """
+ return self.get_parent().get_coordinate()
+
+ def set_highlighted(self, highlight):
+ """
+ Set the parent highlight rather than self.
+ @param highlight true to enable highlighting
+ """
+ self.get_parent().set_highlighted(highlight)
+
+ def is_highlighted(self):
+ """
+ Get the parent's is highlight rather than self.
+ @return the parent's highlighting status
+ """
+ return self.get_parent().is_highlighted()
diff --git a/grc/gui/Preferences.py b/grc/gui/Preferences.py
new file mode 100644
index 000000000..1d89920dd
--- /dev/null
+++ b/grc/gui/Preferences.py
@@ -0,0 +1,86 @@
+"""
+Copyright 2008 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import ConfigParser
+import os
+
+_platform = None
+_config_parser = ConfigParser.ConfigParser()
+
+def file_extension(): return '.'+_platform.get_key()
+def _prefs_file(): return os.path.join(os.path.expanduser('~'), file_extension())
+
+def load(platform):
+ global _platform
+ _platform = platform
+ #create sections
+ _config_parser.add_section('main')
+ _config_parser.add_section('files_open')
+ try: _config_parser.read(_prefs_file())
+ except: pass
+def save():
+ try: _config_parser.write(open(_prefs_file(), 'w'))
+ except: pass
+
+###########################################################################
+# Special methods for specific program functionalities
+###########################################################################
+
+def main_window_size(size=None):
+ if size is not None:
+ _config_parser.set('main', 'main_window_width', size[0])
+ _config_parser.set('main', 'main_window_height', size[1])
+ else:
+ try: return (
+ _config_parser.getint('main', 'main_window_width'),
+ _config_parser.getint('main', 'main_window_height'),
+ )
+ except: return (1, 1)
+
+def file_open(file=None):
+ if file is not None: _config_parser.set('main', 'file_open', file)
+ else:
+ try: return _config_parser.get('main', 'file_open')
+ except: return ''
+
+def files_open(files=None):
+ if files is not None:
+ _config_parser.remove_section('files_open') #clear section
+ _config_parser.add_section('files_open')
+ for i, file in enumerate(files):
+ _config_parser.set('files_open', 'file_open_%d'%i, file)
+ else:
+ files = list()
+ i = 0
+ while True:
+ try: files.append(_config_parser.get('files_open', 'file_open_%d'%i))
+ except: return files
+ i = i + 1
+
+def reports_window_position(pos=None):
+ if pos is not None: _config_parser.set('main', 'reports_window_position', pos)
+ else:
+ try: return _config_parser.getint('main', 'reports_window_position') or 1 #greater than 0
+ except: return -1
+
+def blocks_window_position(pos=None):
+ if pos is not None: _config_parser.set('main', 'blocks_window_position', pos)
+ else:
+ try: return _config_parser.getint('main', 'blocks_window_position') or 1 #greater than 0
+ except: return -1
diff --git a/grc/gui/PropsDialog.py b/grc/gui/PropsDialog.py
new file mode 100644
index 000000000..cc84fd088
--- /dev/null
+++ b/grc/gui/PropsDialog.py
@@ -0,0 +1,170 @@
+"""
+Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+
+from Dialogs import TextDisplay
+from Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT
+
+def get_title_label(title):
+ """
+ Get a title label for the params window.
+ The title will be bold, underlined, and left justified.
+ @param title the text of the title
+ @return a gtk object
+ """
+ label = gtk.Label()
+ label.set_markup('\n<b><span underline="low">%s</span>:</b>\n'%title)
+ hbox = gtk.HBox()
+ hbox.pack_start(label, False, False, padding=11)
+ return hbox
+
+class PropsDialog(gtk.Dialog):
+ """
+ A dialog to set block parameters, view errors, and view documentation.
+ """
+
+ def __init__(self, block):
+ """
+ Properties dialog contructor.
+ @param block a block instance
+ """
+ self._hash = 0
+ LABEL_SPACING = 7
+ gtk.Dialog.__init__(self,
+ title='Properties: %s'%block.get_name(),
+ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT),
+ )
+ self._block = block
+ self.set_size_request(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT)
+ vbox = gtk.VBox()
+ #Create the scrolled window to hold all the parameters
+ scrolled_window = gtk.ScrolledWindow()
+ scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ scrolled_window.add_with_viewport(vbox)
+ self.vbox.pack_start(scrolled_window, True)
+ #Params box for block parameters
+ self._params_box = gtk.VBox()
+ self._params_box.pack_start(get_title_label('Parameters'), False)
+ self._input_object_params = list()
+ #Error Messages for the block
+ self._error_box = gtk.VBox()
+ self._error_messages_text_display = TextDisplay()
+ self._error_box.pack_start(gtk.Label(), False, False, LABEL_SPACING)
+ self._error_box.pack_start(get_title_label('Error Messages'), False)
+ self._error_box.pack_start(self._error_messages_text_display, False)
+ #Docs for the block
+ self._docs_box = err_box = gtk.VBox()
+ self._docs_text_display = TextDisplay()
+ self._docs_box.pack_start(gtk.Label(), False, False, LABEL_SPACING)
+ self._docs_box.pack_start(get_title_label('Documentation'), False)
+ self._docs_box.pack_start(self._docs_text_display, False)
+ #Add the boxes
+ vbox.pack_start(self._params_box, False)
+ vbox.pack_start(self._error_box, False)
+ vbox.pack_start(self._docs_box, False)
+ #connect events
+ self.connect('key-press-event', self._handle_key_press)
+ self.connect('show', self._update_gui)
+ #show all (performs initial gui update)
+ self.show_all()
+
+ def _params_changed(self):
+ """
+ Have the params in this dialog changed?
+ Ex: Added, removed, type change, hide change...
+ To the props dialog, the hide setting of 'none' and 'part' are identical.
+ Therfore, the props dialog only cares if the hide setting is/not 'all'.
+ Make a hash that uniquely represents the params' state.
+ @return true if changed
+ """
+ old_hash = self._hash
+ #create a tuple of things from each param that affects the params box
+ self._hash = hash(tuple([(
+ hash(param), param.get_type(), param.get_hide() == 'all',
+ ) for param in self._block.get_params()]))
+ return self._hash != old_hash
+
+ def _handle_changed(self, *args):
+ """
+ A change occured within a param:
+ Rewrite/validate the block and update the gui.
+ """
+ #update for the block
+ self._block.rewrite()
+ self._block.validate()
+ self._update_gui()
+
+ def _update_gui(self, *args):
+ """
+ Repopulate the parameters box (if changed).
+ Update all the input parameters.
+ Update the error messages box.
+ Hide the box if there are no errors.
+ Update the documentation block.
+ Hide the box if there are no docs.
+ """
+ #update the params box
+ if self._params_changed():
+ #hide params box before changing
+ self._params_box.hide_all()
+ #empty the params box
+ for io_param in list(self._input_object_params):
+ self._params_box.remove(io_param)
+ self._input_object_params.remove(io_param)
+ io_param.destroy()
+ #repopulate the params box
+ for param in self._block.get_params():
+ if param.get_hide() == 'all': continue
+ io_param = param.get_input(self._handle_changed)
+ self._input_object_params.append(io_param)
+ self._params_box.pack_start(io_param, False)
+ #show params box with new params
+ self._params_box.show_all()
+ #update the errors box
+ if self._block.is_valid(): self._error_box.hide()
+ else: self._error_box.show()
+ messages = '\n\n'.join(self._block.get_error_messages())
+ self._error_messages_text_display.set_text(messages)
+ #update the docs box
+ if self._block.get_doc(): self._docs_box.show()
+ else: self._docs_box.hide()
+ self._docs_text_display.set_text(self._block.get_doc())
+
+ def _handle_key_press(self, widget, event):
+ """
+ Handle key presses from the keyboard.
+ Call the ok response when enter is pressed.
+ @return false to forward the keypress
+ """
+ if event.keyval == gtk.keysyms.Return:
+ self.response(gtk.RESPONSE_ACCEPT)
+ return True #handled here
+ return False #forward the keypress
+
+ def run(self):
+ """
+ Run the dialog and get its response.
+ @return true if the response was accept
+ """
+ response = gtk.Dialog.run(self)
+ self.destroy()
+ return response == gtk.RESPONSE_ACCEPT
diff --git a/grc/gui/StateCache.py b/grc/gui/StateCache.py
new file mode 100644
index 000000000..3f6b79224
--- /dev/null
+++ b/grc/gui/StateCache.py
@@ -0,0 +1,92 @@
+"""
+Copyright 2007 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import Actions
+from Constants import STATE_CACHE_SIZE
+
+class StateCache(object):
+ """
+ The state cache is an interface to a list to record data/states and to revert to previous states.
+ States are recorded into the list in a circular fassion by using an index for the current state,
+ and counters for the range where states are stored.
+ """
+
+ def __init__(self, initial_state):
+ """
+ StateCache constructor.
+ @param initial_state the intial state (nested data)
+ """
+ self.states = [None] * STATE_CACHE_SIZE #fill states
+ self.current_state_index = 0
+ self.num_prev_states = 0
+ self.num_next_states = 0
+ self.states[0] = initial_state
+ self.update_actions()
+
+ def save_new_state(self, state):
+ """
+ Save a new state.
+ Place the new state at the next index and add one to the number of previous states.
+ @param state the new state
+ """
+ self.current_state_index = (self.current_state_index + 1)%STATE_CACHE_SIZE
+ self.states[self.current_state_index] = state
+ self.num_prev_states = self.num_prev_states + 1
+ if self.num_prev_states == STATE_CACHE_SIZE: self.num_prev_states = STATE_CACHE_SIZE - 1
+ self.num_next_states = 0
+ self.update_actions()
+
+ def get_current_state(self):
+ """
+ Get the state at the current index.
+ @return the current state (nested data)
+ """
+ self.update_actions()
+ return self.states[self.current_state_index]
+
+ def get_prev_state(self):
+ """
+ Get the previous state and decrement the current index.
+ @return the previous state or None
+ """
+ if self.num_prev_states > 0:
+ self.current_state_index = (self.current_state_index + STATE_CACHE_SIZE -1)%STATE_CACHE_SIZE
+ self.num_next_states = self.num_next_states + 1
+ self.num_prev_states = self.num_prev_states - 1
+ return self.get_current_state()
+ return None
+
+ def get_next_state(self):
+ """
+ Get the nest state and increment the current index.
+ @return the next state or None
+ """
+ if self.num_next_states > 0:
+ self.current_state_index = (self.current_state_index + 1)%STATE_CACHE_SIZE
+ self.num_next_states = self.num_next_states - 1
+ self.num_prev_states = self.num_prev_states + 1
+ return self.get_current_state()
+ return None
+
+ def update_actions(self):
+ """
+ Update the undo and redo actions based on the number of next and prev states.
+ """
+ Actions.FLOW_GRAPH_REDO.set_sensitive(self.num_next_states != 0)
+ Actions.FLOW_GRAPH_UNDO.set_sensitive(self.num_prev_states != 0)
diff --git a/grc/gui/Utils.py b/grc/gui/Utils.py
new file mode 100644
index 000000000..bb19ed3d9
--- /dev/null
+++ b/grc/gui/Utils.py
@@ -0,0 +1,90 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from Constants import POSSIBLE_ROTATIONS
+from Cheetah.Template import Template
+import pygtk
+pygtk.require('2.0')
+import gtk
+import gobject
+
+def rotate_pixmap(gc, src_pixmap, dst_pixmap, angle=gtk.gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE):
+ """
+ Load the destination pixmap with a rotated version of the source pixmap.
+ The source pixmap will be loaded into a pixbuf, rotated, and drawn to the destination pixmap.
+ The pixbuf is a client-side drawable, where a pixmap is a server-side drawable.
+ @param gc the graphics context
+ @param src_pixmap the source pixmap
+ @param dst_pixmap the destination pixmap
+ @param angle the angle to rotate by
+ """
+ width, height = src_pixmap.get_size()
+ pixbuf = gtk.gdk.Pixbuf(
+ colorspace=gtk.gdk.COLORSPACE_RGB,
+ has_alpha=False, bits_per_sample=8,
+ width=width, height=height,
+ )
+ pixbuf.get_from_drawable(src_pixmap, src_pixmap.get_colormap(), 0, 0, 0, 0, -1, -1)
+ pixbuf = pixbuf.rotate_simple(angle)
+ dst_pixmap.draw_pixbuf(gc, pixbuf, 0, 0, 0, 0)
+
+def get_rotated_coordinate(coor, rotation):
+ """
+ Rotate the coordinate by the given rotation.
+ @param coor the coordinate x, y tuple
+ @param rotation the angle in degrees
+ @return the rotated coordinates
+ """
+ #handles negative angles
+ rotation = (rotation + 360)%360
+ if rotation not in POSSIBLE_ROTATIONS:
+ raise ValueError('unusable rotation angle "%s"'%str(rotation))
+ #determine the number of degrees to rotate
+ cos_r, sin_r = {
+ 0: (1, 0),
+ 90: (0, 1),
+ 180: (-1, 0),
+ 270: (0, -1),
+ }[rotation]
+ x, y = coor
+ return (x*cos_r + y*sin_r, -x*sin_r + y*cos_r)
+
+def get_angle_from_coordinates((x1,y1), (x2,y2)):
+ """
+ Given two points, calculate the vector direction from point1 to point2, directions are multiples of 90 degrees.
+ @param (x1,y1) the coordinate of point 1
+ @param (x2,y2) the coordinate of point 2
+ @return the direction in degrees
+ """
+ if y1 == y2:#0 or 180
+ if x2 > x1: return 0
+ else: return 180
+ else:#90 or 270
+ if y2 > y1: return 270
+ else: return 90
+
+def parse_template(tmpl_str, **kwargs):
+ """
+ Parse the template string with the given args.
+ Pass in the xml encode method for pango escape chars.
+ @param tmpl_str the template as a string
+ @return a string of the parsed template
+ """
+ kwargs['encode'] = gobject.markup_escape_text
+ return str(Template(tmpl_str, kwargs))
diff --git a/grc/gui/__init__.py b/grc/gui/__init__.py
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/grc/gui/__init__.py
@@ -0,0 +1 @@
+
diff --git a/grc/python/Block.py b/grc/python/Block.py
new file mode 100644
index 000000000..2c334dfc2
--- /dev/null
+++ b/grc/python/Block.py
@@ -0,0 +1,180 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from .. base.Block import Block as _Block
+from .. gui.Block import Block as _GUIBlock
+import extract_docs
+
+class Block(_Block, _GUIBlock):
+
+ def is_virtual_sink(self): return self.get_key() == 'virtual_sink'
+ def is_virtual_source(self): return self.get_key() == 'virtual_source'
+
+ ##for make source to keep track of indexes
+ _source_count = 0
+ ##for make sink to keep track of indexes
+ _sink_count = 0
+
+ def __init__(self, flow_graph, n):
+ """
+ Make a new block from nested data.
+ @param flow graph the parent element
+ @param n the nested odict
+ @return block a new block
+ """
+ #grab the data
+ self._doc = n.find('doc') or ''
+ self._imports = map(lambda i: i.strip(), n.findall('import'))
+ self._make = n.find('make')
+ self._var_make = n.find('var_make')
+ self._checks = n.findall('check')
+ self._callbacks = n.findall('callback')
+ self._throttle = n.find('throttle') or ''
+ #build the block
+ _Block.__init__(
+ self,
+ flow_graph=flow_graph,
+ n=n,
+ )
+ _GUIBlock.__init__(self)
+
+ def throttle(self): return bool(self._throttle)
+
+ def validate(self):
+ """
+ Validate this block.
+ Call the base class validate.
+ Evaluate the checks: each check must evaluate to True.
+ """
+ _Block.validate(self)
+ #evaluate the checks
+ for check in self._checks:
+ check_res = self.resolve_dependencies(check)
+ try:
+ if not self.get_parent().evaluate(check_res):
+ self.add_error_message('Check "%s" failed.'%check)
+ except: self.add_error_message('Check "%s" did not evaluate.'%check)
+
+ def rewrite(self):
+ """
+ Add and remove ports to adjust for the nports.
+ """
+ _Block.rewrite(self)
+
+ def rectify(ports):
+ #restore integer contiguity after insertion
+ #rectify the port names with the index
+ for i, port in enumerate(ports):
+ port._key = str(i)
+ port._name = port._n['name']
+ if len(ports) > 1: port._name += str(i)
+
+ def insert_port(get_ports, get_port, key):
+ prev_port = get_port(str(int(key)-1))
+ get_ports().insert(
+ get_ports().index(prev_port)+1,
+ prev_port.copy(new_key=key),
+ )
+ rectify(get_ports())
+
+ def remove_port(get_ports, get_port, key):
+ port = get_port(key)
+ for connection in port.get_connections():
+ self.get_parent().remove_element(connection)
+ get_ports().remove(port)
+ rectify(get_ports())
+
+ #adjust nports
+ for get_ports, get_port in (
+ (self.get_sources, self.get_source),
+ (self.get_sinks, self.get_sink),
+ ):
+ master_ports = filter(lambda p: p.get_nports(), get_ports())
+ for i, master_port in enumerate(master_ports):
+ nports = master_port.get_nports()
+ index_first = get_ports().index(master_port)
+ try: index_last = get_ports().index(master_ports[i+1])
+ except IndexError: index_last = len(get_ports())
+ num_ports = index_last - index_first
+ #do nothing if nports is already num ports
+ if nports == num_ports: continue
+ #remove excess ports and connections
+ if nports < num_ports:
+ for key in reversed(map(str, range(index_first+nports, index_first+num_ports))):
+ remove_port(get_ports, get_port, key)
+ continue
+ #add more ports
+ if nports > num_ports:
+ for key in map(str, range(index_first+num_ports, index_first+nports)):
+ insert_port(get_ports, get_port, key)
+ continue
+
+ def port_controller_modify(self, direction):
+ """
+ Change the port controller.
+ @param direction +1 or -1
+ @return true for change
+ """
+ changed = False
+ #concat the nports string from the private nports settings of all ports
+ nports_str = ' '.join([port._nports for port in self.get_ports()])
+ #modify all params whose keys appear in the nports string
+ for param in self.get_params():
+ if param.is_enum() or param.get_key() not in nports_str: continue
+ #try to increment the port controller by direction
+ try:
+ value = param.get_evaluated()
+ value = value + direction
+ if 0 < value:
+ param.set_value(value)
+ changed = True
+ except: pass
+ return changed
+
+ def get_doc(self):
+ doc = self._doc.strip('\n').replace('\\\n', '')
+ #merge custom doc with doxygen docs
+ return '\n'.join([doc, extract_docs.extract(self.get_key())]).strip('\n')
+
+ def get_category(self):
+ return _Block.get_category(self)
+
+ def get_imports(self):
+ """
+ Resolve all import statements.
+ Split each import statement at newlines.
+ Combine all import statments into a list.
+ Filter empty imports.
+ @return a list of import statements
+ """
+ return filter(lambda i: i, sum(map(lambda i: self.resolve_dependencies(i).split('\n'), self._imports), []))
+
+ def get_make(self): return self.resolve_dependencies(self._make)
+ def get_var_make(self): return self.resolve_dependencies(self._var_make)
+
+ def get_callbacks(self):
+ """
+ Get a list of function callbacks for this block.
+ @return a list of strings
+ """
+ def make_callback(callback):
+ callback = self.resolve_dependencies(callback)
+ if 'self.' in callback: return callback
+ return 'self.%s.%s'%(self.get_id(), callback)
+ return map(make_callback, self._callbacks)
diff --git a/grc/python/CMakeLists.txt b/grc/python/CMakeLists.txt
new file mode 100644
index 000000000..4832dd897
--- /dev/null
+++ b/grc/python/CMakeLists.txt
@@ -0,0 +1,44 @@
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+GR_PYTHON_INSTALL(FILES
+ convert_hier.py
+ expr_utils.py
+ extract_docs.py
+ Block.py
+ Connection.py
+ Constants.py
+ FlowGraph.py
+ Generator.py
+ Param.py
+ Platform.py
+ Port.py
+ __init__.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/python
+ COMPONENT "grc"
+)
+
+install(FILES
+ block.dtd
+ default_flow_graph.grc
+ flow_graph.tmpl
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/python
+ COMPONENT "grc"
+)
diff --git a/grc/python/Connection.py b/grc/python/Connection.py
new file mode 100644
index 000000000..341dd2d82
--- /dev/null
+++ b/grc/python/Connection.py
@@ -0,0 +1,46 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import Constants
+from .. base.Element import Element
+from .. base.Connection import Connection as _Connection
+from .. gui.Connection import Connection as _GUIConnection
+
+class Connection(_Connection, _GUIConnection):
+
+ def __init__(self, **kwargs):
+ _Connection.__init__(self, **kwargs)
+ _GUIConnection.__init__(self)
+
+ def is_msg(self):
+ return self.get_source().get_type() == self.get_sink().get_type() == 'msg'
+
+ def is_message(self):
+ return self.get_source().get_type() == self.get_sink().get_type() == 'message'
+
+ def validate(self):
+ """
+ Validate the connections.
+ The ports must match in io size.
+ """
+ Element.validate(self)
+ source_size = Constants.TYPE_TO_SIZEOF[self.get_source().get_type()] * self.get_source().get_vlen()
+ sink_size = Constants.TYPE_TO_SIZEOF[self.get_sink().get_type()] * self.get_sink().get_vlen()
+ if source_size != sink_size:
+ self.add_error_message('Source IO size "%s" does not match sink IO size "%s".'%(source_size, sink_size))
diff --git a/grc/python/Constants.py b/grc/python/Constants.py
new file mode 100644
index 000000000..b8dc9a96a
--- /dev/null
+++ b/grc/python/Constants.py
@@ -0,0 +1,95 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import os
+import stat
+from gnuradio import gr
+
+_gr_prefs = gr.prefs()
+
+#setup paths
+PATH_SEP = {'/':':', '\\':';'}[os.path.sep]
+HIER_BLOCKS_LIB_DIR = os.path.join(os.path.expanduser('~'), '.grc_gnuradio')
+BLOCKS_DIRS = filter( #filter blank strings
+ lambda x: x, PATH_SEP.join([
+ os.environ.get('GRC_BLOCKS_PATH', ''),
+ _gr_prefs.get_string('grc', 'local_blocks_path', ''),
+ _gr_prefs.get_string('grc', 'global_blocks_path', ''),
+ ]).split(PATH_SEP),
+) + [HIER_BLOCKS_LIB_DIR]
+
+#file creation modes
+TOP_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH
+HIER_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH
+
+#data files
+DATA_DIR = os.path.dirname(__file__)
+FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl')
+BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd')
+DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc')
+
+CORE_TYPES = ( #name, key, sizeof, color
+ ('Complex Float 64', 'fc64', 16, '#CC8C69'),
+ ('Complex Float 32', 'fc32', 8, '#3399FF'),
+ ('Complex Integer 64', 'sc64', 16, '#66CC00'),
+ ('Complex Integer 32', 'sc32', 8, '#33cc66'),
+ ('Complex Integer 16', 'sc16', 4, '#cccc00'),
+ ('Complex Integer 8', 'sc8', 2, '#cc00cc'),
+ ('Float 64', 'f64', 8, '#66CCCC'),
+ ('Float 32', 'f32', 4, '#FF8C69'),
+ ('Integer 64', 's64', 8, '#99FF33'),
+ ('Integer 32', 's32', 4, '#00FF99'),
+ ('Integer 16', 's16', 2, '#FFFF66'),
+ ('Integer 8', 's8', 1, '#FF66FF'),
+ ('Message Queue', 'msg', 0, '#777777'),
+ ('Async Message', 'message', 0, '#C0C0C0'),
+ ('Wildcard', '', 0, '#FFFFFF'),
+)
+
+ALIAS_TYPES = {
+ 'complex' : (8, '#3399FF'),
+ 'float' : (4, '#FF8C69'),
+ 'int' : (4, '#00FF99'),
+ 'short' : (2, '#FFFF66'),
+ 'byte' : (1, '#FF66FF'),
+}
+
+TYPE_TO_COLOR = dict()
+TYPE_TO_SIZEOF = dict()
+for name, key, sizeof, color in CORE_TYPES:
+ TYPE_TO_COLOR[key] = color
+ TYPE_TO_SIZEOF[key] = sizeof
+for key, (sizeof, color) in ALIAS_TYPES.iteritems():
+ TYPE_TO_COLOR[key] = color
+ TYPE_TO_SIZEOF[key] = sizeof
+
+#coloring
+COMPLEX_COLOR_SPEC = '#3399FF'
+FLOAT_COLOR_SPEC = '#FF8C69'
+INT_COLOR_SPEC = '#00FF99'
+SHORT_COLOR_SPEC = '#FFFF66'
+BYTE_COLOR_SPEC = '#FF66FF'
+COMPLEX_VECTOR_COLOR_SPEC = '#3399AA'
+FLOAT_VECTOR_COLOR_SPEC = '#CC8C69'
+INT_VECTOR_COLOR_SPEC = '#00CC99'
+SHORT_VECTOR_COLOR_SPEC = '#CCCC33'
+BYTE_VECTOR_COLOR_SPEC = '#CC66CC'
+ID_COLOR_SPEC = '#DDDDDD'
+WILDCARD_COLOR_SPEC = '#FFFFFF'
+MSG_COLOR_SPEC = '#777777'
diff --git a/grc/python/FlowGraph.py b/grc/python/FlowGraph.py
new file mode 100644
index 000000000..376c2e337
--- /dev/null
+++ b/grc/python/FlowGraph.py
@@ -0,0 +1,163 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import expr_utils
+from .. base.FlowGraph import FlowGraph as _FlowGraph
+from .. gui.FlowGraph import FlowGraph as _GUIFlowGraph
+import re
+
+_variable_matcher = re.compile('^(variable\w*)$')
+_parameter_matcher = re.compile('^(parameter)$')
+
+class FlowGraph(_FlowGraph, _GUIFlowGraph):
+
+ def __init__(self, **kwargs):
+ _FlowGraph.__init__(self, **kwargs)
+ _GUIFlowGraph.__init__(self)
+ self._eval_cache = dict()
+
+ def _eval(self, code, namespace, namespace_hash):
+ """
+ Evaluate the code with the given namespace.
+ @param code a string with python code
+ @param namespace a dict representing the namespace
+ @param namespace_hash a unique hash for the namespace
+ @return the resultant object
+ """
+ if not code: raise Exception, 'Cannot evaluate empty statement.'
+ my_hash = hash(code) ^ namespace_hash
+ #cache if does not exist
+ if not self._eval_cache.has_key(my_hash):
+ self._eval_cache[my_hash] = eval(code, namespace, namespace)
+ #return from cache
+ return self._eval_cache[my_hash]
+
+ def get_io_signaturev(self, direction):
+ """
+ Get a list of io signatures for this flow graph.
+ @param direction a string of 'in' or 'out'
+ @return a list of dicts with: type, label, vlen, size
+ """
+ sorted_pads = {
+ 'in': self.get_pad_sources(),
+ 'out': self.get_pad_sinks(),
+ }[direction]
+ # we only want stream ports
+ sorted_pads = filter(lambda b: b.get_param('type').get_evaluated() != 'message', sorted_pads);
+ #load io signature
+ return [{
+ 'label': str(pad.get_param('label').get_evaluated()),
+ 'type': str(pad.get_param('type').get_evaluated()),
+ 'vlen': str(pad.get_param('vlen').get_evaluated()),
+ 'size': pad.get_param('type').get_opt('size'),
+ 'optional': bool(pad.get_param('optional').get_evaluated()),
+ } for pad in sorted_pads]
+
+ def get_pad_sources(self):
+ """
+ Get a list of pad source blocks sorted by id order.
+ @return a list of pad source blocks in this flow graph
+ """
+ pads = filter(lambda b: b.get_key() == 'pad_source', self.get_enabled_blocks())
+ return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id()))
+
+ def get_pad_sinks(self):
+ """
+ Get a list of pad sink blocks sorted by id order.
+ @return a list of pad sink blocks in this flow graph
+ """
+ pads = filter(lambda b: b.get_key() == 'pad_sink', self.get_enabled_blocks())
+ return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id()))
+
+ def get_msg_pad_sources(self):
+ ps = self.get_pad_sources();
+ return filter(lambda b: b.get_param('type').get_evaluated() == 'message', ps);
+
+ def get_msg_pad_sinks(self):
+ ps = self.get_pad_sinks();
+ return filter(lambda b: b.get_param('type').get_evaluated() == 'message', ps);
+
+ def get_imports(self):
+ """
+ Get a set of all import statments in this flow graph namespace.
+ @return a set of import statements
+ """
+ imports = sum([block.get_imports() for block in self.get_enabled_blocks()], [])
+ imports = sorted(set(imports))
+ return imports
+
+ def get_variables(self):
+ """
+ Get a list of all variables in this flow graph namespace.
+ Exclude paramterized variables.
+ @return a sorted list of variable blocks in order of dependency (indep -> dep)
+ """
+ variables = filter(lambda b: _variable_matcher.match(b.get_key()), self.get_enabled_blocks())
+ return expr_utils.sort_objects(variables, lambda v: v.get_id(), lambda v: v.get_var_make())
+
+ def get_parameters(self):
+ """
+ Get a list of all paramterized variables in this flow graph namespace.
+ @return a list of paramterized variables
+ """
+ parameters = filter(lambda b: _parameter_matcher.match(b.get_key()), self.get_enabled_blocks())
+ return parameters
+
+ def rewrite(self):
+ """
+ Flag the namespace to be renewed.
+ """
+ self._renew_eval_ns = True
+ _FlowGraph.rewrite(self)
+
+ def evaluate(self, expr):
+ """
+ Evaluate the expression.
+ @param expr the string expression
+ @throw Exception bad expression
+ @return the evaluated data
+ """
+ if self._renew_eval_ns:
+ self._renew_eval_ns = False
+ #reload namespace
+ n = dict()
+ #load imports
+ for imp in self.get_imports():
+ try: exec imp in n
+ except: pass
+ #load parameters
+ np = dict()
+ for parameter in self.get_parameters():
+ try:
+ e = eval(parameter.get_param('value').to_code(), n, n)
+ np[parameter.get_id()] = e
+ except: pass
+ n.update(np) #merge param namespace
+ #load variables
+ for variable in self.get_variables():
+ try:
+ e = eval(variable.get_param('value').to_code(), n, n)
+ n[variable.get_id()] = e
+ except: pass
+ #make namespace public
+ self.n = n
+ self.n_hash = hash(str(n))
+ #evaluate
+ e = self._eval(expr, self.n, self.n_hash)
+ return e
diff --git a/grc/python/Generator.py b/grc/python/Generator.py
new file mode 100644
index 000000000..616ea00fc
--- /dev/null
+++ b/grc/python/Generator.py
@@ -0,0 +1,152 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import os
+import sys
+import subprocess
+import tempfile
+from Cheetah.Template import Template
+import expr_utils
+from Constants import \
+ TOP_BLOCK_FILE_MODE, HIER_BLOCK_FILE_MODE, \
+ HIER_BLOCKS_LIB_DIR, FLOW_GRAPH_TEMPLATE
+import convert_hier
+from .. gui import Messages
+
+class Generator(object):
+
+ def __init__(self, flow_graph, file_path):
+ """
+ Initialize the generator object.
+ Determine the file to generate.
+ @param flow_graph the flow graph object
+ @param file_path the path to write the file to
+ """
+ self._flow_graph = flow_graph
+ self._generate_options = self._flow_graph.get_option('generate_options')
+ if self._generate_options == 'hb':
+ self._mode = HIER_BLOCK_FILE_MODE
+ dirname = HIER_BLOCKS_LIB_DIR
+ else:
+ self._mode = TOP_BLOCK_FILE_MODE
+ dirname = os.path.dirname(file_path)
+ #handle the case where the directory is read-only
+ #in this case, use the system's temp directory
+ if not os.access(dirname, os.W_OK):
+ dirname = tempfile.gettempdir()
+ filename = self._flow_graph.get_option('id') + '.py'
+ self._file_path = os.path.join(dirname, filename)
+
+ def get_file_path(self): return self._file_path
+
+ def write(self):
+ #do throttle warning
+ throttled = any(map(lambda b: b.throttle(), self._flow_graph.get_enabled_blocks()))
+ if not throttled and self._generate_options != 'hb':
+ Messages.send_warning('''\
+This flow graph may not have flow control: no audio or usrp blocks found. \
+Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''')
+ #generate
+ open(self.get_file_path(), 'w').write(str(self))
+ if self._generate_options == 'hb':
+ #convert hier block to xml wrapper
+ convert_hier.convert_hier(self._flow_graph, self.get_file_path())
+ os.chmod(self.get_file_path(), self._mode)
+
+ def get_popen(self):
+ """
+ Execute this python flow graph.
+ @return a popen object
+ """
+ #extract the path to the python executable
+ python_exe = sys.executable
+
+ #when using wx gui on mac os, execute with pythonw
+ #using pythonw is not necessary anymore, disabled below
+ #if self._generate_options == 'wx_gui' and 'darwin' in sys.platform.lower():
+ # python_exe = 'pythonw'
+
+ #setup the command args to run
+ cmds = [python_exe, '-u', self.get_file_path()] #-u is unbuffered stdio
+
+ #when in no gui mode on linux, use an xterm (looks nice)
+ if self._generate_options == 'no_gui' and 'linux' in sys.platform.lower():
+ cmds = ['xterm', '-e'] + cmds
+
+ p = subprocess.Popen(args=cmds, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False, universal_newlines=True)
+ return p
+
+ def __str__(self):
+ """
+ Convert the flow graph to python code.
+ @return a string of python code
+ """
+ title = self._flow_graph.get_option('title') or self._flow_graph.get_option('id').replace('_', ' ').title()
+ imports = self._flow_graph.get_imports()
+ variables = self._flow_graph.get_variables()
+ parameters = self._flow_graph.get_parameters()
+ #list of blocks not including variables and imports and parameters and disabled
+ def _get_block_sort_text(block):
+ code = block.get_make().replace(block.get_id(), ' ')
+ try: code += block.get_param('notebook').get_value() #older gui markup w/ wxgui
+ except: pass
+ try: code += block.get_param('gui_hint').get_value() #newer gui markup w/ qtgui
+ except: pass
+ return code
+ blocks = expr_utils.sort_objects(
+ self._flow_graph.get_enabled_blocks(),
+ lambda b: b.get_id(), _get_block_sort_text
+ )
+ #list of regular blocks (all blocks minus the special ones)
+ blocks = filter(lambda b: b not in (imports + parameters), blocks)
+ #list of connections where each endpoint is enabled
+ connections = filter(lambda c: not (c.is_msg() or c.is_message()), self._flow_graph.get_enabled_connections())
+ messages = filter(lambda c: c.is_msg(), self._flow_graph.get_enabled_connections())
+ messages2 = filter(lambda c: c.is_message(), self._flow_graph.get_enabled_connections())
+ #list of variable names
+ var_ids = [var.get_id() for var in parameters + variables]
+ #prepend self.
+ replace_dict = dict([(var_id, 'self.%s'%var_id) for var_id in var_ids])
+ #list of callbacks
+ callbacks = [
+ expr_utils.expr_replace(cb, replace_dict)
+ for cb in sum([block.get_callbacks() for block in self._flow_graph.get_enabled_blocks()], [])
+ ]
+ #map var id to callbacks
+ var_id2cbs = dict(
+ [(var_id, filter(lambda c: expr_utils.get_variable_dependencies(c, [var_id]), callbacks))
+ for var_id in var_ids]
+ )
+ #load the namespace
+ namespace = {
+ 'title': title,
+ 'imports': imports,
+ 'flow_graph': self._flow_graph,
+ 'variables': variables,
+ 'parameters': parameters,
+ 'blocks': blocks,
+ 'connections': connections,
+ 'messages': messages,
+ 'messages2': messages2,
+ 'generate_options': self._generate_options,
+ 'var_id2cbs': var_id2cbs,
+ }
+ #build the template
+ t = Template(open(FLOW_GRAPH_TEMPLATE, 'r').read(), namespace)
+ return str(t)
diff --git a/grc/python/Param.py b/grc/python/Param.py
new file mode 100644
index 000000000..2caca4802
--- /dev/null
+++ b/grc/python/Param.py
@@ -0,0 +1,458 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from .. base.Param import Param as _Param
+from .. gui.Param import Param as _GUIParam
+from .. gui.Param import EntryParam
+import Constants
+import numpy
+import os
+import pygtk
+pygtk.require('2.0')
+import gtk
+from gnuradio import eng_notation
+import re
+from gnuradio import gr
+
+_check_id_matcher = re.compile('^[a-z|A-Z]\w*$')
+_show_id_matcher = re.compile('^(variable\w*|parameter|options|notebook)$')
+
+class FileParam(EntryParam):
+ """Provide an entry box for filename and a button to browse for a file."""
+
+ def __init__(self, *args, **kwargs):
+ EntryParam.__init__(self, *args, **kwargs)
+ input = gtk.Button('...')
+ input.connect('clicked', self._handle_clicked)
+ self.pack_start(input, False)
+
+ def _handle_clicked(self, widget=None):
+ """
+ If the button was clicked, open a file dialog in open/save format.
+ Replace the text in the entry with the new filename from the file dialog.
+ """
+ #get the paths
+ file_path = self.param.is_valid() and self.param.get_evaluated() or ''
+ (dirname, basename) = os.path.isfile(file_path) and os.path.split(file_path) or (file_path, '')
+ if not os.path.exists(dirname): dirname = os.getcwd() #fix bad paths
+ #build the dialog
+ if self.param.get_type() == 'file_open':
+ file_dialog = gtk.FileChooserDialog('Open a Data File...', None,
+ gtk.FILE_CHOOSER_ACTION_OPEN, ('gtk-cancel',gtk.RESPONSE_CANCEL,'gtk-open',gtk.RESPONSE_OK))
+ elif self.param.get_type() == 'file_save':
+ file_dialog = gtk.FileChooserDialog('Save a Data File...', None,
+ gtk.FILE_CHOOSER_ACTION_SAVE, ('gtk-cancel',gtk.RESPONSE_CANCEL, 'gtk-save',gtk.RESPONSE_OK))
+ file_dialog.set_do_overwrite_confirmation(True)
+ file_dialog.set_current_name(basename) #show the current filename
+ file_dialog.set_current_folder(dirname) #current directory
+ file_dialog.set_select_multiple(False)
+ file_dialog.set_local_only(True)
+ if gtk.RESPONSE_OK == file_dialog.run(): #run the dialog
+ file_path = file_dialog.get_filename() #get the file path
+ self._input.set_text(file_path)
+ self._handle_changed()
+ file_dialog.destroy() #destroy the dialog
+
+#blacklist certain ids, its not complete, but should help
+import __builtin__
+ID_BLACKLIST = ['self', 'options', 'gr', 'blks2', 'wxgui', 'wx', 'math', 'forms', 'firdes'] + \
+ filter(lambda x: not x.startswith('_'), dir(gr.top_block())) + dir(__builtin__)
+#define types, native python + numpy
+VECTOR_TYPES = (tuple, list, set, numpy.ndarray)
+COMPLEX_TYPES = [complex, numpy.complex, numpy.complex64, numpy.complex128]
+REAL_TYPES = [float, numpy.float, numpy.float32, numpy.float64]
+INT_TYPES = [int, long, numpy.int, numpy.int8, numpy.int16, numpy.int32, numpy.uint64,
+ numpy.uint, numpy.uint8, numpy.uint16, numpy.uint32, numpy.uint64]
+#cast to tuple for isinstance, concat subtypes
+COMPLEX_TYPES = tuple(COMPLEX_TYPES + REAL_TYPES + INT_TYPES)
+REAL_TYPES = tuple(REAL_TYPES + INT_TYPES)
+INT_TYPES = tuple(INT_TYPES)
+
+class Param(_Param, _GUIParam):
+
+ def __init__(self, **kwargs):
+ _Param.__init__(self, **kwargs)
+ _GUIParam.__init__(self)
+ self._init = False
+ self._hostage_cells = list()
+
+ def get_types(self): return (
+ 'raw', 'enum',
+ 'complex', 'real', 'int',
+ 'complex_vector', 'real_vector', 'int_vector',
+ 'hex', 'string', 'bool',
+ 'file_open', 'file_save',
+ 'id', 'stream_id',
+ 'grid_pos', 'notebook', 'gui_hint',
+ 'import',
+ )
+
+ def __repr__(self):
+ """
+ Get the repr (nice string format) for this param.
+ @return the string representation
+ """
+ ##################################################
+ # truncate helper method
+ ##################################################
+ def _truncate(string, style=0):
+ max_len = max(27 - len(self.get_name()), 3)
+ if len(string) > max_len:
+ if style < 0: #front truncate
+ string = '...' + string[3-max_len:]
+ elif style == 0: #center truncate
+ string = string[:max_len/2 -3] + '...' + string[-max_len/2:]
+ elif style > 0: #rear truncate
+ string = string[:max_len-3] + '...'
+ return string
+ ##################################################
+ # simple conditions
+ ##################################################
+ if not self.is_valid(): return _truncate(self.get_value())
+ if self.get_value() in self.get_option_keys(): return self.get_option(self.get_value()).get_name()
+ ##################################################
+ # display logic for numbers
+ ##################################################
+ def num_to_str(num):
+ if isinstance(num, COMPLEX_TYPES):
+ num = complex(num) #cast to python complex
+ if num == 0: return '0' #value is zero
+ elif num.imag == 0: return '%s'%eng_notation.num_to_str(num.real) #value is real
+ elif num.real == 0: return '%sj'%eng_notation.num_to_str(num.imag) #value is imaginary
+ elif num.imag < 0: return '%s-%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(abs(num.imag)))
+ else: return '%s+%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(num.imag))
+ else: return str(num)
+ ##################################################
+ # split up formatting by type
+ ##################################################
+ truncate = 0 #default center truncate
+ e = self.get_evaluated()
+ t = self.get_type()
+ if isinstance(e, bool): return str(e)
+ elif isinstance(e, COMPLEX_TYPES): dt_str = num_to_str(e)
+ elif isinstance(e, VECTOR_TYPES): #vector types
+ if len(e) > 8:
+ dt_str = self.get_value() #large vectors use code
+ truncate = 1
+ else: dt_str = ', '.join(map(num_to_str, e)) #small vectors use eval
+ elif t in ('file_open', 'file_save'):
+ dt_str = self.get_value()
+ truncate = -1
+ else: dt_str = str(e) #other types
+ ##################################################
+ # done
+ ##################################################
+ return _truncate(dt_str, truncate)
+
+ def get_input(self, *args, **kwargs):
+ if self.get_type() in ('file_open', 'file_save'): return FileParam(self, *args, **kwargs)
+ return _GUIParam.get_input(self, *args, **kwargs)
+
+ def get_color(self):
+ """
+ Get the color that represents this param's type.
+ @return a hex color code.
+ """
+ try:
+ return {
+ #number types
+ 'complex': Constants.COMPLEX_COLOR_SPEC,
+ 'real': Constants.FLOAT_COLOR_SPEC,
+ 'int': Constants.INT_COLOR_SPEC,
+ #vector types
+ 'complex_vector': Constants.COMPLEX_VECTOR_COLOR_SPEC,
+ 'real_vector': Constants.FLOAT_VECTOR_COLOR_SPEC,
+ 'int_vector': Constants.INT_VECTOR_COLOR_SPEC,
+ #special
+ 'bool': Constants.INT_COLOR_SPEC,
+ 'hex': Constants.INT_COLOR_SPEC,
+ 'string': Constants.BYTE_VECTOR_COLOR_SPEC,
+ 'id': Constants.ID_COLOR_SPEC,
+ 'stream_id': Constants.ID_COLOR_SPEC,
+ 'grid_pos': Constants.INT_VECTOR_COLOR_SPEC,
+ 'notebook': Constants.INT_VECTOR_COLOR_SPEC,
+ 'raw': Constants.WILDCARD_COLOR_SPEC,
+ }[self.get_type()]
+ except: return _Param.get_color(self)
+
+ def get_hide(self):
+ """
+ Get the hide value from the base class.
+ Hide the ID parameter for most blocks. Exceptions below.
+ If the parameter controls a port type, vlen, or nports, return part.
+ If the parameter is an empty grid position, return part.
+ These parameters are redundant to display in the flow graph view.
+ @return hide the hide property string
+ """
+ hide = _Param.get_hide(self)
+ if hide: return hide
+ #hide ID in non variable blocks
+ if self.get_key() == 'id' and not _show_id_matcher.match(self.get_parent().get_key()): return 'part'
+ #hide port controllers for type and nports
+ if self.get_key() in ' '.join(map(
+ lambda p: ' '.join([p._type, p._nports]), self.get_parent().get_ports())
+ ): return 'part'
+ #hide port controllers for vlen, when == 1
+ if self.get_key() in ' '.join(map(
+ lambda p: p._vlen, self.get_parent().get_ports())
+ ):
+ try:
+ if int(self.get_evaluated()) == 1: return 'part'
+ except: pass
+ #hide empty grid positions
+ if self.get_key() in ('grid_pos', 'notebook') and not self.get_value(): return 'part'
+ return hide
+
+ def validate(self):
+ """
+ Validate the param.
+ A test evaluation is performed
+ """
+ _Param.validate(self) #checks type
+ self._evaluated = None
+ try: self._evaluated = self.evaluate()
+ except Exception, e: self.add_error_message(str(e))
+
+ def get_evaluated(self): return self._evaluated
+
+ def evaluate(self):
+ """
+ Evaluate the value.
+ @return evaluated type
+ """
+ self._init = True
+ self._lisitify_flag = False
+ self._stringify_flag = False
+ self._hostage_cells = list()
+ def eval_string(v):
+ try:
+ e = self.get_parent().get_parent().evaluate(v)
+ if isinstance(e, str): return e
+ raise Exception #want to stringify
+ except:
+ self._stringify_flag = True
+ return v
+ t = self.get_type()
+ v = self.get_value()
+ #########################
+ # Enum Type
+ #########################
+ if self.is_enum(): return v
+ #########################
+ # Numeric Types
+ #########################
+ elif t in ('raw', 'complex', 'real', 'int', 'hex', 'bool'):
+ #raise exception if python cannot evaluate this value
+ try: e = self.get_parent().get_parent().evaluate(v)
+ except Exception, e: raise Exception, 'Value "%s" cannot be evaluated:\n%s'%(v, e)
+ #raise an exception if the data is invalid
+ if t == 'raw': return e
+ elif t == 'complex':
+ if not isinstance(e, COMPLEX_TYPES):
+ raise Exception, 'Expression "%s" is invalid for type complex.'%str(e)
+ return e
+ elif t == 'real':
+ if not isinstance(e, REAL_TYPES):
+ raise Exception, 'Expression "%s" is invalid for type real.'%str(e)
+ return e
+ elif t == 'int':
+ if not isinstance(e, INT_TYPES):
+ raise Exception, 'Expression "%s" is invalid for type integer.'%str(e)
+ return e
+ elif t == 'hex': return hex(e)
+ elif t == 'bool':
+ if not isinstance(e, bool):
+ raise Exception, 'Expression "%s" is invalid for type bool.'%str(e)
+ return e
+ else: raise TypeError, 'Type "%s" not handled'%t
+ #########################
+ # Numeric Vector Types
+ #########################
+ elif t in ('complex_vector', 'real_vector', 'int_vector'):
+ if not v: v = '()' #turn a blank string into an empty list, so it will eval
+ #raise exception if python cannot evaluate this value
+ try: e = self.get_parent().get_parent().evaluate(v)
+ except Exception, e: raise Exception, 'Value "%s" cannot be evaluated:\n%s'%(v, e)
+ #raise an exception if the data is invalid
+ if t == 'complex_vector':
+ if not isinstance(e, VECTOR_TYPES):
+ self._lisitify_flag = True
+ e = [e]
+ if not all([isinstance(ei, COMPLEX_TYPES) for ei in e]):
+ raise Exception, 'Expression "%s" is invalid for type complex vector.'%str(e)
+ return e
+ elif t == 'real_vector':
+ if not isinstance(e, VECTOR_TYPES):
+ self._lisitify_flag = True
+ e = [e]
+ if not all([isinstance(ei, REAL_TYPES) for ei in e]):
+ raise Exception, 'Expression "%s" is invalid for type real vector.'%str(e)
+ return e
+ elif t == 'int_vector':
+ if not isinstance(e, VECTOR_TYPES):
+ self._lisitify_flag = True
+ e = [e]
+ if not all([isinstance(ei, INT_TYPES) for ei in e]):
+ raise Exception, 'Expression "%s" is invalid for type integer vector.'%str(e)
+ return e
+ #########################
+ # String Types
+ #########################
+ elif t in ('string', 'file_open', 'file_save'):
+ #do not check if file/directory exists, that is a runtime issue
+ e = eval_string(v)
+ return str(e)
+ #########################
+ # Unique ID Type
+ #########################
+ elif t == 'id':
+ #can python use this as a variable?
+ if not _check_id_matcher.match(v):
+ raise Exception, 'ID "%s" must begin with a letter and may contain letters, numbers, and underscores.'%v
+ ids = [param.get_value() for param in self.get_all_params(t)]
+ if ids.count(v) > 1: #id should only appear once, or zero times if block is disabled
+ raise Exception, 'ID "%s" is not unique.'%v
+ if v in ID_BLACKLIST:
+ raise Exception, 'ID "%s" is blacklisted.'%v
+ return v
+ #########################
+ # Stream ID Type
+ #########################
+ elif t == 'stream_id':
+ #get a list of all stream ids used in the virtual sinks
+ ids = [param.get_value() for param in filter(
+ lambda p: p.get_parent().is_virtual_sink(),
+ self.get_all_params(t),
+ )]
+ #check that the virtual sink's stream id is unique
+ if self.get_parent().is_virtual_sink():
+ if ids.count(v) > 1: #id should only appear once, or zero times if block is disabled
+ raise Exception, 'Stream ID "%s" is not unique.'%v
+ #check that the virtual source's steam id is found
+ if self.get_parent().is_virtual_source():
+ if v not in ids:
+ raise Exception, 'Stream ID "%s" is not found.'%v
+ return v
+ #########################
+ # GUI Position/Hint
+ #########################
+ elif t == 'gui_hint':
+ if ':' in v: tab, pos = v.split(':')
+ elif '@' in v: tab, pos = v, ''
+ else: tab, pos = '', v
+
+ if '@' in tab: tab, index = tab.split('@')
+ else: index = '?'
+
+ widget_str = ({
+ (True, True): 'self.%(tab)s_grid_layout_%(index)s.addWidget(%(widget)s, %(pos)s)',
+ (True, False): 'self.%(tab)s_layout_%(index)s.addWidget(%(widget)s)',
+ (False, True): 'self.top_grid_layout.addWidget(%(widget)s, %(pos)s)',
+ (False, False): 'self.top_layout.addWidget(%(widget)s)',
+ }[bool(tab), bool(pos)])%{'tab': tab, 'index': index, 'widget': '%s', 'pos': pos}
+
+ def gui_hint(ws, w):
+ if 'layout' in w: ws = ws.replace('addWidget', 'addLayout')
+ return ws%w
+
+ return lambda w: gui_hint(widget_str, w)
+ #########################
+ # Grid Position Type
+ #########################
+ elif t == 'grid_pos':
+ if not v: return '' #allow for empty grid pos
+ e = self.get_parent().get_parent().evaluate(v)
+ if not isinstance(e, (list, tuple)) or len(e) != 4 or not all([isinstance(ei, int) for ei in e]):
+ raise Exception, 'A grid position must be a list of 4 integers.'
+ row, col, row_span, col_span = e
+ #check row, col
+ if row < 0 or col < 0:
+ raise Exception, 'Row and column must be non-negative.'
+ #check row span, col span
+ if row_span <= 0 or col_span <= 0:
+ raise Exception, 'Row and column span must be greater than zero.'
+ #get hostage cell parent
+ try: my_parent = self.get_parent().get_param('notebook').evaluate()
+ except: my_parent = ''
+ #calculate hostage cells
+ for r in range(row_span):
+ for c in range(col_span):
+ self._hostage_cells.append((my_parent, (row+r, col+c)))
+ #avoid collisions
+ params = filter(lambda p: p is not self, self.get_all_params('grid_pos'))
+ for param in params:
+ for parent, cell in param._hostage_cells:
+ if (parent, cell) in self._hostage_cells:
+ raise Exception, 'Another graphical element is using parent "%s", cell "%s".'%(str(parent), str(cell))
+ return e
+ #########################
+ # Notebook Page Type
+ #########################
+ elif t == 'notebook':
+ if not v: return '' #allow for empty notebook
+ #get a list of all notebooks
+ notebook_blocks = filter(lambda b: b.get_key() == 'notebook', self.get_parent().get_parent().get_enabled_blocks())
+ #check for notebook param syntax
+ try: notebook_id, page_index = map(str.strip, v.split(','))
+ except: raise Exception, 'Bad notebook page format.'
+ #check that the notebook id is valid
+ try: notebook_block = filter(lambda b: b.get_id() == notebook_id, notebook_blocks)[0]
+ except: raise Exception, 'Notebook id "%s" is not an existing notebook id.'%notebook_id
+ #check that page index exists
+ if int(page_index) not in range(len(notebook_block.get_param('labels').evaluate())):
+ raise Exception, 'Page index "%s" is not a valid index number.'%page_index
+ return notebook_id, page_index
+ #########################
+ # Import Type
+ #########################
+ elif t == 'import':
+ n = dict() #new namespace
+ try: exec v in n
+ except ImportError: raise Exception, 'Import "%s" failed.'%v
+ except Exception: raise Exception, 'Bad import syntax: "%s".'%v
+ return filter(lambda k: str(k) != '__builtins__', n.keys())
+ #########################
+ else: raise TypeError, 'Type "%s" not handled'%t
+
+ def to_code(self):
+ """
+ Convert the value to code.
+ For string and list types, check the init flag, call evaluate().
+ This ensures that evaluate() was called to set the xxxify_flags.
+ @return a string representing the code
+ """
+ v = self.get_value()
+ t = self.get_type()
+ if t in ('string', 'file_open', 'file_save'): #string types
+ if not self._init: self.evaluate()
+ if self._stringify_flag: return '"%s"'%v.replace('"', '\"')
+ else: return v
+ elif t in ('complex_vector', 'real_vector', 'int_vector'): #vector types
+ if not self._init: self.evaluate()
+ if self._lisitify_flag: return '(%s, )'%v
+ else: return '(%s)'%v
+ else: return v
+
+ def get_all_params(self, type):
+ """
+ Get all the params from the flowgraph that have the given type.
+ @param type the specified type
+ @return a list of params
+ """
+ return sum([filter(lambda p: p.get_type() == type, block.get_params()) for block in self.get_parent().get_parent().get_enabled_blocks()], [])
diff --git a/grc/python/Platform.py b/grc/python/Platform.py
new file mode 100644
index 000000000..e036361ff
--- /dev/null
+++ b/grc/python/Platform.py
@@ -0,0 +1,70 @@
+__doc__ = """
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import os
+from gnuradio import gr
+from .. base.Platform import Platform as _Platform
+from .. gui.Platform import Platform as _GUIPlatform
+from FlowGraph import FlowGraph as _FlowGraph
+from Connection import Connection as _Connection
+from Block import Block as _Block
+from Port import Port as _Port
+from Param import Param as _Param
+from Generator import Generator
+from Constants import \
+ HIER_BLOCKS_LIB_DIR, BLOCK_DTD, \
+ DEFAULT_FLOW_GRAPH, BLOCKS_DIRS
+import Constants
+
+COLORS = [(name, color) for name, key, sizeof, color in Constants.CORE_TYPES]
+
+class Platform(_Platform, _GUIPlatform):
+
+ def __init__(self):
+ """
+ Make a platform for gnuradio.
+ """
+ #ensure hier dir
+ if not os.path.exists(HIER_BLOCKS_LIB_DIR): os.mkdir(HIER_BLOCKS_LIB_DIR)
+ #convert block paths to absolute paths
+ block_paths = set(map(os.path.abspath, BLOCKS_DIRS))
+ #init
+ _Platform.__init__(
+ self,
+ name='GNU Radio Companion',
+ version=gr.version(),
+ key='grc',
+ license=__doc__.strip(),
+ website='http://gnuradio.org/redmine/wiki/gnuradio/GNURadioCompanion',
+ block_paths=block_paths,
+ block_dtd=BLOCK_DTD,
+ default_flow_graph=DEFAULT_FLOW_GRAPH,
+ generator=Generator,
+ colors=COLORS,
+ )
+ _GUIPlatform.__init__(self)
+
+ ##############################################
+ # Constructors
+ ##############################################
+ FlowGraph = _FlowGraph
+ Connection = _Connection
+ Block = _Block
+ Port = _Port
+ Param = _Param
diff --git a/grc/python/Port.py b/grc/python/Port.py
new file mode 100644
index 000000000..8cc9e9ad0
--- /dev/null
+++ b/grc/python/Port.py
@@ -0,0 +1,217 @@
+"""
+Copyright 2008-2012 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from .. base.Port import Port as _Port
+from .. gui.Port import Port as _GUIPort
+import Constants
+
+def _get_source_from_virtual_sink_port(vsp):
+ """
+ Resolve the source port that is connected to the given virtual sink port.
+ Use the get source from virtual source to recursively resolve subsequent ports.
+ """
+ try: return _get_source_from_virtual_source_port(
+ vsp.get_enabled_connections()[0].get_source())
+ except: raise Exception, 'Could not resolve source for virtual sink port %s'%vsp
+
+def _get_source_from_virtual_source_port(vsp, traversed=[]):
+ """
+ Recursively resolve source ports over the virtual connections.
+ Keep track of traversed sources to avoid recursive loops.
+ """
+ if not vsp.get_parent().is_virtual_source(): return vsp
+ if vsp in traversed: raise Exception, 'Loop found when resolving virtual source %s'%vsp
+ try: return _get_source_from_virtual_source_port(
+ _get_source_from_virtual_sink_port(
+ filter(#get all virtual sinks with a matching stream id
+ lambda vs: vs.get_param('stream_id').get_value() == vsp.get_parent().get_param('stream_id').get_value(),
+ filter(#get all enabled blocks that are also virtual sinks
+ lambda b: b.is_virtual_sink(),
+ vsp.get_parent().get_parent().get_enabled_blocks(),
+ ),
+ )[0].get_sinks()[0]
+ ), traversed + [vsp],
+ )
+ except: raise Exception, 'Could not resolve source for virtual source port %s'%vsp
+
+def _get_sink_from_virtual_source_port(vsp):
+ """
+ Resolve the sink port that is connected to the given virtual source port.
+ Use the get sink from virtual sink to recursively resolve subsequent ports.
+ """
+ try: return _get_sink_from_virtual_sink_port(
+ vsp.get_enabled_connections()[0].get_sink()) # Could have many connections, but use first
+ except: raise Exception, 'Could not resolve source for virtual source port %s'%vsp
+
+def _get_sink_from_virtual_sink_port(vsp, traversed=[]):
+ """
+ Recursively resolve sink ports over the virtual connections.
+ Keep track of traversed sinks to avoid recursive loops.
+ """
+ if not vsp.get_parent().is_virtual_sink(): return vsp
+ if vsp in traversed: raise Exception, 'Loop found when resolving virtual sink %s'%vsp
+ try: return _get_sink_from_virtual_sink_port(
+ _get_sink_from_virtual_source_port(
+ filter(#get all virtual source with a matching stream id
+ lambda vs: vs.get_param('stream_id').get_value() == vsp.get_parent().get_param('stream_id').get_value(),
+ filter(#get all enabled blocks that are also virtual sinks
+ lambda b: b.is_virtual_source(),
+ vsp.get_parent().get_parent().get_enabled_blocks(),
+ ),
+ )[0].get_sources()[0]
+ ), traversed + [vsp],
+ )
+ except: raise Exception, 'Could not resolve source for virtual sink port %s'%vsp
+
+class Port(_Port, _GUIPort):
+
+ def __init__(self, block, n, dir):
+ """
+ Make a new port from nested data.
+ @param block the parent element
+ @param n the nested odict
+ @param dir the direction
+ """
+ self._n = n
+ if n['type'] == 'msg': n['key'] = 'msg'
+ if n['type'] == 'message': n['key'] = n['name']
+ if dir == 'source' and not n.find('key'):
+ n['key'] = str(block._source_count)
+ block._source_count += 1
+ if dir == 'sink' and not n.find('key'):
+ n['key'] = str(block._sink_count)
+ block._sink_count += 1
+ #build the port
+ _Port.__init__(
+ self,
+ block=block,
+ n=n,
+ dir=dir,
+ )
+ _GUIPort.__init__(self)
+ self._nports = n.find('nports') or ''
+ self._vlen = n.find('vlen') or ''
+ self._optional = bool(n.find('optional'))
+
+ def get_types(self): return Constants.TYPE_TO_SIZEOF.keys()
+
+ def is_type_empty(self): return not self._n['type']
+
+ def validate(self):
+ _Port.validate(self)
+ if not self.get_enabled_connections() and not self.get_optional():
+ self.add_error_message('Port is not connected.')
+ is_msg = (not self.get_type()) or (self.get_type() == "message")
+ if not self.is_source() and (not is_msg) and len(self.get_enabled_connections()) > 1:
+ self.add_error_message('Port has too many connections.')
+ #message port logic
+ if self.get_type() == 'msg':
+ if self.get_nports():
+ self.add_error_message('A port of type "msg" cannot have "nports" set.')
+ if self.get_vlen() != 1:
+ self.add_error_message('A port of type "msg" must have a "vlen" of 1.')
+
+ def rewrite(self):
+ """
+ Handle the port cloning for virtual blocks.
+ """
+ _Port.rewrite(self)
+ if self.is_type_empty():
+ try: #clone type and vlen
+ source = self.resolve_empty_type()
+ self._type = str(source.get_type())
+ self._vlen = str(source.get_vlen())
+ except: #reset type and vlen
+ self._type = ''
+ self._vlen = ''
+
+ def resolve_virtual_source(self):
+ if self.get_parent().is_virtual_sink(): return _get_source_from_virtual_sink_port(self)
+ if self.get_parent().is_virtual_source(): return _get_source_from_virtual_source_port(self)
+
+ def resolve_empty_type(self):
+ if self.is_sink():
+ try:
+ src = _get_source_from_virtual_sink_port(self)
+ if not src.is_type_empty(): return src
+ except: pass
+ sink = _get_sink_from_virtual_sink_port(self)
+ if not sink.is_type_empty(): return sink
+ if self.is_source():
+ try:
+ src = _get_source_from_virtual_source_port(self)
+ if not src.is_type_empty(): return src
+ except: pass
+ sink = _get_sink_from_virtual_source_port(self)
+ if not sink.is_type_empty(): return sink
+
+ def get_vlen(self):
+ """
+ Get the vector length.
+ If the evaluation of vlen cannot be cast to an integer, return 1.
+ @return the vector length or 1
+ """
+ vlen = self.get_parent().resolve_dependencies(self._vlen)
+ try: return int(self.get_parent().get_parent().evaluate(vlen))
+ except: return 1
+
+ def get_nports(self):
+ """
+ Get the number of ports.
+ If already blank, return a blank
+ If the evaluation of nports cannot be cast to an integer, return 1.
+ @return the number of ports or 1
+ """
+ nports = self.get_parent().resolve_dependencies(self._nports)
+ #return blank if nports is blank
+ if not nports: return ''
+ try:
+ nports = int(self.get_parent().get_parent().evaluate(nports))
+ if 0 < nports: return nports
+ except: return 1
+
+ def get_optional(self): return bool(self._optional)
+
+ def get_color(self):
+ """
+ Get the color that represents this port's type.
+ Codes differ for ports where the vec length is 1 or greater than 1.
+ @return a hex color code.
+ """
+ try:
+ color = Constants.TYPE_TO_COLOR[self.get_type()]
+ vlen = self.get_vlen()
+ if vlen == 1: return color
+ color_val = int(color[1:], 16)
+ r = (color_val >> 16) & 0xff
+ g = (color_val >> 8) & 0xff
+ b = (color_val >> 0) & 0xff
+ dark = (0, 0, 30, 50, 70)[min(4, vlen)]
+ r = max(r-dark, 0)
+ g = max(g-dark, 0)
+ b = max(b-dark, 0)
+ return '#%.2x%.2x%.2x'%(r, g, b)
+ except: return _Port.get_color(self)
+
+ def copy(self, new_key=None):
+ n = self._n.copy()
+ #remove nports from the key so the copy cannot be a duplicator
+ if n.has_key('nports'): n.pop('nports')
+ if new_key: n['key'] = new_key
+ return self.__class__(self.get_parent(), n, self._dir)
diff --git a/grc/python/__init__.py b/grc/python/__init__.py
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/grc/python/__init__.py
@@ -0,0 +1 @@
+
diff --git a/grc/python/block.dtd b/grc/python/block.dtd
new file mode 100644
index 000000000..292ea06cb
--- /dev/null
+++ b/grc/python/block.dtd
@@ -0,0 +1,57 @@
+<!--
+Copyright 2008 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+-->
+<!--
+ gnuradio_python.blocks.dtd
+ Josh Blum
+ The document type definition for blocks.
+ -->
+<!--
+ Top level element.
+ A block contains a name, ...parameters list, and list of IO ports.
+ -->
+<!ELEMENT block (name, key, category?, throttle?, import*, var_make?, make, callback*, param*, check*, sink*, source*, doc?, grc_source?)>
+<!--
+ Sub level elements.
+ -->
+<!ELEMENT param (name, key, value?, type, hide?, option*)>
+<!ELEMENT option (name, key, opt*)>
+<!ELEMENT sink (name, type, vlen?, nports?, optional?)>
+<!ELEMENT source (name, type, vlen?, nports?, optional?)>
+<!--
+ Bottom level elements.
+ Character data only.
+ -->
+<!ELEMENT category (#PCDATA)>
+<!ELEMENT import (#PCDATA)>
+<!ELEMENT doc (#PCDATA)>
+<!ELEMENT grc_source (#PCDATA)>
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT key (#PCDATA)>
+<!ELEMENT check (#PCDATA)>
+<!ELEMENT opt (#PCDATA)>
+<!ELEMENT type (#PCDATA)>
+<!ELEMENT hide (#PCDATA)>
+<!ELEMENT vlen (#PCDATA)>
+<!ELEMENT nports (#PCDATA)>
+<!ELEMENT var_make (#PCDATA)>
+<!ELEMENT make (#PCDATA)>
+<!ELEMENT value (#PCDATA)>
+<!ELEMENT callback (#PCDATA)>
+<!ELEMENT optional (#PCDATA)>
+<!ELEMENT throttle (#PCDATA)>
diff --git a/grc/python/convert_hier.py b/grc/python/convert_hier.py
new file mode 100644
index 000000000..508ec63b2
--- /dev/null
+++ b/grc/python/convert_hier.py
@@ -0,0 +1,98 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+"""
+
+from Constants import BLOCK_DTD
+from .. base import ParseXML
+from .. base import odict
+
+def convert_hier(flow_graph, python_file):
+ #extract info from the flow graph
+ input_sigs = flow_graph.get_io_signaturev('in')
+ output_sigs = flow_graph.get_io_signaturev('out')
+ input_msgp = flow_graph.get_msg_pad_sources();
+ output_msgp = flow_graph.get_msg_pad_sinks();
+ parameters = flow_graph.get_parameters()
+ block_key = flow_graph.get_option('id')
+ block_name = flow_graph.get_option('title') or flow_graph.get_option('id').replace('_', ' ').title()
+ block_category = flow_graph.get_option('category')
+ block_desc = flow_graph.get_option('description')
+ block_author = flow_graph.get_option('author')
+ #build the nested data
+ block_n = odict()
+ block_n['name'] = block_name
+ block_n['key'] = block_key
+ block_n['category'] = block_category
+ block_n['import'] = 'execfile("%s")'%python_file
+ #make data
+ if parameters: block_n['make'] = '%s(\n\t%s,\n)'%(
+ block_key,
+ ',\n\t'.join(['%s=$%s'%(param.get_id(), param.get_id()) for param in parameters]),
+ )
+ else: block_n['make'] = '%s()'%block_key
+ #callback data
+ block_n['callback'] = ['set_%s($%s)'%(param.get_id(), param.get_id()) for param in parameters]
+ #param data
+ params_n = list()
+ for param in parameters:
+ param_n = odict()
+ param_n['name'] = param.get_param('label').get_value() or param.get_id()
+ param_n['key'] = param.get_id()
+ param_n['value'] = param.get_param('value').get_value()
+ param_n['type'] = 'raw'
+ params_n.append(param_n)
+ block_n['param'] = params_n
+ #sink data stream ports
+ block_n['sink'] = list()
+ for input_sig in input_sigs:
+ sink_n = odict()
+ sink_n['name'] = input_sig['label']
+ sink_n['type'] = input_sig['type']
+ sink_n['vlen'] = input_sig['vlen']
+ if input_sig['optional']: sink_n['optional'] = '1'
+ block_n['sink'].append(sink_n)
+ #sink data msg ports
+ for input_sig in input_msgp:
+ sink_n = odict()
+ sink_n['name'] = input_sig.get_param("label").get_value();
+ sink_n['type'] = "message"
+ sink_n['optional'] = input_sig.get_param("optional").get_value();
+ block_n['sink'].append(sink_n)
+ #source data stream ports
+ block_n['source'] = list()
+ for output_sig in output_sigs:
+ source_n = odict()
+ source_n['name'] = output_sig['label']
+ source_n['type'] = output_sig['type']
+ source_n['vlen'] = output_sig['vlen']
+ if output_sig['optional']: source_n['optional'] = '1'
+ block_n['source'].append(source_n)
+ #source data msg ports
+ for output_sig in output_msgp:
+ source_n = odict()
+ source_n['name'] = output_sig.get_param("label").get_value();
+ source_n['type'] = "message"
+ source_n['optional'] = output_sig.get_param("optional").get_value();
+ block_n['source'].append(source_n)
+ #doc data
+ block_n['doc'] = "%s\n%s\n%s"%(block_author, block_desc, python_file)
+ block_n['grc_source'] = "%s"%(flow_graph.grc_file_path)
+ #write the block_n to file
+ xml_file = python_file + '.xml'
+ ParseXML.to_file({'block': block_n}, xml_file)
+ ParseXML.validate_dtd(xml_file, BLOCK_DTD)
diff --git a/grc/python/default_flow_graph.grc b/grc/python/default_flow_graph.grc
new file mode 100644
index 000000000..dea26f3a5
--- /dev/null
+++ b/grc/python/default_flow_graph.grc
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Default Flow Graph:
+## include an options block and a variable for sample rate
+###################################################
+ -->
+<flow_graph>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>top_block</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>samp_rate</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>32000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 170)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+</flow_graph>
diff --git a/grc/python/expr_utils.py b/grc/python/expr_utils.py
new file mode 100644
index 000000000..a2e56eedf
--- /dev/null
+++ b/grc/python/expr_utils.py
@@ -0,0 +1,153 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import string
+VAR_CHARS = string.letters + string.digits + '_'
+
+class graph(object):
+ """
+ Simple graph structure held in a dictionary.
+ """
+
+ def __init__(self): self._graph = dict()
+
+ def __str__(self): return str(self._graph)
+
+ def add_node(self, node_key):
+ if self._graph.has_key(node_key): return
+ self._graph[node_key] = set()
+
+ def remove_node(self, node_key):
+ if not self._graph.has_key(node_key): return
+ for edges in self._graph.values():
+ if node_key in edges: edges.remove(node_key)
+ self._graph.pop(node_key)
+
+ def add_edge(self, src_node_key, dest_node_key):
+ self._graph[src_node_key].add(dest_node_key)
+
+ def remove_edge(self, src_node_key, dest_node_key):
+ self._graph[src_node_key].remove(dest_node_key)
+
+ def get_nodes(self): return self._graph.keys()
+
+ def get_edges(self, node_key): return self._graph[node_key]
+
+def expr_split(expr):
+ """
+ Split up an expression by non alphanumeric characters, including underscore.
+ Leave strings in-tact.
+ #TODO ignore escaped quotes, use raw strings.
+ @param expr an expression string
+ @return a list of string tokens that form expr
+ """
+ toks = list()
+ tok = ''
+ quote = ''
+ for char in expr:
+ if quote or char in VAR_CHARS:
+ if char == quote: quote = ''
+ tok += char
+ elif char in ("'", '"'):
+ toks.append(tok)
+ tok = char
+ quote = char
+ else:
+ toks.append(tok)
+ toks.append(char)
+ tok = ''
+ toks.append(tok)
+ return filter(lambda t: t, toks)
+
+def expr_replace(expr, replace_dict):
+ """
+ Search for vars in the expression and add the prepend.
+ @param expr an expression string
+ @param replace_dict a dict of find:replace
+ @return a new expression with the prepend
+ """
+ expr_splits = expr_split(expr)
+ for i, es in enumerate(expr_splits):
+ if es in replace_dict.keys():
+ expr_splits[i] = replace_dict[es]
+ return ''.join(expr_splits)
+
+def get_variable_dependencies(expr, vars):
+ """
+ Return a set of variables used in this expression.
+ @param expr an expression string
+ @param vars a list of variable names
+ @return a subset of vars used in the expression
+ """
+ expr_toks = expr_split(expr)
+ return set(filter(lambda v: v in expr_toks, vars))
+
+def get_graph(exprs):
+ """
+ Get a graph representing the variable dependencies
+ @param exprs a mapping of variable name to expression
+ @return a graph of variable deps
+ """
+ vars = exprs.keys()
+ #get dependencies for each expression, load into graph
+ var_graph = graph()
+ for var in vars: var_graph.add_node(var)
+ for var, expr in exprs.iteritems():
+ for dep in get_variable_dependencies(expr, vars):
+ if dep != var: var_graph.add_edge(dep, var)
+ return var_graph
+
+def sort_variables(exprs):
+ """
+ Get a list of variables in order of dependencies.
+ @param exprs a mapping of variable name to expression
+ @return a list of variable names
+ @throws Exception circular dependencies
+ """
+ var_graph = get_graph(exprs)
+ sorted_vars = list()
+ #determine dependency order
+ while var_graph.get_nodes():
+ #get a list of nodes with no edges
+ indep_vars = filter(lambda var: not var_graph.get_edges(var), var_graph.get_nodes())
+ if not indep_vars: raise Exception('circular dependency caught in sort_variables')
+ #add the indep vars to the end of the list
+ sorted_vars.extend(sorted(indep_vars))
+ #remove each edge-less node from the graph
+ for var in indep_vars: var_graph.remove_node(var)
+ return reversed(sorted_vars)
+
+def sort_objects(objects, get_id, get_expr):
+ """
+ Sort a list of objects according to their expressions.
+ @param objects the list of objects to sort
+ @param get_id the function to extract an id from the object
+ @param get_expr the function to extract an expression from the object
+ @return a list of sorted objects
+ """
+ id2obj = dict([(get_id(obj), obj) for obj in objects])
+ #map obj id to expression code
+ id2expr = dict([(get_id(obj), get_expr(obj)) for obj in objects])
+ #sort according to dependency
+ sorted_ids = sort_variables(id2expr)
+ #return list of sorted objects
+ return [id2obj[id] for id in sorted_ids]
+
+if __name__ == '__main__':
+ for i in sort_variables({'x':'1', 'y':'x+1', 'a':'x+y', 'b':'y+1', 'c':'a+b+x+y'}): print i
diff --git a/grc/python/extract_docs.py b/grc/python/extract_docs.py
new file mode 100644
index 000000000..33c404362
--- /dev/null
+++ b/grc/python/extract_docs.py
@@ -0,0 +1,66 @@
+"""
+Copyright 2008-2011 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import re
+
+def _extract(key):
+ """
+ Extract the documentation from the python __doc__ strings.
+ If multiple modules match, combine the docs.
+ @param key the block key
+ @return a string with documentation
+ """
+ #extract matches
+ try:
+ module_name, constructor_name = key.split('_', 1)
+ module = __import__('gnuradio.'+module_name)
+ module = getattr(module, module_name)
+ except ImportError:
+ try:
+ module_name, constructor_name = key.split('_', 1)
+ module = __import__(module_name)
+ except: return ''
+ except:
+ return ''
+ pattern = constructor_name.replace('_', '_*').replace('x', '\w')
+ pattern_matcher = re.compile('^%s\w*$'%pattern)
+ matches = filter(lambda x: pattern_matcher.match(x), dir(module))
+ #combine all matches
+ doc_strs = list()
+ for match in matches:
+ try:
+ title = ' --- ' + match + ' --- '
+ doc_strs.append('\n\n'.join([title, getattr(module, match).__doc__]).strip())
+ except: pass
+ return '\n\n'.join(doc_strs)
+
+_docs_cache = dict()
+def extract(key):
+ """
+ Call the private extract and cache the result.
+ @param key the block key
+ @return a string with documentation
+ """
+ if not _docs_cache.has_key(key):
+ _docs_cache[key] = _extract(key)
+ return _docs_cache[key]
+
+if __name__ == '__main__':
+ import sys
+ print extract(sys.argv[1])
diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl
new file mode 100644
index 000000000..163e7f76a
--- /dev/null
+++ b/grc/python/flow_graph.tmpl
@@ -0,0 +1,311 @@
+#!/usr/bin/env python
+########################################################
+##Cheetah template - gnuradio_python
+##
+##@param imports the import statements
+##@param flow_graph the flow_graph
+##@param variables the variable blocks
+##@param parameters the paramater blocks
+##@param blocks the signal blocks
+##@param connections the connections
+##@param messages the msg type connections
+##@param generate_options the type of flow graph
+##@param var_id2cbs variable id map to callback strings
+########################################################
+#def indent($code)
+#set $code = '\n\t\t'.join(str($code).splitlines())
+$code#slurp
+#end def
+#import time
+#set $DIVIDER = '#'*50
+$DIVIDER
+# Gnuradio Python Flow Graph
+# Title: $title
+#if $flow_graph.get_option('author')
+# Author: $flow_graph.get_option('author')
+#end if
+#if $flow_graph.get_option('description')
+# Description: $flow_graph.get_option('description')
+#end if
+# Generated: $time.ctime()
+$DIVIDER
+
+########################################################
+##Create Imports
+########################################################
+#for $imp in $imports
+$imp
+#end for
+
+########################################################
+##Create Class
+## Write the class declaration for a top or hier block.
+## The parameter names are the arguments to __init__.
+## Determine the absolute icon path (wx gui only).
+## Setup the IO signature (hier block only).
+########################################################
+#set $class_name = $flow_graph.get_option('id')
+#set $param_str = ', '.join(['self'] + ['%s=%s'%(param.get_id(), param.get_make()) for param in $parameters])
+#if $generate_options == 'wx_gui'
+ #import gtk
+ #set $icon = gtk.IconTheme().lookup_icon('gnuradio-grc', 32, 0)
+class $(class_name)(grc_wxgui.top_block_gui):
+
+ def __init__($param_str):
+ grc_wxgui.top_block_gui.__init__(self, title="$title")
+ #if $icon
+ _icon_path = "$icon.get_filename()"
+ self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY))
+ #end if
+#elif $generate_options == 'qt_gui'
+class $(class_name)(gr.top_block, Qt.QWidget):
+
+ def __init__($param_str):
+ gr.top_block.__init__(self, "$title")
+ Qt.QWidget.__init__(self)
+ self.setWindowTitle("$title")
+ self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
+ self.top_scroll_layout = Qt.QVBoxLayout()
+ self.setLayout(self.top_scroll_layout)
+ self.top_scroll = Qt.QScrollArea()
+ self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
+ self.top_scroll_layout.addWidget(self.top_scroll)
+ self.top_scroll.setWidgetResizable(True)
+ self.top_widget = Qt.QWidget()
+ self.top_scroll.setWidget(self.top_widget)
+ self.top_layout = Qt.QVBoxLayout(self.top_widget)
+ self.top_grid_layout = Qt.QGridLayout()
+ self.top_layout.addLayout(self.top_grid_layout)
+
+#elif $generate_options == 'no_gui'
+class $(class_name)(gr.top_block):
+
+ def __init__($param_str):
+ gr.top_block.__init__(self, "$title")
+#elif $generate_options == 'hb'
+ #set $in_sigs = $flow_graph.get_io_signaturev('in')
+ #set $out_sigs = $flow_graph.get_io_signaturev('out')
+class $(class_name)(gr.hier_block2):
+#def make_io_sig($io_sigs)
+ #set $size_strs = ['%s*%s'%(io_sig['size'], io_sig['vlen']) for io_sig in $io_sigs]
+ #if len($io_sigs) == 0
+gr.io_signature(0, 0, 0)#slurp
+ #elif len($io_sigs) == 1
+gr.io_signature(1, 1, $size_strs[0])#slurp
+ #else
+gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))])#slurp
+ #end if
+#end def
+
+ def __init__($param_str):
+ gr.hier_block2.__init__(
+ self, "$title",
+ $make_io_sig($in_sigs),
+ $make_io_sig($out_sigs),
+ )
+#end if
+########################################################
+##Create Parameters
+## Set the parameter to a property of self.
+########################################################
+#if $parameters
+
+ $DIVIDER
+ # Parameters
+ $DIVIDER
+#end if
+#for $param in $parameters
+ $indent($param.get_var_make())
+#end for
+########################################################
+##Create Variables
+########################################################
+#if $variables
+
+ $DIVIDER
+ # Variables
+ $DIVIDER
+#end if
+#for $var in $variables
+ $indent($var.get_var_make())
+#end for
+########################################################
+##Create Message Queues
+########################################################
+#if $messages
+
+ $DIVIDER
+ # Message Queues
+ $DIVIDER
+#end if
+#for $msg in $messages
+ $(msg.get_source().get_parent().get_id())_msgq_out = $(msg.get_sink().get_parent().get_id())_msgq_in = gr.msg_queue(2)
+#end for
+########################################################
+##Create Blocks
+########################################################
+#if $blocks
+
+ $DIVIDER
+ # Blocks
+ $DIVIDER
+#end if
+#for $blk in filter(lambda b: b.get_make(), $blocks)
+ #if $blk in $variables
+ $indent($blk.get_make())
+ #else
+ self.$blk.get_id() = $indent($blk.get_make())
+ #end if
+#end for
+########################################################
+##Create Connections
+## The port name should be the id of the parent block.
+## However, port names for IO pads should be self.
+########################################################
+#def make_port_sig($port)
+ #if $port.get_parent().get_key() == 'pad_source'
+(self, $flow_graph.get_pad_sources().index($port.get_parent()))#slurp
+ #elif $port.get_parent().get_key() == 'pad_sink'
+(self, $flow_graph.get_pad_sinks().index($port.get_parent()))#slurp
+ #else
+(self.$port.get_parent().get_id(), $port.get_key())#slurp
+ #end if
+#end def
+#if $connections
+
+ $DIVIDER
+ # Connections
+ $DIVIDER
+#end if
+#for $con in $connections
+ #set $source = $con.get_source()
+ #set $sink = $con.get_sink()
+ ##resolve virtual sources to the actual sources
+ #if $source.get_parent().is_virtual_source()
+ #set $source = $source.resolve_virtual_source()
+ #end if
+ ##do not generate connections with virtual sinks
+ #if not $sink.get_parent().is_virtual_sink()
+ self.connect($make_port_sig($source), $make_port_sig($sink))
+ #end if
+#end for
+
+########################################################
+##Create Asynch Message Connections
+########################################################
+#if $messages2
+ $DIVIDER
+ # Asynch Message Connections
+ $DIVIDER
+#end if
+#for $msg in $messages2
+ #set $sr = $msg.get_source()
+ #set $source = "self.%s"%($sr.get_parent().get_id())
+ #set $source_port = $sr.get_name();
+ #if $sr.get_parent().get_key() == "pad_source"
+ #set $source = "self"
+ #set $source_port = $sr.get_parent().get_param("label").get_value();
+ #end if
+ #set $sk = $msg.get_sink()
+ #set $sink = "self.%s"%($sk.get_parent().get_id())
+ #set $sink_port = $sk.get_name();
+ #if $sk.get_parent().get_key() == "pad_sink"
+ #set $sink = "self"
+ #set $sink_port = $sk.get_parent().get_param("label").get_value();
+ #end if
+ self.msg_connect($source, "$source_port", $sink, "$sink_port")
+#end for
+
+########################################################
+##Create Callbacks
+## Write a set method for this variable that calls the callbacks
+########################################################
+#for $var in $parameters + $variables
+ #set $id = $var.get_id()
+ def get_$(id)(self):
+ return self.$id
+
+ def set_$(id)(self, $id):
+ self.$id = $id
+ #for $callback in $var_id2cbs[$id]
+ $indent($callback)
+ #end for
+
+#end for
+########################################################
+##Create Main
+## For top block code, generate a main routine.
+## Instantiate the top block and run as gui or cli.
+########################################################
+#def make_default($type, $param)
+ #if $type == 'eng_float'
+eng_notation.num_to_str($param.get_make())#slurp
+ #else
+$param.get_make()#slurp
+ #end if
+#end def
+#def make_short_id($param)
+ #set $short_id = $param.get_param('short_id').get_evaluated()
+ #if $short_id
+ #set $short_id = '-' + $short_id
+ #end if
+$short_id#slurp
+#end def
+#if $generate_options != 'hb'
+if __name__ == '__main__':
+ parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
+ #set $params_eq_list = list()
+ #for $param in $parameters
+ #set $type = $param.get_param('type').get_value()
+ #if $type
+ #silent $params_eq_list.append('%s=options.%s'%($param.get_id(), $param.get_id()))
+ parser.add_option("$make_short_id($param)", "--$param.get_id().replace('_', '-')", dest="$param.get_id()", type="$type", default=$make_default($type, $param),
+ help="Set $($param.get_param('label').get_evaluated() or $param.get_id()) [default=%default]")
+ #end if
+ #end for
+ (options, args) = parser.parse_args()
+ #if $flow_graph.get_option('realtime_scheduling')
+ if gr.enable_realtime_scheduling() != gr.RT_OK:
+ print "Error: failed to enable realtime scheduling."
+ #end if
+ #if $generate_options == 'wx_gui'
+ tb = $(class_name)($(', '.join($params_eq_list)))
+ #if $flow_graph.get_option('max_nouts')
+ tb.Run($flow_graph.get_option('run'), $flow_graph.get_option('max_nouts'))
+ #else
+ tb.Run($flow_graph.get_option('run'))
+ #end if
+ #elif $generate_options == 'qt_gui'
+ qapp = Qt.QApplication(sys.argv)
+ tb = $(class_name)($(', '.join($params_eq_list)))
+ #if $flow_graph.get_option('run')
+ #if $flow_graph.get_option('max_nouts')
+ tb.start($flow_graph.get_option('max_nouts'))
+ #else
+ tb.start()
+ #end if
+ #end if
+ tb.show()
+ qapp.exec_()
+ tb.stop()
+ #elif $generate_options == 'no_gui'
+ tb = $(class_name)($(', '.join($params_eq_list)))
+ #set $run_options = $flow_graph.get_option('run_options')
+ #if $run_options == 'prompt'
+ #if $flow_graph.get_option('max_nouts')
+ tb.start($flow_graph.get_option('max_nouts'))
+ #else
+ tb.start()
+ #end if
+ raw_input('Press Enter to quit: ')
+ tb.stop()
+ #elif $run_options == 'run'
+ #if $flow_graph.get_option('max_nouts')
+ tb.run($flow_graph.get_option('max_nouts'))
+ #else
+ tb.run()
+ #end if
+ #end if
+ #end if
+#end if
+
diff --git a/grc/scripts/CMakeLists.txt b/grc/scripts/CMakeLists.txt
new file mode 100644
index 000000000..e90589230
--- /dev/null
+++ b/grc/scripts/CMakeLists.txt
@@ -0,0 +1,25 @@
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+GR_PYTHON_INSTALL(
+ PROGRAMS gnuradio-companion
+ DESTINATION ${GR_RUNTIME_DIR}
+ COMPONENT "grc"
+)
diff --git a/grc/scripts/gnuradio-companion b/grc/scripts/gnuradio-companion
new file mode 100755
index 000000000..dabca3028
--- /dev/null
+++ b/grc/scripts/gnuradio-companion
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+"""
+Copyright 2009-2012 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR 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
+"""
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+
+try: from gnuradio import gr
+except ImportError, e:
+ d = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_CLOSE, message_format="""
+Cannot import gnuradio.
+
+Is the python path environment variable set correctly?
+ All OS: PYTHONPATH
+
+Is the library path environment variable set correctly?
+ Linux: LD_LIBRARY_PATH
+ Windows: PATH
+ MacOSX: DYLD_LIBRARY_PATH
+""")
+ d.set_title(str(e))
+ d.run()
+ exit(-1)
+
+from optparse import OptionParser
+import os
+
+if __name__ == "__main__":
+ if ('GR_DONT_LOAD_PREFS' in os.environ.keys() and
+ (not 'GRC_BLOCKS_PATH' in os.environ.keys() or len(os.environ['GRC_BLOCKS_PATH']) == 0)):
+ d = gtk.MessageDialog(
+ type=gtk.MESSAGE_ERROR,
+ buttons=gtk.BUTTONS_CLOSE,
+ message_format="""Can't find block definitions. Use config.conf or GRC_BLOCKS_PATH. """)
+ d.set_title("No block definitions available.")
+ d.run()
+ exit(-1)
+ usage = 'usage: %prog [options] [saved flow graphs]'
+ version = """
+GNU Radio Companion %s
+
+This program is part of GNU Radio
+GRC comes with ABSOLUTELY NO WARRANTY.
+This is free software,
+and you are welcome to redistribute it.
+"""%gr.version()
+ parser = OptionParser(usage=usage, version=version)
+ (options, args) = parser.parse_args()
+ from gnuradio.grc.python.Platform import Platform
+ from gnuradio.grc.gui.ActionHandler import ActionHandler
+ #setup icon using icon theme
+ try: gtk.window_set_default_icon(gtk.IconTheme().load_icon('gnuradio-grc', 256, 0))
+ except: pass
+ ActionHandler(args, Platform())
+
diff --git a/grc/todo.txt b/grc/todo.txt
new file mode 100644
index 000000000..1205b3ff6
--- /dev/null
+++ b/grc/todo.txt
@@ -0,0 +1,74 @@
+##################################################
+# Examples
+##################################################
+* Push-to-Talk example
+* Start/Stop the flow graph
+
+##################################################
+# Blocks
+##################################################
+* probe: also non-float outputs
+* log slider gui control
+* packet mod: whitening offset
+* wx min window size in options block
+* gr_adaptive_fir_ccf
+* ofdm
+ * gr_ofdm_bpsk_demapper
+ * gr_ofdm_demapper_vcb
+ * gr_ofdm_frame_sink
+ * gr_ofdm_mapper_bcv
+* size params for the graphical sinks
+* callbacks for set average on fft, waterfall, number sinks
+* add units to params: Sps, Hz, dB...
+* add bool type to command line option store_true or store_false
+* messages for packet blocks and probe blocks
+
+##################################################
+# Features
+##################################################
+* extract category from doxygen
+ * fix up block tree to mirror current doxygen group
+ * remove blocks in block tree covered by doxygen
+* param editor, expand entry boxes in focus
+* change param dialog to panel within main window
+* gui grid editor for configuring grid params/placing wxgui plots and controls
+* drag from one port to another to connect
+* per parameter docs
+ * extract individual param docs from doxygen
+ * doc tag in param for handwritten notes
+* separate generated code into top block and gui class
+ * use gui.py in gr-wxgui and remove custom top_block_gui
+* configuration option for adding block paths
+* orientations for ports (top, right, bottom, left)
+ * source defaults to right, sink defaults to left
+* separation of variables and gui controls
+* speedup w/ background layer and animation layer
+* multiple doxygen directories (doc_dir becomes doc_path)
+* use pango markup in tooltips for params
+* use get_var_make to determine if it is a variable, not regexp
+* concept of a project, or project flow graph
+ * collection of blocks, hier and top
+ * system-wide, default/work, and user created
+* use templates/macros to generate the repetative stuff in the xml
+
+##################################################
+# Problems
+##################################################
+* msg ports dont work with virtual connections
+ * dont fix this until pmts are used?
+* hier block generation
+ * auto generate hier library on changes
+ * auto clean hier library when block removed
+ * add hier blocks to tree without restart
+* dont generate py files in saved flowgraph dir
+* save/restore cwd
+* threads dont die on exit in probe and variable sink
+* align param titles in properties dialog
+* weird grid params misbehaving
+* gr hier blocks have more diverse IO capabilities than we allow for
+
+##################################################
+# Future
+##################################################
+* require pygtk 2.12 for treeview tooltips
+ * remove try/except in BlockTreeWindow.py