From: jblum Date: Sun, 7 Sep 2008 21:38:12 +0000 (+0000) Subject: Merged r9481:9518 on jblum/grc_reorganize into trunk. Reorganized grc source under... X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=c86f6c23c6883f73d953d64c28ab42cedb77e4d7;p=debian%2Fgnuradio Merged r9481:9518 on jblum/grc_reorganize into trunk. Reorganized grc source under gnuradio.grc module. Trunk passes make distcheck. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@9525 221aa14e-8319-0410-a670-987f0aec2ac5 --- diff --git a/Makefile.common b/Makefile.common index b24be437..eb739081 100644 --- a/Makefile.common +++ b/Makefile.common @@ -116,3 +116,6 @@ COMPILE_MBH = $(RUN_GUILE) $(top_srcdir)/mblock/src/scheme/gnuradio/compile-mbh. # Base directory for example applications exampledir = $(datadir)/gnuradio/examples + +# Base directory for documentation +gr_docdir = $(docdir)-$(VERSION) diff --git a/config/grc_grc.m4 b/config/grc_grc.m4 index e2b63f51..c8ea1099 100644 --- a/config/grc_grc.m4 +++ b/config/grc_grc.m4 @@ -52,27 +52,30 @@ AC_DEFUN([GRC_GRC],[ AC_SUBST(PYTHONW) AC_CONFIG_FILES([ \ - grc/Makefile \ - grc/data/Makefile \ - grc/data/grc/Makefile \ - grc/data/grc_gnuradio/Makefile \ - grc/data/grc_gnuradio/blocks/Makefile \ - grc/src/Makefile \ - grc/src/grc/Makefile \ - grc/src/grc/gui/Makefile \ - grc/src/grc/gui/elements/Makefile \ - grc/src/grc/elements/Makefile \ grc/src/grc_gnuradio/Makefile \ + grc/src/grc_gnuradio/wxgui/Makefile \ grc/src/grc_gnuradio/blks2/Makefile \ grc/src/grc_gnuradio/usrp/Makefile \ - grc/src/grc_gnuradio/utils/Makefile \ - grc/src/grc_gnuradio/wxgui/Makefile \ - grc/scripts/Makefile \ + grc/src/Makefile \ + grc/src/platforms/Makefile \ + grc/src/platforms/base/Makefile \ + grc/src/platforms/python/Makefile \ + grc/src/platforms/python/utils/Makefile \ + grc/src/platforms/gui/Makefile \ + grc/src/utils/Makefile \ + grc/src/gui/Makefile \ grc/examples/Makefile \ + grc/examples/xmlrpc/Makefile \ + grc/examples/usrp/Makefile \ grc/examples/audio/Makefile \ grc/examples/simple/Makefile \ - grc/examples/usrp/Makefile \ - grc/examples/xmlrpc/Makefile \ + grc/Makefile \ + grc/data/Makefile \ + grc/data/platforms/Makefile \ + grc/data/platforms/base/Makefile \ + grc/data/platforms/python/Makefile \ + grc/data/platforms/python/blocks/Makefile \ + grc/scripts/Makefile \ ]) GRC_BUILD_CONDITIONAL(grc) diff --git a/gnuradio-core/doc/Makefile.am b/gnuradio-core/doc/Makefile.am index 855bbf43..1f5bef2c 100644 --- a/gnuradio-core/doc/Makefile.am +++ b/gnuradio-core/doc/Makefile.am @@ -23,8 +23,6 @@ include $(top_srcdir)/Makefile.common SUBDIRS = other xml-swig -docdir = $(prefix)/share/doc/@PACKAGE@-@VERSION@ - EXTRA_DIST = all-local: prep @generate_docs@ @@ -39,21 +37,21 @@ prep: mkdir -p xml install-data-local: - $(mkinstalldirs) $(DESTDIR)$(docdir) + $(mkinstalldirs) $(DESTDIR)$(gr_docdir) @for i in $(top_srcdir)/README $(top_srcdir)/README.hacking; do \ - echo "$(INSTALL_DATA) $$i $(DESTDIR)$(docdir)"; \ - $(INSTALL_DATA) $$i $(DESTDIR)$(docdir); \ + echo "$(INSTALL_DATA) $$i $(DESTDIR)$(gr_docdir)"; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(gr_docdir); \ done - cp -r html $(DESTDIR)$(docdir) - cp -r xml $(DESTDIR)$(docdir) + cp -r html $(DESTDIR)$(gr_docdir) + cp -r xml $(DESTDIR)$(gr_docdir) uninstall-local: @for i in README README.hacking; do \ - echo "$(RM) $(DESTDIR)$(docdir)/$$i;"; \ - $(RM) $(DESTDIR)$(docdir)/$$i; \ + echo "$(RM) $(DESTDIR)$(gr_docdir)/$$i;"; \ + $(RM) $(DESTDIR)$(gr_docdir)/$$i; \ done - $(RM) -fr $(DESTDIR)$(docdir)/html - $(RM) -fr $(DESTDIR)$(docdir)/xml + $(RM) -fr $(DESTDIR)$(gr_docdir)/html + $(RM) -fr $(DESTDIR)$(gr_docdir)/xml clean-local: $(RM) -fr latex html man xml diff --git a/gr-trellis/doc/Makefile.am b/gr-trellis/doc/Makefile.am index 3bf1ae62..8f6ae260 100644 --- a/gr-trellis/doc/Makefile.am +++ b/gr-trellis/doc/Makefile.am @@ -21,8 +21,6 @@ include $(top_srcdir)/Makefile.common -docdir=$(prefix)/share/doc/@PACKAGE@-@VERSION@ - HTML_FILES = if HAS_XMLTO @@ -52,18 +50,18 @@ gr-trellis.html : gr-trellis.xml ./make_numbered_listing.py $< install-data-local: - mkdir -p $(DESTDIR)$(docdir)/html + mkdir -p $(DESTDIR)$(gr_docdir)/html @for i in $(HTML_FILES); do \ - echo "$(INSTALL_DATA) $$i $(DESTDIR)$(docdir)/html"; \ - $(INSTALL_DATA) $$i $(DESTDIR)$(docdir)/html; \ + echo "$(INSTALL_DATA) $$i $(DESTDIR)$(gr_docdir)/html"; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(gr_docdir)/html; \ done uninstall-local: @for i in $(HTML_FILES); do \ - echo "$(RM) $(DESTDIR)$(docdir)/$$i;"; \ - $(RM) $(DESTDIR)$(docdir)/$$i; \ + echo "$(RM) $(DESTDIR)$(gr_docdir)/$$i;"; \ + $(RM) $(DESTDIR)$(gr_docdir)/$$i; \ done - $(RM) -fr $(DESTDIR)$(docdir)/html + $(RM) -fr $(DESTDIR)$(gr_docdir)/html clean-local: $(RM) -fr $(HTML_FILES) *~ diff --git a/grc/Makefile.inc b/grc/Makefile.inc index ce18b691..8acd4e10 100644 --- a/grc/Makefile.inc +++ b/grc/Makefile.inc @@ -20,9 +20,10 @@ # include $(top_srcdir)/Makefile.common - -grc_data_prefix = @datadir@/${PACKAGE}/grc -grc_examples_prefix = @datadir@/${PACKAGE}/examples/grc -grc_data_dir = $(grc_data_prefix)/grc -grc_gnuradio_data_dir = $(grc_data_prefix)/grc_gnuradio -grc_gnuradio_blocks_dir = $(grc_data_prefix)/grc_gnuradio/blocks +grc_gnuradio_prefix = $(pythondir)/grc_gnuradio +grc_src_prefix = $(pythondir)/gnuradio/grc +grc_data_prefix = $(datadir)/$(PACKAGE)/grc +grc_examples_prefix = $(exampledir)/grc +grc_base_data_dir = $(grc_data_prefix)/platforms/base +grc_python_data_dir = $(grc_data_prefix)/platforms/python +grc_python_blocks_dir = $(grc_data_prefix)/platforms/python/blocks diff --git a/grc/data/Makefile.am b/grc/data/Makefile.am index 7174279b..961c183f 100644 --- a/grc/data/Makefile.am +++ b/grc/data/Makefile.am @@ -21,4 +21,4 @@ include $(top_srcdir)/grc/Makefile.inc -SUBDIRS = grc grc_gnuradio +SUBDIRS = platforms diff --git a/grc/data/grc/Makefile.am b/grc/data/grc/Makefile.am deleted file mode 100644 index f95d17c3..00000000 --- a/grc/data/grc/Makefile.am +++ /dev/null @@ -1,35 +0,0 @@ -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/grc/Makefile.inc - -ourdatadir = $(grc_data_dir) - -DATA_FILES = \ - block_tree.dtd \ - flow_graph.dtd \ - grc-icon-256.png \ - grc-icon-256.svg \ - grc-icon-32.png - -ourdata_DATA = $(DATA_FILES) - -EXTRA_DIST = $(DATA_FILES) diff --git a/grc/data/grc/block_tree.dtd b/grc/data/grc/block_tree.dtd deleted file mode 100644 index be1524a3..00000000 --- a/grc/data/grc/block_tree.dtd +++ /dev/null @@ -1,26 +0,0 @@ - - - - - diff --git a/grc/data/grc/flow_graph.dtd b/grc/data/grc/flow_graph.dtd deleted file mode 100644 index 904147b3..00000000 --- a/grc/data/grc/flow_graph.dtd +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/grc/data/grc/grc-icon-256.png b/grc/data/grc/grc-icon-256.png deleted file mode 100644 index e4e8e54a..00000000 Binary files a/grc/data/grc/grc-icon-256.png and /dev/null differ diff --git a/grc/data/grc/grc-icon-256.svg b/grc/data/grc/grc-icon-256.svg deleted file mode 100644 index 87526d46..00000000 --- a/grc/data/grc/grc-icon-256.svg +++ /dev/null @@ -1,216 +0,0 @@ - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - Patrick Strasser <patrick.strasser@tugraz.at> - - - Icon/Symbol for the GNURadio Companion - grc-icon.svg - 2007-02-23 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/grc/data/grc/grc-icon-32.png b/grc/data/grc/grc-icon-32.png deleted file mode 100644 index 1e4f4f6c..00000000 Binary files a/grc/data/grc/grc-icon-32.png and /dev/null differ diff --git a/grc/data/grc_gnuradio/Makefile.am b/grc/data/grc_gnuradio/Makefile.am deleted file mode 100644 index c0e98960..00000000 --- a/grc/data/grc_gnuradio/Makefile.am +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/grc/Makefile.inc - -SUBDIRS = blocks - -ourdatadir = $(grc_gnuradio_data_dir) - -DATA_FILES = \ - block.dtd \ - block_tree.xml \ - default_flow_graph.grc.xml \ - flow_graph.tmpl - -ourdata_DATA = $(DATA_FILES) - -EXTRA_DIST = $(DATA_FILES) - diff --git a/grc/data/grc_gnuradio/block.dtd b/grc/data/grc_gnuradio/block.dtd deleted file mode 100644 index d892b128..00000000 --- a/grc/data/grc_gnuradio/block.dtd +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/grc/data/grc_gnuradio/block_tree.xml b/grc/data/grc_gnuradio/block_tree.xml deleted file mode 100644 index 7ac9e519..00000000 --- a/grc/data/grc_gnuradio/block_tree.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - Sources - gr_sig_source_x - gr_noise_source_x - gr_vector_source_x - random_source_x - gr_glfsr_source_x - gr_null_source - gr_file_source - gr_udp_source - audio_source - gr_wavfile_source - pad_source - - - Sinks - gr_vector_sink_x - gr_null_sink - gr_file_sink - gr_udp_sink - audio_sink - gr_wavfile_sink - pad_sink - - - Graphical Sinks - wxgui_numbersink2 - wxgui_scopesink2 - wxgui_fftsink2 - wxgui_constellationsink2 - wxgui_waterfallsink2 - - - Operators - gr_add_vxx - gr_sub_xx - gr_multiply_vxx - gr_divide_xx - gr_nlog10_ff - - gr_add_const_vxx - gr_multiply_const_vxx - - gr_not_xx - gr_and_xx - gr_or_xx - gr_xor_xx - - gr_max_xx - gr_argmax_xx - gr_rms_xx - gr_integrate_xx - - gr_conjugate_cc - - gr_fft_vxx - blks2_logpwrfft_x - - - Type Conversions - gr_complex_to_arg - gr_complex_to_mag - gr_complex_to_mag_squared - gr_complex_to_real - gr_complex_to_imag - - gr_complex_to_float - gr_float_to_complex - - gr_float_to_short - gr_short_to_float - - gr_float_to_char - gr_char_to_float - - gr_float_to_uchar - gr_uchar_to_float - - gr_complex_to_interleaved_short - gr_interleaved_short_to_complex - - - Stream Conversions - gr_interleave - gr_deinterleave - - gr_streams_to_stream - gr_stream_to_streams - - gr_streams_to_vector - gr_vector_to_streams - - gr_stream_to_vector - gr_vector_to_stream - - blks2_stream_to_vector_decimator - - - Misc Conversions - gr_unpacked_to_packed_xx - gr_packed_to_unpacked_xx - gr_unpack_k_bits_bb - gr_binary_slicer_fb - gr_chunks_to_symbols_xx - gr_map_bb - - - Synchronizers - gr_clock_recovery_mm_xx - - gr_costas_loop_cc - gr_dd_mpsk_sync_cc - gr_mpsk_sync_cc - gr_mpsk_receiver_cc - - gr_pll_carriertracking_cc - gr_pll_freqdet_cf - gr_pll_refout_cc - - gr_correlate_access_code_bb - gr_pn_correlator_cc - gr_simple_correlator - gr_simple_framer - - - Level Controls - gr_dpll_bb - gr_peak_detector_xb - gr_peak_detector2_fb - gr_sample_and_hold_xx - - gr_agc_xx - gr_agc2_xx - gr_feedforward_agc_cc - - gr_mute_xx - gr_simple_squelch_cc - blks2_standard_squelch - gr_pwr_squelch_xx - gr_threshold_ff - - - Filters - - low_pass_filter - high_pass_filter - band_pass_filter - band_reject_filter - - gr_fir_filter_xxx - gr_interp_fir_filter_xxx - gr_fft_filter_xxx - gr_freq_xlating_fir_filter_xxx - gr_iir_filter_ffd - gr_filter_delay_fc - blks2_channel_model - - gr_single_pole_iir_filter_xx - gr_hilbert_fc - gr_goertzel_fc - gr_cma_equalizer_cc - gr_rational_resampler_base_xxx - blks2_rational_resampler_xxx - gr_fractional_interpolator_xx - gr_keep_one_in_n - gr_moving_average_xx - gr_iqcomp_cc - - - Modulators - gr_vco_f - gr_frequency_modulator_fc - gr_phase_modulator_fc - gr_quadrature_demod_cf - gr_cpfsk_bc - - gr_diff_phasor_cc - gr_constellation_decoder_cb - - gr_diff_encoder_bb - gr_diff_decoder_bb - - blks2_wfm_tx - blks2_wfm_rcv - blks2_wfm_rcv_pll - - blks2_nbfm_tx - blks2_nbfm_rx - - blks2_am_demod_cf - blks2_fm_demod_cf - blks2_fm_deemph - blks2_fm_preemph - - blks2_dxpsk_mod - blks2_dxpsk_demod - - blks2_gmsk_mod - blks2_gmsk_demod - - blks2_qamx_mod - blks2_qamx_demod - - blks2_synthesis_filterbank - blks2_analysis_filterbank - - - Error Correction - - blks2_packet_decoder - blks2_packet_encoder - - gr_encode_ccsds_27_bb - gr_decode_ccsds_27_fb - - - Trellis - trellis_encoder_xx - trellis_metrics_x - trellis_permutation - trellis_siso_combined_f - trellis_siso_f - trellis_viterbi_combined_xx - trellis_viterbi_x - - - USRP - usrp_simple_source_x - usrp_simple_sink_x - usrp_dual_source_x - usrp_dual_sink_x - - - Variables - variable - variable_slider - variable_chooser - variable_text_box - variable_sink - parameter - - - Misc - note - import - - gr_throttle - gr_delay - gr_repeat - - blks2_selector - blks2_valve - blks2_error_rate - - gr_head - gr_skiphead - - gr_kludge_copy - gr_nop - - xmlrpc_server - xmlrpc_client - - diff --git a/grc/data/grc_gnuradio/blocks/Makefile.am b/grc/data/grc_gnuradio/blocks/Makefile.am deleted file mode 100644 index 877ed980..00000000 --- a/grc/data/grc_gnuradio/blocks/Makefile.am +++ /dev/null @@ -1,210 +0,0 @@ -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/grc/Makefile.inc - -ourdatadir = $(grc_gnuradio_blocks_dir) - -DATA_FILES = \ - audio_sink.xml \ - audio_source.xml \ - band_pass_filter.xml \ - band_reject_filter.xml \ - blks2_am_demod_cf.xml \ - blks2_analysis_filterbank.xml \ - blks2_channel_model.xml \ - blks2_dxpsk_demod.xml \ - blks2_dxpsk_mod.xml \ - blks2_error_rate.xml \ - blks2_fm_deemph.xml \ - blks2_fm_demod_cf.xml \ - blks2_fm_preemph.xml \ - blks2_gmsk_demod.xml \ - blks2_gmsk_mod.xml \ - blks2_logpwrfft_x.xml \ - blks2_nbfm_rx.xml \ - blks2_nbfm_tx.xml \ - blks2_packet_decoder.xml \ - blks2_packet_encoder.xml \ - blks2_qamx_demod.xml \ - blks2_qamx_mod.xml \ - blks2_rational_resampler_xxx.xml \ - blks2_selector.xml \ - blks2_standard_squelch.xml \ - blks2_stream_to_vector_decimator.xml \ - blks2_synthesis_filterbank.xml \ - blks2_valve.xml \ - blks2_wfm_rcv.xml \ - blks2_wfm_rcv_pll.xml \ - blks2_wfm_tx.xml \ - gr_add_const_vxx.xml \ - gr_add_vxx.xml \ - gr_agc2_xx.xml \ - gr_agc_xx.xml \ - gr_and_xx.xml \ - gr_argmax_xx.xml \ - gr_binary_slicer_fb.xml \ - gr_char_to_float.xml \ - gr_chunks_to_symbols.xml \ - gr_clock_recovery_mm_xx.xml \ - gr_cma_equalizer_cc.xml \ - gr_complex_to_arg.xml \ - gr_complex_to_float.xml \ - gr_complex_to_imag.xml \ - gr_complex_to_interleaved_short.xml \ - gr_complex_to_mag.xml \ - gr_complex_to_mag_squared.xml \ - gr_complex_to_real.xml \ - gr_conjugate_cc.xml \ - gr_constellation_decoder_cb.xml \ - gr_correlate_access_code_bb.xml \ - gr_costas_loop_cc.xml \ - gr_cpfsk_bc.xml \ - gr_dd_mpsk_sync_cc.xml \ - gr_decode_ccsds_27_fb.xml \ - gr_deinterleave.xml \ - gr_delay.xml \ - gr_diff_decoder_bb.xml \ - gr_diff_encoder_bb.xml \ - gr_diff_phasor_cc.xml \ - gr_divide_xx.xml \ - gr_dpll_bb.xml \ - gr_encode_ccsds_27_bb.xml \ - gr_feedforward_agc_cc.xml \ - gr_fft_filter_xxx.xml \ - gr_fft_vxx.xml \ - gr_file_sink.xml \ - gr_file_source.xml \ - gr_filter_delay_fc.xml \ - gr_fir_filter_xxx.xml \ - gr_float_to_char.xml \ - gr_float_to_complex.xml \ - gr_float_to_short.xml \ - gr_float_to_uchar.xml \ - gr_fractional_interpolator_xx.xml \ - gr_freq_xlating_fir_filter_xxx.xml \ - gr_frequency_modulator_fc.xml \ - gr_glfsr_source_x.xml \ - gr_goertzel_fc.xml \ - gr_head.xml \ - gr_hilbert_fc.xml \ - gr_iir_filter_ffd.xml \ - gr_integrate_xx.xml \ - gr_interleave.xml \ - gr_interleaved_short_to_complex.xml \ - gr_interp_fir_filter_xxx.xml \ - gr_iqcomp_cc.xml \ - gr_keep_one_in_n.xml \ - gr_kludge_copy.xml \ - gr_map_bb.xml \ - gr_max_xx.xml \ - gr_moving_average_xx.xml \ - gr_mpsk_receiver_cc.xml \ - gr_mpsk_sync_cc.xml \ - gr_multiply_const_vxx.xml \ - gr_multiply_vxx.xml \ - gr_mute_xx.xml \ - gr_nlog10_ff.xml \ - gr_noise_source_x.xml \ - gr_nop.xml \ - gr_not_xx.xml \ - gr_null_sink.xml \ - gr_null_source.xml \ - gr_or_xx.xml \ - gr_packed_to_unpacked_xx.xml \ - gr_peak_detector2_fb.xml \ - gr_peak_detector_xb.xml \ - gr_phase_modulator_fc.xml \ - gr_pll_carriertracking_cc.xml \ - gr_pll_freqdet_cf.xml \ - gr_pll_refout_cc.xml \ - gr_pn_correlator_cc.xml \ - gr_pwr_squelch_xx.xml \ - gr_quadrature_demod_cf.xml \ - gr_rational_resampler_base_xxx.xml \ - gr_repeat.xml \ - gr_rms_xx.xml \ - gr_sample_and_hold_xx.xml \ - gr_short_to_float.xml \ - gr_sig_source_x.xml \ - gr_simple_correlator.xml \ - gr_simple_framer.xml \ - gr_simple_squelch_cc.xml \ - gr_single_pole_iir_filter_xx.xml \ - gr_skiphead.xml \ - gr_stream_to_streams.xml \ - gr_stream_to_vector.xml \ - gr_streams_to_stream.xml \ - gr_streams_to_vector.xml \ - gr_sub_xx.xml \ - gr_threshold_ff.xml \ - gr_throttle.xml \ - gr_uchar_to_float.xml \ - gr_udp_sink.xml \ - gr_udp_source.xml \ - gr_unpack_k_bits_bb.xml \ - gr_unpacked_to_packed_xx.xml \ - gr_vco_f.xml \ - gr_vector_sink_x.xml \ - gr_vector_source_x.xml \ - gr_vector_to_stream.xml \ - gr_vector_to_streams.xml \ - gr_wavfile_sink.xml \ - gr_wavfile_source.xml \ - gr_xor_xx.xml \ - high_pass_filter.xml \ - import.xml \ - low_pass_filter.xml \ - note.xml \ - options.xml \ - pad_sink.xml \ - pad_source.xml \ - parameter.xml \ - preferences.xml \ - random_source_x.xml \ - trellis_encoder_xx.xml \ - trellis_metrics_x.xml \ - trellis_permutation.xml \ - trellis_siso_combined_f.xml \ - trellis_siso_f.xml \ - trellis_viterbi_combined_xx.xml \ - trellis_viterbi_x.xml \ - usrp_diagnostics.xml \ - usrp_dual_sink_x.xml \ - usrp_dual_source_x.xml \ - usrp_simple_sink_x.xml \ - usrp_simple_source_x.xml \ - variable.xml \ - variable_chooser.xml \ - variable_sink.xml \ - variable_slider.xml \ - variable_text_box.xml \ - wxgui_constellationsink2.xml \ - wxgui_fftsink2.xml \ - wxgui_numbersink2.xml \ - wxgui_scopesink2.xml \ - wxgui_waterfallsink2.xml \ - xmlrpc_client.xml \ - xmlrpc_server.xml - -ourdata_DATA = $(DATA_FILES) - -EXTRA_DIST = $(DATA_FILES) diff --git a/grc/data/grc_gnuradio/blocks/audio_sink.xml b/grc/data/grc_gnuradio/blocks/audio_sink.xml deleted file mode 100644 index 56c5980f..00000000 --- a/grc/data/grc_gnuradio/blocks/audio_sink.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - Audio Sink - audio_sink - from gnuradio import audio - audio.sink($samp_rate, $device_name, $ok_to_block) - - Sample Rate - samp_rate - 32000 - enum - - - - - - - - - Device Name - device_name - - string - - - OK to Block - ok_to_block - True - enum - - - - - Num Inputs - num_inputs - 1 - int - - 0 < $num_inputs - - in - float - $num_inputs - - -Not all sampling rates will be supported by your hardware. - -Leave the device name blank to choose deafult audio device. \ -Audio device names may look like hw:0,0 - -The audio sink can have multiple inputs depending upon your hardware. \ -For example, set the inputs to 2 for stereo audio. - - diff --git a/grc/data/grc_gnuradio/blocks/audio_source.xml b/grc/data/grc_gnuradio/blocks/audio_source.xml deleted file mode 100644 index 2ae74e49..00000000 --- a/grc/data/grc_gnuradio/blocks/audio_source.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - Audio Source - audio_source - from gnuradio import audio - audio.source($samp_rate, $device_name, $ok_to_block) - - Sample Rate - samp_rate - 32000 - enum - - - - - - - - - Device Name - device_name - - string - - - OK to Block - ok_to_block - True - enum - - - - - Num Outputs - num_outputs - 1 - int - - 0 < $num_outputs - - out - float - $num_outputs - - -Not all sampling rates will be supported by your hardware. - -Leave the device name blank to choose deafult audio device. \ -Audio device names may look like hw:0,0 - -The audio source can have multiple outputs depending upon your hardware. \ -For example, set the outputs to 2 for stereo audio. - - diff --git a/grc/data/grc_gnuradio/blocks/band_pass_filter.xml b/grc/data/grc_gnuradio/blocks/band_pass_filter.xml deleted file mode 100644 index 2dac2960..00000000 --- a/grc/data/grc_gnuradio/blocks/band_pass_filter.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - Band Pass Filter - band_pass_filter - from gnuradio import gr - from gnuradio.gr import firdes - gr.$(type)($decim, firdes.band_pass( - $gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, firdes.$window, $beta)) - set_taps(firdes.band_pass($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, firdes.$window, $beta)) - - FIR Type - type - enum - - - - - - - Decimation - decim - 1 - int - - - Gain - gain - 1 - real - - - Sample Rate - samp_rate - samp_rate - real - - - Low Cutoff Freq - low_cutoff_freq - real - - - High Cutoff Freq - high_cutoff_freq - real - - - Transition Width - width - real - - - Window - window - enum - - - - - - - - Beta - beta - 6.76 - real - - - in - $type.input - - - out - $type.output - - -This filter is a convenience wrapper for an fir filter and a firdes taps generating function. - -The decimation paramater becomes interpolation when the filter type is set to interpolating. - -Sample rate, cutoff frequency, and transition width are in Hertz. - -The beta paramater only applies to the Kaiser window. - - diff --git a/grc/data/grc_gnuradio/blocks/band_reject_filter.xml b/grc/data/grc_gnuradio/blocks/band_reject_filter.xml deleted file mode 100644 index ed6a5fa8..00000000 --- a/grc/data/grc_gnuradio/blocks/band_reject_filter.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - Band Reject Filter - band_reject_filter - from gnuradio import gr - from gnuradio.gr import firdes - gr.$(type)($decim, firdes.band_reject( - $gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, firdes.$window, $beta)) - set_taps(firdes.band_reject($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, firdes.$window, $beta)) - - FIR Type - type - enum - - - - - - - Decimation - decim - 1 - int - - - Gain - gain - 1 - real - - - Sample Rate - samp_rate - samp_rate - real - - - Low Cutoff Freq - low_cutoff_freq - real - - - High Cutoff Freq - high_cutoff_freq - real - - - Transition Width - width - real - - - Window - window - enum - - - - - - - - Beta - beta - 6.76 - real - - - in - $type.input - - - out - $type.output - - -This filter is a convenience wrapper for an fir filter and a firdes taps generating function. - -The decimation paramater becomes interpolation when the filter type is set to interpolating. - -Sample rate, cutoff frequency, and transition width are in Hertz. - -The beta paramater only applies to the Kaiser window. - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_am_demod_cf.xml b/grc/data/grc_gnuradio/blocks/blks2_am_demod_cf.xml deleted file mode 100644 index 898c613b..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_am_demod_cf.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - AM Demod - blks2_am_demod_cf - from gnuradio import blks2 - blks2.am_demod_cf( - channel_rate=$chan_rate, - audio_decim=$audio_decim, - audio_pass=$audio_pass, - audio_stop=$audio_stop, -) - - Channel Rate - chan_rate - real - - - Audio Decimation - audio_decim - int - - - Audio Pass - audio_pass - 5000 - real - - - Audio Stop - audio_stop - 5500 - real - - - in - complex - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_analysis_filterbank.xml b/grc/data/grc_gnuradio/blocks/blks2_analysis_filterbank.xml deleted file mode 100644 index 93cfa30a..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_analysis_filterbank.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - Analysis Filterbank - blks2_analysis_filterbank - from gnuradio import blks2 - blks2.analysis_filterbank(mpoints=$mpoints, taps=$taps) - - MPoints - mpoints - 3 - int - - - Taps - taps - complex_vector - - - in - complex - - - out - complex - $mpoints - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_channel_model.xml b/grc/data/grc_gnuradio/blocks/blks2_channel_model.xml deleted file mode 100644 index 88805636..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_channel_model.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - Channel Model - blks2_channel_model - from gnuradio import blks2 - from gnuradio.gr import firdes - blks2.channel_model( - noise_voltage=$noise_voltage, - frequency_offset=$freq_offset, - epsilon=$epsilon, - taps=$taps, - noise_seed=$seed, -) - set_noise_voltage($noise_voltage) - set_frequency_offset($freq_offset) - set_taps($taps) - - Noise Voltage - noise_voltage - 0.0 - real - - - Frequency Offset - freq_offset - 0.0 - real - - - Epsilon - epsilon - 1.0 - real - - - Taps - taps - 1.0, 0.0 - complex_vector - - - Seed - seed - 42 - int - - - in - complex - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_dxpsk_demod.xml b/grc/data/grc_gnuradio/blocks/blks2_dxpsk_demod.xml deleted file mode 100644 index 20c7bd7f..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_dxpsk_demod.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - DPSK Demod - blks2_dxpsk_demod - from gnuradio import blks2 - blks2.$(type)_demod( - samples_per_symbol=$samples_per_symbol, - excess_bw=$excess_bw, - costas_alpha=$costas_alpha, - gain_mu=$gain_mu, - mu=$mu, - omega_relative_limit=$omega_relative_limit, - gray_code=$gray_code, -) - - Type - type - enum - - - - - - Samples/Symbol - samples_per_symbol - 2 - int - - - Excess BW - excess_bw - 0.35 - real - - - Costas Alpha - costas_alpha - 0.175 - real - - - Gain Mu - gain_mu - 0.175 - real - - - Mu - mu - 0.5 - real - - - Omega Relative Limit - omega_relative_limit - 0.005 - real - - - Gray Code - gray_code - True - enum - - - - - in - complex - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_dxpsk_mod.xml b/grc/data/grc_gnuradio/blocks/blks2_dxpsk_mod.xml deleted file mode 100644 index e165fe9b..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_dxpsk_mod.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - DPSK Mod - blks2_dxpsk_mod - from gnuradio import blks2 - blks2.$(type)_mod( - samples_per_symbol=$samples_per_symbol, - excess_bw=$excess_bw, - gray_code=$gray_code, -) - - Type - type - enum - - - - - - Samples/Symbol - samples_per_symbol - 2 - int - - - Excess BW - excess_bw - 0.35 - real - - - Gray Code - gray_code - True - enum - - - - - in - byte - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_error_rate.xml b/grc/data/grc_gnuradio/blocks/blks2_error_rate.xml deleted file mode 100644 index 79703f6e..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_error_rate.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - Error Rate - blks2_error_rate - from grc_gnuradio import blks2 as grc_blks2 - grc_blks2.error_rate( - type=$type, - win_size=$win_size, - bits_per_symbol=$bits_per_symbol, -) - - Type - type - enum - - - - - Window Size - win_size - 1000 - int - - - Bits per Symbol - bits_per_symbol - 2 - int - - - ref - byte - - - in - byte - - - out - float - - -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. - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_fm_deemph.xml b/grc/data/grc_gnuradio/blocks/blks2_fm_deemph.xml deleted file mode 100644 index 6f38dab6..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_fm_deemph.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - FM Deemphasis - blks2_fm_deemph - from gnuradio import blks2 - blks2.fm_deemph(fs=$samp_rate, tau=$tau) - - Sample Rate - samp_rate - real - - - Tau - tau - 75e-6 - real - - - in - float - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_fm_demod_cf.xml b/grc/data/grc_gnuradio/blocks/blks2_fm_demod_cf.xml deleted file mode 100644 index 2ce1fb97..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_fm_demod_cf.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - FM Demod - blks2_fm_demod_cf - from gnuradio import blks2 - 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, -) - - Channel Rate - chan_rate - real - - - Audio Decimation - audio_decim - int - - - Deviation - deviation - 75000 - real - - - Audio Pass - audio_pass - 15000 - real - - - Audio Stop - audio_stop - 16000 - real - - - Gain - gain - 1.0 - real - - - Tau - tau - 75e-6 - real - - - in - complex - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_fm_preemph.xml b/grc/data/grc_gnuradio/blocks/blks2_fm_preemph.xml deleted file mode 100644 index 672a7a7b..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_fm_preemph.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - FM Preemphasis - blks2_fm_preemph - from gnuradio import blks2 - blks2.fm_preemph(fs=$samp_rate, tau=$tau) - - Sample Rate - samp_rate - real - - - Tau - tau - 75e-6 - real - - - in - float - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_gmsk_demod.xml b/grc/data/grc_gnuradio/blocks/blks2_gmsk_demod.xml deleted file mode 100644 index c8103981..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_gmsk_demod.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - GMSK Demod - blks2_gmsk_demod - from gnuradio import blks2 - blks2.gmsk_demod( - samples_per_symbol=$samples_per_symbol, - gain_mu=$gain_mu, - mu=$mu, - omega_relative_limit=$omega_relative_limit, - freq_error=$freq_error, -) - - Samples/Symbol - samples_per_symbol - 2 - int - - - Gain Mu - gain_mu - 0.175 - real - - - Mu - mu - 0.5 - real - - - Omega Relative Limit - omega_relative_limit - 0.005 - real - - - Freq Error - freq_error - 0.0 - real - - - in - complex - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_gmsk_mod.xml b/grc/data/grc_gnuradio/blocks/blks2_gmsk_mod.xml deleted file mode 100644 index ab57357e..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_gmsk_mod.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - GMSK Mod - blks2_gmsk_mod - from gnuradio import blks2 - blks2.gmsk_mod( - samples_per_symbol=$samples_per_symbol, - bt=$bt, -) - - Samples/Symbol - samples_per_symbol - 2 - int - - - BT - bt - 0.35 - real - - - in - byte - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_logpwrfft_x.xml b/grc/data/grc_gnuradio/blocks/blks2_logpwrfft_x.xml deleted file mode 100644 index ef49c443..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_logpwrfft_x.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - Log Power FFT - blks2_logpwrfft_x - from gnuradio import blks2 - 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, -) - set_sample_rate($sample_rate) - set_avg_alpha($avg_alpha) - - Input Type - type - enum - - - - - Sample Rate - sample_rate - samp_rate - real - - - FFT Size - fft_size - 1024 - int - - - Reference Scale - ref_scale - 2 - real - - - Frame Rate - frame_rate - 30 - real - - - Average Alpha - avg_alpha - 1.0 - real - - - Average - average - False - enum - - - - - in - $type - - - out - float - $fft_size - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_nbfm_rx.xml b/grc/data/grc_gnuradio/blocks/blks2_nbfm_rx.xml deleted file mode 100644 index d332b9a6..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_nbfm_rx.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - NBFM Receive - blks2_nbfm_rx - from gnuradio import blks2 - blks2.nbfm_rx( - audio_rate=$audio_rate, - quad_rate=$quad_rate, - tau=$tau, - max_dev=$max_dev, -) - - Audio Rate - audio_rate - int - - - Quadrature Rate - quad_rate - int - - - Tau - tau - 75e-6 - real - - - Max Deviation - max_dev - 5e3 - real - - $quad_rate%$audio_rate == 0 - - in - complex - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_nbfm_tx.xml b/grc/data/grc_gnuradio/blocks/blks2_nbfm_tx.xml deleted file mode 100644 index 3aa7ede0..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_nbfm_tx.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - NBFM Transmit - blks2_nbfm_tx - from gnuradio import blks2 - blks2.nbfm_tx( - audio_rate=$audio_rate, - quad_rate=$quad_rate, - tau=$tau, - max_dev=$max_dev, -) - - Audio Rate - audio_rate - int - - - Quadrature Rate - quad_rate - int - - - Tau - tau - 75e-6 - real - - - Max Deviation - max_dev - 5e3 - real - - $quad_rate%$audio_rate == 0 - - in - float - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_packet_decoder.xml b/grc/data/grc_gnuradio/blocks/blks2_packet_decoder.xml deleted file mode 100644 index d360bc17..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_packet_decoder.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - Packet Decoder - blks2_packet_decoder - from grc_gnuradio import blks2 as grc_blks2 - from gnuradio import gr - grc_blks2.packet_decoder( - item_size_out=$type.size*$vlen, - access_code=$access_code, - threshold=$threshold, -) - - Output Type - type - float - enum - - - - - - - - Access Code - access_code - - string - - - Threshold - threshold - -1 - int - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - byte - - - out - $type - $vlen - - -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 default. - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_packet_encoder.xml b/grc/data/grc_gnuradio/blocks/blks2_packet_encoder.xml deleted file mode 100644 index ea992722..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_packet_encoder.xml +++ /dev/null @@ -1,117 +0,0 @@ - - - - Packet Encoder - blks2_packet_encoder - from grc_gnuradio import blks2 as grc_blks2 - from gnuradio import gr - grc_blks2.packet_encoder( - item_size_in=$type.size*$vlen, - 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, -) - - Input Type - type - float - enum - - - - - - - - Samples/Symbol - samples_per_symbol - int - - - Bits/Symbol - bits_per_symbol - int - - - Access Code - access_code - - string - - - Pad for USRP - pad_for_usrp - enum - - - - - Payload Length - payload_length - -1 - int - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - - out - byte - - -Packet encoder block, for use with the gnuradio modulator blocks: gmsk, psk, qam. - -Access Code: string of 1's and 0's, leave blank for default. - -Bits/Symbol should be set accordingly: - gmsk -> 1 - dbpsk -> 1 - dqpsk -> 2 - d8psk -> 3 - qam8 -> 3 - qam16 -> 4 - qam64 -> 6 - qam256 -> 8 - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_qamx_demod.xml b/grc/data/grc_gnuradio/blocks/blks2_qamx_demod.xml deleted file mode 100644 index 93dbe4bb..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_qamx_demod.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - QAM Demod - blks2_qamx_demod - from gnuradio import blks2 - blks2.$(type)_demod( - samples_per_symbol=$samples_per_symbol, - excess_bw=$excess_bw, - costas_alpha=$costas_alpha, - gain_mu=$gain_mu, - mu=$mu, - omega_relative_limit=$omega_relative_limit, - gray_code=$gray_code, -) - - Type - type - enum - - - - - - - Samples/Symbol - samples_per_symbol - 2 - int - - - Excess BW - excess_bw - 0.35 - real - - - Costas Alpha - costas_alpha - 0.175 - real - - - Gain Mu - gain_mu - 0.03 - real - - - Mu - mu - 0.05 - real - - - Omega Relative Limit - omega_relative_limit - 0.005 - real - - - Gray Code - gray_code - True - enum - - - - - in - complex - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_qamx_mod.xml b/grc/data/grc_gnuradio/blocks/blks2_qamx_mod.xml deleted file mode 100644 index 25a9fb24..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_qamx_mod.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - QAM Mod - blks2_qamx_mod - from gnuradio import blks2 - blks2.$(type)_mod( - samples_per_symbol=$samples_per_symbol, - excess_bw=$excess_bw, - gray_code=$gray_code, -) - - Type - type - enum - - - - - - - Samples/Symbol - samples_per_symbol - 2 - int - - - Excess BW - excess_bw - 0.35 - real - - - Gray Code - gray_code - True - enum - - - - - in - byte - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_rational_resampler_xxx.xml b/grc/data/grc_gnuradio/blocks/blks2_rational_resampler_xxx.xml deleted file mode 100644 index 2f81a50e..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_rational_resampler_xxx.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - Rational Resampler - blks2_rational_resampler_xxx - from gnuradio import blks2 - from gnuradio.gr import firdes - blks2.rational_resampler_$(type)( - interpolation=$interp, - decimation=$decim, -#if $taps.eval - taps=$taps, -#else - taps=None, -#end if -#if $fractional_bw.eval != 0 - fractional_bw=$fractional_bw, -#else - fractional_bw=None, -#end if -) - - Type - type - enum - - - - - - Decimation - decim - 1 - int - - - Interpolation - interp - 1 - int - - - Taps - taps - [] - $type.taps - - - Fractional BW - fractional_bw - 0 - real - - - in - $type.input - - - out - $type.output - - -Leave taps empty for automatic value. -Leave fractional bandwidth 0 for automatic value. - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_selector.xml b/grc/data/grc_gnuradio/blocks/blks2_selector.xml deleted file mode 100644 index 457f8695..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_selector.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - - Selector - blks2_selector - from grc_gnuradio import blks2 as grc_blks2 - grc_blks2.selector( - item_size=$type.size*$vlen, - num_inputs=$num_inputs, - num_outputs=$num_outputs, - input_index=$input_index, - output_index=$output_index, -) - set_input_index($input_index) - set_output_index($output_index) - - Type - type - enum - - - - - - - - Num Inputs - num_inputs - 2 - int - - - Num Outputs - num_outputs - 2 - int - - - Input Index - input_index - 0 - int - - - Output Index - output_index - 0 - int - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - $num_inputs - - - out - $type - $vlen - $num_outputs - - -Connect the sink at input index to the source at output index. Leave all other ports disconnected. - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_standard_squelch.xml b/grc/data/grc_gnuradio/blocks/blks2_standard_squelch.xml deleted file mode 100644 index fa32c6c3..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_standard_squelch.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - Standard Squelch - blks2_standard_squelch - from gnuradio import blks2 - blks2.standard_squelch(audio_rate=$audio_rate) -$id.set_threshold($threshold) - set_threshold($threshold) - - Audio Rate - audio_rate - real - - - Threshold - threshold - real - - - in - float - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_stream_to_vector_decimator.xml b/grc/data/grc_gnuradio/blocks/blks2_stream_to_vector_decimator.xml deleted file mode 100644 index 25f8f7a6..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_stream_to_vector_decimator.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - Stream to Vec Decim - blks2_stream_to_vector_decimator - from gnuradio import blks2 - blks2.stream_to_vector_decimator( - item_size=$type.size, - sample_rate=$sample_rate, - vec_rate=$vec_rate, - vec_len=$vlen, -) - set_sample_rate($sample_rate) - set_vec_rate($vec_rate) - - IO Type - type - enum - - - - - - - - Sample Rate - sample_rate - samp_rate - real - - - Vec Rate - vec_rate - 30 - real - - - Vec Length - vlen - 1024 - int - - $vlen >= 1 - - in - $type - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_synthesis_filterbank.xml b/grc/data/grc_gnuradio/blocks/blks2_synthesis_filterbank.xml deleted file mode 100644 index 5979ed3f..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_synthesis_filterbank.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - Synthesis Filterbank - blks2_synthesis_filterbank - from gnuradio import blks2 - blks2.synthesis_filterbank(mpoints=$mpoints, taps=$taps) - - MPoints - mpoints - 3 - int - - - Taps - taps - complex_vector - - - in - complex - $mpoints - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_valve.xml b/grc/data/grc_gnuradio/blocks/blks2_valve.xml deleted file mode 100644 index 47c55352..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_valve.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - Valve - blks2_valve - from grc_gnuradio import blks2 as grc_blks2 - grc_blks2.valve(item_size=$type.size*$vlen, open=bool($open)) - set_open(bool($open)) - - Type - type - enum - - - - - - - - Open - open - 0 - raw - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - $num_inputs - - - out - $type - $vlen - $num_outputs - - -Connect output to input when valve is closed (not open). - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_wfm_rcv.xml b/grc/data/grc_gnuradio/blocks/blks2_wfm_rcv.xml deleted file mode 100644 index 37fb3ba8..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_wfm_rcv.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - WBFM Receive - blks2_wfm_rcv - from gnuradio import blks2 - blks2.wfm_rcv( - quad_rate=$quad_rate, - audio_decimation=$audio_decimation, -) - - Quadrature Rate - quad_rate - real - - - Audio Decimation - audio_decimation - int - - - in - complex - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_wfm_rcv_pll.xml b/grc/data/grc_gnuradio/blocks/blks2_wfm_rcv_pll.xml deleted file mode 100644 index 3563a1f2..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_wfm_rcv_pll.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - WBFM Receive PLL - blks2_wfm_rcv_pll - from gnuradio import blks2 - blks2.wfm_rcv_pll( - demod_rate=$quad_rate, - audio_decimation=$audio_decimation, -) - - Quadrature Rate - quad_rate - real - - - Audio Decimation - audio_decimation - int - - - in - complex - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/blks2_wfm_tx.xml b/grc/data/grc_gnuradio/blocks/blks2_wfm_tx.xml deleted file mode 100644 index cff92d81..00000000 --- a/grc/data/grc_gnuradio/blocks/blks2_wfm_tx.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - WBFM Transmit - blks2_wfm_tx - from gnuradio import blks2 - blks2.wfm_tx( - audio_rate=$audio_rate, - quad_rate=$quad_rate, - tau=$tau, - max_dev=$max_dev, -) - - Audio Rate - audio_rate - int - - - Quadrature Rate - quad_rate - int - - - Tau - tau - 75e-6 - real - - - Max Deviation - max_dev - 75e3 - real - - $quad_rate%$audio_rate == 0 - - in - float - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_add_const_vxx.xml b/grc/data/grc_gnuradio/blocks/gr_add_const_vxx.xml deleted file mode 100644 index 9f1c545a..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_add_const_vxx.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - Add Const - gr_add_const_vxx - from gnuradio import gr - gr.add_const_v$(type.fcn)($const) - set_k($const) - - IO Type - type - enum - - - - - - - Constant - const - 0 - $type.const_type - - - Vec Length - vlen - 1 - int - - len($const) == $vlen - $vlen > 0 - - in - $type - $vlen - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_add_vxx.xml b/grc/data/grc_gnuradio/blocks/gr_add_vxx.xml deleted file mode 100644 index 479cdaae..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_add_vxx.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - Add - gr_add_vxx - from gnuradio import gr - gr.add_v$(type.fcn)($vlen) - - IO Type - type - enum - - - - - - - Num Inputs - num_inputs - 2 - int - - - Vec Length - vlen - 1 - int - - $num_inputs > 1 - $vlen > 0 - - in - $type - $vlen - $num_inputs - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_agc2_xx.xml b/grc/data/grc_gnuradio/blocks/gr_agc2_xx.xml deleted file mode 100644 index fb3ae570..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_agc2_xx.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - AGC2 - gr_agc2_xx - from gnuradio import gr - gr.agc2_$(type.fcn)($attack_rate, $decay_rate, $reference, $gain, $max_gain) - - Type - type - enum - - - - - Attack Rate - attack_rate - 1e-1 - real - - - Decay Rate - decay_rate - 1e-2 - real - - - Reference - reference - 1.0 - real - - - Gain - gain - 1.0 - real - - - Max Gain - max_gain - 0.0 - real - - - in - $type - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_agc_xx.xml b/grc/data/grc_gnuradio/blocks/gr_agc_xx.xml deleted file mode 100644 index c87d239e..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_agc_xx.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - AGC - gr_agc_xx - from gnuradio import gr - gr.agc_$(type.fcn)($rate, $reference, $gain, $max_gain) - - Type - type - enum - - - - - Rate - rate - 1e-4 - real - - - Reference - reference - 1.0 - real - - - Gain - gain - 1.0 - real - - - Max Gain - max_gain - 0.0 - real - - - in - $type - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_and_xx.xml b/grc/data/grc_gnuradio/blocks/gr_and_xx.xml deleted file mode 100644 index 9ed00609..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_and_xx.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - And - gr_and_xx - from gnuradio import gr - gr.and_$(type.fcn)() - - IO Type - type - enum - - - - - - Num Inputs - num_inputs - 2 - int - - $num_inputs >= 2 - - in - $type - $num_inputs - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_argmax_xx.xml b/grc/data/grc_gnuradio/blocks/gr_argmax_xx.xml deleted file mode 100644 index e3e4e3ea..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_argmax_xx.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - Argmax - gr_argmax_xx - from gnuradio import gr - gr.argmax_$(type.fcn)($vlen) - - IO Type - type - enum - - - - - - Num Inputs - num_inputs - 2 - int - - - Vec Length - vlen - 1 - int - - $num_inputs >= 2 - $vlen >= 1 - - in - $type - $vlen - $num_inputs - - - out - short - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_binary_slicer_fb.xml b/grc/data/grc_gnuradio/blocks/gr_binary_slicer_fb.xml deleted file mode 100644 index 85d71e70..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_binary_slicer_fb.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - Binary Slicer - gr_binary_slicer_fb - from gnuradio import gr - gr.binary_slicer_fb() - - in - float - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_char_to_float.xml b/grc/data/grc_gnuradio/blocks/gr_char_to_float.xml deleted file mode 100644 index 9ab77805..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_char_to_float.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - Char To Float - gr_char_to_float - from gnuradio import gr - gr.char_to_float() - - in - byte - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/gr_chunks_to_symbols.xml b/grc/data/grc_gnuradio/blocks/gr_chunks_to_symbols.xml deleted file mode 100644 index b54e710e..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_chunks_to_symbols.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - Chunks to Symbols - gr_chunks_to_symbols_xx - from gnuradio import gr - gr.chunks_to_symbols_$(in_type.fcn)$(out_type.fcn)($symbol_table, $dimension) - - Input Type - in_type - enum - - - - - - Output Type - out_type - enum - - - - - Symbol Table - symbol_table - $out_type.table - - - Dimension - dimension - 2 - int - - - in - $in_type - - - out - $out_type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_clock_recovery_mm_xx.xml b/grc/data/grc_gnuradio/blocks/gr_clock_recovery_mm_xx.xml deleted file mode 100644 index 613cc23b..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_clock_recovery_mm_xx.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - Clock Recovery MM - gr_clock_recovery_mm_xx - from gnuradio import gr - gr.clock_recovery_mm_$(type.fcn)($omega, $gain_omega, $mu, $gain_mu, $omega_relative_limit) - set_omega($omega) - set_gain_omega($gain_omega) - set_mu($mu) - set_gain_mu($gain_mu) - - Type - type - enum - - - - - Omega - omega - real - - - Gain Omega - gain_omega - real - - - Mu - mu - real - - - Gain Mu - gain_mu - real - - - Omega Relative Limit - omega_relative_limit - real - - - in - $type - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_cma_equalizer_cc.xml b/grc/data/grc_gnuradio/blocks/gr_cma_equalizer_cc.xml deleted file mode 100644 index 142fb6d8..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_cma_equalizer_cc.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - CMA Equalizer - gr_cma_equalizer_cc - from gnuradio import gr - gr.cma_equalizer_cc($num_taps, $modulus, $mu) - - Num Taps - num_taps - 64 - int - - - Modulus - modulus - real - - - Mu - mu - real - - - in - complex - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_complex_to_arg.xml b/grc/data/grc_gnuradio/blocks/gr_complex_to_arg.xml deleted file mode 100644 index a7bbacd7..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_complex_to_arg.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - Complex to Arg - gr_complex_to_arg - from gnuradio import gr - gr.complex_to_arg($vlen) - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - complex - $vlen - - - out - float - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_complex_to_float.xml b/grc/data/grc_gnuradio/blocks/gr_complex_to_float.xml deleted file mode 100644 index 5b02c3d3..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_complex_to_float.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - Complex To Float - gr_complex_to_float - from gnuradio import gr - gr.complex_to_float($vlen) - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - complex - $vlen - - - out - float - $vlen - - - out - float - $vlen - 1 - - diff --git a/grc/data/grc_gnuradio/blocks/gr_complex_to_imag.xml b/grc/data/grc_gnuradio/blocks/gr_complex_to_imag.xml deleted file mode 100644 index 7c120eed..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_complex_to_imag.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - Complex to Imag - gr_complex_to_imag - from gnuradio import gr - gr.complex_to_imag($vlen) - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - complex - $vlen - - - out - float - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_complex_to_interleaved_short.xml b/grc/data/grc_gnuradio/blocks/gr_complex_to_interleaved_short.xml deleted file mode 100644 index 5e999599..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_complex_to_interleaved_short.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - Complex To IShort - gr_complex_to_interleaved_short - from gnuradio import gr - gr.complex_to_interleaved_short() - - in - complex - - - out - short - - diff --git a/grc/data/grc_gnuradio/blocks/gr_complex_to_mag.xml b/grc/data/grc_gnuradio/blocks/gr_complex_to_mag.xml deleted file mode 100644 index adc95f20..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_complex_to_mag.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - Complex to Mag - gr_complex_to_mag - from gnuradio import gr - gr.complex_to_mag($vlen) - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - complex - $vlen - - - out - float - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_complex_to_mag_squared.xml b/grc/data/grc_gnuradio/blocks/gr_complex_to_mag_squared.xml deleted file mode 100644 index cd23bfb5..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_complex_to_mag_squared.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - Complex to Mag^2 - gr_complex_to_mag_squared - from gnuradio import gr - gr.complex_to_mag_squared($vlen) - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - complex - $vlen - - - out - float - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_complex_to_real.xml b/grc/data/grc_gnuradio/blocks/gr_complex_to_real.xml deleted file mode 100644 index ae9ec7b1..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_complex_to_real.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - Complex to Real - gr_complex_to_real - from gnuradio import gr - gr.complex_to_real($vlen) - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - complex - $vlen - - - out - float - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_conjugate_cc.xml b/grc/data/grc_gnuradio/blocks/gr_conjugate_cc.xml deleted file mode 100644 index 0b4deb34..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_conjugate_cc.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - Complex Conjugate - gr_conjugate_cc - from gnuradio import gr - gr.conjugate_cc() - - in - complex - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_constellation_decoder_cb.xml b/grc/data/grc_gnuradio/blocks/gr_constellation_decoder_cb.xml deleted file mode 100644 index 99d897a3..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_constellation_decoder_cb.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - Constellation Decoder - gr_constellation_decoder_cb - from gnuradio import gr - gr.constellation_decoder_cb($sym_position, $sym_value_out) - - Symbol Position - sym_position - complex_vector - - - Symbol Value Out - sym_value_out - int_vector - - - in - complex - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_correlate_access_code_bb.xml b/grc/data/grc_gnuradio/blocks/gr_correlate_access_code_bb.xml deleted file mode 100644 index e13d2d07..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_correlate_access_code_bb.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - Correlate Access Code - gr_correlate_access_code_bb - from gnuradio import gr - gr.correlate_access_code_bb($access_code, $threshold) - - Access Code - access_code - 101010 - string - - - Threshold - threshold - int - - - in - byte - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_costas_loop_cc.xml b/grc/data/grc_gnuradio/blocks/gr_costas_loop_cc.xml deleted file mode 100644 index e0db8bc5..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_costas_loop_cc.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - Costas Loop - gr_costas_loop_cc - from gnuradio import gr - gr.costas_loop_cc($alpha, $beta, $max_freq, $min_freq, $order) - set_alpha($alpha) - set_beta($beta) - - Alpha - alpha - real - - - Beta - beta - real - - - Max Freq - max_freq - real - - - Min Freq - min_freq - real - - - Order - order - int - - - in - complex - - - out - complex - - - out - complex - 1 - - diff --git a/grc/data/grc_gnuradio/blocks/gr_cpfsk_bc.xml b/grc/data/grc_gnuradio/blocks/gr_cpfsk_bc.xml deleted file mode 100644 index 12450b0c..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_cpfsk_bc.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - CPFSK - gr_cpfsk_bc - from gnuradio import gr - cpfsk_bc($k, $amplitude, $samples_per_symbol) - set_amplitude($amplitude) - - K - k - real - - - Amplitude - amplitude - real - - - Samples/Symbol - samples_per_symbol - 2 - int - - - in - byte - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_dd_mpsk_sync_cc.xml b/grc/data/grc_gnuradio/blocks/gr_dd_mpsk_sync_cc.xml deleted file mode 100644 index aed0e8d3..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_dd_mpsk_sync_cc.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - DD MPSK Sync - gr_dd_mpsk_sync_cc - from gnuradio import gr - gr.dd_mpsk_sync_cc($alpha, $beta, $max_freq, $min_freq, $ref_phase, $omega, $gain_omega, $mu, $gain_mu) - - Alpha - alpha - real - - - Beta - beta - real - - - Max Freq - max_freq - real - - - Min Freq - min_freq - real - - - Reference Phase - ref_phase - real - - - Omega - omega - real - - - Gain Omega - gain_omega - real - - - Mu - mu - real - - - Gain Mu - gain_mu - real - - - in - complex - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_decode_ccsds_27_fb.xml b/grc/data/grc_gnuradio/blocks/gr_decode_ccsds_27_fb.xml deleted file mode 100644 index 03b31db8..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_decode_ccsds_27_fb.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - Decode CCSDS 27 - gr_decode_ccsds_27_fb - from gnuradio import gr - gr.decode_ccsds_27_fb() - - in - float - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_deinterleave.xml b/grc/data/grc_gnuradio/blocks/gr_deinterleave.xml deleted file mode 100644 index a7482978..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_deinterleave.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - Deinterleave - gr_deinterleave - from gnuradio import gr - gr.deinterleave($type.size*$vlen) - - IO Type - type - enum - - - - - - - - Num Streams - num_streams - 2 - int - - - Vec Length - vlen - 1 - int - - $num_streams > 0 - $vlen >= 1 - - in - $type - $vlen - - - out - $type - $vlen - $num_streams - - diff --git a/grc/data/grc_gnuradio/blocks/gr_delay.xml b/grc/data/grc_gnuradio/blocks/gr_delay.xml deleted file mode 100644 index b9d42979..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_delay.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - Delay - gr_delay - from gnuradio import gr - gr.head($type.size*$vlen, $delay) - - Type - type - enum - - - - - - - - Delay - delay - 0 - int - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_diff_decoder_bb.xml b/grc/data/grc_gnuradio/blocks/gr_diff_decoder_bb.xml deleted file mode 100644 index ea7cf173..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_diff_decoder_bb.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - Differential Decoder - gr_diff_decoder_bb - from gnuradio import gr - gr.diff_decoder_bb($modulus) - - Modulus - modulus - int - - - in - byte - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_diff_encoder_bb.xml b/grc/data/grc_gnuradio/blocks/gr_diff_encoder_bb.xml deleted file mode 100644 index 21241eac..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_diff_encoder_bb.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - Differential Encoder - gr_diff_encoder_bb - from gnuradio import gr - gr.diff_encoder_bb($modulus) - - Modulus - modulus - int - - - in - byte - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_diff_phasor_cc.xml b/grc/data/grc_gnuradio/blocks/gr_diff_phasor_cc.xml deleted file mode 100644 index 2b2d7e37..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_diff_phasor_cc.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - Differential Phasor - gr_diff_phasor_cc - from gnuradio import gr - gr.diff_phasor_cc() - - in - complex - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_divide_xx.xml b/grc/data/grc_gnuradio/blocks/gr_divide_xx.xml deleted file mode 100644 index 7f875291..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_divide_xx.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - Divide - gr_divide_xx - from gnuradio import gr - gr.divide_$(type.fcn)() - - IO Type - type - enum - - - - - - - Num Inputs - num_inputs - 2 - int - - $num_inputs >= 2 - - in - $type - $num_inputs - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_dpll_bb.xml b/grc/data/grc_gnuradio/blocks/gr_dpll_bb.xml deleted file mode 100644 index 044d398f..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_dpll_bb.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - Detect Peak - gr_dpll_bb - from gnuradio import gr - gr.dpll_bb($period, $gain) - - Period - period - real - - - Gain - gain - real - - - in - byte - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_encode_ccsds_27_bb.xml b/grc/data/grc_gnuradio/blocks/gr_encode_ccsds_27_bb.xml deleted file mode 100644 index f31e6b6c..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_encode_ccsds_27_bb.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - Encode CCSDS 27 - gr_encode_ccsds_27_bb - from gnuradio import gr - gr.encode_ccsds_27_bb() - - in - byte - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_feedforward_agc_cc.xml b/grc/data/grc_gnuradio/blocks/gr_feedforward_agc_cc.xml deleted file mode 100644 index 24e80953..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_feedforward_agc_cc.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - Feed Forward AGC - gr_feedforward_agc_cc - from gnuradio import gr - gr.feedforward_agc_cc($num_samples, $reference) - - Num Samples - num_samples - 1024 - int - - - Reference - reference - 1.0 - real - - - in - complex - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_fft_filter_xxx.xml b/grc/data/grc_gnuradio/blocks/gr_fft_filter_xxx.xml deleted file mode 100644 index c1633094..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_fft_filter_xxx.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - FFT Filter - gr_fft_filter_xxx - from gnuradio import gr - from gnuradio.gr import firdes - gr.fft_filter_$(type)($decim, $taps) - set_taps($taps) - - Type - type - enum - - - - - Decimation - decim - 1 - int - - - Taps - taps - $type.taps - - - in - $type.input - - - out - $type.output - - diff --git a/grc/data/grc_gnuradio/blocks/gr_fft_vxx.xml b/grc/data/grc_gnuradio/blocks/gr_fft_vxx.xml deleted file mode 100644 index c2c13d0a..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_fft_vxx.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - FFT - gr_fft_vxx - from gnuradio import gr - from gnuradio import window - #if $type.eval == "complex" -gr.fft_vcc($fft_size, $forward, $window, $shift) -#else -gr.fft_vfc($fft_size, $forward, $window) -#end if - - Input Type - type - enum - - - - - FFT Size - fft_size - 1024 - int - - - Forward/Reverse - forward - enum - - - - - Window - window - window.blackmanharris(1024) - real_vector - - - Shift - shift - enum - $type.hide_shift - - - - - in - $type - $fft_size - - - out - complex - $fft_size - - diff --git a/grc/data/grc_gnuradio/blocks/gr_file_sink.xml b/grc/data/grc_gnuradio/blocks/gr_file_sink.xml deleted file mode 100644 index 880dc275..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_file_sink.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - File Sink - gr_file_sink - from gnuradio import gr - gr.file_sink($type.size*$vlen, $file) - - File - file - - file_save - - - Input Type - type - enum - - - - - - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_file_source.xml b/grc/data/grc_gnuradio/blocks/gr_file_source.xml deleted file mode 100644 index fcc7a704..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_file_source.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - File Source - gr_file_source - from gnuradio import gr - gr.file_source($type.size*$vlen, $file, $repeat) - - File - file - - file_open - - - Output Type - type - enum - - - - - - - - Repeat - repeat - True - enum - - - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_filter_delay_fc.xml b/grc/data/grc_gnuradio/blocks/gr_filter_delay_fc.xml deleted file mode 100644 index 30d65bf8..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_filter_delay_fc.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - Filter Delay - gr_filter_delay_fc - from gnuradio import gr - from gnuradio.gr import firdes - gr.filter_delay_fc($taps) - - Taps - taps - real_vector - - - in - float - - - in - float - 1 - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_fir_filter_xxx.xml b/grc/data/grc_gnuradio/blocks/gr_fir_filter_xxx.xml deleted file mode 100644 index c4de8f53..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_fir_filter_xxx.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - Decimating FIR Filter - gr_fir_filter_xxx - from gnuradio import gr - from gnuradio.gr import firdes - gr.fir_filter_$(type)($decim, $taps) - set_taps($taps) - - Type - type - enum - - - - - - - - - Decimation - decim - 1 - int - - - Taps - taps - $type.taps - - - in - $type.input - - - out - $type.output - - diff --git a/grc/data/grc_gnuradio/blocks/gr_float_to_char.xml b/grc/data/grc_gnuradio/blocks/gr_float_to_char.xml deleted file mode 100644 index 5714130a..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_float_to_char.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - Float To Char - gr_float_to_char - from gnuradio import gr - gr.gr_float_to_char() - - in - float - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_float_to_complex.xml b/grc/data/grc_gnuradio/blocks/gr_float_to_complex.xml deleted file mode 100644 index e8734fc6..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_float_to_complex.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - Float To Complex - gr_float_to_complex - from gnuradio import gr - gr.float_to_complex() - - in - float - - - in - float - 1 - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_float_to_short.xml b/grc/data/grc_gnuradio/blocks/gr_float_to_short.xml deleted file mode 100644 index cb2bcd4b..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_float_to_short.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - Float To Short - gr_float_to_short - from gnuradio import gr - gr.float_to_short() - - in - float - - - out - short - - diff --git a/grc/data/grc_gnuradio/blocks/gr_float_to_uchar.xml b/grc/data/grc_gnuradio/blocks/gr_float_to_uchar.xml deleted file mode 100644 index aa804d7d..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_float_to_uchar.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - Float To UChar - gr_float_to_uchar - from gnuradio import gr - gr.float_to_uchar() - - in - float - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_fractional_interpolator_xx.xml b/grc/data/grc_gnuradio/blocks/gr_fractional_interpolator_xx.xml deleted file mode 100644 index 8d65ff8b..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_fractional_interpolator_xx.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - Fractional Interpolator - gr_fractional_interpolator_xx - from gnuradio import gr - gr.fractional_interpolator_$(type.fcn)($phase_shift, $interp_ratio) - set_interp_ratio($interp_ratio) - - Type - type - enum - - - - - Phase Shift - phase_shift - real - - - Interpolation Ratio - interp_ratio - real - - - in - $type - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_freq_xlating_fir_filter_xxx.xml b/grc/data/grc_gnuradio/blocks/gr_freq_xlating_fir_filter_xxx.xml deleted file mode 100644 index e3ee6697..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_freq_xlating_fir_filter_xxx.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - Frequency Xlating FIR Filter - gr_freq_xlating_fir_filter_xxx - from gnuradio import gr - from gnuradio.gr import firdes - gr.freq_xlating_fir_filter_$(type)($decim, $taps, $center_freq, $samp_rate) - set_taps($taps) - set_center_freq($center_freq) - - Type - type - enum - - - - - - - - - Decimation - decim - 1 - int - - - Taps - taps - $type.taps - - - Center Frequency - center_freq - 0 - real - - - Sample Rate - samp_rate - samp_rate - real - - - in - $type.input - - - out - $type.output - - diff --git a/grc/data/grc_gnuradio/blocks/gr_frequency_modulator_fc.xml b/grc/data/grc_gnuradio/blocks/gr_frequency_modulator_fc.xml deleted file mode 100644 index f18d9f1e..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_frequency_modulator_fc.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - Frequency Mod - gr_frequency_modulator_fc - from gnuradio import gr - gr.frequency_modulator_fc($sensitivity) - - Sensitivity - sensitivity - real - - - in - float - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_glfsr_source_x.xml b/grc/data/grc_gnuradio/blocks/gr_glfsr_source_x.xml deleted file mode 100644 index 88fb6679..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_glfsr_source_x.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - GLFSR Source - gr_glfsr_source_x - from gnuradio import gr - gr.glfsr_source_$(type.fcn)($degree, $repeat, $mask, $seed) - - Type - type - enum - - - - - Degree - degree - int - - - Repeat - repeat - enum - - - - - Mask - mask - int - - - Seed - seed - int - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_goertzel_fc.xml b/grc/data/grc_gnuradio/blocks/gr_goertzel_fc.xml deleted file mode 100644 index 2105445d..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_goertzel_fc.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - Goertzel - gr_goertzel_fc - from gnuradio import gr - gr.goertzel_fc($rate, $len, $freq) - - Rate - rate - int - - - Length - len - int - - - Frequency - freq - real - - - in - float - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_head.xml b/grc/data/grc_gnuradio/blocks/gr_head.xml deleted file mode 100644 index e5ff7f6a..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_head.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - Head - gr_head - from gnuradio import gr - gr.head($type.size*$vlen, $num_items) - - Type - type - enum - - - - - - - - Num Items - num_items - 1024 - int - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_hilbert_fc.xml b/grc/data/grc_gnuradio/blocks/gr_hilbert_fc.xml deleted file mode 100644 index 165e8da2..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_hilbert_fc.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - Hilbert - gr_hilbert_fc - from gnuradio import gr - gr.hilbert_fc($num_taps) - - Num Taps - num_taps - 64 - int - - - in - float - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_iir_filter_ffd.xml b/grc/data/grc_gnuradio/blocks/gr_iir_filter_ffd.xml deleted file mode 100644 index 9799150e..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_iir_filter_ffd.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - IIR Filter - gr_iir_filter_ffd - from gnuradio import gr - gr.iir_filter_ffd($fftaps, $fbtaps) - set_taps($fftaps, $fbtaps) - - Feed-forward Taps - fftaps - real_vector - - - Feedback Taps - fbtaps - real_vector - - - in - float - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/gr_integrate_xx.xml b/grc/data/grc_gnuradio/blocks/gr_integrate_xx.xml deleted file mode 100644 index d0ebd42e..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_integrate_xx.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - Integrate - gr_integrate_xx - from gnuradio import gr - gr.integrate_$(type.fcn)($decim) - - IO Type - type - enum - - - - - - - Decimation - decim - int - - - in - $type - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_interleave.xml b/grc/data/grc_gnuradio/blocks/gr_interleave.xml deleted file mode 100644 index 3db16ab5..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_interleave.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - Interleave - gr_interleave - from gnuradio import gr - gr.interleave($type.size*$vlen) - - IO Type - type - enum - - - - - - - - Num Streams - num_streams - 2 - int - - - Vec Length - vlen - 1 - int - - $num_streams > 0 - $vlen >= 1 - - in - $type - $vlen - $num_streams - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_interleaved_short_to_complex.xml b/grc/data/grc_gnuradio/blocks/gr_interleaved_short_to_complex.xml deleted file mode 100644 index e3023e49..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_interleaved_short_to_complex.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - IShort To Complex - gr_interleaved_short_to_complex - from gnuradio import gr - gr.interleaved_short_to_complex() - - in - short - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_interp_fir_filter_xxx.xml b/grc/data/grc_gnuradio/blocks/gr_interp_fir_filter_xxx.xml deleted file mode 100644 index 55375ae0..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_interp_fir_filter_xxx.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - Interpolating FIR Filter - gr_interp_fir_filter_xxx - from gnuradio import gr - from gnuradio.gr import firdes - gr.interp_fir_filter_$(type)($interp, $taps) - set_taps($taps) - - Type - type - enum - - - - - - - - - Interpolation - interp - 1 - int - - - Taps - taps - $type.taps - - - in - $type.input - - - out - $type.output - - diff --git a/grc/data/grc_gnuradio/blocks/gr_iqcomp_cc.xml b/grc/data/grc_gnuradio/blocks/gr_iqcomp_cc.xml deleted file mode 100644 index 1603bdc4..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_iqcomp_cc.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - IQ Comp - gr_iqcomp_cc - from gnuradio import gr - gr.iqcomp_cc($mu) - - Mu - mu - real - - - in - complex - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_keep_one_in_n.xml b/grc/data/grc_gnuradio/blocks/gr_keep_one_in_n.xml deleted file mode 100644 index 21595b75..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_keep_one_in_n.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - Keep 1 in N - gr_keep_one_in_n - from gnuradio import gr - gr.keep_one_in_n($type.size*$vlen, $n) - set_n($n) - - Type - type - enum - - - - - - - - N - n - 1 - int - - - Vec Length - vlen - 1 - int - - $n > 0 - $vlen > 0 - - in - $type - $vlen - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_kludge_copy.xml b/grc/data/grc_gnuradio/blocks/gr_kludge_copy.xml deleted file mode 100644 index 3c817c57..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_kludge_copy.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - Copy - gr_kludge_copy - from gnuradio import gr - gr.kludge_copy($type.size*$vlen) - - Type - type - enum - - - - - - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_map_bb.xml b/grc/data/grc_gnuradio/blocks/gr_map_bb.xml deleted file mode 100644 index 20d6bd2b..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_map_bb.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - Map - gr_map_bb - from gnuradio import gr - gr.map_bb($map) - - Map - map - int_vector - - - in - byte - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_max_xx.xml b/grc/data/grc_gnuradio/blocks/gr_max_xx.xml deleted file mode 100644 index 9dbbe60e..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_max_xx.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - Max - gr_max_xx - from gnuradio import gr - gr.max_$(type.fcn)($vlen) - - IO Type - type - enum - - - - - - Num Inputs - num_inputs - 2 - int - - - Vec Length - vlen - 1 - int - - $num_inputs >= 2 - $vlen >= 1 - - in - $type - $vlen - $num_inputs - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_moving_average_xx.xml b/grc/data/grc_gnuradio/blocks/gr_moving_average_xx.xml deleted file mode 100644 index 2c3be403..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_moving_average_xx.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - Moving Average - gr_moving_average_xx - from gnuradio import gr - gr.moving_average_$(type.fcn)($length, $scale, $max_iter) - - Type - type - enum - - - - - - - Length - length - 1000 - int - - - Scale - scale - 1 - $type.scale - - - Max Iter - max_iter - 4000 - int - - - in - $type - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_mpsk_receiver_cc.xml b/grc/data/grc_gnuradio/blocks/gr_mpsk_receiver_cc.xml deleted file mode 100644 index 843c3a4c..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_mpsk_receiver_cc.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - MPSK Receiver - gr_mpsk_receiver_cc - from gnuradio import gr - gr.mpsk_receiver_cc($M, $theta, $alpha, $beta, $fmin, $fmax, $mu, $gain_mu, $omega, $gain_omega, $omega_relative_limit) - set_alpha($alpha) - set_beta($beta) - set_mu($mu) - set_gain_mu($gain_mu) - set_omega($omega) - set_gain_omega($gain_omega) - - M - M - int - - - Theta - theta - real - - - Alpha - alpha - real - - - Beta - beta - real - - - Min Freq - fmin - real - - - Max Freq - fmax - real - - - Mu - mu - real - - - Gain Mu - gain_mu - real - - - Omega - omega - real - - - Gain Omega - gain_omega - real - - - Omega Relative Limit - omega_relative_limit - real - - - in - complex - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_mpsk_sync_cc.xml b/grc/data/grc_gnuradio/blocks/gr_mpsk_sync_cc.xml deleted file mode 100644 index fd08f834..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_mpsk_sync_cc.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - MPSK Sync - gr_mpsk_sync_cc - from gnuradio import gr - gr.mpsk_sync_cc($alpha, $beta, $max_freq, $min_freq, $ref_phase, $omega, $gain_omega, $mu, $gain_mu) - set_mu($mu) - set_gain_mu($gain_mu) - set_omega($omega) - set_gain_omega($gain_omega) - - Alpha - alpha - real - - - Beta - beta - real - - - Max Freq - max_freq - real - - - Min Freq - min_freq - real - - - Reference Phase - ref_phase - real - - - Omega - omega - real - - - Gain Omega - gain_omega - real - - - Mu - mu - real - - - Gain Mu - gain_mu - real - - - in - complex - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_multiply_const_vxx.xml b/grc/data/grc_gnuradio/blocks/gr_multiply_const_vxx.xml deleted file mode 100644 index 1309d75c..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_multiply_const_vxx.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - Multiply Const - gr_multiply_const_vxx - from gnuradio import gr - gr.multiply_const_v$(type.fcn)($const) - set_k($const) - - IO Type - type - enum - - - - - - - Constant - const - 0 - $type.const_type - - - Vec Length - vlen - 1 - int - - len($const) == $vlen - $vlen > 0 - - in - $type - $vlen - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_multiply_vxx.xml b/grc/data/grc_gnuradio/blocks/gr_multiply_vxx.xml deleted file mode 100644 index ea0d555b..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_multiply_vxx.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - Multiply - gr_multiply_vxx - from gnuradio import gr - gr.multiply_v$(type.fcn)($vlen) - - IO Type - type - enum - - - - - - - Num Inputs - num_inputs - 2 - int - - - Vec Length - vlen - 1 - int - - $num_inputs > 1 - $vlen > 0 - - in - $type - $vlen - $num_inputs - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_mute_xx.xml b/grc/data/grc_gnuradio/blocks/gr_mute_xx.xml deleted file mode 100644 index 668d7c59..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_mute_xx.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - Mute - gr_mute_xx - from gnuradio import gr - gr.mute_$(type.fcn)(bool($mute)) - set_mute(bool($mute)) - - IO Type - type - enum - - - - - - - Mute - mute - False - raw - - - in - $type - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_nlog10_ff.xml b/grc/data/grc_gnuradio/blocks/gr_nlog10_ff.xml deleted file mode 100644 index 93507823..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_nlog10_ff.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - Log10 - gr_nlog10_ff - from gnuradio import gr - gr.nlog10_ff($n, $vlen, $k) - - n - n - 1 - real - - - k - k - 0 - real - - - Vec Length - vlen - 1 - int - - $vlen >= 1 - - in - float - $vlen - - - out - float - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_noise_source_x.xml b/grc/data/grc_gnuradio/blocks/gr_noise_source_x.xml deleted file mode 100644 index 664a108d..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_noise_source_x.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - Noise Source - gr_noise_source_x - from gnuradio import gr - gr.noise_source_$(type.fcn)($noise_type, $amp, $seed) - set_amplitude($amp) - - Output Type - type - enum - - - - - - - Noise Type - noise_type - gr.GR_GAUSSIAN - enum - - - - - - - Amplitude - amp - 1 - real - - - Seed - seed - 42 - int - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_nop.xml b/grc/data/grc_gnuradio/blocks/gr_nop.xml deleted file mode 100644 index 127a78a5..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_nop.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - Nop - gr_nop - from gnuradio import gr - gr.nop($type.size*$vlen) - - Type - type - enum - - - - - - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_not_xx.xml b/grc/data/grc_gnuradio/blocks/gr_not_xx.xml deleted file mode 100644 index 7af7e4b6..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_not_xx.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - Not - gr_not_xx - from gnuradio import gr - gr.not_$(type.fcn)() - - IO Type - type - enum - - - - - - Num Inputs - num_inputs - 2 - int - - $num_inputs >= 2 - - in - $type - $num_inputs - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_null_sink.xml b/grc/data/grc_gnuradio/blocks/gr_null_sink.xml deleted file mode 100644 index ed106b49..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_null_sink.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - Null Sink - gr_null_sink - from gnuradio import gr - gr.null_sink($type.size*$vlen) - - Input Type - type - enum - - - - - - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_null_source.xml b/grc/data/grc_gnuradio/blocks/gr_null_source.xml deleted file mode 100644 index 6132eae3..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_null_source.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - Null Source - gr_null_source - from gnuradio import gr - gr.null_source($type.size*$vlen) - - Output Type - type - enum - - - - - - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_or_xx.xml b/grc/data/grc_gnuradio/blocks/gr_or_xx.xml deleted file mode 100644 index b374aa22..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_or_xx.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - Or - gr_or_xx - from gnuradio import gr - gr.or_$(type.fcn)() - - IO Type - type - enum - - - - - - Num Inputs - num_inputs - 2 - int - - $num_inputs >= 2 - - in - $type - $num_inputs - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_packed_to_unpacked_xx.xml b/grc/data/grc_gnuradio/blocks/gr_packed_to_unpacked_xx.xml deleted file mode 100644 index 5fd9729a..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_packed_to_unpacked_xx.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - Packed to Unpacked - gr_packed_to_unpacked_xx - from gnuradio import gr - gr.packed_to_unpacked_$(type.fcn)($bits_per_chunk, $endianness) - - Type - type - enum - - - - - - Bits per Chunk - bits_per_chunk - 2 - int - - - Endianness - endianness - enum - - - - - in - $type - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_peak_detector2_fb.xml b/grc/data/grc_gnuradio/blocks/gr_peak_detector2_fb.xml deleted file mode 100644 index 6c496da7..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_peak_detector2_fb.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - Peak Detector2 - gr_peak_detector2_fb - from gnuradio import gr - gr.peak_detector2_fb($threshold_factor_rise, $look_ahead, $alpha) - set_threshold_factor_rise($threshold_factor_rise) - set_look_ahead($look_ahead) - set_alpha($alpha) - - Input Type - type - enum - - - - - - TH Factor Rise - threshold_factor_rise - real - - - Look Ahead - look_ahead - int - - - Alpha - alpha - real - - - in - float - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_peak_detector_xb.xml b/grc/data/grc_gnuradio/blocks/gr_peak_detector_xb.xml deleted file mode 100644 index 394b0697..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_peak_detector_xb.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - Peak Detector - gr_peak_detector_xb - from gnuradio import gr - gr.peak_detector_$(type.fcn)b($threshold_factor_rise, $threshold_factor_fall, $look_ahead, $alpha) - set_threshold_factor_rise($threshold_factor_rise) - set_threshold_factor_fall($threshold_factor_fall) - set_look_ahead($look_ahead) - set_alpha($alpha) - - Input Type - type - enum - - - - - - TH Factor Rise - threshold_factor_rise - real - - - TH Factor Fall - threshold_factor_fall - real - - - Look Ahead - look_ahead - int - - - Alpha - alpha - real - - - in - $type - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_phase_modulator_fc.xml b/grc/data/grc_gnuradio/blocks/gr_phase_modulator_fc.xml deleted file mode 100644 index 758c5086..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_phase_modulator_fc.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - Phase Mod - gr_phase_modulator_fc - from gnuradio import gr - gr.phase_modulator_fc($sensitivity) - - Sensitivity - sensitivity - real - - - in - float - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_pll_carriertracking_cc.xml b/grc/data/grc_gnuradio/blocks/gr_pll_carriertracking_cc.xml deleted file mode 100644 index 5b876b25..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_pll_carriertracking_cc.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - PLL Carrier Tracking - gr_pll_carriertracking_cc - from gnuradio import gr - gr.pll_carriertracking_cc($alpha, $beta, $max_freq, $min_freq) - - Alpha - alpha - real - - - Beta - beta - real - - - Max Freq - max_freq - real - - - Min Freq - min_freq - real - - - in - complex - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_pll_freqdet_cf.xml b/grc/data/grc_gnuradio/blocks/gr_pll_freqdet_cf.xml deleted file mode 100644 index 8ec1fb3b..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_pll_freqdet_cf.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - PLL Freq Det - gr_pll_freqdet_cf - from gnuradio import gr - gr.pll_freqdet_cf($alpha, $beta, $max_freq, $min_freq) - - Alpha - alpha - real - - - Beta - beta - real - - - Max Freq - max_freq - real - - - Min Freq - min_freq - real - - - in - complex - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/gr_pll_refout_cc.xml b/grc/data/grc_gnuradio/blocks/gr_pll_refout_cc.xml deleted file mode 100644 index 64cf2bfb..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_pll_refout_cc.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - PLL Ref Out - gr_pll_refout_cc - from gnuradio import gr - gr.pll_refout_cc($alpha, $beta, $max_freq, $min_freq) - - Alpha - alpha - real - - - Beta - beta - real - - - Max Freq - max_freq - real - - - Min Freq - min_freq - real - - - in - complex - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_pn_correlator_cc.xml b/grc/data/grc_gnuradio/blocks/gr_pn_correlator_cc.xml deleted file mode 100644 index 094f46cd..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_pn_correlator_cc.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - PN Correlator - gr_pn_correlator_cc - from gnuradio import gr - gr.pn_correlator_cc($degree, $mask, $seed) - - Degree - degree - int - - - Mask - mask - int - - - Seed - seed - int - - - in - complex - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_pwr_squelch_xx.xml b/grc/data/grc_gnuradio/blocks/gr_pwr_squelch_xx.xml deleted file mode 100644 index 08d62117..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_pwr_squelch_xx.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - Power Squelch - gr_pwr_squelch_xx - from gnuradio import gr - gr.pwr_squelch_$(type.fcn)($threshold, $alpha, $ramp, $gate) - set_threshold($threshold) - set_alpha($alpha) - - Type - type - enum - - - - - Threshold (dB) - threshold - real - - - Alpha - alpha - real - - - Ramp - ramp - int - - - Gate - gate - enum - - - - - in - $type - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_quadrature_demod_cf.xml b/grc/data/grc_gnuradio/blocks/gr_quadrature_demod_cf.xml deleted file mode 100644 index a0e630c7..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_quadrature_demod_cf.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - Quadrature Demod - gr_quadrature_demod_cf - from gnuradio import gr - gr.quadrature_demod_cf($gain) - - Gain - gain - real - - - in - complex - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/gr_rational_resampler_base_xxx.xml b/grc/data/grc_gnuradio/blocks/gr_rational_resampler_base_xxx.xml deleted file mode 100644 index 4b772017..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_rational_resampler_base_xxx.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - Rational Resampler Base - gr_rational_resampler_base_xxx - from gnuradio import gr - from gnuradio.gr import firdes - gr.rational_resampler_base_$(type)($interp, $decim, $taps) - set_taps($taps) - - Type - type - enum - - - - - - - - - Interpolation - interp - 1 - int - - - Decimation - decim - 1 - int - - - Taps - taps - $type.taps - - - in - $type.input - - - out - $type.output - - diff --git a/grc/data/grc_gnuradio/blocks/gr_repeat.xml b/grc/data/grc_gnuradio/blocks/gr_repeat.xml deleted file mode 100644 index ba652a4d..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_repeat.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - Repeat - gr_repeat - from gnuradio import gr - gr.repeat($type.size*$vlen, $interp) - - Type - type - enum - - - - - - - - Interpolation - interp - int - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_rms_xx.xml b/grc/data/grc_gnuradio/blocks/gr_rms_xx.xml deleted file mode 100644 index 1e094719..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_rms_xx.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - RMS - gr_rms_xx - from gnuradio import gr - gr.rms_$(type.fcn)f($alpha) - set_alpha($alpha) - - Input Type - type - enum - - - - - Alpha - alpha - real - - - in - $type - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/gr_sample_and_hold_xx.xml b/grc/data/grc_gnuradio/blocks/gr_sample_and_hold_xx.xml deleted file mode 100644 index bfe66bb0..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_sample_and_hold_xx.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - Sample and Hold - gr_sample_and_hold_xx - from gnuradio import gr - gr.sample_and_hold_$(type.fcn)() - - Type - type - enum - - - - - - - in - $type - - - ctrl - $type - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_short_to_float.xml b/grc/data/grc_gnuradio/blocks/gr_short_to_float.xml deleted file mode 100644 index 8dac97c0..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_short_to_float.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - Short To Float - gr_short_to_float - from gnuradio import gr - gr.short_to_float() - - in - short - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/gr_sig_source_x.xml b/grc/data/grc_gnuradio/blocks/gr_sig_source_x.xml deleted file mode 100644 index 7ad0c20a..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_sig_source_x.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - Signal Source - gr_sig_source_x - from gnuradio import gr - gr.sig_source_$(type.fcn)($samp_rate, $waveform, $freq, $amp, $offset) - set_sampling_freq($samp_rate) - set_frequency($freq) - set_amplitude($amp) - set_offset($offset) - - Output Type - type - enum - - - - - - - Sample Rate - samp_rate - samp_rate - real - - - Waveform - waveform - gr.GR_COS_WAVE - enum - - - - - - - - - Frequency - freq - 1000 - real - - - Amplitude - amp - 1 - real - - - Offset - offset - 0 - complex - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_simple_correlator.xml b/grc/data/grc_gnuradio/blocks/gr_simple_correlator.xml deleted file mode 100644 index 820523a6..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_simple_correlator.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - Simple Correlator - gr_simple_correlator - from gnuradio import gr - gr.simple_correlator($payload_bytesize) - - Payload Byte Size - payload_bytesize - int - - - in - float - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_simple_framer.xml b/grc/data/grc_gnuradio/blocks/gr_simple_framer.xml deleted file mode 100644 index 2a0295c4..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_simple_framer.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - Simple Framer - gr_simple_framer - from gnuradio import gr - gr.simple_framer($payload_bytesize) - - Payload Byte Size - payload_bytesize - int - - - in - byte - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_simple_squelch_cc.xml b/grc/data/grc_gnuradio/blocks/gr_simple_squelch_cc.xml deleted file mode 100644 index 5c0727f5..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_simple_squelch_cc.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - Simple Squelch - gr_simple_squelch_cc - from gnuradio import gr - gr.simple_squelch_cc($threshold, $alpha) - set_threshold($threshold) - set_alpha($alpha) - - Threshold (dB) - threshold - real - - - Alpha - alpha - real - - - in - complex - - - out - complex - - diff --git a/grc/data/grc_gnuradio/blocks/gr_single_pole_iir_filter_xx.xml b/grc/data/grc_gnuradio/blocks/gr_single_pole_iir_filter_xx.xml deleted file mode 100644 index 50cf4a82..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_single_pole_iir_filter_xx.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - Single Pole IIR Filter - gr_single_pole_iir_filter_xx - from gnuradio import gr - gr.single_pole_iir_filter_$(type.fcn)($alpha, $vlen) - set_taps($alpha) - - Type - type - enum - - - - - Alpha - alpha - 1.0 - real - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_skiphead.xml b/grc/data/grc_gnuradio/blocks/gr_skiphead.xml deleted file mode 100644 index 0849ad29..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_skiphead.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - Skip Head - gr_skiphead - from gnuradio import gr - gr.skiphead($type.size*$vlen, $num_items) - - Type - type - enum - - - - - - - - Num Items - num_items - 1024 - int - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_stream_to_streams.xml b/grc/data/grc_gnuradio/blocks/gr_stream_to_streams.xml deleted file mode 100644 index 82542b8d..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_stream_to_streams.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - Stream to Streams - gr_stream_to_streams - from gnuradio import gr - gr.stream_to_streams($type.size*$vlen, $num_streams) - - IO Type - type - enum - - - - - - - - Num Streams - num_streams - 2 - int - - - Vec Length - vlen - 1 - int - - $num_streams > 0 - $vlen >= 1 - - in - $type - $vlen - - - out - $type - $vlen - $num_streams - - diff --git a/grc/data/grc_gnuradio/blocks/gr_stream_to_vector.xml b/grc/data/grc_gnuradio/blocks/gr_stream_to_vector.xml deleted file mode 100644 index 296d786f..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_stream_to_vector.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - Stream to Vector - gr_stream_to_vector - from gnuradio import gr - gr.stream_to_vector($type.size*$vlen, $num_items) - - IO Type - type - enum - - - - - - - - Num Items - num_items - 2 - int - - - Vec Length - vlen - 1 - int - - $num_items > 0 - $vlen >= 1 - - in - $type - $vlen - - - out - $type - $vlen*$num_items - - diff --git a/grc/data/grc_gnuradio/blocks/gr_streams_to_stream.xml b/grc/data/grc_gnuradio/blocks/gr_streams_to_stream.xml deleted file mode 100644 index 7aadd7ee..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_streams_to_stream.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - Streams to Stream - gr_streams_to_stream - from gnuradio import gr - gr.streams_to_stream($type.size*$vlen, $num_streams) - - IO Type - type - enum - - - - - - - - Num Streams - num_streams - 2 - int - - - Vec Length - vlen - 1 - int - - $num_streams > 0 - $vlen >= 1 - - in - $type - $vlen - $num_streams - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_streams_to_vector.xml b/grc/data/grc_gnuradio/blocks/gr_streams_to_vector.xml deleted file mode 100644 index 4ecdcb2d..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_streams_to_vector.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - Streams to Vector - gr_streams_to_vector - from gnuradio import gr - gr.streams_to_vector($type.size*$vlen, $num_streams) - - IO Type - type - enum - - - - - - - - Num Streams - num_streams - 2 - int - - - Vec Length - vlen - 1 - int - - $num_streams > 0 - $vlen >= 1 - - in - $type - $vlen - $num_streams - - - out - $type - $vlen*$num_streams - - diff --git a/grc/data/grc_gnuradio/blocks/gr_sub_xx.xml b/grc/data/grc_gnuradio/blocks/gr_sub_xx.xml deleted file mode 100644 index 488e6c36..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_sub_xx.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - Subtract - gr_sub_xx - from gnuradio import gr - gr.sub_$(type.fcn)() - - IO Type - type - enum - - - - - - - Num Inputs - num_inputs - 2 - int - - $num_inputs >= 2 - - in - $type - $num_inputs - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_threshold_ff.xml b/grc/data/grc_gnuradio/blocks/gr_threshold_ff.xml deleted file mode 100644 index 97764d73..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_threshold_ff.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - Threshold - gr_threshold_ff - from gnuradio import gr - gr.threshold_ff($low, $high, $init) - - Low - low - -100 - real - - - High - high - 100 - real - - - Initial State - init - 0 - real - - - in - float - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/gr_throttle.xml b/grc/data/grc_gnuradio/blocks/gr_throttle.xml deleted file mode 100644 index ab8506f5..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_throttle.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - Throttle - gr_throttle - from gnuradio import gr - gr.throttle($type.size*$vlen, $samples_per_second) - - Type - type - enum - - - - - - - - Sample Rate - samples_per_second - samp_rate - real - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_uchar_to_float.xml b/grc/data/grc_gnuradio/blocks/gr_uchar_to_float.xml deleted file mode 100644 index 0a5f7f96..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_uchar_to_float.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - UChar To Float - gr_uchar_to_float - from gnuradio import gr - gr.uchar_to_float() - - in - byte - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/gr_udp_sink.xml b/grc/data/grc_gnuradio/blocks/gr_udp_sink.xml deleted file mode 100644 index e9f6c2be..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_udp_sink.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - UDP Sink - gr_udp_sink - from gnuradio import gr - gr.udp_sink($type.size*$vlen, $ipaddr_local, $port_local, $ipaddr_remote, $port_remote, $mtu) - set_mtu($mtu) - - Input Type - type - enum - - - - - - - - Local IP Address - ipaddr_local - 127.0.0.1 - string - - - Local Port - port_local - 0 - int - - - Remote IP Address - ipaddr_remote - 127.0.0.1 - string - - - Remote Port - port_remote - 1234 - int - - - MTU - mtu - 1024 - int - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_udp_source.xml b/grc/data/grc_gnuradio/blocks/gr_udp_source.xml deleted file mode 100644 index f03adf80..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_udp_source.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - UDP Source - gr_udp_source - from gnuradio import gr - gr.udp_source($type.size*$vlen, $ipaddr, $port, $mtu) - set_mtu($mtu) - - Output Type - type - enum - - - - - - - - IP Address - ipaddr - 127.0.0.1 - string - - - Port - port - 1234 - int - - - MTU - mtu - 1024 - int - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_unpack_k_bits_bb.xml b/grc/data/grc_gnuradio/blocks/gr_unpack_k_bits_bb.xml deleted file mode 100644 index 9917644a..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_unpack_k_bits_bb.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - Unpack K Bits - gr_unpack_k_bits_bb - from gnuradio import gr - gr.unpack_k_bits_bb($k) - - K - k - int - - - in - byte - - - out - byte - - diff --git a/grc/data/grc_gnuradio/blocks/gr_unpacked_to_packed_xx.xml b/grc/data/grc_gnuradio/blocks/gr_unpacked_to_packed_xx.xml deleted file mode 100644 index f7457eb5..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_unpacked_to_packed_xx.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - Unpacked to Packed - gr_unpacked_to_packed_xx - from gnuradio import gr - gr.unpacked_to_packed_$(type.fcn)($bits_per_chunk, $endianness) - - Type - type - enum - - - - - - Bits per Chunk - bits_per_chunk - 2 - int - - - Endianness - endianness - enum - - - - - in - $type - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_vco_f.xml b/grc/data/grc_gnuradio/blocks/gr_vco_f.xml deleted file mode 100644 index e49c5396..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_vco_f.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - VCO - gr_vco_f - from gnuradio import gr - gr.vco_f($samp_rate, $sensitivity, $amplitude) - - Sample Rate - samp_rate - real - - - Sensitivity - sensitivity - real - - - Amplitude - amplitude - real - - - in - float - - - out - float - - diff --git a/grc/data/grc_gnuradio/blocks/gr_vector_sink_x.xml b/grc/data/grc_gnuradio/blocks/gr_vector_sink_x.xml deleted file mode 100644 index d901b1d7..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_vector_sink_x.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - Vector Sink - gr_vector_sink_x - from gnuradio import gr - gr.vector_sink_$(type.fcn)() - - Input Type - type - enum - - - - - - - - in - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_vector_source_x.xml b/grc/data/grc_gnuradio/blocks/gr_vector_source_x.xml deleted file mode 100644 index 240273e4..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_vector_source_x.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - Vector Source - gr_vector_source_x - from gnuradio import gr - gr.vector_source_$(type.fcn)($vector, $repeat) - - Output Type - type - enum - - - - - - - - Vector - vector - 0, 0, 0 - $type.vec_type - - - Repeat - repeat - True - enum - - - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/gr_vector_to_stream.xml b/grc/data/grc_gnuradio/blocks/gr_vector_to_stream.xml deleted file mode 100644 index d56d3406..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_vector_to_stream.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - Vector to Stream - gr_vector_to_stream - from gnuradio import gr - gr.vector_to_stream($type.size*$vlen, $num_items) - - IO Type - type - enum - - - - - - - - Num Items - num_items - 2 - int - - - Vec Length - vlen - 1 - int - - $num_items > 0 - $vlen >= 1 - - in - $type - $vlen*$num_items - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/gr_vector_to_streams.xml b/grc/data/grc_gnuradio/blocks/gr_vector_to_streams.xml deleted file mode 100644 index 86cb5681..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_vector_to_streams.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - Vector to Streams - gr_vector_to_streams - from gnuradio import gr - gr.vector_to_streams($type.size*$vlen, $num_streams) - - IO Type - type - enum - - - - - - - - Num Streams - num_streams - 2 - int - - - Vec Length - vlen - 1 - int - - $num_streams > 0 - $vlen >= 1 - - in - $type - $vlen*$num_streams - - - out - $type - $vlen - $num_streams - - diff --git a/grc/data/grc_gnuradio/blocks/gr_wavfile_sink.xml b/grc/data/grc_gnuradio/blocks/gr_wavfile_sink.xml deleted file mode 100644 index f2c8a009..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_wavfile_sink.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - Wav File Sink - gr_wavfile_sink - from gnuradio import gr - gr.wavfile_sink($file, $nchan, $samp_rate, $bits_per_sample) - - File - file - - file_save - - - N Channels - nchan - 1 - int - - - Sample Rate - samp_rate - samp_rate - int - - - Bits per Sample - bits_per_sample - 8 - int - - 1 <= $nchan - - in - float - $nchan - - diff --git a/grc/data/grc_gnuradio/blocks/gr_wavfile_source.xml b/grc/data/grc_gnuradio/blocks/gr_wavfile_source.xml deleted file mode 100644 index 433bb0af..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_wavfile_source.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - Wav File Source - gr_wavfile_source - from gnuradio import gr - gr.wavfile_source($file, $repeat) - - File - file - - file_open - - - Repeat - repeat - True - enum - - - - - N Channels - nchan - 1 - int - - 1 <= $nchan - - out - float - $nchan - - diff --git a/grc/data/grc_gnuradio/blocks/gr_xor_xx.xml b/grc/data/grc_gnuradio/blocks/gr_xor_xx.xml deleted file mode 100644 index c014cbe5..00000000 --- a/grc/data/grc_gnuradio/blocks/gr_xor_xx.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - Xor - gr_xor_xx - from gnuradio import gr - gr.xor_$(type.fcn)() - - IO Type - type - enum - - - - - - Num Inputs - num_inputs - 2 - int - - $num_inputs >= 2 - - in - $type - $num_inputs - - - out - $type - - diff --git a/grc/data/grc_gnuradio/blocks/high_pass_filter.xml b/grc/data/grc_gnuradio/blocks/high_pass_filter.xml deleted file mode 100644 index 0673fd12..00000000 --- a/grc/data/grc_gnuradio/blocks/high_pass_filter.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - High Pass Filter - high_pass_filter - from gnuradio import gr - from gnuradio.gr import firdes - gr.$(type)($decim, firdes.high_pass( - $gain, $samp_rate, $cutoff_freq, $width, firdes.$window, $beta)) - set_taps(firdes.high_pass($gain, $samp_rate, $cutoff_freq, $width, firdes.$window, $beta)) - - FIR Type - type - enum - - - - - - - Decimation - decim - 1 - int - - - Gain - gain - 1 - real - - - Sample Rate - samp_rate - samp_rate - real - - - Cutoff Freq - cutoff_freq - real - - - Transition Width - width - real - - - Window - window - enum - - - - - - - - Beta - beta - 6.76 - real - - - in - $type.input - - - out - $type.output - - -This filter is a convenience wrapper for an fir filter and a firdes taps generating function. - -The decimation paramater becomes interpolation when the filter type is set to interpolating. - -Sample rate, cutoff frequency, and transition width are in Hertz. - -The beta paramater only applies to the Kaiser window. - - diff --git a/grc/data/grc_gnuradio/blocks/import.xml b/grc/data/grc_gnuradio/blocks/import.xml deleted file mode 100644 index feea052d..00000000 --- a/grc/data/grc_gnuradio/blocks/import.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - Import - import - $import - - - Import - import - - import - - -Import additional python modules into the namespace. - -Examples: -from gnuradio.gr import firdes -import math,cmath -from math import pi - - diff --git a/grc/data/grc_gnuradio/blocks/low_pass_filter.xml b/grc/data/grc_gnuradio/blocks/low_pass_filter.xml deleted file mode 100644 index 1e8802c8..00000000 --- a/grc/data/grc_gnuradio/blocks/low_pass_filter.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Low Pass Filter - low_pass_filter - from gnuradio import gr - from gnuradio.gr import firdes - gr.$(type)($decim, firdes.low_pass( - $gain, $samp_rate, $cutoff_freq, $width, firdes.$window, $beta)) - set_taps(firdes.low_pass($gain, $samp_rate, $cutoff_freq, $width, firdes.$window, $beta)) - - FIR Type - type - enum - - - - - - - Decimation - decim - 1 - int - - - Gain - gain - 1 - real - - - Sample Rate - samp_rate - samp_rate - real - - - Cutoff Freq - cutoff_freq - real - - - Transition Width - width - real - - - Window - window - enum - - - - - - - - Beta - beta - 6.76 - real - - - in - $type.input - - - out - $type.output - - -This filter is a convenience wrapper for an fir filter and a firdes taps generating function. - -The decimation paramater becomes interpolation when the filter type is set to interpolating. - -Sample rate, cutoff frequency, and transition width are in Hertz. - -The beta paramater only applies to the Kaiser window. - - diff --git a/grc/data/grc_gnuradio/blocks/note.xml b/grc/data/grc_gnuradio/blocks/note.xml deleted file mode 100644 index db6687c0..00000000 --- a/grc/data/grc_gnuradio/blocks/note.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - Note - note - - - Note - note - - string - - diff --git a/grc/data/grc_gnuradio/blocks/options.xml b/grc/data/grc_gnuradio/blocks/options.xml deleted file mode 100644 index 8e8f0689..00000000 --- a/grc/data/grc_gnuradio/blocks/options.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - Options - options - from gnuradio import gr -#if $generate_options.eval == 'wx_gui' -from grc_gnuradio import wxgui as grc_wxgui -import wx -#end if - - - - Title - title - untitled - string - - - Author - author - unknown - string - - - Description - description - gnuradio flow graph - string - - - Window Size - window_size - 1280, 1024 - int_vector - - - Generate Options - generate_options - wx_gui - enum - - - - - - Category - category - Custom - string - $generate_options.hide_category - - len($window_size) == 2 - 300 <= $(window_size)[0] <= 2048 - 300 <= $(window_size)[1] <= 2048 - -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 (2048, 2048). - -The generate options controls the type of code generated. \ -Non-graphical flow graphs should avoid using graphical sinks or graphical variable controls. - -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. - - diff --git a/grc/data/grc_gnuradio/blocks/pad_sink.xml b/grc/data/grc_gnuradio/blocks/pad_sink.xml deleted file mode 100644 index 477f2ad1..00000000 --- a/grc/data/grc_gnuradio/blocks/pad_sink.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - Pad Sink - pad_sink - - - Num Inputs - nports - 1 - int - - - Input Type - type - enum - - - - - - - - Vec Length - vlen - 1 - int - - $vlen > 0 - 0 < $nports - - in - $type - $vlen - $nports - - -This is a sink pad block for creating hierarchical flow graphs. \ -The inputs of this block will become the outputs to this flow graph when it is instantiated as a hierarchical block. \ -Limit one sink pad block per flow graph. - -Remember to set the generate options to hier block. - - diff --git a/grc/data/grc_gnuradio/blocks/pad_source.xml b/grc/data/grc_gnuradio/blocks/pad_source.xml deleted file mode 100644 index b6ef2c55..00000000 --- a/grc/data/grc_gnuradio/blocks/pad_source.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - Pad Source - pad_source - - - Num Outputs - nports - 1 - int - - - Output Type - type - enum - - - - - - - - Vec Length - vlen - 1 - int - - $vlen > 0 - 0 < $nports - - out - $type - $vlen - $nports - - -This is a source pad block for creating hierarchical flow graphs. \ -The outputs of this block will become the inputs to this flow graph when it is instantiated as a hierarchical block. \ -Limit one source pad block per flow graph. - -Remember to set the generate options to hier block. - - diff --git a/grc/data/grc_gnuradio/blocks/parameter.xml b/grc/data/grc_gnuradio/blocks/parameter.xml deleted file mode 100644 index b9dcce42..00000000 --- a/grc/data/grc_gnuradio/blocks/parameter.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - Parameter - parameter - $value - - Label - label - - string - - - Value - value - 0 - raw - - -This block represents a parameter to the flow graph, \ -used when the flow graph is instantiated as a hier block. - -The paramater value cannot depend on any variables. - -Leave the label blank to use the parameter id as the label. - - diff --git a/grc/data/grc_gnuradio/blocks/preferences.xml b/grc/data/grc_gnuradio/blocks/preferences.xml deleted file mode 100644 index 51138c12..00000000 --- a/grc/data/grc_gnuradio/blocks/preferences.xml +++ /dev/null @@ -1,146 +0,0 @@ - - - - Preferences - preferences - - - - Prefs File - prefs_file - .grc - string - - - File Open - file_open - - string - - - Files Open - files_open - - string - - - Window Size - window_size - 800, 600 - int_vector - - - - Snap to Grid - snap_to_grid - off - enum - - - - - Grid Size - grid_size - 20 - enum - - - - - - - Show Grid - show_grid - hide - enum - - - - - - Show Reports Window - show_reports - show - enum - - - - - Show Params Labels - show_params - show - enum - - - - - Show ID Label - show_id - show - enum - - - - - - Restore Open Files - restore_files - yes - enum - - - - diff --git a/grc/data/grc_gnuradio/blocks/random_source_x.xml b/grc/data/grc_gnuradio/blocks/random_source_x.xml deleted file mode 100644 index f04dcd8d..00000000 --- a/grc/data/grc_gnuradio/blocks/random_source_x.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - Random Source - random_source_x - from gnuradio import gr - import numpy - gr.vector_source_$(type.fcn)(numpy.random.randint($min, $max, $num_samps), $repeat) - - Output Type - type - enum - - - - - - Minimum - min - 0 - int - - - Maximum - max - 1 - int - - - Num Samples - num_samps - 1000 - int - - - Repeat - repeat - True - enum - - - - - out - $type - - -Generate num samples of random numbers of [min, max). Repeat samples if specified. - - diff --git a/grc/data/grc_gnuradio/blocks/trellis_encoder_xx.xml b/grc/data/grc_gnuradio/blocks/trellis_encoder_xx.xml deleted file mode 100644 index 74a8cc34..00000000 --- a/grc/data/grc_gnuradio/blocks/trellis_encoder_xx.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - Trellis Encoder - trellis_encoder_xx - from gnuradio import trellis - trellis.encoder_$(type)(trellis.fsm($fsm_args), $init_state) - - Type - type - enum - - - - - - - - - FSM Args - fsm_args - raw - - - Initial State - init_state - int - - - in - $type.input - - - out - $type.output - - -The fsm arguments are passed directly to the trellis.fsm() constructor. - - diff --git a/grc/data/grc_gnuradio/blocks/trellis_metrics_x.xml b/grc/data/grc_gnuradio/blocks/trellis_metrics_x.xml deleted file mode 100644 index f09d54f0..00000000 --- a/grc/data/grc_gnuradio/blocks/trellis_metrics_x.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - Trellis Metrics - trellis_metrics_x - from gnuradio import trellis - trellis.metrics_$(type)($card, $dim, $table, $metric_type) - - Type - type - enum - - - - - - - Output Cardinality - card - int - - - Dimensionality - dim - int - - - Constellation - table - $type.table - - - Metric Type - metric_type - enum - - - - - - in - $type.io - - - out - $type.io - - -Generate metrics required for Viterbi or SISO algorithms. - - diff --git a/grc/data/grc_gnuradio/blocks/trellis_permutation.xml b/grc/data/grc_gnuradio/blocks/trellis_permutation.xml deleted file mode 100644 index 7721cc71..00000000 --- a/grc/data/grc_gnuradio/blocks/trellis_permutation.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - Trellis Permutation - trellis_permutation - from gnuradio import trellis - trellis.permutation($block_size, $table, $syms_per_block, $type.size*$vlen) - - Type - type - enum - - - - - - - - Block Size - block_size - int - - - Table - table - int_vector - - - Symbols per Block - syms_per_block - int - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - - out - $type - $vlen - - diff --git a/grc/data/grc_gnuradio/blocks/trellis_siso_combined_f.xml b/grc/data/grc_gnuradio/blocks/trellis_siso_combined_f.xml deleted file mode 100644 index 98874d7f..00000000 --- a/grc/data/grc_gnuradio/blocks/trellis_siso_combined_f.xml +++ /dev/null @@ -1,112 +0,0 @@ - - - - Trellis SISO Combo - trellis_siso_combined_f - from gnuradio import trellis - trellis.siso_combined_f(trellis.fsm($fsm_args), $block_size, $init_state, $final_state, $a_post_in, $a_post_out, $siso_type, $dim, $table, $metric_type) - - FSM Args - fsm_args - raw - - - Block Size - block_size - int - - - Initial State - init_state - -1 - int - - - Final State - final_state - -1 - int - - - A-posteriori In - a_post_in - enum - - - - - A-posteriori Out - a_post_out - enum - - - - - SISO Type - siso_type - enum - - - - - Dimensionality - dim - int - - - Constellation - table - real_vector - - - Metric Type - metric_type - enum - - - - - - in - float - - - out - float - - -BCJR Algorithm combined with metric calculation. \ -The fsm arguments are passed directly to the trellis.fsm() constructor. - - diff --git a/grc/data/grc_gnuradio/blocks/trellis_siso_f.xml b/grc/data/grc_gnuradio/blocks/trellis_siso_f.xml deleted file mode 100644 index 2b9cfe5f..00000000 --- a/grc/data/grc_gnuradio/blocks/trellis_siso_f.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - Trellis SISO - trellis_siso_f - from gnuradio import trellis - trellis.siso_f(trellis.fsm($fsm_args), $block_size, $init_state, $final_state, $a_post_in, $a_post_out, $siso_type) - - FSM Args - fsm_args - raw - - - Block Size - block_size - int - - - Initial State - init_state - -1 - int - - - Final State - final_state - -1 - int - - - A-posteriori In - a_post_in - enum - - - - - A-posteriori Out - a_post_out - enum - - - - - SISO Type - siso_type - enum - - - - - in - float - - - out - float - - -BCJR Algorithm. \ -The fsm arguments are passed directly to the trellis.fsm() constructor. - - diff --git a/grc/data/grc_gnuradio/blocks/trellis_viterbi_combined_xx.xml b/grc/data/grc_gnuradio/blocks/trellis_viterbi_combined_xx.xml deleted file mode 100644 index 0a67d0bf..00000000 --- a/grc/data/grc_gnuradio/blocks/trellis_viterbi_combined_xx.xml +++ /dev/null @@ -1,122 +0,0 @@ - - - - Trellis Viterbi Combo - trellis_viterbi_combined_xx - from gnuradio import trellis - trellis.viterbi_combined_$(type)$(out_type)(trellis.fsm($fsm_args), $block_size, $init_state, $final_state, $dim, $table, $metric_type) - - Input Type - type - enum - - - - - - - Output Type - out_type - enum - - - - - - FSM Args - fsm_args - raw - - - Block Size - block_size - int - - - Initial State - init_state - -1 - int - - - Final State - final_state - -1 - int - - - Dimensionality - dim - int - - - Constellation - table - $type.table - - - Metric Type - metric_type - enum - - - - - - in - $type.io - - - out - $out_type.io - - -Viterbi Decoder combined with metric calculation. \ -The fsm arguments are passed directly to the trellis.fsm() constructor. - - diff --git a/grc/data/grc_gnuradio/blocks/trellis_viterbi_x.xml b/grc/data/grc_gnuradio/blocks/trellis_viterbi_x.xml deleted file mode 100644 index 7465b11d..00000000 --- a/grc/data/grc_gnuradio/blocks/trellis_viterbi_x.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - Trellis Viterbi - trellis_viterbi_x - from gnuradio import trellis - trellis.viterbi_$(type)(trellis.fsm($fsm_args), $block_size, $init_state, $final_state) - - Type - type - enum - - - - - - FSM Args - fsm_args - raw - - - Block Size - block_size - int - - - Initial State - init_state - -1 - int - - - Final State - final_state - -1 - int - - - in - $type.io - - - out - $type.io - - -Viterbi Decoder. \ -The fsm arguments are passed directly to the trellis.fsm() constructor. - - diff --git a/grc/data/grc_gnuradio/blocks/usrp_diagnostics.xml b/grc/data/grc_gnuradio/blocks/usrp_diagnostics.xml deleted file mode 100644 index 52dd885a..00000000 --- a/grc/data/grc_gnuradio/blocks/usrp_diagnostics.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - USRP Diagnostics - usrp_diagnostics - - - USRP Number - usrp_number - 0 - int - - - USRP Type - usrp_type - rx - enum - - - - - Side:Subdevice - side_subdev - (0, 0) - enum - - - - - - diff --git a/grc/data/grc_gnuradio/blocks/usrp_dual_sink_x.xml b/grc/data/grc_gnuradio/blocks/usrp_dual_sink_x.xml deleted file mode 100644 index acc14b1f..00000000 --- a/grc/data/grc_gnuradio/blocks/usrp_dual_sink_x.xml +++ /dev/null @@ -1,154 +0,0 @@ - - - - USRP Dual Sink - usrp_dual_sink_x - from grc_gnuradio import usrp as grc_usrp - grc_usrp.dual_sink_$(type.fcn)( - number=$number, - frequency_a=$frequency_a, - frequency_b=$frequency_b, - interpolation=$interpolation, - gain_a=$gain_a, - gain_b=$gain_b, - mux=$mux, - auto_tr=$auto_tr, - tx_enb_a=$tx_enb_a, - tx_enb_b=$tx_enb_b, -) - set_interp_rate($interpolation) - set_frequency_a($frequency_a) - set_gain_a($gain_a) - set_frequency_b($frequency_b) - set_gain_b($gain_b) - - Input Type - type - enum - - - - - Unit Number - number - 0 - int - - - Frequency A - frequency_a - real - - - Frequency B - frequency_b - real - - - Interpolation - interpolation - int - - - Gain A - gain_a - real - - - Gain B - gain_b - real - - - Mux - mux - 0xba98 - hex - - - Auto T/R - auto_tr - None - enum - - - - - - TX Enable A - tx_enb_a - None - enum - - - - - - TX Enable B - tx_enb_b - None - enum - - - - - - Ain - $type - - - Bin - $type - - -The USRP sink inputs 128 Megasamples per second / interpolation. - ---- Flex RF specific --- -The "Auto TR" and "TX Enable" settings are flex rf specific and should be left at "Ignore" unless this is a flex rf board. - -If enabled, "Auto Transmit/Receive Switching" handles the preference for transmit packets vs receive packets. \ -By default, "Auto TR" is disabled. - -The "Transmit Enable" configures the transmitter to be on or off. \ -Do not leave this unconfigured. - - diff --git a/grc/data/grc_gnuradio/blocks/usrp_dual_source_x.xml b/grc/data/grc_gnuradio/blocks/usrp_dual_source_x.xml deleted file mode 100644 index 68526b47..00000000 --- a/grc/data/grc_gnuradio/blocks/usrp_dual_source_x.xml +++ /dev/null @@ -1,154 +0,0 @@ - - - - USRP Dual Source - usrp_dual_source_x - from grc_gnuradio import usrp as grc_usrp - grc_usrp.dual_source_$(type.fcn)( - number=$number, - frequency_a=$frequency_a, - frequency_b=$frequency_b, - decimation=$decimation, - gain_a=$gain_a, - gain_b=$gain_b, - mux=$mux, - auto_tr=$auto_tr, - rx_ant_a=$rx_ant_a, - rx_ant_b=$rx_ant_b, -) - set_decim_rate($decimation) - set_frequency_a($frequency_a) - set_gain_a($gain_a) - set_frequency_b($frequency_b) - set_gain_b($gain_b) - - Output Type - type - enum - - - - - Unit Number - number - 0 - int - - - Frequency A - frequency_a - real - - - Frequency B - frequency_b - real - - - Decimation - decimation - int - - - Gain A - gain_a - real - - - Gain B - gain_b - real - - - Mux - mux - 0x3210 - hex - - - Auto T/R - auto_tr - None - enum - - - - - - RX Antenna B - rx_ant_a - None - enum - - - - - - RX Antenna B - rx_ant_b - None - enum - - - - - - Aout - $type - - - Bout - $type - - -The USRP source outputs 64 Megasamples per second / decimation. - ---- Flex RF specific --- -The "Auto TR" and "RX Antenna" settings are flex rf specific and should be left at "Ignore" unless this is a flex rf board. - -If enabled, "Auto Transmit/Receive Switching" handles the preference for transmit packets vs receive packets. \ -By default, "Auto TR" is disabled. - -The "Receive Antenna Setting" selects one of the SMA connectors as the data source. \ -By default, 'TX/RX' is selected. - - diff --git a/grc/data/grc_gnuradio/blocks/usrp_simple_sink_x.xml b/grc/data/grc_gnuradio/blocks/usrp_simple_sink_x.xml deleted file mode 100644 index b525d031..00000000 --- a/grc/data/grc_gnuradio/blocks/usrp_simple_sink_x.xml +++ /dev/null @@ -1,140 +0,0 @@ - - - - USRP Sink - usrp_simple_sink_x - from grc_gnuradio import usrp as grc_usrp - grc_usrp.simple_sink_$(type.fcn)( - number=$number, - subdev_spec=$subdev_spec, - frequency=$frequency, - interpolation=$interpolation, - gain=$gain, -#if $mux.eval == hex(0) - mux=None, -#else - mux=$mux, -#end if - auto_tr=$auto_tr, - tx_enb=$tx_enb, -) - set_interp_rate($interpolation) - set_frequency($frequency) - set_gain($gain) - - Input Type - type - enum - - - - - Unit Number - number - 0 - int - - - Subdev Spec - subdev_spec - auto - enum - - - - - - Frequency - frequency - real - - - Interpolation - interpolation - int - - - Gain - gain - real - - - Mux - mux - 0x0 - hex - - - Auto T/R - auto_tr - None - enum - - - - - - TX Enable - tx_enb - None - enum - - - - - - in - $type - - -The USRP sink inputs 128 Megasamples per second / interpolation. - ---- Flex RF specific --- -The "Auto TR" and "TX Enable" settings are flex rf specific and should be left at "Ignore" unless this is a flex rf board. - -If enabled, "Auto Transmit/Receive Switching" handles the preference for transmit packets vs receive packets. \ -By default, "Auto TR" is disabled. - -The "Transmit Enable" configures the transmitter to be on or off. \ -Do not leave this unconfigured. - - diff --git a/grc/data/grc_gnuradio/blocks/usrp_simple_source_x.xml b/grc/data/grc_gnuradio/blocks/usrp_simple_source_x.xml deleted file mode 100644 index a1598583..00000000 --- a/grc/data/grc_gnuradio/blocks/usrp_simple_source_x.xml +++ /dev/null @@ -1,148 +0,0 @@ - - - - USRP Source - usrp_simple_source_x - from grc_gnuradio import usrp as grc_usrp - grc_usrp.simple_source_$(type.fcn)( - number=$number, - subdev_spec=$subdev_spec, - frequency=$frequency, - decimation=$decimation, - gain=$gain, -#if $mux.eval == hex(0) - mux=None, -#else - mux=$mux, -#end if - auto_tr=$auto_tr, - rx_ant=$rx_ant, -) - set_decim_rate($decimation) - set_frequency($frequency) - set_gain($gain) - - Output Type - type - enum - - - - - Unit Number - number - 0 - int - - - Subdev Spec - subdev_spec - auto - enum - - - - - - - - Frequency - frequency - real - - - Decimation - decimation - int - - - Gain - gain - real - - - Mux - mux - 0x0 - hex - - - Auto T/R - auto_tr - None - enum - - - - - - RX Antenna - rx_ant - None - enum - - - - - - out - $type - - -The USRP source outputs 64 Megasamples per second / decimation. - ---- Flex RF specific --- -The "Auto TR" and "RX Antenna" settings are flex rf specific and should be left at "Ignore" unless this is a flex rf board. - -If enabled, "Auto Transmit/Receive Switching" handles the preference for transmit packets vs receive packets. \ -By default, "Auto TR" is disabled. - -The "Receive Antenna Setting" selects one of the SMA connectors as the data source. \ -By default, 'TX/RX' is selected. - - diff --git a/grc/data/grc_gnuradio/blocks/variable.xml b/grc/data/grc_gnuradio/blocks/variable.xml deleted file mode 100644 index d620e160..00000000 --- a/grc/data/grc_gnuradio/blocks/variable.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - Variable - variable - $value - - Value - value - 0 - raw - - -This block maps a value to a unique variable. \ -This variable block has no graphical representation. - - diff --git a/grc/data/grc_gnuradio/blocks/variable_chooser.xml b/grc/data/grc_gnuradio/blocks/variable_chooser.xml deleted file mode 100644 index 4eba84d4..00000000 --- a/grc/data/grc_gnuradio/blocks/variable_chooser.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - Variable Chooser - variable_chooser - $(choices)[$value_index] -_$(id)_control = grc_wxgui.$(chooser_type)_control( - window=self.GetWin(), - callback=self.set_$(id), - #if $label.eval - label=$label, - #else - label="$id", - #end if - index=$value_index, - choices=$choices, - labels=$labels, -) -#set $grid_pos = $grid_pos.eval -#if not grid_pos -self.Add(_$(id)_control) -#else -self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) -#end if - - Label - label - - string - - - Value Index - value_index - 0 - int - - - Choices - choices - [1, 2, 3] - raw - - - Labels - labels - [] - raw - - - Chooser Type - chooser_type - drop_down - enum - - - - - - - Grid Position - grid_pos - - grid_pos - - $value_index in range(len($choices)) - not $labels or len($labels) == len($choices) - -This block creates a variable with a drop down, radio buttons, or a button. \ -Leave the label blank to use the variable id as the label. \ -The value index is the index of a particular choice, \ -which defines the default choice when the flow graph starts. \ -The choices must be a list of possible values. \ -Leave labels empty to use the choices as the labels. - -Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. - - diff --git a/grc/data/grc_gnuradio/blocks/variable_sink.xml b/grc/data/grc_gnuradio/blocks/variable_sink.xml deleted file mode 100644 index 13737b2c..00000000 --- a/grc/data/grc_gnuradio/blocks/variable_sink.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - Variable Sink - variable_sink - from grc_gnuradio import blks2 as grc_blks2 - grc_blks2.queue_sink_$(type.fcn)($vlen) -grc_blks2.queue_sink_thread(self.$id, set_$(variable)) - - Type - type - enum - - - - - - - - Variable - variable - - raw - - - Vec Length - vlen - 1 - int - - $vlen > 0 - - in - $type - $vlen - - -Read samples from the input stream and write each sample to the variable. - -The variable must be the id of an existing variable block. - - diff --git a/grc/data/grc_gnuradio/blocks/variable_slider.xml b/grc/data/grc_gnuradio/blocks/variable_slider.xml deleted file mode 100644 index 2f6374b9..00000000 --- a/grc/data/grc_gnuradio/blocks/variable_slider.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - Variable Slider - variable_slider - $value -_$(id)_control = grc_wxgui.slider_$(slider_type)_control( - window=self.GetWin(), - callback=self.set_$(id), - #if $label.eval - label=$label, - #else - label="$id", - #end if - value=$id, - min=$min, - max=$max, - num_steps=$num_steps, -) -#set $grid_pos = $grid_pos.eval -#if not grid_pos -self.Add(_$(id)_control) -#else -self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) -#end if - - Label - label - - string - - - Default Value - value - 50 - real - - - Minimum - min - 0 - real - - - Maximum - max - 100 - real - - - Num Steps - num_steps - 100 - int - - - Slider Type - slider_type - horizontal - enum - - - - - Grid Position - grid_pos - - grid_pos - - $min <= $value <= $max - $min < $max - 0 < $num_steps <= 1000 - -This block creates a variable with a slider. \ -Leave the label blank to use the variable id as the label. \ -The value must be a real number. \ -The value must be between the minimum and the maximum. \ -The number of steps must be between 0 and 1000. - -Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. - - diff --git a/grc/data/grc_gnuradio/blocks/variable_text_box.xml b/grc/data/grc_gnuradio/blocks/variable_text_box.xml deleted file mode 100644 index 0dad3d82..00000000 --- a/grc/data/grc_gnuradio/blocks/variable_text_box.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - Variable Text Box - variable_text_box - $value -_$(id)_control = grc_wxgui.text_box_control( - window=self.GetWin(), - callback=self.set_$(id), - #if $label.eval - label=$label, - #else - label="$id", - #end if - value=$id, -) -#set $grid_pos = $grid_pos.eval -#if not grid_pos -self.Add(_$(id)_control) -#else -self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) -#end if - - Label - label - - string - - - Default Value - value - 0 - raw - - - Grid Position - grid_pos - - grid_pos - - -This block creates a variable with a text box. \ -Leave the label blank to use the variable id as the label. - -Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. - - diff --git a/grc/data/grc_gnuradio/blocks/wxgui_constellationsink2.xml b/grc/data/grc_gnuradio/blocks/wxgui_constellationsink2.xml deleted file mode 100644 index cf3f2928..00000000 --- a/grc/data/grc_gnuradio/blocks/wxgui_constellationsink2.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - Constellation Sink - wxgui_constellationsink2 - from gnuradio.wxgui import scopesink2 - scopesink2.constellation_sink( - self.GetWin(), - title=$title, - sample_rate=$samp_rate, - frame_decim=$frame_decim, -) -self.$(id).win.$(marker)() -#set $grid_pos = $grid_pos.eval -#if not grid_pos -self.Add(self.$(id).win) -#else -self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) -#end if - set_sample_rate($samp_rate) - - Title - title - Constellation Plot - string - - - Sample Rate - samp_rate - samp_rate - real - - - Frame Decimation - frame_decim - 15 - int - - - Marker - marker - set_format_plus - enum - - - - - - Grid Position - grid_pos - - grid_pos - - - in - complex - - -Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. - - diff --git a/grc/data/grc_gnuradio/blocks/wxgui_fftsink2.xml b/grc/data/grc_gnuradio/blocks/wxgui_fftsink2.xml deleted file mode 100644 index 68b07ba9..00000000 --- a/grc/data/grc_gnuradio/blocks/wxgui_fftsink2.xml +++ /dev/null @@ -1,148 +0,0 @@ - - - - FFT Sink - wxgui_fftsink2 - from gnuradio.wxgui import fftsink2 - fftsink2.$(type.fcn)( - self.GetWin(), - baseband_freq=$baseband_freq, - y_per_div=$y_per_div, - y_divs=$y_divs, - ref_level=$ref_level, - sample_rate=$samp_rate, - fft_size=$fft_size, - fft_rate=$fft_rate, - average=$average, -#if $avg_alpha.eval == 0 - avg_alpha=None, -#else - avg_alpha=$avg_alpha, -#end if - title=$title, - peak_hold=$peak_hold, -) -#set $grid_pos = $grid_pos.eval -#if not grid_pos -self.Add(self.$(id).win) -#else -self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) -#end if - - Type - type - complex - enum - - - - - Title - title - FFT Plot - string - - - Sample Rate - samp_rate - samp_rate - real - - - Baseband Freq - baseband_freq - 0 - real - - - Y per Div - y_per_div - 10 - real - - - Y Divs - y_divs - 8 - real - - - Reference Level - ref_level - 50 - real - - - FFT Size - fft_size - 1024 - int - - - Refresh Rate - fft_rate - 30 - int - - - Average Alpha - avg_alpha - 0 - real - - - Average - average - False - enum - - - - - Peak Hold - peak_hold - False - enum - - - - - Grid Position - grid_pos - - grid_pos - - - in - $type - - -Set Average Alpha to 0 for automatic setting. - -Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. - - diff --git a/grc/data/grc_gnuradio/blocks/wxgui_numbersink2.xml b/grc/data/grc_gnuradio/blocks/wxgui_numbersink2.xml deleted file mode 100644 index e54da3e6..00000000 --- a/grc/data/grc_gnuradio/blocks/wxgui_numbersink2.xml +++ /dev/null @@ -1,173 +0,0 @@ - - - - Number Sink - wxgui_numbersink2 - from gnuradio.wxgui import numbersink2 - numbersink2.$(type.fcn)( - self.GetWin(), - unit=$units, - base_value=$base_value, - minval=$min_value, - maxval=$max_value, - factor=$factor, - decimal_places=$decimal_places, - ref_level=$ref_level, - sample_rate=$samp_rate, - number_rate=$number_rate, - average=$options.average, -#if $avg_alpha.eval == 0 - avg_alpha=None, -#else - avg_alpha=$avg_alpha, -#end if - label=$title, - peak_hold=$options.peak_hold, -) -self.$(id).set_show_gauge($show_gauge) -#set $grid_pos = $grid_pos.eval -#if not grid_pos -self.Add(self.$(id).win) -#else -self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) -#end if - - Type - type - complex - enum - - - - - Title - title - Number Plot - string - - - Units - units - Units - string - - - Sample Rate - samp_rate - samp_rate - real - - - Base Value - base_value - 0.0 - real - - - Min Value - min_value - -100 - real - - - Max Value - max_value - 100 - real - - - Factor - factor - 1.0 - real - - - Decimal Places - decimal_places - 10 - int - - - Reference Level - ref_level - 50 - real - - - Number Rate - number_rate - 15 - int - - - Average Alpha - avg_alpha - 0 - real - - - Options - options - none - enum - - - - - - Show Gauge - show_gauge - True - enum - - - - - Grid Position - grid_pos - - grid_pos - - - in - $type - - -Set Average Alpha to 0 for automatic setting. - -Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. - - diff --git a/grc/data/grc_gnuradio/blocks/wxgui_scopesink2.xml b/grc/data/grc_gnuradio/blocks/wxgui_scopesink2.xml deleted file mode 100644 index 7cf49d5d..00000000 --- a/grc/data/grc_gnuradio/blocks/wxgui_scopesink2.xml +++ /dev/null @@ -1,146 +0,0 @@ - - - - Scope Sink - wxgui_scopesink2 - from gnuradio.wxgui import scopesink2 - from gnuradio import gr - scopesink2.$(type.fcn)( - self.GetWin(), - title=$title, - sample_rate=$samp_rate, - frame_decim=$frame_decim, -#if $v_scale.eval == 0 - v_scale=None, -#else - v_scale=$v_scale, -#end if - t_scale=$t_scale, - num_inputs=$num_inputs, -) -self.$(id).win.$(marker)() -#set $grid_pos = $grid_pos.eval -#if not grid_pos -self.Add(self.$(id).win) -#else -self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) -#end if - - set_sample_rate($samp_rate) - - Type - type - complex - enum - - - - - Title - title - Scope Plot - string - - - Sample Rate - samp_rate - samp_rate - real - - - Frame Decimation - frame_decim - 15 - int - - - V Scale - v_scale - 0 - real - - - T Scale - t_scale - .001 - real - - - Marker - marker - set_format_line - enum - - - - - - - Num Inputs - num_inputs - 1 - int - - - Grid Position - grid_pos - - grid_pos - - - in - $type - $num_inputs - - -Set the V Scale to 0 for the scope to auto-scale. - -Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. - - diff --git a/grc/data/grc_gnuradio/blocks/wxgui_waterfallsink2.xml b/grc/data/grc_gnuradio/blocks/wxgui_waterfallsink2.xml deleted file mode 100644 index b5172f09..00000000 --- a/grc/data/grc_gnuradio/blocks/wxgui_waterfallsink2.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - - Waterfall Sink - wxgui_waterfallsink2 - from gnuradio.wxgui import waterfallsink2 - waterfallsink2.$(type.fcn)( - self.GetWin(), - baseband_freq=$baseband_freq, - y_per_div=$y_per_div, - ref_level=$ref_level, - sample_rate=$samp_rate, - fft_size=$fft_size, - fft_rate=$fft_rate, - average=$options.average, -#if $avg_alpha.eval == 0 - avg_alpha=None, -#else - avg_alpha=$avg_alpha, -#end if - title=$title, -) -#set $grid_pos = $grid_pos.eval -#if not grid_pos -self.Add(self.$(id).win) -#else -self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) -#end if - - Type - type - complex - enum - - - - - Title - title - Waterfall Plot - string - - - Sample Rate - samp_rate - samp_rate - real - - - Baseband Freq - baseband_freq - 0 - real - - - Y per Div - y_per_div - 10 - real - - - Reference Level - ref_level - 50 - real - - - FFT Size - fft_size - 512 - int - - - FFT Rate - fft_rate - 15 - int - - - Average Alpha - avg_alpha - 0 - real - - - Options - options - none - enum - - - - - Grid Position - grid_pos - - grid_pos - - - in - $type - - -Set Average Alpha to 0 for automatic setting. - -Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. - - diff --git a/grc/data/grc_gnuradio/blocks/xmlrpc_client.xml b/grc/data/grc_gnuradio/blocks/xmlrpc_client.xml deleted file mode 100644 index 82ae8cee..00000000 --- a/grc/data/grc_gnuradio/blocks/xmlrpc_client.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - XMLRPC Client - xmlrpc_client - import xmlrpclib - xmlrpclib.Server("http://$(addr.eval):$(port)") - $(callback.eval)($variable) - - Address - addr - localhost - string - - - Port - port - 8080 - int - - - Callback - callback - set_ - string - - - Variable - variable - raw - - -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. - - diff --git a/grc/data/grc_gnuradio/blocks/xmlrpc_server.xml b/grc/data/grc_gnuradio/blocks/xmlrpc_server.xml deleted file mode 100644 index 40e547ef..00000000 --- a/grc/data/grc_gnuradio/blocks/xmlrpc_server.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - XMLRPC Server - xmlrpc_server - import SimpleXMLRPCServer - import threading - SimpleXMLRPCServer.SimpleXMLRPCServer(($addr, $port), allow_none=True) -self.$(id).register_instance(self) -threading.Thread(target=self.$(id).serve_forever).start() - - Address - addr - localhost - string - - - Port - port - 8080 - int - - -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) - - diff --git a/grc/data/grc_gnuradio/default_flow_graph.grc.xml b/grc/data/grc_gnuradio/default_flow_graph.grc.xml deleted file mode 100644 index dea26f3a..00000000 --- a/grc/data/grc_gnuradio/default_flow_graph.grc.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - options - - id - top_block - - - _coordinate - (10, 10) - - - _rotation - 0 - - - - variable - - id - samp_rate - - - value - 32000 - - - _coordinate - (10, 170) - - - _rotation - 0 - - - diff --git a/grc/data/grc_gnuradio/flow_graph.tmpl b/grc/data/grc_gnuradio/flow_graph.tmpl deleted file mode 100644 index 90ef3bba..00000000 --- a/grc/data/grc_gnuradio/flow_graph.tmpl +++ /dev/null @@ -1,194 +0,0 @@ -#!/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 controls the variables with gui controls -##@param parameters the paramater blocks -##@param blocks the signal blocks -##@param connections the connections -##@param generate_options the type of flow graph -##@param var_id2expr variable id map to expression -##@param var_id2deps variable id map to direct dependencies -##@param var_id2cbs variable id map to callback strings -######################################################## -#import time -#set $DIVIDER = '#'*50 -$DIVIDER -# Gnuradio Python Flow Graph -$('# Title: %s'%$flow_graph.get_option('title')) -$('# Author: %s'%$flow_graph.get_option('author')) -$('# Description: %s'%$flow_graph.get_option('description')) -$('# Generated: %s'%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' - #from grc.Constants import MAIN_WINDOW_PREFIX, DATA_DIR -class $(class_name)(grc_wxgui.top_block_gui): - - def __init__($param_str): - grc_wxgui.top_block_gui.__init__( - self, - title="$MAIN_WINDOW_PREFIX - Executing: $flow_graph.get_option('title')", - icon="$(os.path.join($DATA_DIR, 'grc-icon-32.png'))", - ) -#elif $generate_options == 'no_gui' -class $(class_name)(gr.top_block): - - def __init__($param_str): - gr.top_block.__init__(self, "$flow_graph.get_option('title')") -#elif $generate_options == 'hb' - #set $in_sig = $flow_graph.get_input_signature() - #set $out_sig = $flow_graph.get_output_signature() -class $(class_name)(gr.hier_block2): - - def __init__($param_str): - gr.hier_block2.__init__( - self, - "$flow_graph.get_option('title')", - gr.io_signature($in_sig.nports, $in_sig.nports, $in_sig.size*$in_sig.vlen), - gr.io_signature($out_sig.nports, $out_sig.nports, $out_sig.size*$out_sig.vlen), - ) -#end if -######################################################## -##Create Parameters -## Set the parameter to a property of self.. -######################################################## -#if $parameters - - $DIVIDER - # Parameters - $DIVIDER -#end if -#for $param in $parameters - self.$param.get_id() = $param.get_id() -#end for -######################################################## -##Create Variables -## Set the variable to a property of self. -## Write the first line of the variable make. -######################################################## -#if $variables - - $DIVIDER - # Variables - $DIVIDER -#end if -#for $var in $variables - #set $code = $var.get_make().splitlines()[0] - self.$var.get_id() = $var.get_id() = $code -#end for -######################################################## -##Create Controls -## Write the variable make (excluding first line). -## Indent each line with 2 tabs. -######################################################## -#if $controls - - $DIVIDER - # Controls - $DIVIDER -#end if -#for $ctrl in $controls - #set $code = '\n\t\t'.join($ctrl.get_make().splitlines()[1:]) - $code -#end for -######################################################## -##Create Blocks -## Write the block make, and indent with 2 tabs. -######################################################## -#if $blocks - - $DIVIDER - # Blocks - $DIVIDER -#end if -#for $blk in filter(lambda b: b.get_make(), $blocks) - #set $code = '\n\t\t'.join($blk.get_make().splitlines()) - $("self.%s = %s"%($blk.get_id(), $code)) -#end for -######################################################## -##Create Connections -## The port name should be the id of the parent block. -## However, port names for IO pads should be self. -######################################################## -#if $connections - - $DIVIDER - # Connections - $DIVIDER -#end if -#for $con in $connections - #set $source = $con.get_source() - #set $sink = $con.get_sink() - #if $source.get_parent().get_key() == 'pad_source' - #set $source_name = 'self' - #else - #set $source_name = 'self.' + $source.get_parent().get_id() - #end if - #if $sink.get_parent().get_key() == 'pad_sink' - #set $sink_name = 'self' - #else - #set $sink_name = 'self.' + $sink.get_parent().get_id() - #end if - $("self.connect((%s, %s), (%s, %s))"%( - $source_name, - $source.get_key(), - $sink_name, - $sink.get_key(), - ) - ) -#end for - -######################################################## -##Create Callbacks -## Write a set method for this variable that calls the callbacks -## and sets the direct variable dependencies. -######################################################## -#for $var in $parameters + $variables - #set $id = $var.get_id() - def set_$(id)(self, $id): - self.$id = $id - #for $dep in $var_id2deps[$id] - self.set_$(dep)($var_id2expr[$dep]) - #end for - #for $callback in $var_id2cbs[$id] - self.$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. -######################################################## -#if $generate_options != 'hb' -if __name__ == '__main__': - tb = $(class_name)() - #if $generate_options == 'wx_gui' - tb.Run() - #elif $generate_options == 'no_gui' - tb.start() - raw_input('Press Enter to quit: ') - tb.stop() - #end if -#end if - diff --git a/grc/data/platforms/Makefile.am b/grc/data/platforms/Makefile.am new file mode 100644 index 00000000..d26abd9b --- /dev/null +++ b/grc/data/platforms/Makefile.am @@ -0,0 +1,24 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +SUBDIRS = base python diff --git a/grc/data/platforms/base/Makefile.am b/grc/data/platforms/base/Makefile.am new file mode 100644 index 00000000..f3bd0aba --- /dev/null +++ b/grc/data/platforms/base/Makefile.am @@ -0,0 +1,35 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +ourdatadir = $(grc_base_data_dir) + +DATA_FILES = \ + block_tree.dtd \ + flow_graph.dtd \ + grc-icon-256.png \ + grc-icon-256.svg \ + grc-icon-32.png + +ourdata_DATA = $(DATA_FILES) + +EXTRA_DIST = $(DATA_FILES) diff --git a/grc/data/platforms/base/block_tree.dtd b/grc/data/platforms/base/block_tree.dtd new file mode 100644 index 00000000..be1524a3 --- /dev/null +++ b/grc/data/platforms/base/block_tree.dtd @@ -0,0 +1,26 @@ + + + + + diff --git a/grc/data/platforms/base/flow_graph.dtd b/grc/data/platforms/base/flow_graph.dtd new file mode 100644 index 00000000..904147b3 --- /dev/null +++ b/grc/data/platforms/base/flow_graph.dtd @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + diff --git a/grc/data/platforms/base/grc-icon-256.png b/grc/data/platforms/base/grc-icon-256.png new file mode 100644 index 00000000..e4e8e54a Binary files /dev/null and b/grc/data/platforms/base/grc-icon-256.png differ diff --git a/grc/data/platforms/base/grc-icon-256.svg b/grc/data/platforms/base/grc-icon-256.svg new file mode 100644 index 00000000..87526d46 --- /dev/null +++ b/grc/data/platforms/base/grc-icon-256.svg @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Patrick Strasser <patrick.strasser@tugraz.at> + + + Icon/Symbol for the GNURadio Companion + grc-icon.svg + 2007-02-23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/grc/data/platforms/base/grc-icon-32.png b/grc/data/platforms/base/grc-icon-32.png new file mode 100644 index 00000000..1e4f4f6c Binary files /dev/null and b/grc/data/platforms/base/grc-icon-32.png differ diff --git a/grc/data/platforms/python/Makefile.am b/grc/data/platforms/python/Makefile.am new file mode 100644 index 00000000..a23e0401 --- /dev/null +++ b/grc/data/platforms/python/Makefile.am @@ -0,0 +1,37 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +SUBDIRS = blocks + +ourdatadir = $(grc_python_data_dir) + +DATA_FILES = \ + block.dtd \ + block_tree.xml \ + default_flow_graph.grc.xml \ + flow_graph.tmpl + +ourdata_DATA = $(DATA_FILES) + +EXTRA_DIST = $(DATA_FILES) + diff --git a/grc/data/platforms/python/block.dtd b/grc/data/platforms/python/block.dtd new file mode 100644 index 00000000..d892b128 --- /dev/null +++ b/grc/data/platforms/python/block.dtd @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/grc/data/platforms/python/block_tree.xml b/grc/data/platforms/python/block_tree.xml new file mode 100644 index 00000000..7ac9e519 --- /dev/null +++ b/grc/data/platforms/python/block_tree.xml @@ -0,0 +1,272 @@ + + + + + + Sources + gr_sig_source_x + gr_noise_source_x + gr_vector_source_x + random_source_x + gr_glfsr_source_x + gr_null_source + gr_file_source + gr_udp_source + audio_source + gr_wavfile_source + pad_source + + + Sinks + gr_vector_sink_x + gr_null_sink + gr_file_sink + gr_udp_sink + audio_sink + gr_wavfile_sink + pad_sink + + + Graphical Sinks + wxgui_numbersink2 + wxgui_scopesink2 + wxgui_fftsink2 + wxgui_constellationsink2 + wxgui_waterfallsink2 + + + Operators + gr_add_vxx + gr_sub_xx + gr_multiply_vxx + gr_divide_xx + gr_nlog10_ff + + gr_add_const_vxx + gr_multiply_const_vxx + + gr_not_xx + gr_and_xx + gr_or_xx + gr_xor_xx + + gr_max_xx + gr_argmax_xx + gr_rms_xx + gr_integrate_xx + + gr_conjugate_cc + + gr_fft_vxx + blks2_logpwrfft_x + + + Type Conversions + gr_complex_to_arg + gr_complex_to_mag + gr_complex_to_mag_squared + gr_complex_to_real + gr_complex_to_imag + + gr_complex_to_float + gr_float_to_complex + + gr_float_to_short + gr_short_to_float + + gr_float_to_char + gr_char_to_float + + gr_float_to_uchar + gr_uchar_to_float + + gr_complex_to_interleaved_short + gr_interleaved_short_to_complex + + + Stream Conversions + gr_interleave + gr_deinterleave + + gr_streams_to_stream + gr_stream_to_streams + + gr_streams_to_vector + gr_vector_to_streams + + gr_stream_to_vector + gr_vector_to_stream + + blks2_stream_to_vector_decimator + + + Misc Conversions + gr_unpacked_to_packed_xx + gr_packed_to_unpacked_xx + gr_unpack_k_bits_bb + gr_binary_slicer_fb + gr_chunks_to_symbols_xx + gr_map_bb + + + Synchronizers + gr_clock_recovery_mm_xx + + gr_costas_loop_cc + gr_dd_mpsk_sync_cc + gr_mpsk_sync_cc + gr_mpsk_receiver_cc + + gr_pll_carriertracking_cc + gr_pll_freqdet_cf + gr_pll_refout_cc + + gr_correlate_access_code_bb + gr_pn_correlator_cc + gr_simple_correlator + gr_simple_framer + + + Level Controls + gr_dpll_bb + gr_peak_detector_xb + gr_peak_detector2_fb + gr_sample_and_hold_xx + + gr_agc_xx + gr_agc2_xx + gr_feedforward_agc_cc + + gr_mute_xx + gr_simple_squelch_cc + blks2_standard_squelch + gr_pwr_squelch_xx + gr_threshold_ff + + + Filters + + low_pass_filter + high_pass_filter + band_pass_filter + band_reject_filter + + gr_fir_filter_xxx + gr_interp_fir_filter_xxx + gr_fft_filter_xxx + gr_freq_xlating_fir_filter_xxx + gr_iir_filter_ffd + gr_filter_delay_fc + blks2_channel_model + + gr_single_pole_iir_filter_xx + gr_hilbert_fc + gr_goertzel_fc + gr_cma_equalizer_cc + gr_rational_resampler_base_xxx + blks2_rational_resampler_xxx + gr_fractional_interpolator_xx + gr_keep_one_in_n + gr_moving_average_xx + gr_iqcomp_cc + + + Modulators + gr_vco_f + gr_frequency_modulator_fc + gr_phase_modulator_fc + gr_quadrature_demod_cf + gr_cpfsk_bc + + gr_diff_phasor_cc + gr_constellation_decoder_cb + + gr_diff_encoder_bb + gr_diff_decoder_bb + + blks2_wfm_tx + blks2_wfm_rcv + blks2_wfm_rcv_pll + + blks2_nbfm_tx + blks2_nbfm_rx + + blks2_am_demod_cf + blks2_fm_demod_cf + blks2_fm_deemph + blks2_fm_preemph + + blks2_dxpsk_mod + blks2_dxpsk_demod + + blks2_gmsk_mod + blks2_gmsk_demod + + blks2_qamx_mod + blks2_qamx_demod + + blks2_synthesis_filterbank + blks2_analysis_filterbank + + + Error Correction + + blks2_packet_decoder + blks2_packet_encoder + + gr_encode_ccsds_27_bb + gr_decode_ccsds_27_fb + + + Trellis + trellis_encoder_xx + trellis_metrics_x + trellis_permutation + trellis_siso_combined_f + trellis_siso_f + trellis_viterbi_combined_xx + trellis_viterbi_x + + + USRP + usrp_simple_source_x + usrp_simple_sink_x + usrp_dual_source_x + usrp_dual_sink_x + + + Variables + variable + variable_slider + variable_chooser + variable_text_box + variable_sink + parameter + + + Misc + note + import + + gr_throttle + gr_delay + gr_repeat + + blks2_selector + blks2_valve + blks2_error_rate + + gr_head + gr_skiphead + + gr_kludge_copy + gr_nop + + xmlrpc_server + xmlrpc_client + + diff --git a/grc/data/platforms/python/blocks/Makefile.am b/grc/data/platforms/python/blocks/Makefile.am new file mode 100644 index 00000000..76615647 --- /dev/null +++ b/grc/data/platforms/python/blocks/Makefile.am @@ -0,0 +1,210 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +ourdatadir = $(grc_python_blocks_dir) + +DATA_FILES = \ + audio_sink.xml \ + audio_source.xml \ + band_pass_filter.xml \ + band_reject_filter.xml \ + blks2_am_demod_cf.xml \ + blks2_analysis_filterbank.xml \ + blks2_channel_model.xml \ + blks2_dxpsk_demod.xml \ + blks2_dxpsk_mod.xml \ + blks2_error_rate.xml \ + blks2_fm_deemph.xml \ + blks2_fm_demod_cf.xml \ + blks2_fm_preemph.xml \ + blks2_gmsk_demod.xml \ + blks2_gmsk_mod.xml \ + blks2_logpwrfft_x.xml \ + blks2_nbfm_rx.xml \ + blks2_nbfm_tx.xml \ + blks2_packet_decoder.xml \ + blks2_packet_encoder.xml \ + blks2_qamx_demod.xml \ + blks2_qamx_mod.xml \ + blks2_rational_resampler_xxx.xml \ + blks2_selector.xml \ + blks2_standard_squelch.xml \ + blks2_stream_to_vector_decimator.xml \ + blks2_synthesis_filterbank.xml \ + blks2_valve.xml \ + blks2_wfm_rcv.xml \ + blks2_wfm_rcv_pll.xml \ + blks2_wfm_tx.xml \ + gr_add_const_vxx.xml \ + gr_add_vxx.xml \ + gr_agc2_xx.xml \ + gr_agc_xx.xml \ + gr_and_xx.xml \ + gr_argmax_xx.xml \ + gr_binary_slicer_fb.xml \ + gr_char_to_float.xml \ + gr_chunks_to_symbols.xml \ + gr_clock_recovery_mm_xx.xml \ + gr_cma_equalizer_cc.xml \ + gr_complex_to_arg.xml \ + gr_complex_to_float.xml \ + gr_complex_to_imag.xml \ + gr_complex_to_interleaved_short.xml \ + gr_complex_to_mag.xml \ + gr_complex_to_mag_squared.xml \ + gr_complex_to_real.xml \ + gr_conjugate_cc.xml \ + gr_constellation_decoder_cb.xml \ + gr_correlate_access_code_bb.xml \ + gr_costas_loop_cc.xml \ + gr_cpfsk_bc.xml \ + gr_dd_mpsk_sync_cc.xml \ + gr_decode_ccsds_27_fb.xml \ + gr_deinterleave.xml \ + gr_delay.xml \ + gr_diff_decoder_bb.xml \ + gr_diff_encoder_bb.xml \ + gr_diff_phasor_cc.xml \ + gr_divide_xx.xml \ + gr_dpll_bb.xml \ + gr_encode_ccsds_27_bb.xml \ + gr_feedforward_agc_cc.xml \ + gr_fft_filter_xxx.xml \ + gr_fft_vxx.xml \ + gr_file_sink.xml \ + gr_file_source.xml \ + gr_filter_delay_fc.xml \ + gr_fir_filter_xxx.xml \ + gr_float_to_char.xml \ + gr_float_to_complex.xml \ + gr_float_to_short.xml \ + gr_float_to_uchar.xml \ + gr_fractional_interpolator_xx.xml \ + gr_freq_xlating_fir_filter_xxx.xml \ + gr_frequency_modulator_fc.xml \ + gr_glfsr_source_x.xml \ + gr_goertzel_fc.xml \ + gr_head.xml \ + gr_hilbert_fc.xml \ + gr_iir_filter_ffd.xml \ + gr_integrate_xx.xml \ + gr_interleave.xml \ + gr_interleaved_short_to_complex.xml \ + gr_interp_fir_filter_xxx.xml \ + gr_iqcomp_cc.xml \ + gr_keep_one_in_n.xml \ + gr_kludge_copy.xml \ + gr_map_bb.xml \ + gr_max_xx.xml \ + gr_moving_average_xx.xml \ + gr_mpsk_receiver_cc.xml \ + gr_mpsk_sync_cc.xml \ + gr_multiply_const_vxx.xml \ + gr_multiply_vxx.xml \ + gr_mute_xx.xml \ + gr_nlog10_ff.xml \ + gr_noise_source_x.xml \ + gr_nop.xml \ + gr_not_xx.xml \ + gr_null_sink.xml \ + gr_null_source.xml \ + gr_or_xx.xml \ + gr_packed_to_unpacked_xx.xml \ + gr_peak_detector2_fb.xml \ + gr_peak_detector_xb.xml \ + gr_phase_modulator_fc.xml \ + gr_pll_carriertracking_cc.xml \ + gr_pll_freqdet_cf.xml \ + gr_pll_refout_cc.xml \ + gr_pn_correlator_cc.xml \ + gr_pwr_squelch_xx.xml \ + gr_quadrature_demod_cf.xml \ + gr_rational_resampler_base_xxx.xml \ + gr_repeat.xml \ + gr_rms_xx.xml \ + gr_sample_and_hold_xx.xml \ + gr_short_to_float.xml \ + gr_sig_source_x.xml \ + gr_simple_correlator.xml \ + gr_simple_framer.xml \ + gr_simple_squelch_cc.xml \ + gr_single_pole_iir_filter_xx.xml \ + gr_skiphead.xml \ + gr_stream_to_streams.xml \ + gr_stream_to_vector.xml \ + gr_streams_to_stream.xml \ + gr_streams_to_vector.xml \ + gr_sub_xx.xml \ + gr_threshold_ff.xml \ + gr_throttle.xml \ + gr_uchar_to_float.xml \ + gr_udp_sink.xml \ + gr_udp_source.xml \ + gr_unpack_k_bits_bb.xml \ + gr_unpacked_to_packed_xx.xml \ + gr_vco_f.xml \ + gr_vector_sink_x.xml \ + gr_vector_source_x.xml \ + gr_vector_to_stream.xml \ + gr_vector_to_streams.xml \ + gr_wavfile_sink.xml \ + gr_wavfile_source.xml \ + gr_xor_xx.xml \ + high_pass_filter.xml \ + import.xml \ + low_pass_filter.xml \ + note.xml \ + options.xml \ + pad_sink.xml \ + pad_source.xml \ + parameter.xml \ + preferences.xml \ + random_source_x.xml \ + trellis_encoder_xx.xml \ + trellis_metrics_x.xml \ + trellis_permutation.xml \ + trellis_siso_combined_f.xml \ + trellis_siso_f.xml \ + trellis_viterbi_combined_xx.xml \ + trellis_viterbi_x.xml \ + usrp_diagnostics.xml \ + usrp_dual_sink_x.xml \ + usrp_dual_source_x.xml \ + usrp_simple_sink_x.xml \ + usrp_simple_source_x.xml \ + variable.xml \ + variable_chooser.xml \ + variable_sink.xml \ + variable_slider.xml \ + variable_text_box.xml \ + wxgui_constellationsink2.xml \ + wxgui_fftsink2.xml \ + wxgui_numbersink2.xml \ + wxgui_scopesink2.xml \ + wxgui_waterfallsink2.xml \ + xmlrpc_client.xml \ + xmlrpc_server.xml + +ourdata_DATA = $(DATA_FILES) + +EXTRA_DIST = $(DATA_FILES) diff --git a/grc/data/platforms/python/blocks/audio_sink.xml b/grc/data/platforms/python/blocks/audio_sink.xml new file mode 100644 index 00000000..56c5980f --- /dev/null +++ b/grc/data/platforms/python/blocks/audio_sink.xml @@ -0,0 +1,83 @@ + + + + Audio Sink + audio_sink + from gnuradio import audio + audio.sink($samp_rate, $device_name, $ok_to_block) + + Sample Rate + samp_rate + 32000 + enum + + + + + + + + + Device Name + device_name + + string + + + OK to Block + ok_to_block + True + enum + + + + + Num Inputs + num_inputs + 1 + int + + 0 < $num_inputs + + in + float + $num_inputs + + +Not all sampling rates will be supported by your hardware. + +Leave the device name blank to choose deafult audio device. \ +Audio device names may look like hw:0,0 + +The audio sink can have multiple inputs depending upon your hardware. \ +For example, set the inputs to 2 for stereo audio. + + diff --git a/grc/data/platforms/python/blocks/audio_source.xml b/grc/data/platforms/python/blocks/audio_source.xml new file mode 100644 index 00000000..2ae74e49 --- /dev/null +++ b/grc/data/platforms/python/blocks/audio_source.xml @@ -0,0 +1,83 @@ + + + + Audio Source + audio_source + from gnuradio import audio + audio.source($samp_rate, $device_name, $ok_to_block) + + Sample Rate + samp_rate + 32000 + enum + + + + + + + + + Device Name + device_name + + string + + + OK to Block + ok_to_block + True + enum + + + + + Num Outputs + num_outputs + 1 + int + + 0 < $num_outputs + + out + float + $num_outputs + + +Not all sampling rates will be supported by your hardware. + +Leave the device name blank to choose deafult audio device. \ +Audio device names may look like hw:0,0 + +The audio source can have multiple outputs depending upon your hardware. \ +For example, set the outputs to 2 for stereo audio. + + diff --git a/grc/data/platforms/python/blocks/band_pass_filter.xml b/grc/data/platforms/python/blocks/band_pass_filter.xml new file mode 100644 index 00000000..2dac2960 --- /dev/null +++ b/grc/data/platforms/python/blocks/band_pass_filter.xml @@ -0,0 +1,125 @@ + + + + Band Pass Filter + band_pass_filter + from gnuradio import gr + from gnuradio.gr import firdes + gr.$(type)($decim, firdes.band_pass( + $gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, firdes.$window, $beta)) + set_taps(firdes.band_pass($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, firdes.$window, $beta)) + + FIR Type + type + enum + + + + + + + Decimation + decim + 1 + int + + + Gain + gain + 1 + real + + + Sample Rate + samp_rate + samp_rate + real + + + Low Cutoff Freq + low_cutoff_freq + real + + + High Cutoff Freq + high_cutoff_freq + real + + + Transition Width + width + real + + + Window + window + enum + + + + + + + + Beta + beta + 6.76 + real + + + in + $type.input + + + out + $type.output + + +This filter is a convenience wrapper for an fir filter and a firdes taps generating function. + +The decimation paramater becomes interpolation when the filter type is set to interpolating. + +Sample rate, cutoff frequency, and transition width are in Hertz. + +The beta paramater only applies to the Kaiser window. + + diff --git a/grc/data/platforms/python/blocks/band_reject_filter.xml b/grc/data/platforms/python/blocks/band_reject_filter.xml new file mode 100644 index 00000000..ed6a5fa8 --- /dev/null +++ b/grc/data/platforms/python/blocks/band_reject_filter.xml @@ -0,0 +1,125 @@ + + + + Band Reject Filter + band_reject_filter + from gnuradio import gr + from gnuradio.gr import firdes + gr.$(type)($decim, firdes.band_reject( + $gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, firdes.$window, $beta)) + set_taps(firdes.band_reject($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, firdes.$window, $beta)) + + FIR Type + type + enum + + + + + + + Decimation + decim + 1 + int + + + Gain + gain + 1 + real + + + Sample Rate + samp_rate + samp_rate + real + + + Low Cutoff Freq + low_cutoff_freq + real + + + High Cutoff Freq + high_cutoff_freq + real + + + Transition Width + width + real + + + Window + window + enum + + + + + + + + Beta + beta + 6.76 + real + + + in + $type.input + + + out + $type.output + + +This filter is a convenience wrapper for an fir filter and a firdes taps generating function. + +The decimation paramater becomes interpolation when the filter type is set to interpolating. + +Sample rate, cutoff frequency, and transition width are in Hertz. + +The beta paramater only applies to the Kaiser window. + + diff --git a/grc/data/platforms/python/blocks/blks2_am_demod_cf.xml b/grc/data/platforms/python/blocks/blks2_am_demod_cf.xml new file mode 100644 index 00000000..898c613b --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_am_demod_cf.xml @@ -0,0 +1,47 @@ + + + + AM Demod + blks2_am_demod_cf + from gnuradio import blks2 + blks2.am_demod_cf( + channel_rate=$chan_rate, + audio_decim=$audio_decim, + audio_pass=$audio_pass, + audio_stop=$audio_stop, +) + + Channel Rate + chan_rate + real + + + Audio Decimation + audio_decim + int + + + Audio Pass + audio_pass + 5000 + real + + + Audio Stop + audio_stop + 5500 + real + + + in + complex + + + out + float + + diff --git a/grc/data/platforms/python/blocks/blks2_analysis_filterbank.xml b/grc/data/platforms/python/blocks/blks2_analysis_filterbank.xml new file mode 100644 index 00000000..93cfa30a --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_analysis_filterbank.xml @@ -0,0 +1,32 @@ + + + + Analysis Filterbank + blks2_analysis_filterbank + from gnuradio import blks2 + blks2.analysis_filterbank(mpoints=$mpoints, taps=$taps) + + MPoints + mpoints + 3 + int + + + Taps + taps + complex_vector + + + in + complex + + + out + complex + $mpoints + + diff --git a/grc/data/platforms/python/blocks/blks2_channel_model.xml b/grc/data/platforms/python/blocks/blks2_channel_model.xml new file mode 100644 index 00000000..88805636 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_channel_model.xml @@ -0,0 +1,60 @@ + + + + Channel Model + blks2_channel_model + from gnuradio import blks2 + from gnuradio.gr import firdes + blks2.channel_model( + noise_voltage=$noise_voltage, + frequency_offset=$freq_offset, + epsilon=$epsilon, + taps=$taps, + noise_seed=$seed, +) + set_noise_voltage($noise_voltage) + set_frequency_offset($freq_offset) + set_taps($taps) + + Noise Voltage + noise_voltage + 0.0 + real + + + Frequency Offset + freq_offset + 0.0 + real + + + Epsilon + epsilon + 1.0 + real + + + Taps + taps + 1.0, 0.0 + complex_vector + + + Seed + seed + 42 + int + + + in + complex + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/blks2_dxpsk_demod.xml b/grc/data/platforms/python/blocks/blks2_dxpsk_demod.xml new file mode 100644 index 00000000..20c7bd7f --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_dxpsk_demod.xml @@ -0,0 +1,95 @@ + + + + DPSK Demod + blks2_dxpsk_demod + from gnuradio import blks2 + blks2.$(type)_demod( + samples_per_symbol=$samples_per_symbol, + excess_bw=$excess_bw, + costas_alpha=$costas_alpha, + gain_mu=$gain_mu, + mu=$mu, + omega_relative_limit=$omega_relative_limit, + gray_code=$gray_code, +) + + Type + type + enum + + + + + + Samples/Symbol + samples_per_symbol + 2 + int + + + Excess BW + excess_bw + 0.35 + real + + + Costas Alpha + costas_alpha + 0.175 + real + + + Gain Mu + gain_mu + 0.175 + real + + + Mu + mu + 0.5 + real + + + Omega Relative Limit + omega_relative_limit + 0.005 + real + + + Gray Code + gray_code + True + enum + + + + + in + complex + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/blks2_dxpsk_mod.xml b/grc/data/platforms/python/blocks/blks2_dxpsk_mod.xml new file mode 100644 index 00000000..e165fe9b --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_dxpsk_mod.xml @@ -0,0 +1,67 @@ + + + + DPSK Mod + blks2_dxpsk_mod + from gnuradio import blks2 + blks2.$(type)_mod( + samples_per_symbol=$samples_per_symbol, + excess_bw=$excess_bw, + gray_code=$gray_code, +) + + Type + type + enum + + + + + + Samples/Symbol + samples_per_symbol + 2 + int + + + Excess BW + excess_bw + 0.35 + real + + + Gray Code + gray_code + True + enum + + + + + in + byte + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/blks2_error_rate.xml b/grc/data/platforms/python/blocks/blks2_error_rate.xml new file mode 100644 index 00000000..79703f6e --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_error_rate.xml @@ -0,0 +1,66 @@ + + + + Error Rate + blks2_error_rate + from grc_gnuradio import blks2 as grc_blks2 + grc_blks2.error_rate( + type=$type, + win_size=$win_size, + bits_per_symbol=$bits_per_symbol, +) + + Type + type + enum + + + + + Window Size + win_size + 1000 + int + + + Bits per Symbol + bits_per_symbol + 2 + int + + + ref + byte + + + in + byte + + + out + float + + +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. + + diff --git a/grc/data/platforms/python/blocks/blks2_fm_deemph.xml b/grc/data/platforms/python/blocks/blks2_fm_deemph.xml new file mode 100644 index 00000000..6f38dab6 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_fm_deemph.xml @@ -0,0 +1,31 @@ + + + + FM Deemphasis + blks2_fm_deemph + from gnuradio import blks2 + blks2.fm_deemph(fs=$samp_rate, tau=$tau) + + Sample Rate + samp_rate + real + + + Tau + tau + 75e-6 + real + + + in + float + + + out + float + + diff --git a/grc/data/platforms/python/blocks/blks2_fm_demod_cf.xml b/grc/data/platforms/python/blocks/blks2_fm_demod_cf.xml new file mode 100644 index 00000000..2ce1fb97 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_fm_demod_cf.xml @@ -0,0 +1,68 @@ + + + + FM Demod + blks2_fm_demod_cf + from gnuradio import blks2 + 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, +) + + Channel Rate + chan_rate + real + + + Audio Decimation + audio_decim + int + + + Deviation + deviation + 75000 + real + + + Audio Pass + audio_pass + 15000 + real + + + Audio Stop + audio_stop + 16000 + real + + + Gain + gain + 1.0 + real + + + Tau + tau + 75e-6 + real + + + in + complex + + + out + float + + diff --git a/grc/data/platforms/python/blocks/blks2_fm_preemph.xml b/grc/data/platforms/python/blocks/blks2_fm_preemph.xml new file mode 100644 index 00000000..672a7a7b --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_fm_preemph.xml @@ -0,0 +1,31 @@ + + + + FM Preemphasis + blks2_fm_preemph + from gnuradio import blks2 + blks2.fm_preemph(fs=$samp_rate, tau=$tau) + + Sample Rate + samp_rate + real + + + Tau + tau + 75e-6 + real + + + in + float + + + out + float + + diff --git a/grc/data/platforms/python/blocks/blks2_gmsk_demod.xml b/grc/data/platforms/python/blocks/blks2_gmsk_demod.xml new file mode 100644 index 00000000..c8103981 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_gmsk_demod.xml @@ -0,0 +1,56 @@ + + + + GMSK Demod + blks2_gmsk_demod + from gnuradio import blks2 + blks2.gmsk_demod( + samples_per_symbol=$samples_per_symbol, + gain_mu=$gain_mu, + mu=$mu, + omega_relative_limit=$omega_relative_limit, + freq_error=$freq_error, +) + + Samples/Symbol + samples_per_symbol + 2 + int + + + Gain Mu + gain_mu + 0.175 + real + + + Mu + mu + 0.5 + real + + + Omega Relative Limit + omega_relative_limit + 0.005 + real + + + Freq Error + freq_error + 0.0 + real + + + in + complex + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/blks2_gmsk_mod.xml b/grc/data/platforms/python/blocks/blks2_gmsk_mod.xml new file mode 100644 index 00000000..ab57357e --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_gmsk_mod.xml @@ -0,0 +1,35 @@ + + + + GMSK Mod + blks2_gmsk_mod + from gnuradio import blks2 + blks2.gmsk_mod( + samples_per_symbol=$samples_per_symbol, + bt=$bt, +) + + Samples/Symbol + samples_per_symbol + 2 + int + + + BT + bt + 0.35 + real + + + in + byte + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/blks2_logpwrfft_x.xml b/grc/data/platforms/python/blocks/blks2_logpwrfft_x.xml new file mode 100644 index 00000000..ef49c443 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_logpwrfft_x.xml @@ -0,0 +1,89 @@ + + + + Log Power FFT + blks2_logpwrfft_x + from gnuradio import blks2 + 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, +) + set_sample_rate($sample_rate) + set_avg_alpha($avg_alpha) + + Input Type + type + enum + + + + + Sample Rate + sample_rate + samp_rate + real + + + FFT Size + fft_size + 1024 + int + + + Reference Scale + ref_scale + 2 + real + + + Frame Rate + frame_rate + 30 + real + + + Average Alpha + avg_alpha + 1.0 + real + + + Average + average + False + enum + + + + + in + $type + + + out + float + $fft_size + + diff --git a/grc/data/platforms/python/blocks/blks2_nbfm_rx.xml b/grc/data/platforms/python/blocks/blks2_nbfm_rx.xml new file mode 100644 index 00000000..d332b9a6 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_nbfm_rx.xml @@ -0,0 +1,48 @@ + + + + NBFM Receive + blks2_nbfm_rx + from gnuradio import blks2 + blks2.nbfm_rx( + audio_rate=$audio_rate, + quad_rate=$quad_rate, + tau=$tau, + max_dev=$max_dev, +) + + Audio Rate + audio_rate + int + + + Quadrature Rate + quad_rate + int + + + Tau + tau + 75e-6 + real + + + Max Deviation + max_dev + 5e3 + real + + $quad_rate%$audio_rate == 0 + + in + complex + + + out + float + + diff --git a/grc/data/platforms/python/blocks/blks2_nbfm_tx.xml b/grc/data/platforms/python/blocks/blks2_nbfm_tx.xml new file mode 100644 index 00000000..3aa7ede0 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_nbfm_tx.xml @@ -0,0 +1,48 @@ + + + + NBFM Transmit + blks2_nbfm_tx + from gnuradio import blks2 + blks2.nbfm_tx( + audio_rate=$audio_rate, + quad_rate=$quad_rate, + tau=$tau, + max_dev=$max_dev, +) + + Audio Rate + audio_rate + int + + + Quadrature Rate + quad_rate + int + + + Tau + tau + 75e-6 + real + + + Max Deviation + max_dev + 5e3 + real + + $quad_rate%$audio_rate == 0 + + in + float + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/blks2_packet_decoder.xml b/grc/data/platforms/python/blocks/blks2_packet_decoder.xml new file mode 100644 index 00000000..d360bc17 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_packet_decoder.xml @@ -0,0 +1,81 @@ + + + + Packet Decoder + blks2_packet_decoder + from grc_gnuradio import blks2 as grc_blks2 + from gnuradio import gr + grc_blks2.packet_decoder( + item_size_out=$type.size*$vlen, + access_code=$access_code, + threshold=$threshold, +) + + Output Type + type + float + enum + + + + + + + + Access Code + access_code + + string + + + Threshold + threshold + -1 + int + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + byte + + + out + $type + $vlen + + +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 default. + + diff --git a/grc/data/platforms/python/blocks/blks2_packet_encoder.xml b/grc/data/platforms/python/blocks/blks2_packet_encoder.xml new file mode 100644 index 00000000..ea992722 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_packet_encoder.xml @@ -0,0 +1,117 @@ + + + + Packet Encoder + blks2_packet_encoder + from grc_gnuradio import blks2 as grc_blks2 + from gnuradio import gr + grc_blks2.packet_encoder( + item_size_in=$type.size*$vlen, + 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, +) + + Input Type + type + float + enum + + + + + + + + Samples/Symbol + samples_per_symbol + int + + + Bits/Symbol + bits_per_symbol + int + + + Access Code + access_code + + string + + + Pad for USRP + pad_for_usrp + enum + + + + + Payload Length + payload_length + -1 + int + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + + out + byte + + +Packet encoder block, for use with the gnuradio modulator blocks: gmsk, psk, qam. + +Access Code: string of 1's and 0's, leave blank for default. + +Bits/Symbol should be set accordingly: + gmsk -> 1 + dbpsk -> 1 + dqpsk -> 2 + d8psk -> 3 + qam8 -> 3 + qam16 -> 4 + qam64 -> 6 + qam256 -> 8 + + diff --git a/grc/data/platforms/python/blocks/blks2_qamx_demod.xml b/grc/data/platforms/python/blocks/blks2_qamx_demod.xml new file mode 100644 index 00000000..93dbe4bb --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_qamx_demod.xml @@ -0,0 +1,99 @@ + + + + QAM Demod + blks2_qamx_demod + from gnuradio import blks2 + blks2.$(type)_demod( + samples_per_symbol=$samples_per_symbol, + excess_bw=$excess_bw, + costas_alpha=$costas_alpha, + gain_mu=$gain_mu, + mu=$mu, + omega_relative_limit=$omega_relative_limit, + gray_code=$gray_code, +) + + Type + type + enum + + + + + + + Samples/Symbol + samples_per_symbol + 2 + int + + + Excess BW + excess_bw + 0.35 + real + + + Costas Alpha + costas_alpha + 0.175 + real + + + Gain Mu + gain_mu + 0.03 + real + + + Mu + mu + 0.05 + real + + + Omega Relative Limit + omega_relative_limit + 0.005 + real + + + Gray Code + gray_code + True + enum + + + + + in + complex + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/blks2_qamx_mod.xml b/grc/data/platforms/python/blocks/blks2_qamx_mod.xml new file mode 100644 index 00000000..25a9fb24 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_qamx_mod.xml @@ -0,0 +1,71 @@ + + + + QAM Mod + blks2_qamx_mod + from gnuradio import blks2 + blks2.$(type)_mod( + samples_per_symbol=$samples_per_symbol, + excess_bw=$excess_bw, + gray_code=$gray_code, +) + + Type + type + enum + + + + + + + Samples/Symbol + samples_per_symbol + 2 + int + + + Excess BW + excess_bw + 0.35 + real + + + Gray Code + gray_code + True + enum + + + + + in + byte + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/blks2_rational_resampler_xxx.xml b/grc/data/platforms/python/blocks/blks2_rational_resampler_xxx.xml new file mode 100644 index 00000000..2f81a50e --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_rational_resampler_xxx.xml @@ -0,0 +1,88 @@ + + + + Rational Resampler + blks2_rational_resampler_xxx + from gnuradio import blks2 + from gnuradio.gr import firdes + blks2.rational_resampler_$(type)( + interpolation=$interp, + decimation=$decim, +#if $taps.eval + taps=$taps, +#else + taps=None, +#end if +#if $fractional_bw.eval != 0 + fractional_bw=$fractional_bw, +#else + fractional_bw=None, +#end if +) + + Type + type + enum + + + + + + Decimation + decim + 1 + int + + + Interpolation + interp + 1 + int + + + Taps + taps + [] + $type.taps + + + Fractional BW + fractional_bw + 0 + real + + + in + $type.input + + + out + $type.output + + +Leave taps empty for automatic value. +Leave fractional bandwidth 0 for automatic value. + + diff --git a/grc/data/platforms/python/blocks/blks2_selector.xml b/grc/data/platforms/python/blocks/blks2_selector.xml new file mode 100644 index 00000000..457f8695 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_selector.xml @@ -0,0 +1,97 @@ + + + + Selector + blks2_selector + from grc_gnuradio import blks2 as grc_blks2 + grc_blks2.selector( + item_size=$type.size*$vlen, + num_inputs=$num_inputs, + num_outputs=$num_outputs, + input_index=$input_index, + output_index=$output_index, +) + set_input_index($input_index) + set_output_index($output_index) + + Type + type + enum + + + + + + + + Num Inputs + num_inputs + 2 + int + + + Num Outputs + num_outputs + 2 + int + + + Input Index + input_index + 0 + int + + + Output Index + output_index + 0 + int + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + $num_inputs + + + out + $type + $vlen + $num_outputs + + +Connect the sink at input index to the source at output index. Leave all other ports disconnected. + + diff --git a/grc/data/platforms/python/blocks/blks2_standard_squelch.xml b/grc/data/platforms/python/blocks/blks2_standard_squelch.xml new file mode 100644 index 00000000..fa32c6c3 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_standard_squelch.xml @@ -0,0 +1,32 @@ + + + + Standard Squelch + blks2_standard_squelch + from gnuradio import blks2 + blks2.standard_squelch(audio_rate=$audio_rate) +$id.set_threshold($threshold) + set_threshold($threshold) + + Audio Rate + audio_rate + real + + + Threshold + threshold + real + + + in + float + + + out + float + + diff --git a/grc/data/platforms/python/blocks/blks2_stream_to_vector_decimator.xml b/grc/data/platforms/python/blocks/blks2_stream_to_vector_decimator.xml new file mode 100644 index 00000000..25f8f7a6 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_stream_to_vector_decimator.xml @@ -0,0 +1,77 @@ + + + + Stream to Vec Decim + blks2_stream_to_vector_decimator + from gnuradio import blks2 + blks2.stream_to_vector_decimator( + item_size=$type.size, + sample_rate=$sample_rate, + vec_rate=$vec_rate, + vec_len=$vlen, +) + set_sample_rate($sample_rate) + set_vec_rate($vec_rate) + + IO Type + type + enum + + + + + + + + Sample Rate + sample_rate + samp_rate + real + + + Vec Rate + vec_rate + 30 + real + + + Vec Length + vlen + 1024 + int + + $vlen >= 1 + + in + $type + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/blks2_synthesis_filterbank.xml b/grc/data/platforms/python/blocks/blks2_synthesis_filterbank.xml new file mode 100644 index 00000000..5979ed3f --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_synthesis_filterbank.xml @@ -0,0 +1,32 @@ + + + + Synthesis Filterbank + blks2_synthesis_filterbank + from gnuradio import blks2 + blks2.synthesis_filterbank(mpoints=$mpoints, taps=$taps) + + MPoints + mpoints + 3 + int + + + Taps + taps + complex_vector + + + in + complex + $mpoints + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/blks2_valve.xml b/grc/data/platforms/python/blocks/blks2_valve.xml new file mode 100644 index 00000000..47c55352 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_valve.xml @@ -0,0 +1,72 @@ + + + + Valve + blks2_valve + from grc_gnuradio import blks2 as grc_blks2 + grc_blks2.valve(item_size=$type.size*$vlen, open=bool($open)) + set_open(bool($open)) + + Type + type + enum + + + + + + + + Open + open + 0 + raw + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + $num_inputs + + + out + $type + $vlen + $num_outputs + + +Connect output to input when valve is closed (not open). + + diff --git a/grc/data/platforms/python/blocks/blks2_wfm_rcv.xml b/grc/data/platforms/python/blocks/blks2_wfm_rcv.xml new file mode 100644 index 00000000..37fb3ba8 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_wfm_rcv.xml @@ -0,0 +1,33 @@ + + + + WBFM Receive + blks2_wfm_rcv + from gnuradio import blks2 + blks2.wfm_rcv( + quad_rate=$quad_rate, + audio_decimation=$audio_decimation, +) + + Quadrature Rate + quad_rate + real + + + Audio Decimation + audio_decimation + int + + + in + complex + + + out + float + + diff --git a/grc/data/platforms/python/blocks/blks2_wfm_rcv_pll.xml b/grc/data/platforms/python/blocks/blks2_wfm_rcv_pll.xml new file mode 100644 index 00000000..3563a1f2 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_wfm_rcv_pll.xml @@ -0,0 +1,33 @@ + + + + WBFM Receive PLL + blks2_wfm_rcv_pll + from gnuradio import blks2 + blks2.wfm_rcv_pll( + demod_rate=$quad_rate, + audio_decimation=$audio_decimation, +) + + Quadrature Rate + quad_rate + real + + + Audio Decimation + audio_decimation + int + + + in + complex + + + out + float + + diff --git a/grc/data/platforms/python/blocks/blks2_wfm_tx.xml b/grc/data/platforms/python/blocks/blks2_wfm_tx.xml new file mode 100644 index 00000000..cff92d81 --- /dev/null +++ b/grc/data/platforms/python/blocks/blks2_wfm_tx.xml @@ -0,0 +1,48 @@ + + + + WBFM Transmit + blks2_wfm_tx + from gnuradio import blks2 + blks2.wfm_tx( + audio_rate=$audio_rate, + quad_rate=$quad_rate, + tau=$tau, + max_dev=$max_dev, +) + + Audio Rate + audio_rate + int + + + Quadrature Rate + quad_rate + int + + + Tau + tau + 75e-6 + real + + + Max Deviation + max_dev + 75e3 + real + + $quad_rate%$audio_rate == 0 + + in + float + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_add_const_vxx.xml b/grc/data/platforms/python/blocks/gr_add_const_vxx.xml new file mode 100644 index 00000000..9f1c545a --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_add_const_vxx.xml @@ -0,0 +1,67 @@ + + + + Add Const + gr_add_const_vxx + from gnuradio import gr + gr.add_const_v$(type.fcn)($const) + set_k($const) + + IO Type + type + enum + + + + + + + Constant + const + 0 + $type.const_type + + + Vec Length + vlen + 1 + int + + len($const) == $vlen + $vlen > 0 + + in + $type + $vlen + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_add_vxx.xml b/grc/data/platforms/python/blocks/gr_add_vxx.xml new file mode 100644 index 00000000..479cdaae --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_add_vxx.xml @@ -0,0 +1,63 @@ + + + + Add + gr_add_vxx + from gnuradio import gr + gr.add_v$(type.fcn)($vlen) + + IO Type + type + enum + + + + + + + Num Inputs + num_inputs + 2 + int + + + Vec Length + vlen + 1 + int + + $num_inputs > 1 + $vlen > 0 + + in + $type + $vlen + $num_inputs + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_agc2_xx.xml b/grc/data/platforms/python/blocks/gr_agc2_xx.xml new file mode 100644 index 00000000..fb3ae570 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_agc2_xx.xml @@ -0,0 +1,65 @@ + + + + AGC2 + gr_agc2_xx + from gnuradio import gr + gr.agc2_$(type.fcn)($attack_rate, $decay_rate, $reference, $gain, $max_gain) + + Type + type + enum + + + + + Attack Rate + attack_rate + 1e-1 + real + + + Decay Rate + decay_rate + 1e-2 + real + + + Reference + reference + 1.0 + real + + + Gain + gain + 1.0 + real + + + Max Gain + max_gain + 0.0 + real + + + in + $type + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_agc_xx.xml b/grc/data/platforms/python/blocks/gr_agc_xx.xml new file mode 100644 index 00000000..c87d239e --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_agc_xx.xml @@ -0,0 +1,59 @@ + + + + AGC + gr_agc_xx + from gnuradio import gr + gr.agc_$(type.fcn)($rate, $reference, $gain, $max_gain) + + Type + type + enum + + + + + Rate + rate + 1e-4 + real + + + Reference + reference + 1.0 + real + + + Gain + gain + 1.0 + real + + + Max Gain + max_gain + 0.0 + real + + + in + $type + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_and_xx.xml b/grc/data/platforms/python/blocks/gr_and_xx.xml new file mode 100644 index 00000000..9ed00609 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_and_xx.xml @@ -0,0 +1,48 @@ + + + + And + gr_and_xx + from gnuradio import gr + gr.and_$(type.fcn)() + + IO Type + type + enum + + + + + + Num Inputs + num_inputs + 2 + int + + $num_inputs >= 2 + + in + $type + $num_inputs + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_argmax_xx.xml b/grc/data/platforms/python/blocks/gr_argmax_xx.xml new file mode 100644 index 00000000..e3e4e3ea --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_argmax_xx.xml @@ -0,0 +1,58 @@ + + + + Argmax + gr_argmax_xx + from gnuradio import gr + gr.argmax_$(type.fcn)($vlen) + + IO Type + type + enum + + + + + + Num Inputs + num_inputs + 2 + int + + + Vec Length + vlen + 1 + int + + $num_inputs >= 2 + $vlen >= 1 + + in + $type + $vlen + $num_inputs + + + out + short + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_binary_slicer_fb.xml b/grc/data/platforms/python/blocks/gr_binary_slicer_fb.xml new file mode 100644 index 00000000..85d71e70 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_binary_slicer_fb.xml @@ -0,0 +1,20 @@ + + + + Binary Slicer + gr_binary_slicer_fb + from gnuradio import gr + gr.binary_slicer_fb() + + in + float + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_char_to_float.xml b/grc/data/platforms/python/blocks/gr_char_to_float.xml new file mode 100644 index 00000000..9ab77805 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_char_to_float.xml @@ -0,0 +1,20 @@ + + + + Char To Float + gr_char_to_float + from gnuradio import gr + gr.char_to_float() + + in + byte + + + out + float + + diff --git a/grc/data/platforms/python/blocks/gr_chunks_to_symbols.xml b/grc/data/platforms/python/blocks/gr_chunks_to_symbols.xml new file mode 100644 index 00000000..b54e710e --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_chunks_to_symbols.xml @@ -0,0 +1,68 @@ + + + + Chunks to Symbols + gr_chunks_to_symbols_xx + from gnuradio import gr + gr.chunks_to_symbols_$(in_type.fcn)$(out_type.fcn)($symbol_table, $dimension) + + Input Type + in_type + enum + + + + + + Output Type + out_type + enum + + + + + Symbol Table + symbol_table + $out_type.table + + + Dimension + dimension + 2 + int + + + in + $in_type + + + out + $out_type + + diff --git a/grc/data/platforms/python/blocks/gr_clock_recovery_mm_xx.xml b/grc/data/platforms/python/blocks/gr_clock_recovery_mm_xx.xml new file mode 100644 index 00000000..613cc23b --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_clock_recovery_mm_xx.xml @@ -0,0 +1,64 @@ + + + + Clock Recovery MM + gr_clock_recovery_mm_xx + from gnuradio import gr + gr.clock_recovery_mm_$(type.fcn)($omega, $gain_omega, $mu, $gain_mu, $omega_relative_limit) + set_omega($omega) + set_gain_omega($gain_omega) + set_mu($mu) + set_gain_mu($gain_mu) + + Type + type + enum + + + + + Omega + omega + real + + + Gain Omega + gain_omega + real + + + Mu + mu + real + + + Gain Mu + gain_mu + real + + + Omega Relative Limit + omega_relative_limit + real + + + in + $type + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_cma_equalizer_cc.xml b/grc/data/platforms/python/blocks/gr_cma_equalizer_cc.xml new file mode 100644 index 00000000..142fb6d8 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_cma_equalizer_cc.xml @@ -0,0 +1,36 @@ + + + + CMA Equalizer + gr_cma_equalizer_cc + from gnuradio import gr + gr.cma_equalizer_cc($num_taps, $modulus, $mu) + + Num Taps + num_taps + 64 + int + + + Modulus + modulus + real + + + Mu + mu + real + + + in + complex + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_complex_to_arg.xml b/grc/data/platforms/python/blocks/gr_complex_to_arg.xml new file mode 100644 index 00000000..a7bbacd7 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_complex_to_arg.xml @@ -0,0 +1,29 @@ + + + + Complex to Arg + gr_complex_to_arg + from gnuradio import gr + gr.complex_to_arg($vlen) + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + complex + $vlen + + + out + float + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_complex_to_float.xml b/grc/data/platforms/python/blocks/gr_complex_to_float.xml new file mode 100644 index 00000000..5b02c3d3 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_complex_to_float.xml @@ -0,0 +1,36 @@ + + + + Complex To Float + gr_complex_to_float + from gnuradio import gr + gr.complex_to_float($vlen) + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + complex + $vlen + + + out + float + $vlen + + + out + float + $vlen + 1 + + diff --git a/grc/data/platforms/python/blocks/gr_complex_to_imag.xml b/grc/data/platforms/python/blocks/gr_complex_to_imag.xml new file mode 100644 index 00000000..7c120eed --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_complex_to_imag.xml @@ -0,0 +1,29 @@ + + + + Complex to Imag + gr_complex_to_imag + from gnuradio import gr + gr.complex_to_imag($vlen) + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + complex + $vlen + + + out + float + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_complex_to_interleaved_short.xml b/grc/data/platforms/python/blocks/gr_complex_to_interleaved_short.xml new file mode 100644 index 00000000..5e999599 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_complex_to_interleaved_short.xml @@ -0,0 +1,20 @@ + + + + Complex To IShort + gr_complex_to_interleaved_short + from gnuradio import gr + gr.complex_to_interleaved_short() + + in + complex + + + out + short + + diff --git a/grc/data/platforms/python/blocks/gr_complex_to_mag.xml b/grc/data/platforms/python/blocks/gr_complex_to_mag.xml new file mode 100644 index 00000000..adc95f20 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_complex_to_mag.xml @@ -0,0 +1,29 @@ + + + + Complex to Mag + gr_complex_to_mag + from gnuradio import gr + gr.complex_to_mag($vlen) + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + complex + $vlen + + + out + float + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_complex_to_mag_squared.xml b/grc/data/platforms/python/blocks/gr_complex_to_mag_squared.xml new file mode 100644 index 00000000..cd23bfb5 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_complex_to_mag_squared.xml @@ -0,0 +1,29 @@ + + + + Complex to Mag^2 + gr_complex_to_mag_squared + from gnuradio import gr + gr.complex_to_mag_squared($vlen) + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + complex + $vlen + + + out + float + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_complex_to_real.xml b/grc/data/platforms/python/blocks/gr_complex_to_real.xml new file mode 100644 index 00000000..ae9ec7b1 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_complex_to_real.xml @@ -0,0 +1,29 @@ + + + + Complex to Real + gr_complex_to_real + from gnuradio import gr + gr.complex_to_real($vlen) + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + complex + $vlen + + + out + float + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_conjugate_cc.xml b/grc/data/platforms/python/blocks/gr_conjugate_cc.xml new file mode 100644 index 00000000..0b4deb34 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_conjugate_cc.xml @@ -0,0 +1,20 @@ + + + + Complex Conjugate + gr_conjugate_cc + from gnuradio import gr + gr.conjugate_cc() + + in + complex + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_constellation_decoder_cb.xml b/grc/data/platforms/python/blocks/gr_constellation_decoder_cb.xml new file mode 100644 index 00000000..99d897a3 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_constellation_decoder_cb.xml @@ -0,0 +1,30 @@ + + + + Constellation Decoder + gr_constellation_decoder_cb + from gnuradio import gr + gr.constellation_decoder_cb($sym_position, $sym_value_out) + + Symbol Position + sym_position + complex_vector + + + Symbol Value Out + sym_value_out + int_vector + + + in + complex + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_correlate_access_code_bb.xml b/grc/data/platforms/python/blocks/gr_correlate_access_code_bb.xml new file mode 100644 index 00000000..e13d2d07 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_correlate_access_code_bb.xml @@ -0,0 +1,31 @@ + + + + Correlate Access Code + gr_correlate_access_code_bb + from gnuradio import gr + gr.correlate_access_code_bb($access_code, $threshold) + + Access Code + access_code + 101010 + string + + + Threshold + threshold + int + + + in + byte + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_costas_loop_cc.xml b/grc/data/platforms/python/blocks/gr_costas_loop_cc.xml new file mode 100644 index 00000000..e0db8bc5 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_costas_loop_cc.xml @@ -0,0 +1,52 @@ + + + + Costas Loop + gr_costas_loop_cc + from gnuradio import gr + gr.costas_loop_cc($alpha, $beta, $max_freq, $min_freq, $order) + set_alpha($alpha) + set_beta($beta) + + Alpha + alpha + real + + + Beta + beta + real + + + Max Freq + max_freq + real + + + Min Freq + min_freq + real + + + Order + order + int + + + in + complex + + + out + complex + + + out + complex + 1 + + diff --git a/grc/data/platforms/python/blocks/gr_cpfsk_bc.xml b/grc/data/platforms/python/blocks/gr_cpfsk_bc.xml new file mode 100644 index 00000000..12450b0c --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_cpfsk_bc.xml @@ -0,0 +1,37 @@ + + + + CPFSK + gr_cpfsk_bc + from gnuradio import gr + cpfsk_bc($k, $amplitude, $samples_per_symbol) + set_amplitude($amplitude) + + K + k + real + + + Amplitude + amplitude + real + + + Samples/Symbol + samples_per_symbol + 2 + int + + + in + byte + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_dd_mpsk_sync_cc.xml b/grc/data/platforms/python/blocks/gr_dd_mpsk_sync_cc.xml new file mode 100644 index 00000000..aed0e8d3 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_dd_mpsk_sync_cc.xml @@ -0,0 +1,65 @@ + + + + DD MPSK Sync + gr_dd_mpsk_sync_cc + from gnuradio import gr + gr.dd_mpsk_sync_cc($alpha, $beta, $max_freq, $min_freq, $ref_phase, $omega, $gain_omega, $mu, $gain_mu) + + Alpha + alpha + real + + + Beta + beta + real + + + Max Freq + max_freq + real + + + Min Freq + min_freq + real + + + Reference Phase + ref_phase + real + + + Omega + omega + real + + + Gain Omega + gain_omega + real + + + Mu + mu + real + + + Gain Mu + gain_mu + real + + + in + complex + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_decode_ccsds_27_fb.xml b/grc/data/platforms/python/blocks/gr_decode_ccsds_27_fb.xml new file mode 100644 index 00000000..03b31db8 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_decode_ccsds_27_fb.xml @@ -0,0 +1,20 @@ + + + + Decode CCSDS 27 + gr_decode_ccsds_27_fb + from gnuradio import gr + gr.decode_ccsds_27_fb() + + in + float + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_deinterleave.xml b/grc/data/platforms/python/blocks/gr_deinterleave.xml new file mode 100644 index 00000000..a7482978 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_deinterleave.xml @@ -0,0 +1,67 @@ + + + + Deinterleave + gr_deinterleave + from gnuradio import gr + gr.deinterleave($type.size*$vlen) + + IO Type + type + enum + + + + + + + + Num Streams + num_streams + 2 + int + + + Vec Length + vlen + 1 + int + + $num_streams > 0 + $vlen >= 1 + + in + $type + $vlen + + + out + $type + $vlen + $num_streams + + diff --git a/grc/data/platforms/python/blocks/gr_delay.xml b/grc/data/platforms/python/blocks/gr_delay.xml new file mode 100644 index 00000000..b9d42979 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_delay.xml @@ -0,0 +1,65 @@ + + + + Delay + gr_delay + from gnuradio import gr + gr.head($type.size*$vlen, $delay) + + Type + type + enum + + + + + + + + Delay + delay + 0 + int + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_diff_decoder_bb.xml b/grc/data/platforms/python/blocks/gr_diff_decoder_bb.xml new file mode 100644 index 00000000..ea7cf173 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_diff_decoder_bb.xml @@ -0,0 +1,25 @@ + + + + Differential Decoder + gr_diff_decoder_bb + from gnuradio import gr + gr.diff_decoder_bb($modulus) + + Modulus + modulus + int + + + in + byte + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_diff_encoder_bb.xml b/grc/data/platforms/python/blocks/gr_diff_encoder_bb.xml new file mode 100644 index 00000000..21241eac --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_diff_encoder_bb.xml @@ -0,0 +1,25 @@ + + + + Differential Encoder + gr_diff_encoder_bb + from gnuradio import gr + gr.diff_encoder_bb($modulus) + + Modulus + modulus + int + + + in + byte + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_diff_phasor_cc.xml b/grc/data/platforms/python/blocks/gr_diff_phasor_cc.xml new file mode 100644 index 00000000..2b2d7e37 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_diff_phasor_cc.xml @@ -0,0 +1,20 @@ + + + + Differential Phasor + gr_diff_phasor_cc + from gnuradio import gr + gr.diff_phasor_cc() + + in + complex + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_divide_xx.xml b/grc/data/platforms/python/blocks/gr_divide_xx.xml new file mode 100644 index 00000000..7f875291 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_divide_xx.xml @@ -0,0 +1,54 @@ + + + + Divide + gr_divide_xx + from gnuradio import gr + gr.divide_$(type.fcn)() + + IO Type + type + enum + + + + + + + Num Inputs + num_inputs + 2 + int + + $num_inputs >= 2 + + in + $type + $num_inputs + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_dpll_bb.xml b/grc/data/platforms/python/blocks/gr_dpll_bb.xml new file mode 100644 index 00000000..044d398f --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_dpll_bb.xml @@ -0,0 +1,30 @@ + + + + Detect Peak + gr_dpll_bb + from gnuradio import gr + gr.dpll_bb($period, $gain) + + Period + period + real + + + Gain + gain + real + + + in + byte + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_encode_ccsds_27_bb.xml b/grc/data/platforms/python/blocks/gr_encode_ccsds_27_bb.xml new file mode 100644 index 00000000..f31e6b6c --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_encode_ccsds_27_bb.xml @@ -0,0 +1,20 @@ + + + + Encode CCSDS 27 + gr_encode_ccsds_27_bb + from gnuradio import gr + gr.encode_ccsds_27_bb() + + in + byte + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_feedforward_agc_cc.xml b/grc/data/platforms/python/blocks/gr_feedforward_agc_cc.xml new file mode 100644 index 00000000..24e80953 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_feedforward_agc_cc.xml @@ -0,0 +1,32 @@ + + + + Feed Forward AGC + gr_feedforward_agc_cc + from gnuradio import gr + gr.feedforward_agc_cc($num_samples, $reference) + + Num Samples + num_samples + 1024 + int + + + Reference + reference + 1.0 + real + + + in + complex + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_fft_filter_xxx.xml b/grc/data/platforms/python/blocks/gr_fft_filter_xxx.xml new file mode 100644 index 00000000..c1633094 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_fft_filter_xxx.xml @@ -0,0 +1,52 @@ + + + + FFT Filter + gr_fft_filter_xxx + from gnuradio import gr + from gnuradio.gr import firdes + gr.fft_filter_$(type)($decim, $taps) + set_taps($taps) + + Type + type + enum + + + + + Decimation + decim + 1 + int + + + Taps + taps + $type.taps + + + in + $type.input + + + out + $type.output + + diff --git a/grc/data/platforms/python/blocks/gr_fft_vxx.xml b/grc/data/platforms/python/blocks/gr_fft_vxx.xml new file mode 100644 index 00000000..c2c13d0a --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_fft_vxx.xml @@ -0,0 +1,81 @@ + + + + FFT + gr_fft_vxx + from gnuradio import gr + from gnuradio import window + #if $type.eval == "complex" +gr.fft_vcc($fft_size, $forward, $window, $shift) +#else +gr.fft_vfc($fft_size, $forward, $window) +#end if + + Input Type + type + enum + + + + + FFT Size + fft_size + 1024 + int + + + Forward/Reverse + forward + enum + + + + + Window + window + window.blackmanharris(1024) + real_vector + + + Shift + shift + enum + $type.hide_shift + + + + + in + $type + $fft_size + + + out + complex + $fft_size + + diff --git a/grc/data/platforms/python/blocks/gr_file_sink.xml b/grc/data/platforms/python/blocks/gr_file_sink.xml new file mode 100644 index 00000000..880dc275 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_file_sink.xml @@ -0,0 +1,60 @@ + + + + File Sink + gr_file_sink + from gnuradio import gr + gr.file_sink($type.size*$vlen, $file) + + File + file + + file_save + + + Input Type + type + enum + + + + + + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_file_source.xml b/grc/data/platforms/python/blocks/gr_file_source.xml new file mode 100644 index 00000000..fcc7a704 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_file_source.xml @@ -0,0 +1,74 @@ + + + + File Source + gr_file_source + from gnuradio import gr + gr.file_source($type.size*$vlen, $file, $repeat) + + File + file + + file_open + + + Output Type + type + enum + + + + + + + + Repeat + repeat + True + enum + + + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_filter_delay_fc.xml b/grc/data/platforms/python/blocks/gr_filter_delay_fc.xml new file mode 100644 index 00000000..30d65bf8 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_filter_delay_fc.xml @@ -0,0 +1,31 @@ + + + + Filter Delay + gr_filter_delay_fc + from gnuradio import gr + from gnuradio.gr import firdes + gr.filter_delay_fc($taps) + + Taps + taps + real_vector + + + in + float + + + in + float + 1 + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_fir_filter_xxx.xml b/grc/data/platforms/python/blocks/gr_fir_filter_xxx.xml new file mode 100644 index 00000000..c4de8f53 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_fir_filter_xxx.xml @@ -0,0 +1,80 @@ + + + + Decimating FIR Filter + gr_fir_filter_xxx + from gnuradio import gr + from gnuradio.gr import firdes + gr.fir_filter_$(type)($decim, $taps) + set_taps($taps) + + Type + type + enum + + + + + + + + + Decimation + decim + 1 + int + + + Taps + taps + $type.taps + + + in + $type.input + + + out + $type.output + + diff --git a/grc/data/platforms/python/blocks/gr_float_to_char.xml b/grc/data/platforms/python/blocks/gr_float_to_char.xml new file mode 100644 index 00000000..5714130a --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_float_to_char.xml @@ -0,0 +1,20 @@ + + + + Float To Char + gr_float_to_char + from gnuradio import gr + gr.gr_float_to_char() + + in + float + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_float_to_complex.xml b/grc/data/platforms/python/blocks/gr_float_to_complex.xml new file mode 100644 index 00000000..e8734fc6 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_float_to_complex.xml @@ -0,0 +1,26 @@ + + + + Float To Complex + gr_float_to_complex + from gnuradio import gr + gr.float_to_complex() + + in + float + + + in + float + 1 + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_float_to_short.xml b/grc/data/platforms/python/blocks/gr_float_to_short.xml new file mode 100644 index 00000000..cb2bcd4b --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_float_to_short.xml @@ -0,0 +1,20 @@ + + + + Float To Short + gr_float_to_short + from gnuradio import gr + gr.float_to_short() + + in + float + + + out + short + + diff --git a/grc/data/platforms/python/blocks/gr_float_to_uchar.xml b/grc/data/platforms/python/blocks/gr_float_to_uchar.xml new file mode 100644 index 00000000..aa804d7d --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_float_to_uchar.xml @@ -0,0 +1,20 @@ + + + + Float To UChar + gr_float_to_uchar + from gnuradio import gr + gr.float_to_uchar() + + in + float + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_fractional_interpolator_xx.xml b/grc/data/platforms/python/blocks/gr_fractional_interpolator_xx.xml new file mode 100644 index 00000000..8d65ff8b --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_fractional_interpolator_xx.xml @@ -0,0 +1,46 @@ + + + + Fractional Interpolator + gr_fractional_interpolator_xx + from gnuradio import gr + gr.fractional_interpolator_$(type.fcn)($phase_shift, $interp_ratio) + set_interp_ratio($interp_ratio) + + Type + type + enum + + + + + Phase Shift + phase_shift + real + + + Interpolation Ratio + interp_ratio + real + + + in + $type + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_freq_xlating_fir_filter_xxx.xml b/grc/data/platforms/python/blocks/gr_freq_xlating_fir_filter_xxx.xml new file mode 100644 index 00000000..e3ee6697 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_freq_xlating_fir_filter_xxx.xml @@ -0,0 +1,93 @@ + + + + Frequency Xlating FIR Filter + gr_freq_xlating_fir_filter_xxx + from gnuradio import gr + from gnuradio.gr import firdes + gr.freq_xlating_fir_filter_$(type)($decim, $taps, $center_freq, $samp_rate) + set_taps($taps) + set_center_freq($center_freq) + + Type + type + enum + + + + + + + + + Decimation + decim + 1 + int + + + Taps + taps + $type.taps + + + Center Frequency + center_freq + 0 + real + + + Sample Rate + samp_rate + samp_rate + real + + + in + $type.input + + + out + $type.output + + diff --git a/grc/data/platforms/python/blocks/gr_frequency_modulator_fc.xml b/grc/data/platforms/python/blocks/gr_frequency_modulator_fc.xml new file mode 100644 index 00000000..f18d9f1e --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_frequency_modulator_fc.xml @@ -0,0 +1,25 @@ + + + + Frequency Mod + gr_frequency_modulator_fc + from gnuradio import gr + gr.frequency_modulator_fc($sensitivity) + + Sensitivity + sensitivity + real + + + in + float + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_glfsr_source_x.xml b/grc/data/platforms/python/blocks/gr_glfsr_source_x.xml new file mode 100644 index 00000000..88fb6679 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_glfsr_source_x.xml @@ -0,0 +1,59 @@ + + + + GLFSR Source + gr_glfsr_source_x + from gnuradio import gr + gr.glfsr_source_$(type.fcn)($degree, $repeat, $mask, $seed) + + Type + type + enum + + + + + Degree + degree + int + + + Repeat + repeat + enum + + + + + Mask + mask + int + + + Seed + seed + int + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_goertzel_fc.xml b/grc/data/platforms/python/blocks/gr_goertzel_fc.xml new file mode 100644 index 00000000..2105445d --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_goertzel_fc.xml @@ -0,0 +1,35 @@ + + + + Goertzel + gr_goertzel_fc + from gnuradio import gr + gr.goertzel_fc($rate, $len, $freq) + + Rate + rate + int + + + Length + len + int + + + Frequency + freq + real + + + in + float + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_head.xml b/grc/data/platforms/python/blocks/gr_head.xml new file mode 100644 index 00000000..e5ff7f6a --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_head.xml @@ -0,0 +1,65 @@ + + + + Head + gr_head + from gnuradio import gr + gr.head($type.size*$vlen, $num_items) + + Type + type + enum + + + + + + + + Num Items + num_items + 1024 + int + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_hilbert_fc.xml b/grc/data/platforms/python/blocks/gr_hilbert_fc.xml new file mode 100644 index 00000000..165e8da2 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_hilbert_fc.xml @@ -0,0 +1,26 @@ + + + + Hilbert + gr_hilbert_fc + from gnuradio import gr + gr.hilbert_fc($num_taps) + + Num Taps + num_taps + 64 + int + + + in + float + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_iir_filter_ffd.xml b/grc/data/platforms/python/blocks/gr_iir_filter_ffd.xml new file mode 100644 index 00000000..9799150e --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_iir_filter_ffd.xml @@ -0,0 +1,31 @@ + + + + IIR Filter + gr_iir_filter_ffd + from gnuradio import gr + gr.iir_filter_ffd($fftaps, $fbtaps) + set_taps($fftaps, $fbtaps) + + Feed-forward Taps + fftaps + real_vector + + + Feedback Taps + fbtaps + real_vector + + + in + float + + + out + float + + diff --git a/grc/data/platforms/python/blocks/gr_integrate_xx.xml b/grc/data/platforms/python/blocks/gr_integrate_xx.xml new file mode 100644 index 00000000..d0ebd42e --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_integrate_xx.xml @@ -0,0 +1,50 @@ + + + + Integrate + gr_integrate_xx + from gnuradio import gr + gr.integrate_$(type.fcn)($decim) + + IO Type + type + enum + + + + + + + Decimation + decim + int + + + in + $type + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_interleave.xml b/grc/data/platforms/python/blocks/gr_interleave.xml new file mode 100644 index 00000000..3db16ab5 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_interleave.xml @@ -0,0 +1,67 @@ + + + + Interleave + gr_interleave + from gnuradio import gr + gr.interleave($type.size*$vlen) + + IO Type + type + enum + + + + + + + + Num Streams + num_streams + 2 + int + + + Vec Length + vlen + 1 + int + + $num_streams > 0 + $vlen >= 1 + + in + $type + $vlen + $num_streams + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_interleaved_short_to_complex.xml b/grc/data/platforms/python/blocks/gr_interleaved_short_to_complex.xml new file mode 100644 index 00000000..e3023e49 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_interleaved_short_to_complex.xml @@ -0,0 +1,20 @@ + + + + IShort To Complex + gr_interleaved_short_to_complex + from gnuradio import gr + gr.interleaved_short_to_complex() + + in + short + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_interp_fir_filter_xxx.xml b/grc/data/platforms/python/blocks/gr_interp_fir_filter_xxx.xml new file mode 100644 index 00000000..55375ae0 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_interp_fir_filter_xxx.xml @@ -0,0 +1,80 @@ + + + + Interpolating FIR Filter + gr_interp_fir_filter_xxx + from gnuradio import gr + from gnuradio.gr import firdes + gr.interp_fir_filter_$(type)($interp, $taps) + set_taps($taps) + + Type + type + enum + + + + + + + + + Interpolation + interp + 1 + int + + + Taps + taps + $type.taps + + + in + $type.input + + + out + $type.output + + diff --git a/grc/data/platforms/python/blocks/gr_iqcomp_cc.xml b/grc/data/platforms/python/blocks/gr_iqcomp_cc.xml new file mode 100644 index 00000000..1603bdc4 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_iqcomp_cc.xml @@ -0,0 +1,25 @@ + + + + IQ Comp + gr_iqcomp_cc + from gnuradio import gr + gr.iqcomp_cc($mu) + + Mu + mu + real + + + in + complex + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_keep_one_in_n.xml b/grc/data/platforms/python/blocks/gr_keep_one_in_n.xml new file mode 100644 index 00000000..21595b75 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_keep_one_in_n.xml @@ -0,0 +1,67 @@ + + + + Keep 1 in N + gr_keep_one_in_n + from gnuradio import gr + gr.keep_one_in_n($type.size*$vlen, $n) + set_n($n) + + Type + type + enum + + + + + + + + N + n + 1 + int + + + Vec Length + vlen + 1 + int + + $n > 0 + $vlen > 0 + + in + $type + $vlen + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_kludge_copy.xml b/grc/data/platforms/python/blocks/gr_kludge_copy.xml new file mode 100644 index 00000000..3c817c57 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_kludge_copy.xml @@ -0,0 +1,59 @@ + + + + Copy + gr_kludge_copy + from gnuradio import gr + gr.kludge_copy($type.size*$vlen) + + Type + type + enum + + + + + + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_map_bb.xml b/grc/data/platforms/python/blocks/gr_map_bb.xml new file mode 100644 index 00000000..20d6bd2b --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_map_bb.xml @@ -0,0 +1,25 @@ + + + + Map + gr_map_bb + from gnuradio import gr + gr.map_bb($map) + + Map + map + int_vector + + + in + byte + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_max_xx.xml b/grc/data/platforms/python/blocks/gr_max_xx.xml new file mode 100644 index 00000000..9dbbe60e --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_max_xx.xml @@ -0,0 +1,58 @@ + + + + Max + gr_max_xx + from gnuradio import gr + gr.max_$(type.fcn)($vlen) + + IO Type + type + enum + + + + + + Num Inputs + num_inputs + 2 + int + + + Vec Length + vlen + 1 + int + + $num_inputs >= 2 + $vlen >= 1 + + in + $type + $vlen + $num_inputs + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_moving_average_xx.xml b/grc/data/platforms/python/blocks/gr_moving_average_xx.xml new file mode 100644 index 00000000..2c3be403 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_moving_average_xx.xml @@ -0,0 +1,67 @@ + + + + Moving Average + gr_moving_average_xx + from gnuradio import gr + gr.moving_average_$(type.fcn)($length, $scale, $max_iter) + + Type + type + enum + + + + + + + Length + length + 1000 + int + + + Scale + scale + 1 + $type.scale + + + Max Iter + max_iter + 4000 + int + + + in + $type + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_mpsk_receiver_cc.xml b/grc/data/platforms/python/blocks/gr_mpsk_receiver_cc.xml new file mode 100644 index 00000000..843c3a4c --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_mpsk_receiver_cc.xml @@ -0,0 +1,81 @@ + + + + MPSK Receiver + gr_mpsk_receiver_cc + from gnuradio import gr + gr.mpsk_receiver_cc($M, $theta, $alpha, $beta, $fmin, $fmax, $mu, $gain_mu, $omega, $gain_omega, $omega_relative_limit) + set_alpha($alpha) + set_beta($beta) + set_mu($mu) + set_gain_mu($gain_mu) + set_omega($omega) + set_gain_omega($gain_omega) + + M + M + int + + + Theta + theta + real + + + Alpha + alpha + real + + + Beta + beta + real + + + Min Freq + fmin + real + + + Max Freq + fmax + real + + + Mu + mu + real + + + Gain Mu + gain_mu + real + + + Omega + omega + real + + + Gain Omega + gain_omega + real + + + Omega Relative Limit + omega_relative_limit + real + + + in + complex + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_mpsk_sync_cc.xml b/grc/data/platforms/python/blocks/gr_mpsk_sync_cc.xml new file mode 100644 index 00000000..fd08f834 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_mpsk_sync_cc.xml @@ -0,0 +1,69 @@ + + + + MPSK Sync + gr_mpsk_sync_cc + from gnuradio import gr + gr.mpsk_sync_cc($alpha, $beta, $max_freq, $min_freq, $ref_phase, $omega, $gain_omega, $mu, $gain_mu) + set_mu($mu) + set_gain_mu($gain_mu) + set_omega($omega) + set_gain_omega($gain_omega) + + Alpha + alpha + real + + + Beta + beta + real + + + Max Freq + max_freq + real + + + Min Freq + min_freq + real + + + Reference Phase + ref_phase + real + + + Omega + omega + real + + + Gain Omega + gain_omega + real + + + Mu + mu + real + + + Gain Mu + gain_mu + real + + + in + complex + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_multiply_const_vxx.xml b/grc/data/platforms/python/blocks/gr_multiply_const_vxx.xml new file mode 100644 index 00000000..1309d75c --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_multiply_const_vxx.xml @@ -0,0 +1,67 @@ + + + + Multiply Const + gr_multiply_const_vxx + from gnuradio import gr + gr.multiply_const_v$(type.fcn)($const) + set_k($const) + + IO Type + type + enum + + + + + + + Constant + const + 0 + $type.const_type + + + Vec Length + vlen + 1 + int + + len($const) == $vlen + $vlen > 0 + + in + $type + $vlen + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_multiply_vxx.xml b/grc/data/platforms/python/blocks/gr_multiply_vxx.xml new file mode 100644 index 00000000..ea0d555b --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_multiply_vxx.xml @@ -0,0 +1,63 @@ + + + + Multiply + gr_multiply_vxx + from gnuradio import gr + gr.multiply_v$(type.fcn)($vlen) + + IO Type + type + enum + + + + + + + Num Inputs + num_inputs + 2 + int + + + Vec Length + vlen + 1 + int + + $num_inputs > 1 + $vlen > 0 + + in + $type + $vlen + $num_inputs + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_mute_xx.xml b/grc/data/platforms/python/blocks/gr_mute_xx.xml new file mode 100644 index 00000000..668d7c59 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_mute_xx.xml @@ -0,0 +1,53 @@ + + + + Mute + gr_mute_xx + from gnuradio import gr + gr.mute_$(type.fcn)(bool($mute)) + set_mute(bool($mute)) + + IO Type + type + enum + + + + + + + Mute + mute + False + raw + + + in + $type + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_nlog10_ff.xml b/grc/data/platforms/python/blocks/gr_nlog10_ff.xml new file mode 100644 index 00000000..93507823 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_nlog10_ff.xml @@ -0,0 +1,42 @@ + + + + Log10 + gr_nlog10_ff + from gnuradio import gr + gr.nlog10_ff($n, $vlen, $k) + + n + n + 1 + real + + + k + k + 0 + real + + + Vec Length + vlen + 1 + int + + $vlen >= 1 + + in + float + $vlen + + + out + float + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_noise_source_x.xml b/grc/data/platforms/python/blocks/gr_noise_source_x.xml new file mode 100644 index 00000000..664a108d --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_noise_source_x.xml @@ -0,0 +1,76 @@ + + + + Noise Source + gr_noise_source_x + from gnuradio import gr + gr.noise_source_$(type.fcn)($noise_type, $amp, $seed) + set_amplitude($amp) + + Output Type + type + enum + + + + + + + Noise Type + noise_type + gr.GR_GAUSSIAN + enum + + + + + + + Amplitude + amp + 1 + real + + + Seed + seed + 42 + int + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_nop.xml b/grc/data/platforms/python/blocks/gr_nop.xml new file mode 100644 index 00000000..127a78a5 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_nop.xml @@ -0,0 +1,59 @@ + + + + Nop + gr_nop + from gnuradio import gr + gr.nop($type.size*$vlen) + + Type + type + enum + + + + + + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_not_xx.xml b/grc/data/platforms/python/blocks/gr_not_xx.xml new file mode 100644 index 00000000..7af7e4b6 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_not_xx.xml @@ -0,0 +1,48 @@ + + + + Not + gr_not_xx + from gnuradio import gr + gr.not_$(type.fcn)() + + IO Type + type + enum + + + + + + Num Inputs + num_inputs + 2 + int + + $num_inputs >= 2 + + in + $type + $num_inputs + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_null_sink.xml b/grc/data/platforms/python/blocks/gr_null_sink.xml new file mode 100644 index 00000000..ed106b49 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_null_sink.xml @@ -0,0 +1,54 @@ + + + + Null Sink + gr_null_sink + from gnuradio import gr + gr.null_sink($type.size*$vlen) + + Input Type + type + enum + + + + + + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_null_source.xml b/grc/data/platforms/python/blocks/gr_null_source.xml new file mode 100644 index 00000000..6132eae3 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_null_source.xml @@ -0,0 +1,54 @@ + + + + Null Source + gr_null_source + from gnuradio import gr + gr.null_source($type.size*$vlen) + + Output Type + type + enum + + + + + + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_or_xx.xml b/grc/data/platforms/python/blocks/gr_or_xx.xml new file mode 100644 index 00000000..b374aa22 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_or_xx.xml @@ -0,0 +1,48 @@ + + + + Or + gr_or_xx + from gnuradio import gr + gr.or_$(type.fcn)() + + IO Type + type + enum + + + + + + Num Inputs + num_inputs + 2 + int + + $num_inputs >= 2 + + in + $type + $num_inputs + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_packed_to_unpacked_xx.xml b/grc/data/platforms/python/blocks/gr_packed_to_unpacked_xx.xml new file mode 100644 index 00000000..5fd9729a --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_packed_to_unpacked_xx.xml @@ -0,0 +1,59 @@ + + + + Packed to Unpacked + gr_packed_to_unpacked_xx + from gnuradio import gr + gr.packed_to_unpacked_$(type.fcn)($bits_per_chunk, $endianness) + + Type + type + enum + + + + + + Bits per Chunk + bits_per_chunk + 2 + int + + + Endianness + endianness + enum + + + + + in + $type + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_peak_detector2_fb.xml b/grc/data/platforms/python/blocks/gr_peak_detector2_fb.xml new file mode 100644 index 00000000..6c496da7 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_peak_detector2_fb.xml @@ -0,0 +1,58 @@ + + + + Peak Detector2 + gr_peak_detector2_fb + from gnuradio import gr + gr.peak_detector2_fb($threshold_factor_rise, $look_ahead, $alpha) + set_threshold_factor_rise($threshold_factor_rise) + set_look_ahead($look_ahead) + set_alpha($alpha) + + Input Type + type + enum + + + + + + TH Factor Rise + threshold_factor_rise + real + + + Look Ahead + look_ahead + int + + + Alpha + alpha + real + + + in + float + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_peak_detector_xb.xml b/grc/data/platforms/python/blocks/gr_peak_detector_xb.xml new file mode 100644 index 00000000..394b0697 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_peak_detector_xb.xml @@ -0,0 +1,64 @@ + + + + Peak Detector + gr_peak_detector_xb + from gnuradio import gr + gr.peak_detector_$(type.fcn)b($threshold_factor_rise, $threshold_factor_fall, $look_ahead, $alpha) + set_threshold_factor_rise($threshold_factor_rise) + set_threshold_factor_fall($threshold_factor_fall) + set_look_ahead($look_ahead) + set_alpha($alpha) + + Input Type + type + enum + + + + + + TH Factor Rise + threshold_factor_rise + real + + + TH Factor Fall + threshold_factor_fall + real + + + Look Ahead + look_ahead + int + + + Alpha + alpha + real + + + in + $type + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_phase_modulator_fc.xml b/grc/data/platforms/python/blocks/gr_phase_modulator_fc.xml new file mode 100644 index 00000000..758c5086 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_phase_modulator_fc.xml @@ -0,0 +1,25 @@ + + + + Phase Mod + gr_phase_modulator_fc + from gnuradio import gr + gr.phase_modulator_fc($sensitivity) + + Sensitivity + sensitivity + real + + + in + float + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_pll_carriertracking_cc.xml b/grc/data/platforms/python/blocks/gr_pll_carriertracking_cc.xml new file mode 100644 index 00000000..5b876b25 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_pll_carriertracking_cc.xml @@ -0,0 +1,40 @@ + + + + PLL Carrier Tracking + gr_pll_carriertracking_cc + from gnuradio import gr + gr.pll_carriertracking_cc($alpha, $beta, $max_freq, $min_freq) + + Alpha + alpha + real + + + Beta + beta + real + + + Max Freq + max_freq + real + + + Min Freq + min_freq + real + + + in + complex + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_pll_freqdet_cf.xml b/grc/data/platforms/python/blocks/gr_pll_freqdet_cf.xml new file mode 100644 index 00000000..8ec1fb3b --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_pll_freqdet_cf.xml @@ -0,0 +1,40 @@ + + + + PLL Freq Det + gr_pll_freqdet_cf + from gnuradio import gr + gr.pll_freqdet_cf($alpha, $beta, $max_freq, $min_freq) + + Alpha + alpha + real + + + Beta + beta + real + + + Max Freq + max_freq + real + + + Min Freq + min_freq + real + + + in + complex + + + out + float + + diff --git a/grc/data/platforms/python/blocks/gr_pll_refout_cc.xml b/grc/data/platforms/python/blocks/gr_pll_refout_cc.xml new file mode 100644 index 00000000..64cf2bfb --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_pll_refout_cc.xml @@ -0,0 +1,40 @@ + + + + PLL Ref Out + gr_pll_refout_cc + from gnuradio import gr + gr.pll_refout_cc($alpha, $beta, $max_freq, $min_freq) + + Alpha + alpha + real + + + Beta + beta + real + + + Max Freq + max_freq + real + + + Min Freq + min_freq + real + + + in + complex + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_pn_correlator_cc.xml b/grc/data/platforms/python/blocks/gr_pn_correlator_cc.xml new file mode 100644 index 00000000..094f46cd --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_pn_correlator_cc.xml @@ -0,0 +1,35 @@ + + + + PN Correlator + gr_pn_correlator_cc + from gnuradio import gr + gr.pn_correlator_cc($degree, $mask, $seed) + + Degree + degree + int + + + Mask + mask + int + + + Seed + seed + int + + + in + complex + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_pwr_squelch_xx.xml b/grc/data/platforms/python/blocks/gr_pwr_squelch_xx.xml new file mode 100644 index 00000000..08d62117 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_pwr_squelch_xx.xml @@ -0,0 +1,65 @@ + + + + Power Squelch + gr_pwr_squelch_xx + from gnuradio import gr + gr.pwr_squelch_$(type.fcn)($threshold, $alpha, $ramp, $gate) + set_threshold($threshold) + set_alpha($alpha) + + Type + type + enum + + + + + Threshold (dB) + threshold + real + + + Alpha + alpha + real + + + Ramp + ramp + int + + + Gate + gate + enum + + + + + in + $type + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_quadrature_demod_cf.xml b/grc/data/platforms/python/blocks/gr_quadrature_demod_cf.xml new file mode 100644 index 00000000..a0e630c7 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_quadrature_demod_cf.xml @@ -0,0 +1,25 @@ + + + + Quadrature Demod + gr_quadrature_demod_cf + from gnuradio import gr + gr.quadrature_demod_cf($gain) + + Gain + gain + real + + + in + complex + + + out + float + + diff --git a/grc/data/platforms/python/blocks/gr_rational_resampler_base_xxx.xml b/grc/data/platforms/python/blocks/gr_rational_resampler_base_xxx.xml new file mode 100644 index 00000000..4b772017 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_rational_resampler_base_xxx.xml @@ -0,0 +1,86 @@ + + + + Rational Resampler Base + gr_rational_resampler_base_xxx + from gnuradio import gr + from gnuradio.gr import firdes + gr.rational_resampler_base_$(type)($interp, $decim, $taps) + set_taps($taps) + + Type + type + enum + + + + + + + + + Interpolation + interp + 1 + int + + + Decimation + decim + 1 + int + + + Taps + taps + $type.taps + + + in + $type.input + + + out + $type.output + + diff --git a/grc/data/platforms/python/blocks/gr_repeat.xml b/grc/data/platforms/python/blocks/gr_repeat.xml new file mode 100644 index 00000000..ba652a4d --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_repeat.xml @@ -0,0 +1,64 @@ + + + + Repeat + gr_repeat + from gnuradio import gr + gr.repeat($type.size*$vlen, $interp) + + Type + type + enum + + + + + + + + Interpolation + interp + int + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_rms_xx.xml b/grc/data/platforms/python/blocks/gr_rms_xx.xml new file mode 100644 index 00000000..1e094719 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_rms_xx.xml @@ -0,0 +1,41 @@ + + + + RMS + gr_rms_xx + from gnuradio import gr + gr.rms_$(type.fcn)f($alpha) + set_alpha($alpha) + + Input Type + type + enum + + + + + Alpha + alpha + real + + + in + $type + + + out + float + + diff --git a/grc/data/platforms/python/blocks/gr_sample_and_hold_xx.xml b/grc/data/platforms/python/blocks/gr_sample_and_hold_xx.xml new file mode 100644 index 00000000..bfe66bb0 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_sample_and_hold_xx.xml @@ -0,0 +1,49 @@ + + + + Sample and Hold + gr_sample_and_hold_xx + from gnuradio import gr + gr.sample_and_hold_$(type.fcn)() + + Type + type + enum + + + + + + + in + $type + + + ctrl + $type + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_short_to_float.xml b/grc/data/platforms/python/blocks/gr_short_to_float.xml new file mode 100644 index 00000000..8dac97c0 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_short_to_float.xml @@ -0,0 +1,20 @@ + + + + Short To Float + gr_short_to_float + from gnuradio import gr + gr.short_to_float() + + in + short + + + out + float + + diff --git a/grc/data/platforms/python/blocks/gr_sig_source_x.xml b/grc/data/platforms/python/blocks/gr_sig_source_x.xml new file mode 100644 index 00000000..7ad0c20a --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_sig_source_x.xml @@ -0,0 +1,99 @@ + + + + Signal Source + gr_sig_source_x + from gnuradio import gr + gr.sig_source_$(type.fcn)($samp_rate, $waveform, $freq, $amp, $offset) + set_sampling_freq($samp_rate) + set_frequency($freq) + set_amplitude($amp) + set_offset($offset) + + Output Type + type + enum + + + + + + + Sample Rate + samp_rate + samp_rate + real + + + Waveform + waveform + gr.GR_COS_WAVE + enum + + + + + + + + + Frequency + freq + 1000 + real + + + Amplitude + amp + 1 + real + + + Offset + offset + 0 + complex + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_simple_correlator.xml b/grc/data/platforms/python/blocks/gr_simple_correlator.xml new file mode 100644 index 00000000..820523a6 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_simple_correlator.xml @@ -0,0 +1,25 @@ + + + + Simple Correlator + gr_simple_correlator + from gnuradio import gr + gr.simple_correlator($payload_bytesize) + + Payload Byte Size + payload_bytesize + int + + + in + float + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_simple_framer.xml b/grc/data/platforms/python/blocks/gr_simple_framer.xml new file mode 100644 index 00000000..2a0295c4 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_simple_framer.xml @@ -0,0 +1,25 @@ + + + + Simple Framer + gr_simple_framer + from gnuradio import gr + gr.simple_framer($payload_bytesize) + + Payload Byte Size + payload_bytesize + int + + + in + byte + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_simple_squelch_cc.xml b/grc/data/platforms/python/blocks/gr_simple_squelch_cc.xml new file mode 100644 index 00000000..5c0727f5 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_simple_squelch_cc.xml @@ -0,0 +1,32 @@ + + + + Simple Squelch + gr_simple_squelch_cc + from gnuradio import gr + gr.simple_squelch_cc($threshold, $alpha) + set_threshold($threshold) + set_alpha($alpha) + + Threshold (dB) + threshold + real + + + Alpha + alpha + real + + + in + complex + + + out + complex + + diff --git a/grc/data/platforms/python/blocks/gr_single_pole_iir_filter_xx.xml b/grc/data/platforms/python/blocks/gr_single_pole_iir_filter_xx.xml new file mode 100644 index 00000000..50cf4a82 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_single_pole_iir_filter_xx.xml @@ -0,0 +1,51 @@ + + + + Single Pole IIR Filter + gr_single_pole_iir_filter_xx + from gnuradio import gr + gr.single_pole_iir_filter_$(type.fcn)($alpha, $vlen) + set_taps($alpha) + + Type + type + enum + + + + + Alpha + alpha + 1.0 + real + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_skiphead.xml b/grc/data/platforms/python/blocks/gr_skiphead.xml new file mode 100644 index 00000000..0849ad29 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_skiphead.xml @@ -0,0 +1,65 @@ + + + + Skip Head + gr_skiphead + from gnuradio import gr + gr.skiphead($type.size*$vlen, $num_items) + + Type + type + enum + + + + + + + + Num Items + num_items + 1024 + int + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_stream_to_streams.xml b/grc/data/platforms/python/blocks/gr_stream_to_streams.xml new file mode 100644 index 00000000..82542b8d --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_stream_to_streams.xml @@ -0,0 +1,67 @@ + + + + Stream to Streams + gr_stream_to_streams + from gnuradio import gr + gr.stream_to_streams($type.size*$vlen, $num_streams) + + IO Type + type + enum + + + + + + + + Num Streams + num_streams + 2 + int + + + Vec Length + vlen + 1 + int + + $num_streams > 0 + $vlen >= 1 + + in + $type + $vlen + + + out + $type + $vlen + $num_streams + + diff --git a/grc/data/platforms/python/blocks/gr_stream_to_vector.xml b/grc/data/platforms/python/blocks/gr_stream_to_vector.xml new file mode 100644 index 00000000..296d786f --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_stream_to_vector.xml @@ -0,0 +1,66 @@ + + + + Stream to Vector + gr_stream_to_vector + from gnuradio import gr + gr.stream_to_vector($type.size*$vlen, $num_items) + + IO Type + type + enum + + + + + + + + Num Items + num_items + 2 + int + + + Vec Length + vlen + 1 + int + + $num_items > 0 + $vlen >= 1 + + in + $type + $vlen + + + out + $type + $vlen*$num_items + + diff --git a/grc/data/platforms/python/blocks/gr_streams_to_stream.xml b/grc/data/platforms/python/blocks/gr_streams_to_stream.xml new file mode 100644 index 00000000..7aadd7ee --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_streams_to_stream.xml @@ -0,0 +1,67 @@ + + + + Streams to Stream + gr_streams_to_stream + from gnuradio import gr + gr.streams_to_stream($type.size*$vlen, $num_streams) + + IO Type + type + enum + + + + + + + + Num Streams + num_streams + 2 + int + + + Vec Length + vlen + 1 + int + + $num_streams > 0 + $vlen >= 1 + + in + $type + $vlen + $num_streams + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_streams_to_vector.xml b/grc/data/platforms/python/blocks/gr_streams_to_vector.xml new file mode 100644 index 00000000..4ecdcb2d --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_streams_to_vector.xml @@ -0,0 +1,67 @@ + + + + Streams to Vector + gr_streams_to_vector + from gnuradio import gr + gr.streams_to_vector($type.size*$vlen, $num_streams) + + IO Type + type + enum + + + + + + + + Num Streams + num_streams + 2 + int + + + Vec Length + vlen + 1 + int + + $num_streams > 0 + $vlen >= 1 + + in + $type + $vlen + $num_streams + + + out + $type + $vlen*$num_streams + + diff --git a/grc/data/platforms/python/blocks/gr_sub_xx.xml b/grc/data/platforms/python/blocks/gr_sub_xx.xml new file mode 100644 index 00000000..488e6c36 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_sub_xx.xml @@ -0,0 +1,54 @@ + + + + Subtract + gr_sub_xx + from gnuradio import gr + gr.sub_$(type.fcn)() + + IO Type + type + enum + + + + + + + Num Inputs + num_inputs + 2 + int + + $num_inputs >= 2 + + in + $type + $num_inputs + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_threshold_ff.xml b/grc/data/platforms/python/blocks/gr_threshold_ff.xml new file mode 100644 index 00000000..97764d73 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_threshold_ff.xml @@ -0,0 +1,38 @@ + + + + Threshold + gr_threshold_ff + from gnuradio import gr + gr.threshold_ff($low, $high, $init) + + Low + low + -100 + real + + + High + high + 100 + real + + + Initial State + init + 0 + real + + + in + float + + + out + float + + diff --git a/grc/data/platforms/python/blocks/gr_throttle.xml b/grc/data/platforms/python/blocks/gr_throttle.xml new file mode 100644 index 00000000..ab8506f5 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_throttle.xml @@ -0,0 +1,65 @@ + + + + Throttle + gr_throttle + from gnuradio import gr + gr.throttle($type.size*$vlen, $samples_per_second) + + Type + type + enum + + + + + + + + Sample Rate + samples_per_second + samp_rate + real + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_uchar_to_float.xml b/grc/data/platforms/python/blocks/gr_uchar_to_float.xml new file mode 100644 index 00000000..0a5f7f96 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_uchar_to_float.xml @@ -0,0 +1,20 @@ + + + + UChar To Float + gr_uchar_to_float + from gnuradio import gr + gr.uchar_to_float() + + in + byte + + + out + float + + diff --git a/grc/data/platforms/python/blocks/gr_udp_sink.xml b/grc/data/platforms/python/blocks/gr_udp_sink.xml new file mode 100644 index 00000000..e9f6c2be --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_udp_sink.xml @@ -0,0 +1,85 @@ + + + + UDP Sink + gr_udp_sink + from gnuradio import gr + gr.udp_sink($type.size*$vlen, $ipaddr_local, $port_local, $ipaddr_remote, $port_remote, $mtu) + set_mtu($mtu) + + Input Type + type + enum + + + + + + + + Local IP Address + ipaddr_local + 127.0.0.1 + string + + + Local Port + port_local + 0 + int + + + Remote IP Address + ipaddr_remote + 127.0.0.1 + string + + + Remote Port + port_remote + 1234 + int + + + MTU + mtu + 1024 + int + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_udp_source.xml b/grc/data/platforms/python/blocks/gr_udp_source.xml new file mode 100644 index 00000000..f03adf80 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_udp_source.xml @@ -0,0 +1,73 @@ + + + + UDP Source + gr_udp_source + from gnuradio import gr + gr.udp_source($type.size*$vlen, $ipaddr, $port, $mtu) + set_mtu($mtu) + + Output Type + type + enum + + + + + + + + IP Address + ipaddr + 127.0.0.1 + string + + + Port + port + 1234 + int + + + MTU + mtu + 1024 + int + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_unpack_k_bits_bb.xml b/grc/data/platforms/python/blocks/gr_unpack_k_bits_bb.xml new file mode 100644 index 00000000..9917644a --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_unpack_k_bits_bb.xml @@ -0,0 +1,25 @@ + + + + Unpack K Bits + gr_unpack_k_bits_bb + from gnuradio import gr + gr.unpack_k_bits_bb($k) + + K + k + int + + + in + byte + + + out + byte + + diff --git a/grc/data/platforms/python/blocks/gr_unpacked_to_packed_xx.xml b/grc/data/platforms/python/blocks/gr_unpacked_to_packed_xx.xml new file mode 100644 index 00000000..f7457eb5 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_unpacked_to_packed_xx.xml @@ -0,0 +1,59 @@ + + + + Unpacked to Packed + gr_unpacked_to_packed_xx + from gnuradio import gr + gr.unpacked_to_packed_$(type.fcn)($bits_per_chunk, $endianness) + + Type + type + enum + + + + + + Bits per Chunk + bits_per_chunk + 2 + int + + + Endianness + endianness + enum + + + + + in + $type + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_vco_f.xml b/grc/data/platforms/python/blocks/gr_vco_f.xml new file mode 100644 index 00000000..e49c5396 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_vco_f.xml @@ -0,0 +1,35 @@ + + + + VCO + gr_vco_f + from gnuradio import gr + gr.vco_f($samp_rate, $sensitivity, $amplitude) + + Sample Rate + samp_rate + real + + + Sensitivity + sensitivity + real + + + Amplitude + amplitude + real + + + in + float + + + out + float + + diff --git a/grc/data/platforms/python/blocks/gr_vector_sink_x.xml b/grc/data/platforms/python/blocks/gr_vector_sink_x.xml new file mode 100644 index 00000000..d901b1d7 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_vector_sink_x.xml @@ -0,0 +1,46 @@ + + + + Vector Sink + gr_vector_sink_x + from gnuradio import gr + gr.vector_sink_$(type.fcn)() + + Input Type + type + enum + + + + + + + + in + $type + + diff --git a/grc/data/platforms/python/blocks/gr_vector_source_x.xml b/grc/data/platforms/python/blocks/gr_vector_source_x.xml new file mode 100644 index 00000000..240273e4 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_vector_source_x.xml @@ -0,0 +1,71 @@ + + + + Vector Source + gr_vector_source_x + from gnuradio import gr + gr.vector_source_$(type.fcn)($vector, $repeat) + + Output Type + type + enum + + + + + + + + Vector + vector + 0, 0, 0 + $type.vec_type + + + Repeat + repeat + True + enum + + + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/gr_vector_to_stream.xml b/grc/data/platforms/python/blocks/gr_vector_to_stream.xml new file mode 100644 index 00000000..d56d3406 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_vector_to_stream.xml @@ -0,0 +1,66 @@ + + + + Vector to Stream + gr_vector_to_stream + from gnuradio import gr + gr.vector_to_stream($type.size*$vlen, $num_items) + + IO Type + type + enum + + + + + + + + Num Items + num_items + 2 + int + + + Vec Length + vlen + 1 + int + + $num_items > 0 + $vlen >= 1 + + in + $type + $vlen*$num_items + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/gr_vector_to_streams.xml b/grc/data/platforms/python/blocks/gr_vector_to_streams.xml new file mode 100644 index 00000000..86cb5681 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_vector_to_streams.xml @@ -0,0 +1,67 @@ + + + + Vector to Streams + gr_vector_to_streams + from gnuradio import gr + gr.vector_to_streams($type.size*$vlen, $num_streams) + + IO Type + type + enum + + + + + + + + Num Streams + num_streams + 2 + int + + + Vec Length + vlen + 1 + int + + $num_streams > 0 + $vlen >= 1 + + in + $type + $vlen*$num_streams + + + out + $type + $vlen + $num_streams + + diff --git a/grc/data/platforms/python/blocks/gr_wavfile_sink.xml b/grc/data/platforms/python/blocks/gr_wavfile_sink.xml new file mode 100644 index 00000000..f2c8a009 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_wavfile_sink.xml @@ -0,0 +1,42 @@ + + + + Wav File Sink + gr_wavfile_sink + from gnuradio import gr + gr.wavfile_sink($file, $nchan, $samp_rate, $bits_per_sample) + + File + file + + file_save + + + N Channels + nchan + 1 + int + + + Sample Rate + samp_rate + samp_rate + int + + + Bits per Sample + bits_per_sample + 8 + int + + 1 <= $nchan + + in + float + $nchan + + diff --git a/grc/data/platforms/python/blocks/gr_wavfile_source.xml b/grc/data/platforms/python/blocks/gr_wavfile_source.xml new file mode 100644 index 00000000..433bb0af --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_wavfile_source.xml @@ -0,0 +1,44 @@ + + + + Wav File Source + gr_wavfile_source + from gnuradio import gr + gr.wavfile_source($file, $repeat) + + File + file + + file_open + + + Repeat + repeat + True + enum + + + + + N Channels + nchan + 1 + int + + 1 <= $nchan + + out + float + $nchan + + diff --git a/grc/data/platforms/python/blocks/gr_xor_xx.xml b/grc/data/platforms/python/blocks/gr_xor_xx.xml new file mode 100644 index 00000000..c014cbe5 --- /dev/null +++ b/grc/data/platforms/python/blocks/gr_xor_xx.xml @@ -0,0 +1,48 @@ + + + + Xor + gr_xor_xx + from gnuradio import gr + gr.xor_$(type.fcn)() + + IO Type + type + enum + + + + + + Num Inputs + num_inputs + 2 + int + + $num_inputs >= 2 + + in + $type + $num_inputs + + + out + $type + + diff --git a/grc/data/platforms/python/blocks/high_pass_filter.xml b/grc/data/platforms/python/blocks/high_pass_filter.xml new file mode 100644 index 00000000..0673fd12 --- /dev/null +++ b/grc/data/platforms/python/blocks/high_pass_filter.xml @@ -0,0 +1,120 @@ + + + + High Pass Filter + high_pass_filter + from gnuradio import gr + from gnuradio.gr import firdes + gr.$(type)($decim, firdes.high_pass( + $gain, $samp_rate, $cutoff_freq, $width, firdes.$window, $beta)) + set_taps(firdes.high_pass($gain, $samp_rate, $cutoff_freq, $width, firdes.$window, $beta)) + + FIR Type + type + enum + + + + + + + Decimation + decim + 1 + int + + + Gain + gain + 1 + real + + + Sample Rate + samp_rate + samp_rate + real + + + Cutoff Freq + cutoff_freq + real + + + Transition Width + width + real + + + Window + window + enum + + + + + + + + Beta + beta + 6.76 + real + + + in + $type.input + + + out + $type.output + + +This filter is a convenience wrapper for an fir filter and a firdes taps generating function. + +The decimation paramater becomes interpolation when the filter type is set to interpolating. + +Sample rate, cutoff frequency, and transition width are in Hertz. + +The beta paramater only applies to the Kaiser window. + + diff --git a/grc/data/platforms/python/blocks/import.xml b/grc/data/platforms/python/blocks/import.xml new file mode 100644 index 00000000..feea052d --- /dev/null +++ b/grc/data/platforms/python/blocks/import.xml @@ -0,0 +1,26 @@ + + + + Import + import + $import + + + Import + import + + import + + +Import additional python modules into the namespace. + +Examples: +from gnuradio.gr import firdes +import math,cmath +from math import pi + + diff --git a/grc/data/platforms/python/blocks/low_pass_filter.xml b/grc/data/platforms/python/blocks/low_pass_filter.xml new file mode 100644 index 00000000..1e8802c8 --- /dev/null +++ b/grc/data/platforms/python/blocks/low_pass_filter.xml @@ -0,0 +1,120 @@ + + + + Low Pass Filter + low_pass_filter + from gnuradio import gr + from gnuradio.gr import firdes + gr.$(type)($decim, firdes.low_pass( + $gain, $samp_rate, $cutoff_freq, $width, firdes.$window, $beta)) + set_taps(firdes.low_pass($gain, $samp_rate, $cutoff_freq, $width, firdes.$window, $beta)) + + FIR Type + type + enum + + + + + + + Decimation + decim + 1 + int + + + Gain + gain + 1 + real + + + Sample Rate + samp_rate + samp_rate + real + + + Cutoff Freq + cutoff_freq + real + + + Transition Width + width + real + + + Window + window + enum + + + + + + + + Beta + beta + 6.76 + real + + + in + $type.input + + + out + $type.output + + +This filter is a convenience wrapper for an fir filter and a firdes taps generating function. + +The decimation paramater becomes interpolation when the filter type is set to interpolating. + +Sample rate, cutoff frequency, and transition width are in Hertz. + +The beta paramater only applies to the Kaiser window. + + diff --git a/grc/data/platforms/python/blocks/note.xml b/grc/data/platforms/python/blocks/note.xml new file mode 100644 index 00000000..db6687c0 --- /dev/null +++ b/grc/data/platforms/python/blocks/note.xml @@ -0,0 +1,17 @@ + + + + Note + note + + + Note + note + + string + + diff --git a/grc/data/platforms/python/blocks/options.xml b/grc/data/platforms/python/blocks/options.xml new file mode 100644 index 00000000..8e8f0689 --- /dev/null +++ b/grc/data/platforms/python/blocks/options.xml @@ -0,0 +1,93 @@ + + + + Options + options + from gnuradio import gr +#if $generate_options.eval == 'wx_gui' +from grc_gnuradio import wxgui as grc_wxgui +import wx +#end if + + + + Title + title + untitled + string + + + Author + author + unknown + string + + + Description + description + gnuradio flow graph + string + + + Window Size + window_size + 1280, 1024 + int_vector + + + Generate Options + generate_options + wx_gui + enum + + + + + + Category + category + Custom + string + $generate_options.hide_category + + len($window_size) == 2 + 300 <= $(window_size)[0] <= 2048 + 300 <= $(window_size)[1] <= 2048 + +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 (2048, 2048). + +The generate options controls the type of code generated. \ +Non-graphical flow graphs should avoid using graphical sinks or graphical variable controls. + +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. + + diff --git a/grc/data/platforms/python/blocks/pad_sink.xml b/grc/data/platforms/python/blocks/pad_sink.xml new file mode 100644 index 00000000..477f2ad1 --- /dev/null +++ b/grc/data/platforms/python/blocks/pad_sink.xml @@ -0,0 +1,68 @@ + + + + Pad Sink + pad_sink + + + Num Inputs + nports + 1 + int + + + Input Type + type + enum + + + + + + + + Vec Length + vlen + 1 + int + + $vlen > 0 + 0 < $nports + + in + $type + $vlen + $nports + + +This is a sink pad block for creating hierarchical flow graphs. \ +The inputs of this block will become the outputs to this flow graph when it is instantiated as a hierarchical block. \ +Limit one sink pad block per flow graph. + +Remember to set the generate options to hier block. + + diff --git a/grc/data/platforms/python/blocks/pad_source.xml b/grc/data/platforms/python/blocks/pad_source.xml new file mode 100644 index 00000000..b6ef2c55 --- /dev/null +++ b/grc/data/platforms/python/blocks/pad_source.xml @@ -0,0 +1,68 @@ + + + + Pad Source + pad_source + + + Num Outputs + nports + 1 + int + + + Output Type + type + enum + + + + + + + + Vec Length + vlen + 1 + int + + $vlen > 0 + 0 < $nports + + out + $type + $vlen + $nports + + +This is a source pad block for creating hierarchical flow graphs. \ +The outputs of this block will become the inputs to this flow graph when it is instantiated as a hierarchical block. \ +Limit one source pad block per flow graph. + +Remember to set the generate options to hier block. + + diff --git a/grc/data/platforms/python/blocks/parameter.xml b/grc/data/platforms/python/blocks/parameter.xml new file mode 100644 index 00000000..b9dcce42 --- /dev/null +++ b/grc/data/platforms/python/blocks/parameter.xml @@ -0,0 +1,31 @@ + + + + Parameter + parameter + $value + + Label + label + + string + + + Value + value + 0 + raw + + +This block represents a parameter to the flow graph, \ +used when the flow graph is instantiated as a hier block. + +The paramater value cannot depend on any variables. + +Leave the label blank to use the parameter id as the label. + + diff --git a/grc/data/platforms/python/blocks/preferences.xml b/grc/data/platforms/python/blocks/preferences.xml new file mode 100644 index 00000000..51138c12 --- /dev/null +++ b/grc/data/platforms/python/blocks/preferences.xml @@ -0,0 +1,146 @@ + + + + Preferences + preferences + + + + Prefs File + prefs_file + .grc + string + + + File Open + file_open + + string + + + Files Open + files_open + + string + + + Window Size + window_size + 800, 600 + int_vector + + + + Snap to Grid + snap_to_grid + off + enum + + + + + Grid Size + grid_size + 20 + enum + + + + + + + Show Grid + show_grid + hide + enum + + + + + + Show Reports Window + show_reports + show + enum + + + + + Show Params Labels + show_params + show + enum + + + + + Show ID Label + show_id + show + enum + + + + + + Restore Open Files + restore_files + yes + enum + + + + diff --git a/grc/data/platforms/python/blocks/random_source_x.xml b/grc/data/platforms/python/blocks/random_source_x.xml new file mode 100644 index 00000000..f04dcd8d --- /dev/null +++ b/grc/data/platforms/python/blocks/random_source_x.xml @@ -0,0 +1,73 @@ + + + + Random Source + random_source_x + from gnuradio import gr + import numpy + gr.vector_source_$(type.fcn)(numpy.random.randint($min, $max, $num_samps), $repeat) + + Output Type + type + enum + + + + + + Minimum + min + 0 + int + + + Maximum + max + 1 + int + + + Num Samples + num_samps + 1000 + int + + + Repeat + repeat + True + enum + + + + + out + $type + + +Generate num samples of random numbers of [min, max). Repeat samples if specified. + + diff --git a/grc/data/platforms/python/blocks/trellis_encoder_xx.xml b/grc/data/platforms/python/blocks/trellis_encoder_xx.xml new file mode 100644 index 00000000..74a8cc34 --- /dev/null +++ b/grc/data/platforms/python/blocks/trellis_encoder_xx.xml @@ -0,0 +1,74 @@ + + + + Trellis Encoder + trellis_encoder_xx + from gnuradio import trellis + trellis.encoder_$(type)(trellis.fsm($fsm_args), $init_state) + + Type + type + enum + + + + + + + + + FSM Args + fsm_args + raw + + + Initial State + init_state + int + + + in + $type.input + + + out + $type.output + + +The fsm arguments are passed directly to the trellis.fsm() constructor. + + diff --git a/grc/data/platforms/python/blocks/trellis_metrics_x.xml b/grc/data/platforms/python/blocks/trellis_metrics_x.xml new file mode 100644 index 00000000..f09d54f0 --- /dev/null +++ b/grc/data/platforms/python/blocks/trellis_metrics_x.xml @@ -0,0 +1,84 @@ + + + + Trellis Metrics + trellis_metrics_x + from gnuradio import trellis + trellis.metrics_$(type)($card, $dim, $table, $metric_type) + + Type + type + enum + + + + + + + Output Cardinality + card + int + + + Dimensionality + dim + int + + + Constellation + table + $type.table + + + Metric Type + metric_type + enum + + + + + + in + $type.io + + + out + $type.io + + +Generate metrics required for Viterbi or SISO algorithms. + + diff --git a/grc/data/platforms/python/blocks/trellis_permutation.xml b/grc/data/platforms/python/blocks/trellis_permutation.xml new file mode 100644 index 00000000..7721cc71 --- /dev/null +++ b/grc/data/platforms/python/blocks/trellis_permutation.xml @@ -0,0 +1,74 @@ + + + + Trellis Permutation + trellis_permutation + from gnuradio import trellis + trellis.permutation($block_size, $table, $syms_per_block, $type.size*$vlen) + + Type + type + enum + + + + + + + + Block Size + block_size + int + + + Table + table + int_vector + + + Symbols per Block + syms_per_block + int + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + + out + $type + $vlen + + diff --git a/grc/data/platforms/python/blocks/trellis_siso_combined_f.xml b/grc/data/platforms/python/blocks/trellis_siso_combined_f.xml new file mode 100644 index 00000000..98874d7f --- /dev/null +++ b/grc/data/platforms/python/blocks/trellis_siso_combined_f.xml @@ -0,0 +1,112 @@ + + + + Trellis SISO Combo + trellis_siso_combined_f + from gnuradio import trellis + trellis.siso_combined_f(trellis.fsm($fsm_args), $block_size, $init_state, $final_state, $a_post_in, $a_post_out, $siso_type, $dim, $table, $metric_type) + + FSM Args + fsm_args + raw + + + Block Size + block_size + int + + + Initial State + init_state + -1 + int + + + Final State + final_state + -1 + int + + + A-posteriori In + a_post_in + enum + + + + + A-posteriori Out + a_post_out + enum + + + + + SISO Type + siso_type + enum + + + + + Dimensionality + dim + int + + + Constellation + table + real_vector + + + Metric Type + metric_type + enum + + + + + + in + float + + + out + float + + +BCJR Algorithm combined with metric calculation. \ +The fsm arguments are passed directly to the trellis.fsm() constructor. + + diff --git a/grc/data/platforms/python/blocks/trellis_siso_f.xml b/grc/data/platforms/python/blocks/trellis_siso_f.xml new file mode 100644 index 00000000..2b9cfe5f --- /dev/null +++ b/grc/data/platforms/python/blocks/trellis_siso_f.xml @@ -0,0 +1,85 @@ + + + + Trellis SISO + trellis_siso_f + from gnuradio import trellis + trellis.siso_f(trellis.fsm($fsm_args), $block_size, $init_state, $final_state, $a_post_in, $a_post_out, $siso_type) + + FSM Args + fsm_args + raw + + + Block Size + block_size + int + + + Initial State + init_state + -1 + int + + + Final State + final_state + -1 + int + + + A-posteriori In + a_post_in + enum + + + + + A-posteriori Out + a_post_out + enum + + + + + SISO Type + siso_type + enum + + + + + in + float + + + out + float + + +BCJR Algorithm. \ +The fsm arguments are passed directly to the trellis.fsm() constructor. + + diff --git a/grc/data/platforms/python/blocks/trellis_viterbi_combined_xx.xml b/grc/data/platforms/python/blocks/trellis_viterbi_combined_xx.xml new file mode 100644 index 00000000..0a67d0bf --- /dev/null +++ b/grc/data/platforms/python/blocks/trellis_viterbi_combined_xx.xml @@ -0,0 +1,122 @@ + + + + Trellis Viterbi Combo + trellis_viterbi_combined_xx + from gnuradio import trellis + trellis.viterbi_combined_$(type)$(out_type)(trellis.fsm($fsm_args), $block_size, $init_state, $final_state, $dim, $table, $metric_type) + + Input Type + type + enum + + + + + + + Output Type + out_type + enum + + + + + + FSM Args + fsm_args + raw + + + Block Size + block_size + int + + + Initial State + init_state + -1 + int + + + Final State + final_state + -1 + int + + + Dimensionality + dim + int + + + Constellation + table + $type.table + + + Metric Type + metric_type + enum + + + + + + in + $type.io + + + out + $out_type.io + + +Viterbi Decoder combined with metric calculation. \ +The fsm arguments are passed directly to the trellis.fsm() constructor. + + diff --git a/grc/data/platforms/python/blocks/trellis_viterbi_x.xml b/grc/data/platforms/python/blocks/trellis_viterbi_x.xml new file mode 100644 index 00000000..7465b11d --- /dev/null +++ b/grc/data/platforms/python/blocks/trellis_viterbi_x.xml @@ -0,0 +1,66 @@ + + + + Trellis Viterbi + trellis_viterbi_x + from gnuradio import trellis + trellis.viterbi_$(type)(trellis.fsm($fsm_args), $block_size, $init_state, $final_state) + + Type + type + enum + + + + + + FSM Args + fsm_args + raw + + + Block Size + block_size + int + + + Initial State + init_state + -1 + int + + + Final State + final_state + -1 + int + + + in + $type.io + + + out + $type.io + + +Viterbi Decoder. \ +The fsm arguments are passed directly to the trellis.fsm() constructor. + + diff --git a/grc/data/platforms/python/blocks/usrp_diagnostics.xml b/grc/data/platforms/python/blocks/usrp_diagnostics.xml new file mode 100644 index 00000000..52dd885a --- /dev/null +++ b/grc/data/platforms/python/blocks/usrp_diagnostics.xml @@ -0,0 +1,54 @@ + + + + USRP Diagnostics + usrp_diagnostics + + + USRP Number + usrp_number + 0 + int + + + USRP Type + usrp_type + rx + enum + + + + + Side:Subdevice + side_subdev + (0, 0) + enum + + + + + + diff --git a/grc/data/platforms/python/blocks/usrp_dual_sink_x.xml b/grc/data/platforms/python/blocks/usrp_dual_sink_x.xml new file mode 100644 index 00000000..acc14b1f --- /dev/null +++ b/grc/data/platforms/python/blocks/usrp_dual_sink_x.xml @@ -0,0 +1,154 @@ + + + + USRP Dual Sink + usrp_dual_sink_x + from grc_gnuradio import usrp as grc_usrp + grc_usrp.dual_sink_$(type.fcn)( + number=$number, + frequency_a=$frequency_a, + frequency_b=$frequency_b, + interpolation=$interpolation, + gain_a=$gain_a, + gain_b=$gain_b, + mux=$mux, + auto_tr=$auto_tr, + tx_enb_a=$tx_enb_a, + tx_enb_b=$tx_enb_b, +) + set_interp_rate($interpolation) + set_frequency_a($frequency_a) + set_gain_a($gain_a) + set_frequency_b($frequency_b) + set_gain_b($gain_b) + + Input Type + type + enum + + + + + Unit Number + number + 0 + int + + + Frequency A + frequency_a + real + + + Frequency B + frequency_b + real + + + Interpolation + interpolation + int + + + Gain A + gain_a + real + + + Gain B + gain_b + real + + + Mux + mux + 0xba98 + hex + + + Auto T/R + auto_tr + None + enum + + + + + + TX Enable A + tx_enb_a + None + enum + + + + + + TX Enable B + tx_enb_b + None + enum + + + + + + Ain + $type + + + Bin + $type + + +The USRP sink inputs 128 Megasamples per second / interpolation. + +--- Flex RF specific --- +The "Auto TR" and "TX Enable" settings are flex rf specific and should be left at "Ignore" unless this is a flex rf board. + +If enabled, "Auto Transmit/Receive Switching" handles the preference for transmit packets vs receive packets. \ +By default, "Auto TR" is disabled. + +The "Transmit Enable" configures the transmitter to be on or off. \ +Do not leave this unconfigured. + + diff --git a/grc/data/platforms/python/blocks/usrp_dual_source_x.xml b/grc/data/platforms/python/blocks/usrp_dual_source_x.xml new file mode 100644 index 00000000..68526b47 --- /dev/null +++ b/grc/data/platforms/python/blocks/usrp_dual_source_x.xml @@ -0,0 +1,154 @@ + + + + USRP Dual Source + usrp_dual_source_x + from grc_gnuradio import usrp as grc_usrp + grc_usrp.dual_source_$(type.fcn)( + number=$number, + frequency_a=$frequency_a, + frequency_b=$frequency_b, + decimation=$decimation, + gain_a=$gain_a, + gain_b=$gain_b, + mux=$mux, + auto_tr=$auto_tr, + rx_ant_a=$rx_ant_a, + rx_ant_b=$rx_ant_b, +) + set_decim_rate($decimation) + set_frequency_a($frequency_a) + set_gain_a($gain_a) + set_frequency_b($frequency_b) + set_gain_b($gain_b) + + Output Type + type + enum + + + + + Unit Number + number + 0 + int + + + Frequency A + frequency_a + real + + + Frequency B + frequency_b + real + + + Decimation + decimation + int + + + Gain A + gain_a + real + + + Gain B + gain_b + real + + + Mux + mux + 0x3210 + hex + + + Auto T/R + auto_tr + None + enum + + + + + + RX Antenna B + rx_ant_a + None + enum + + + + + + RX Antenna B + rx_ant_b + None + enum + + + + + + Aout + $type + + + Bout + $type + + +The USRP source outputs 64 Megasamples per second / decimation. + +--- Flex RF specific --- +The "Auto TR" and "RX Antenna" settings are flex rf specific and should be left at "Ignore" unless this is a flex rf board. + +If enabled, "Auto Transmit/Receive Switching" handles the preference for transmit packets vs receive packets. \ +By default, "Auto TR" is disabled. + +The "Receive Antenna Setting" selects one of the SMA connectors as the data source. \ +By default, 'TX/RX' is selected. + + diff --git a/grc/data/platforms/python/blocks/usrp_simple_sink_x.xml b/grc/data/platforms/python/blocks/usrp_simple_sink_x.xml new file mode 100644 index 00000000..b525d031 --- /dev/null +++ b/grc/data/platforms/python/blocks/usrp_simple_sink_x.xml @@ -0,0 +1,140 @@ + + + + USRP Sink + usrp_simple_sink_x + from grc_gnuradio import usrp as grc_usrp + grc_usrp.simple_sink_$(type.fcn)( + number=$number, + subdev_spec=$subdev_spec, + frequency=$frequency, + interpolation=$interpolation, + gain=$gain, +#if $mux.eval == hex(0) + mux=None, +#else + mux=$mux, +#end if + auto_tr=$auto_tr, + tx_enb=$tx_enb, +) + set_interp_rate($interpolation) + set_frequency($frequency) + set_gain($gain) + + Input Type + type + enum + + + + + Unit Number + number + 0 + int + + + Subdev Spec + subdev_spec + auto + enum + + + + + + Frequency + frequency + real + + + Interpolation + interpolation + int + + + Gain + gain + real + + + Mux + mux + 0x0 + hex + + + Auto T/R + auto_tr + None + enum + + + + + + TX Enable + tx_enb + None + enum + + + + + + in + $type + + +The USRP sink inputs 128 Megasamples per second / interpolation. + +--- Flex RF specific --- +The "Auto TR" and "TX Enable" settings are flex rf specific and should be left at "Ignore" unless this is a flex rf board. + +If enabled, "Auto Transmit/Receive Switching" handles the preference for transmit packets vs receive packets. \ +By default, "Auto TR" is disabled. + +The "Transmit Enable" configures the transmitter to be on or off. \ +Do not leave this unconfigured. + + diff --git a/grc/data/platforms/python/blocks/usrp_simple_source_x.xml b/grc/data/platforms/python/blocks/usrp_simple_source_x.xml new file mode 100644 index 00000000..a1598583 --- /dev/null +++ b/grc/data/platforms/python/blocks/usrp_simple_source_x.xml @@ -0,0 +1,148 @@ + + + + USRP Source + usrp_simple_source_x + from grc_gnuradio import usrp as grc_usrp + grc_usrp.simple_source_$(type.fcn)( + number=$number, + subdev_spec=$subdev_spec, + frequency=$frequency, + decimation=$decimation, + gain=$gain, +#if $mux.eval == hex(0) + mux=None, +#else + mux=$mux, +#end if + auto_tr=$auto_tr, + rx_ant=$rx_ant, +) + set_decim_rate($decimation) + set_frequency($frequency) + set_gain($gain) + + Output Type + type + enum + + + + + Unit Number + number + 0 + int + + + Subdev Spec + subdev_spec + auto + enum + + + + + + + + Frequency + frequency + real + + + Decimation + decimation + int + + + Gain + gain + real + + + Mux + mux + 0x0 + hex + + + Auto T/R + auto_tr + None + enum + + + + + + RX Antenna + rx_ant + None + enum + + + + + + out + $type + + +The USRP source outputs 64 Megasamples per second / decimation. + +--- Flex RF specific --- +The "Auto TR" and "RX Antenna" settings are flex rf specific and should be left at "Ignore" unless this is a flex rf board. + +If enabled, "Auto Transmit/Receive Switching" handles the preference for transmit packets vs receive packets. \ +By default, "Auto TR" is disabled. + +The "Receive Antenna Setting" selects one of the SMA connectors as the data source. \ +By default, 'TX/RX' is selected. + + diff --git a/grc/data/platforms/python/blocks/variable.xml b/grc/data/platforms/python/blocks/variable.xml new file mode 100644 index 00000000..d620e160 --- /dev/null +++ b/grc/data/platforms/python/blocks/variable.xml @@ -0,0 +1,21 @@ + + + + Variable + variable + $value + + Value + value + 0 + raw + + +This block maps a value to a unique variable. \ +This variable block has no graphical representation. + + diff --git a/grc/data/platforms/python/blocks/variable_chooser.xml b/grc/data/platforms/python/blocks/variable_chooser.xml new file mode 100644 index 00000000..4eba84d4 --- /dev/null +++ b/grc/data/platforms/python/blocks/variable_chooser.xml @@ -0,0 +1,93 @@ + + + + Variable Chooser + variable_chooser + $(choices)[$value_index] +_$(id)_control = grc_wxgui.$(chooser_type)_control( + window=self.GetWin(), + callback=self.set_$(id), + #if $label.eval + label=$label, + #else + label="$id", + #end if + index=$value_index, + choices=$choices, + labels=$labels, +) +#set $grid_pos = $grid_pos.eval +#if not grid_pos +self.Add(_$(id)_control) +#else +self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) +#end if + + Label + label + + string + + + Value Index + value_index + 0 + int + + + Choices + choices + [1, 2, 3] + raw + + + Labels + labels + [] + raw + + + Chooser Type + chooser_type + drop_down + enum + + + + + + + Grid Position + grid_pos + + grid_pos + + $value_index in range(len($choices)) + not $labels or len($labels) == len($choices) + +This block creates a variable with a drop down, radio buttons, or a button. \ +Leave the label blank to use the variable id as the label. \ +The value index is the index of a particular choice, \ +which defines the default choice when the flow graph starts. \ +The choices must be a list of possible values. \ +Leave labels empty to use the choices as the labels. + +Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. + + diff --git a/grc/data/platforms/python/blocks/variable_sink.xml b/grc/data/platforms/python/blocks/variable_sink.xml new file mode 100644 index 00000000..13737b2c --- /dev/null +++ b/grc/data/platforms/python/blocks/variable_sink.xml @@ -0,0 +1,66 @@ + + + + Variable Sink + variable_sink + from grc_gnuradio import blks2 as grc_blks2 + grc_blks2.queue_sink_$(type.fcn)($vlen) +grc_blks2.queue_sink_thread(self.$id, set_$(variable)) + + Type + type + enum + + + + + + + + Variable + variable + + raw + + + Vec Length + vlen + 1 + int + + $vlen > 0 + + in + $type + $vlen + + +Read samples from the input stream and write each sample to the variable. + +The variable must be the id of an existing variable block. + + diff --git a/grc/data/platforms/python/blocks/variable_slider.xml b/grc/data/platforms/python/blocks/variable_slider.xml new file mode 100644 index 00000000..2f6374b9 --- /dev/null +++ b/grc/data/platforms/python/blocks/variable_slider.xml @@ -0,0 +1,92 @@ + + + + Variable Slider + variable_slider + $value +_$(id)_control = grc_wxgui.slider_$(slider_type)_control( + window=self.GetWin(), + callback=self.set_$(id), + #if $label.eval + label=$label, + #else + label="$id", + #end if + value=$id, + min=$min, + max=$max, + num_steps=$num_steps, +) +#set $grid_pos = $grid_pos.eval +#if not grid_pos +self.Add(_$(id)_control) +#else +self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) +#end if + + Label + label + + string + + + Default Value + value + 50 + real + + + Minimum + min + 0 + real + + + Maximum + max + 100 + real + + + Num Steps + num_steps + 100 + int + + + Slider Type + slider_type + horizontal + enum + + + + + Grid Position + grid_pos + + grid_pos + + $min <= $value <= $max + $min < $max + 0 < $num_steps <= 1000 + +This block creates a variable with a slider. \ +Leave the label blank to use the variable id as the label. \ +The value must be a real number. \ +The value must be between the minimum and the maximum. \ +The number of steps must be between 0 and 1000. + +Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. + + diff --git a/grc/data/platforms/python/blocks/variable_text_box.xml b/grc/data/platforms/python/blocks/variable_text_box.xml new file mode 100644 index 00000000..0dad3d82 --- /dev/null +++ b/grc/data/platforms/python/blocks/variable_text_box.xml @@ -0,0 +1,51 @@ + + + + Variable Text Box + variable_text_box + $value +_$(id)_control = grc_wxgui.text_box_control( + window=self.GetWin(), + callback=self.set_$(id), + #if $label.eval + label=$label, + #else + label="$id", + #end if + value=$id, +) +#set $grid_pos = $grid_pos.eval +#if not grid_pos +self.Add(_$(id)_control) +#else +self.GridAdd(_$(id)_control, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) +#end if + + Label + label + + string + + + Default Value + value + 0 + raw + + + Grid Position + grid_pos + + grid_pos + + +This block creates a variable with a text box. \ +Leave the label blank to use the variable id as the label. + +Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. + + diff --git a/grc/data/platforms/python/blocks/wxgui_constellationsink2.xml b/grc/data/platforms/python/blocks/wxgui_constellationsink2.xml new file mode 100644 index 00000000..cf3f2928 --- /dev/null +++ b/grc/data/platforms/python/blocks/wxgui_constellationsink2.xml @@ -0,0 +1,74 @@ + + + + Constellation Sink + wxgui_constellationsink2 + from gnuradio.wxgui import scopesink2 + scopesink2.constellation_sink( + self.GetWin(), + title=$title, + sample_rate=$samp_rate, + frame_decim=$frame_decim, +) +self.$(id).win.$(marker)() +#set $grid_pos = $grid_pos.eval +#if not grid_pos +self.Add(self.$(id).win) +#else +self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) +#end if + set_sample_rate($samp_rate) + + Title + title + Constellation Plot + string + + + Sample Rate + samp_rate + samp_rate + real + + + Frame Decimation + frame_decim + 15 + int + + + Marker + marker + set_format_plus + enum + + + + + + Grid Position + grid_pos + + grid_pos + + + in + complex + + +Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. + + diff --git a/grc/data/platforms/python/blocks/wxgui_fftsink2.xml b/grc/data/platforms/python/blocks/wxgui_fftsink2.xml new file mode 100644 index 00000000..68b07ba9 --- /dev/null +++ b/grc/data/platforms/python/blocks/wxgui_fftsink2.xml @@ -0,0 +1,148 @@ + + + + FFT Sink + wxgui_fftsink2 + from gnuradio.wxgui import fftsink2 + fftsink2.$(type.fcn)( + self.GetWin(), + baseband_freq=$baseband_freq, + y_per_div=$y_per_div, + y_divs=$y_divs, + ref_level=$ref_level, + sample_rate=$samp_rate, + fft_size=$fft_size, + fft_rate=$fft_rate, + average=$average, +#if $avg_alpha.eval == 0 + avg_alpha=None, +#else + avg_alpha=$avg_alpha, +#end if + title=$title, + peak_hold=$peak_hold, +) +#set $grid_pos = $grid_pos.eval +#if not grid_pos +self.Add(self.$(id).win) +#else +self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) +#end if + + Type + type + complex + enum + + + + + Title + title + FFT Plot + string + + + Sample Rate + samp_rate + samp_rate + real + + + Baseband Freq + baseband_freq + 0 + real + + + Y per Div + y_per_div + 10 + real + + + Y Divs + y_divs + 8 + real + + + Reference Level + ref_level + 50 + real + + + FFT Size + fft_size + 1024 + int + + + Refresh Rate + fft_rate + 30 + int + + + Average Alpha + avg_alpha + 0 + real + + + Average + average + False + enum + + + + + Peak Hold + peak_hold + False + enum + + + + + Grid Position + grid_pos + + grid_pos + + + in + $type + + +Set Average Alpha to 0 for automatic setting. + +Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. + + diff --git a/grc/data/platforms/python/blocks/wxgui_numbersink2.xml b/grc/data/platforms/python/blocks/wxgui_numbersink2.xml new file mode 100644 index 00000000..e54da3e6 --- /dev/null +++ b/grc/data/platforms/python/blocks/wxgui_numbersink2.xml @@ -0,0 +1,173 @@ + + + + Number Sink + wxgui_numbersink2 + from gnuradio.wxgui import numbersink2 + numbersink2.$(type.fcn)( + self.GetWin(), + unit=$units, + base_value=$base_value, + minval=$min_value, + maxval=$max_value, + factor=$factor, + decimal_places=$decimal_places, + ref_level=$ref_level, + sample_rate=$samp_rate, + number_rate=$number_rate, + average=$options.average, +#if $avg_alpha.eval == 0 + avg_alpha=None, +#else + avg_alpha=$avg_alpha, +#end if + label=$title, + peak_hold=$options.peak_hold, +) +self.$(id).set_show_gauge($show_gauge) +#set $grid_pos = $grid_pos.eval +#if not grid_pos +self.Add(self.$(id).win) +#else +self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) +#end if + + Type + type + complex + enum + + + + + Title + title + Number Plot + string + + + Units + units + Units + string + + + Sample Rate + samp_rate + samp_rate + real + + + Base Value + base_value + 0.0 + real + + + Min Value + min_value + -100 + real + + + Max Value + max_value + 100 + real + + + Factor + factor + 1.0 + real + + + Decimal Places + decimal_places + 10 + int + + + Reference Level + ref_level + 50 + real + + + Number Rate + number_rate + 15 + int + + + Average Alpha + avg_alpha + 0 + real + + + Options + options + none + enum + + + + + + Show Gauge + show_gauge + True + enum + + + + + Grid Position + grid_pos + + grid_pos + + + in + $type + + +Set Average Alpha to 0 for automatic setting. + +Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. + + diff --git a/grc/data/platforms/python/blocks/wxgui_scopesink2.xml b/grc/data/platforms/python/blocks/wxgui_scopesink2.xml new file mode 100644 index 00000000..7cf49d5d --- /dev/null +++ b/grc/data/platforms/python/blocks/wxgui_scopesink2.xml @@ -0,0 +1,146 @@ + + + + Scope Sink + wxgui_scopesink2 + from gnuradio.wxgui import scopesink2 + from gnuradio import gr + scopesink2.$(type.fcn)( + self.GetWin(), + title=$title, + sample_rate=$samp_rate, + frame_decim=$frame_decim, +#if $v_scale.eval == 0 + v_scale=None, +#else + v_scale=$v_scale, +#end if + t_scale=$t_scale, + num_inputs=$num_inputs, +) +self.$(id).win.$(marker)() +#set $grid_pos = $grid_pos.eval +#if not grid_pos +self.Add(self.$(id).win) +#else +self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) +#end if + + set_sample_rate($samp_rate) + + Type + type + complex + enum + + + + + Title + title + Scope Plot + string + + + Sample Rate + samp_rate + samp_rate + real + + + Frame Decimation + frame_decim + 15 + int + + + V Scale + v_scale + 0 + real + + + T Scale + t_scale + .001 + real + + + Marker + marker + set_format_line + enum + + + + + + + Num Inputs + num_inputs + 1 + int + + + Grid Position + grid_pos + + grid_pos + + + in + $type + $num_inputs + + +Set the V Scale to 0 for the scope to auto-scale. + +Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. + + diff --git a/grc/data/platforms/python/blocks/wxgui_waterfallsink2.xml b/grc/data/platforms/python/blocks/wxgui_waterfallsink2.xml new file mode 100644 index 00000000..b5172f09 --- /dev/null +++ b/grc/data/platforms/python/blocks/wxgui_waterfallsink2.xml @@ -0,0 +1,128 @@ + + + + Waterfall Sink + wxgui_waterfallsink2 + from gnuradio.wxgui import waterfallsink2 + waterfallsink2.$(type.fcn)( + self.GetWin(), + baseband_freq=$baseband_freq, + y_per_div=$y_per_div, + ref_level=$ref_level, + sample_rate=$samp_rate, + fft_size=$fft_size, + fft_rate=$fft_rate, + average=$options.average, +#if $avg_alpha.eval == 0 + avg_alpha=None, +#else + avg_alpha=$avg_alpha, +#end if + title=$title, +) +#set $grid_pos = $grid_pos.eval +#if not grid_pos +self.Add(self.$(id).win) +#else +self.GridAdd(self.$(id).win, $grid_pos[0], $grid_pos[1], $grid_pos[2], $grid_pos[3]) +#end if + + Type + type + complex + enum + + + + + Title + title + Waterfall Plot + string + + + Sample Rate + samp_rate + samp_rate + real + + + Baseband Freq + baseband_freq + 0 + real + + + Y per Div + y_per_div + 10 + real + + + Reference Level + ref_level + 50 + real + + + FFT Size + fft_size + 512 + int + + + FFT Rate + fft_rate + 15 + int + + + Average Alpha + avg_alpha + 0 + real + + + Options + options + none + enum + + + + + Grid Position + grid_pos + + grid_pos + + + in + $type + + +Set Average Alpha to 0 for automatic setting. + +Use the Grid Position (row, column, row span, column span) to position the graphical element in the window. + + diff --git a/grc/data/platforms/python/blocks/xmlrpc_client.xml b/grc/data/platforms/python/blocks/xmlrpc_client.xml new file mode 100644 index 00000000..82ae8cee --- /dev/null +++ b/grc/data/platforms/python/blocks/xmlrpc_client.xml @@ -0,0 +1,42 @@ + + + + XMLRPC Client + xmlrpc_client + import xmlrpclib + xmlrpclib.Server("http://$(addr.eval):$(port)") + $(callback.eval)($variable) + + Address + addr + localhost + string + + + Port + port + 8080 + int + + + Callback + callback + set_ + string + + + Variable + variable + raw + + +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. + + diff --git a/grc/data/platforms/python/blocks/xmlrpc_server.xml b/grc/data/platforms/python/blocks/xmlrpc_server.xml new file mode 100644 index 00000000..40e547ef --- /dev/null +++ b/grc/data/platforms/python/blocks/xmlrpc_server.xml @@ -0,0 +1,39 @@ + + + + XMLRPC Server + xmlrpc_server + import SimpleXMLRPCServer + import threading + SimpleXMLRPCServer.SimpleXMLRPCServer(($addr, $port), allow_none=True) +self.$(id).register_instance(self) +threading.Thread(target=self.$(id).serve_forever).start() + + Address + addr + localhost + string + + + Port + port + 8080 + int + + +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) + + diff --git a/grc/data/platforms/python/default_flow_graph.grc.xml b/grc/data/platforms/python/default_flow_graph.grc.xml new file mode 100644 index 00000000..dea26f3a --- /dev/null +++ b/grc/data/platforms/python/default_flow_graph.grc.xml @@ -0,0 +1,43 @@ + + + + + options + + id + top_block + + + _coordinate + (10, 10) + + + _rotation + 0 + + + + variable + + id + samp_rate + + + value + 32000 + + + _coordinate + (10, 170) + + + _rotation + 0 + + + diff --git a/grc/data/platforms/python/flow_graph.tmpl b/grc/data/platforms/python/flow_graph.tmpl new file mode 100644 index 00000000..2341ef46 --- /dev/null +++ b/grc/data/platforms/python/flow_graph.tmpl @@ -0,0 +1,195 @@ +#!/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 controls the variables with gui controls +##@param parameters the paramater blocks +##@param blocks the signal blocks +##@param connections the connections +##@param generate_options the type of flow graph +##@param var_id2expr variable id map to expression +##@param var_id2deps variable id map to direct dependencies +##@param var_id2cbs variable id map to callback strings +######################################################## +#import time +#set $DIVIDER = '#'*50 +$DIVIDER +# Gnuradio Python Flow Graph +$('# Title: %s'%$flow_graph.get_option('title')) +$('# Author: %s'%$flow_graph.get_option('author')) +$('# Description: %s'%$flow_graph.get_option('description')) +$('# Generated: %s'%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' + #from gnuradio.grc.platforms.base.Constants import DATA_DIR + #from gnuradio.grc.gui.Constants import MAIN_WINDOW_PREFIX +class $(class_name)(grc_wxgui.top_block_gui): + + def __init__($param_str): + grc_wxgui.top_block_gui.__init__( + self, + title="$MAIN_WINDOW_PREFIX - Executing: $flow_graph.get_option('title')", + icon="$(os.path.join($DATA_DIR, 'grc-icon-32.png'))", + ) +#elif $generate_options == 'no_gui' +class $(class_name)(gr.top_block): + + def __init__($param_str): + gr.top_block.__init__(self, "$flow_graph.get_option('title')") +#elif $generate_options == 'hb' + #set $in_sig = $flow_graph.get_input_signature() + #set $out_sig = $flow_graph.get_output_signature() +class $(class_name)(gr.hier_block2): + + def __init__($param_str): + gr.hier_block2.__init__( + self, + "$flow_graph.get_option('title')", + gr.io_signature($in_sig.nports, $in_sig.nports, $in_sig.size*$in_sig.vlen), + gr.io_signature($out_sig.nports, $out_sig.nports, $out_sig.size*$out_sig.vlen), + ) +#end if +######################################################## +##Create Parameters +## Set the parameter to a property of self.. +######################################################## +#if $parameters + + $DIVIDER + # Parameters + $DIVIDER +#end if +#for $param in $parameters + self.$param.get_id() = $param.get_id() +#end for +######################################################## +##Create Variables +## Set the variable to a property of self. +## Write the first line of the variable make. +######################################################## +#if $variables + + $DIVIDER + # Variables + $DIVIDER +#end if +#for $var in $variables + #set $code = $var.get_make().splitlines()[0] + self.$var.get_id() = $var.get_id() = $code +#end for +######################################################## +##Create Controls +## Write the variable make (excluding first line). +## Indent each line with 2 tabs. +######################################################## +#if $controls + + $DIVIDER + # Controls + $DIVIDER +#end if +#for $ctrl in $controls + #set $code = '\n\t\t'.join($ctrl.get_make().splitlines()[1:]) + $code +#end for +######################################################## +##Create Blocks +## Write the block make, and indent with 2 tabs. +######################################################## +#if $blocks + + $DIVIDER + # Blocks + $DIVIDER +#end if +#for $blk in filter(lambda b: b.get_make(), $blocks) + #set $code = '\n\t\t'.join($blk.get_make().splitlines()) + $("self.%s = %s"%($blk.get_id(), $code)) +#end for +######################################################## +##Create Connections +## The port name should be the id of the parent block. +## However, port names for IO pads should be self. +######################################################## +#if $connections + + $DIVIDER + # Connections + $DIVIDER +#end if +#for $con in $connections + #set $source = $con.get_source() + #set $sink = $con.get_sink() + #if $source.get_parent().get_key() == 'pad_source' + #set $source_name = 'self' + #else + #set $source_name = 'self.' + $source.get_parent().get_id() + #end if + #if $sink.get_parent().get_key() == 'pad_sink' + #set $sink_name = 'self' + #else + #set $sink_name = 'self.' + $sink.get_parent().get_id() + #end if + $("self.connect((%s, %s), (%s, %s))"%( + $source_name, + $source.get_key(), + $sink_name, + $sink.get_key(), + ) + ) +#end for + +######################################################## +##Create Callbacks +## Write a set method for this variable that calls the callbacks +## and sets the direct variable dependencies. +######################################################## +#for $var in $parameters + $variables + #set $id = $var.get_id() + def set_$(id)(self, $id): + self.$id = $id + #for $dep in $var_id2deps[$id] + self.set_$(dep)($var_id2expr[$dep]) + #end for + #for $callback in $var_id2cbs[$id] + self.$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. +######################################################## +#if $generate_options != 'hb' +if __name__ == '__main__': + tb = $(class_name)() + #if $generate_options == 'wx_gui' + tb.Run() + #elif $generate_options == 'no_gui' + tb.start() + raw_input('Press Enter to quit: ') + tb.stop() + #end if +#end if + diff --git a/grc/scripts/Makefile.am b/grc/scripts/Makefile.am index be4ae1b8..27a77b18 100644 --- a/grc/scripts/Makefile.am +++ b/grc/scripts/Makefile.am @@ -19,7 +19,7 @@ # Boston, MA 02110-1301, USA. # -include $(top_srcdir)/Makefile.common +include $(top_srcdir)/grc/Makefile.inc EXTRA_DIST = $(bin_SCRIPTS) diff --git a/grc/scripts/grc b/grc/scripts/grc index 44d07a7e..93a9a05c 100755 --- a/grc/scripts/grc +++ b/grc/scripts/grc @@ -17,12 +17,8 @@ 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 """ -##@package Editor -#Execute the flow graph editor GUI. This file must be called by the python interpreter. -#@author Josh Blum -import grc -from grc.Constants import VERSION,FLOW_GRAPH_FILE_EXTENSION +from gnuradio.grc.platforms.base.Constants import VERSION, FLOW_GRAPH_FILE_EXTENSION from optparse import OptionParser if __name__ == "__main__": @@ -37,7 +33,7 @@ and you are welcome to redistribute it. """%VERSION parser = OptionParser(usage=usage, version=version) (options, args) = parser.parse_args() - from grc_gnuradio.Platform import Platform - from grc.ActionHandler import ActionHandler + from gnuradio.grc.platforms.python.Platform import Platform + from gnuradio.grc.gui.ActionHandler import ActionHandler ActionHandler(args, Platform()) diff --git a/grc/scripts/usrp_diagnostics b/grc/scripts/usrp_diagnostics index a7d9d6f5..b8e31639 100755 --- a/grc/scripts/usrp_diagnostics +++ b/grc/scripts/usrp_diagnostics @@ -17,9 +17,6 @@ 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 """ -##@package Graphics.USRPDiagnostics -#A dialog for querying USRP subdevices. USRP interfacing methods encapsulated here. -#@author Josh Blum from gnuradio import usrp import os @@ -28,12 +25,12 @@ import pygtk pygtk.require('2.0') import gtk -from grc.gui.Dialogs import TextDisplay +from gnuradio.grc.gui.Dialogs import TextDisplay -from grc_gnuradio.Platform import Platform +from gnuradio.grc.platforms.python.Platform import Platform platform = Platform(block_paths_internal_only=['usrp_diagnostics.xml']) -from grc.gui.elements.Platform import Platform +from gnuradio.grc.platforms.gui.Platform import Platform platform = Platform(platform) flow_graph = platform.get_new_flow_graph() diff --git a/grc/src/Makefile.am b/grc/src/Makefile.am index 01c35d58..a726d493 100644 --- a/grc/src/Makefile.am +++ b/grc/src/Makefile.am @@ -19,6 +19,14 @@ # Boston, MA 02110-1301, USA. # -include $(top_srcdir)/Makefile.common +include $(top_srcdir)/grc/Makefile.inc -SUBDIRS = grc grc_gnuradio +SUBDIRS = \ + platforms \ + grc_gnuradio \ + gui \ + utils + +ourpythondir = $(grc_src_prefix) + +ourpython_PYTHON = __init__.py diff --git a/grc/src/__init__.py b/grc/src/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/grc/src/__init__.py @@ -0,0 +1 @@ + diff --git a/grc/src/grc/ActionHandler.py b/grc/src/grc/ActionHandler.py deleted file mode 100644 index ccaeb570..00000000 --- a/grc/src/grc/ActionHandler.py +++ /dev/null @@ -1,441 +0,0 @@ -""" -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 -""" -##@package ActionHandler -#ActionHandler builds the interface and handles most of the user inputs. - -import os -import signal -from Constants import * -from Actions import * -import pygtk -pygtk.require('2.0') -import gtk -import gui -import Preferences -from threading import Thread -import Messages -import ParseXML -import random -from grc.gui.elements.Platform import Platform - -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 - platform = Platform(platform) - if PY_GTK_ICON: gtk.window_set_default_icon_from_file(PY_GTK_ICON) - for action in ACTIONS_LIST: action.connect('activate', self._handle_actions) - #setup the main window - self.main_window = gui.MainWindow(self.handle_states, 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.drawing_area.get_focus_flag - #setup the messages - Messages.register_messenger(self.main_window.add_report_line) - Messages.send_init() - #initialize - self.init_file_paths = file_paths - self.handle_states(APPLICATION_INITIALIZE) - #enter the mainloop - gtk.gdk.threads_init() - gtk.main() - - def _handle_key_press(self, widget, event): - """ - Handle key presses from the keyboard. - Translate key combos into actions. - Key combinations that do not include special keys, such as ctrl or Fcn*, - Also, require that the flow graph has mouse focus when choosing to handle keys. - @return true if the flow graph is in active use - """ - keyname = gtk.gdk.keyval_name(event.keyval) - ctrl = event.state & gtk.gdk.CONTROL_MASK - alt = event.state & gtk.gdk.MOD1_MASK - shift = event.state & gtk.gdk.SHIFT_MASK - #################### save/open/new/close ############################### - if ctrl and keyname == 's': - self.handle_states(FLOW_GRAPH_SAVE) - elif ctrl and keyname == 'o': - self.handle_states(FLOW_GRAPH_OPEN) - elif ctrl and keyname == 'n': - self.handle_states(FLOW_GRAPH_NEW) - elif ctrl and keyname == 'q': - self.handle_states(FLOW_GRAPH_CLOSE) - #################### Cut/Copy/Paste ############################### - elif self.get_focus_flag() and ctrl and keyname == 'x': #mouse focus - self.handle_states(BLOCK_CUT) - elif self.get_focus_flag() and ctrl and keyname == 'c': #mouse focus - self.handle_states(BLOCK_COPY) - elif self.get_focus_flag() and ctrl and keyname == 'v': #mouse focus - self.handle_states(BLOCK_PASTE) - #################### Undo/Redo ############################### - elif ctrl and keyname == 'z': - self.handle_states(FLOW_GRAPH_UNDO) - elif ctrl and keyname == 'y': - self.handle_states(FLOW_GRAPH_REDO) - #################### Delete ############################### - elif self.get_focus_flag() and keyname == 'Delete': #mouse focus - self.handle_states(ELEMENT_DELETE) - #################### Params ############################### - elif self.get_focus_flag() and keyname == 'Return': #mouse focus - self.handle_states(BLOCK_PARAM_MODIFY) - #################### Rotate ############################### - elif self.get_focus_flag() and keyname == 'Right': #mouse focus - self.handle_states(BLOCK_ROTATE_RIGHT) - elif self.get_focus_flag() and keyname == 'Left': #mouse focus - self.handle_states(BLOCK_ROTATE_LEFT) - #################### Enable/Disable ############################### - elif self.get_focus_flag() and keyname == 'e': #mouse focus - self.handle_states(BLOCK_ENABLE) - elif self.get_focus_flag() and keyname == 'd': #mouse focus - self.handle_states(BLOCK_DISABLE) - #################### Data Type ############################### - elif self.get_focus_flag() and keyname == 'Down': #mouse focus - self.handle_states(BLOCK_INC_TYPE) - elif self.get_focus_flag() and keyname == 'Up': #mouse focus - self.handle_states(BLOCK_DEC_TYPE) - #################### Port Controllers ############################### - elif self.get_focus_flag() and keyname in ('equal','plus', 'KP_Add'): #mouse focus - self.handle_states(PORT_CONTROLLER_INC) - elif self.get_focus_flag() and keyname in ('minus', 'KP_Subtract'): #mouse focus - self.handle_states(PORT_CONTROLLER_DEC) - #################### Gen/Exec/Stop/Print ############################### - elif keyname == 'F5': - self.handle_states(FLOW_GRAPH_GEN) - elif keyname == 'F6': - self.handle_states(FLOW_GRAPH_EXEC) - elif keyname == 'F7': - self.handle_states(FLOW_GRAPH_KILL) - elif keyname == 'Print': - self.handle_states(FLOW_GRAPH_SCREEN_CAPTURE) - #propagate this if the fg is not in focus or nothing is selected - return self.get_focus_flag() and self.get_flow_graph().is_selected() - - 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 - """ - self.handle_states(APPLICATION_QUIT) - return True - - def _handle_actions(self, event): - """ - Handle all of the activate signals from the gtk actions. - The action signals derive from clicking on a toolbar or menu bar button. - Forward the action to the state handler. - """ - self.handle_states(event.get_name()) - - def handle_states(self, state=''): - """! - Handle the state changes in the GUI. - Handle all of the state changes that arise from the action handler or other gui and - inputs in the application. The state passed to the handle_states method is a string descriping - the change. A series of if/elif statements handle the state by greying out action buttons, causing - changes in the flow graph, saving/opening files... The handle_states method is passed to the - contructors of many of the classes used in this application enabling them to report any state change. - @param state a string describing the state change - """ - #print state - ############################################################################################## - # Initalize/Quit - ############################################################################################## - if state == APPLICATION_INITIALIZE: - for action in ACTIONS_LIST: action.set_sensitive(False) #set all actions disabled - # enable a select few actions - for action in ( - APPLICATION_QUIT, FLOW_GRAPH_NEW, FLOW_GRAPH_OPEN, FLOW_GRAPH_SAVE_AS, FLOW_GRAPH_CLOSE, - ABOUT_WINDOW_DISPLAY, HOTKEYS_WINDOW_DISPLAY, - PREFS_WINDOW_DISPLAY, FLOW_GRAPH_SCREEN_CAPTURE, - ): get_action_from_name(action).set_sensitive(True) - if not self.init_file_paths and Preferences.restore_files(): 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 state == APPLICATION_QUIT: - if self.main_window.close_pages(): - gtk.main_quit() - exit(0) - ############################################################################################## - # Selections - ############################################################################################## - elif state == ELEMENT_SELECT: - self.get_flow_graph().update() - elif state == NOTHING_SELECT: - self.get_flow_graph().unselect() - self.get_flow_graph().update() - ############################################################################################## - # Enable/Disable - ############################################################################################## - elif state == 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 state == 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 state == BLOCK_CUT: - self.handle_states(BLOCK_COPY) - self.handle_states(ELEMENT_DELETE) - elif state == BLOCK_COPY: - self.clipboard = self.get_flow_graph().copy_to_clipboard() - elif state == 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) - ############################################################################################## - # Move/Rotate/Delete/Create - ############################################################################################## - elif state == BLOCK_MOVE: - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - elif state == BLOCK_ROTATE_LEFT: - if self.get_flow_graph().rotate_selected(DIR_LEFT): - 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 state == BLOCK_ROTATE_RIGHT: - if self.get_flow_graph().rotate_selected(DIR_RIGHT): - 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 state == ELEMENT_DELETE: - if self.get_flow_graph().remove_selected(): - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.handle_states(NOTHING_SELECT) - self.get_page().set_saved(False) - elif state == ELEMENT_CREATE: - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.handle_states(NOTHING_SELECT) - self.get_page().set_saved(False) - elif state == 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 state == 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 state == PORT_CONTROLLER_INC: - if self.get_flow_graph().port_controller_modify_selected(1): - self.get_flow_graph().update() - self.get_flow_graph().update() #2 times - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - elif state == PORT_CONTROLLER_DEC: - if self.get_flow_graph().port_controller_modify_selected(-1): - self.get_flow_graph().update() - self.get_flow_graph().update() #2 times - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - ############################################################################################## - # Window stuff - ############################################################################################## - elif state == PREFS_WINDOW_DISPLAY: - gui.PreferencesDialog() - self.get_flow_graph().update() - elif state == ABOUT_WINDOW_DISPLAY: - gui.AboutDialog() - elif state == HOTKEYS_WINDOW_DISPLAY: - gui.HotKeysDialog() - ############################################################################################## - # Param Modifications - ############################################################################################## - elif state == BLOCK_PARAM_MODIFY: - if self.get_flow_graph().param_modify_selected(): - 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) - ############################################################################################## - # Undo/Redo - ############################################################################################## - elif state == 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 state == 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 state == FLOW_GRAPH_NEW: - self.main_window.new_page() - elif state == FLOW_GRAPH_OPEN: - file_paths = gui.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 state == FLOW_GRAPH_CLOSE: - self.main_window.close_page() - elif state == FLOW_GRAPH_SAVE: - if not self.get_page().get_file_path(): self.handle_states(FLOW_GRAPH_SAVE_AS) - else: - try: - ParseXML.to_file(self.get_flow_graph().export_data(), 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 state == FLOW_GRAPH_SAVE_AS: - file_path = gui.SaveFlowGraphFileDialog(self.get_page().get_file_path()).run() - if file_path != None: - self.get_page().set_file_path(file_path) - self.handle_states(FLOW_GRAPH_SAVE) - elif state == FLOW_GRAPH_SCREEN_CAPTURE: - file_path = gui.SaveImageFileDialog(self.get_page().get_file_path()).run() - if file_path != None: - pixmap = self.get_flow_graph().get_drawing_area().pixmap - width, height = pixmap.get_size() - pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, width, height) - pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(), 0, 0, 0, 0, width, height) - pixbuf.save(file_path, IMAGE_FILE_EXTENSION[1:]) - ############################################################################################## - # Gen/Exec/Stop - ############################################################################################## - elif state == FLOW_GRAPH_GEN: - if not self.get_page().get_pid(): - if not self.get_page().get_saved() or not self.get_page().get_file_path(): - self.handle_states(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 state == FLOW_GRAPH_EXEC: - if not self.get_page().get_pid(): - self.handle_states(FLOW_GRAPH_GEN) - if self.get_page().get_saved() and self.get_page().get_file_path(): - ExecFlowGraphThread(self) - elif state == FLOW_GRAPH_KILL: - if self.get_page().get_pid(): - try: os.kill(self.get_page().get_pid(), signal.SIGKILL) - except: print "could not kill pid: %s"%self.get_page().get_pid() - elif state == '': #pass and run the global actions - pass - else: print '!!! State "%s" not handled !!!'%state - ############################################################################################## - # Global Actions for all States - ############################################################################################## - #update general buttons - get_action_from_name(ELEMENT_DELETE).set_sensitive(bool(self.get_flow_graph().get_selected_elements())) - get_action_from_name(BLOCK_PARAM_MODIFY).set_sensitive(bool(self.get_flow_graph().get_selected_block())) - get_action_from_name(BLOCK_ROTATE_RIGHT).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) - get_action_from_name(BLOCK_ROTATE_LEFT).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) - #update cut/copy/paste - get_action_from_name(BLOCK_CUT).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) - get_action_from_name(BLOCK_COPY).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) - get_action_from_name(BLOCK_PASTE).set_sensitive(bool(self.clipboard)) - #update enable/disable - get_action_from_name(BLOCK_ENABLE).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) - get_action_from_name(BLOCK_DISABLE).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) - #set the exec and stop buttons - self.update_exec_stop() - #saved status - get_action_from_name(FLOW_GRAPH_SAVE).set_sensitive(not self.get_page().get_saved()) - self.main_window.update() - #draw the flow graph - self.get_flow_graph().draw() - - 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_pid() - get_action_from_name(FLOW_GRAPH_GEN).set_sensitive(sensitive) - get_action_from_name(FLOW_GRAPH_EXEC).set_sensitive(sensitive) - get_action_from_name(FLOW_GRAPH_KILL).set_sensitive(self.get_page().get_pid() != 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_pid(self.p.pid) - #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 flow graph.""" - #handle completion - r = "\n" - while(r): - gtk.gdk.threads_enter() - Messages.send_verbose_exec(r) - gtk.gdk.threads_leave() - r = os.read(self.p.stdout.fileno(), 1024) - gtk.gdk.threads_enter() - Messages.send_end_exec() - self.page.set_pid(None) - self.update_exec_stop() - gtk.gdk.threads_leave() - diff --git a/grc/src/grc/Actions.py b/grc/src/grc/Actions.py deleted file mode 100644 index ebf10c7e..00000000 --- a/grc/src/grc/Actions.py +++ /dev/null @@ -1,107 +0,0 @@ -""" -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 -""" -##@package Actions -#Global actions for gui elements to communicate state changes to the action handler. -#Use gtk.stock_list_ids() to get a list of possible stock ids (for toolbar/menu icons) - -import pygtk -pygtk.require('2.0') -import gtk - -###################################################################################################### -# States -###################################################################################################### -APPLICATION_INITIALIZE = 'app init' -APPLICATION_QUIT = 'app quit' -PARAM_MODIFY = 'param modify' -BLOCK_MOVE = 'block move' -BLOCK_ROTATE_LEFT = 'block rotate left' -BLOCK_ROTATE_RIGHT = 'block rotate right' -BLOCK_PARAM_MODIFY = 'block param modify' -BLOCK_INC_TYPE = 'block increment type' -BLOCK_DEC_TYPE = 'block decrement type' -BLOCK_ENABLE = 'block enable' -BLOCK_DISABLE = 'block disable' -BLOCK_CUT = 'block cut' -BLOCK_COPY = 'block copy' -BLOCK_PASTE = 'block paste' -PORT_CONTROLLER_INC = 'port controller increment' -PORT_CONTROLLER_DEC = 'port controller decrement' -ELEMENT_CREATE = 'element create' -ELEMENT_DELETE = 'element delete' -ELEMENT_SELECT = 'element select' -NOTHING_SELECT = 'nothing select' -FLOW_GRAPH_OPEN = 'flow graph open' -FLOW_GRAPH_UNDO = 'flow graph undo' -FLOW_GRAPH_REDO = 'flow graph redo' -FLOW_GRAPH_SAVE = 'flow graph save' -FLOW_GRAPH_SAVE_AS = 'flow graph save as' -FLOW_GRAPH_CLOSE = 'flow graph close' -FLOW_GRAPH_NEW = 'flow graph new' -FLOW_GRAPH_GEN = 'flow graph gen' -FLOW_GRAPH_EXEC = 'flow graph exec' -FLOW_GRAPH_KILL = 'flow graph kill' -FLOW_GRAPH_SCREEN_CAPTURE = 'flow graph screen capture' -ABOUT_WINDOW_DISPLAY = 'about window display' -HOTKEYS_WINDOW_DISPLAY = 'hotkeys window display' -PREFS_WINDOW_DISPLAY = 'prefs window display' - -###################################################################################################### -# Actions -###################################################################################################### -ACTIONS_LIST = ( - gtk.Action(FLOW_GRAPH_NEW, '_New', 'Create a new flow graph', 'gtk-new'), - gtk.Action(FLOW_GRAPH_OPEN, '_Open', 'Open an existing flow graph', 'gtk-open'), - gtk.Action(FLOW_GRAPH_SAVE, '_Save', 'Save the current flow graph', 'gtk-save'), - gtk.Action(FLOW_GRAPH_SAVE_AS, 'Save _As', 'Save the current flow graph as...', 'gtk-save-as'), - gtk.Action(FLOW_GRAPH_CLOSE, '_Close', 'Close the current flow graph', 'gtk-close'), - gtk.Action(APPLICATION_QUIT, '_Quit', 'Quit program', 'gtk-quit'), - gtk.Action(FLOW_GRAPH_UNDO, '_Undo', 'Undo a change to the flow graph', 'gtk-undo'), - gtk.Action(FLOW_GRAPH_REDO, '_Redo', 'Redo a change to the flow graph', 'gtk-redo'), - gtk.Action(ELEMENT_DELETE, '_Delete', 'Delete the selected blocks', 'gtk-delete'), - gtk.Action(BLOCK_ROTATE_LEFT, 'Rotate _Left', 'Rotate the selected blocks 90 degrees', 'gtk-go-back'), - gtk.Action(BLOCK_ROTATE_RIGHT, 'Rotate _Right', 'Rotate the selected blocks -90 degrees', 'gtk-go-forward'), - gtk.Action(BLOCK_PARAM_MODIFY, '_Properties', 'Modify params for the selected block', 'gtk-properties'), - gtk.Action(BLOCK_ENABLE, 'E_nable', 'Enable the selected blocks', 'gtk-connect'), - gtk.Action(BLOCK_DISABLE, 'D_isable', 'Disable the selected blocks', 'gtk-disconnect'), - gtk.Action(BLOCK_CUT, 'Cu_t', 'Cut', 'gtk-cut'), - gtk.Action(BLOCK_COPY, '_Copy', 'Copy', 'gtk-copy'), - gtk.Action(BLOCK_PASTE, '_Paste', 'Paste', 'gtk-paste'), - gtk.Action(PREFS_WINDOW_DISPLAY, '_Preferences', 'Configure Preferences', 'gtk-preferences'), - gtk.Action(ABOUT_WINDOW_DISPLAY, '_About', 'About this program', 'gtk-about'), - gtk.Action(HOTKEYS_WINDOW_DISPLAY, '_HotKeys', 'Hot Keys', 'gtk-info'), - gtk.Action(FLOW_GRAPH_GEN, '_Generate', 'Generate the flow graph', 'gtk-convert'), - gtk.Action(FLOW_GRAPH_EXEC, '_Execute', 'Execute the flow graph', 'gtk-execute'), - gtk.Action(FLOW_GRAPH_KILL, '_Kill', 'Kill the flow graph', 'gtk-stop'), - gtk.Action(FLOW_GRAPH_SCREEN_CAPTURE, 'S_creen Capture', 'Create a screen capture of the flow graph', 'gtk-print'), -) - -ACTIONS_DICT = dict((action.get_name(), action) for action in ACTIONS_LIST) - -def get_action_from_name(action_name): - """! - Retrieve the action from the action list. - Search the list and find an action with said name. - @param action_name the action name(string) - @throw KeyError bad action name - @return a gtk action object - """ - if ACTIONS_DICT.has_key(action_name): return ACTIONS_DICT[action_name] - raise KeyError('Action Name: "%s" does not exist'%action_name) - diff --git a/grc/src/grc/Constants.py.in b/grc/src/grc/Constants.py.in deleted file mode 100644 index a1671508..00000000 --- a/grc/src/grc/Constants.py.in +++ /dev/null @@ -1,154 +0,0 @@ -""" -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 -""" -##@package grc.Constants -#Global constants -#@author Josh Blum - -import os - -###################################################################################################### -## Global Titles -###################################################################################################### - -##The current version of this code -VERSION = '@VERSION@' - -##The name to appear in the main window for a flow graph that has not been saved to file. -NEW_FLOGRAPH_TITLE = 'untitled' - -##The prefix title on the main window. -MAIN_WINDOW_PREFIX = "GRC" - -###################################################################################################### -## Signal block connector lengths -###################################################################################################### - -##The length that a connection must extend from the port until the length depends on the index of the port. -CONNECTOR_EXTENSION_INITIAL_LENGTH = 11 - -##The length that a connection must extend from the initial length times the index of the port, after this length, the connection may have a bend. -CONNECTOR_EXTENSION_LENGTH = 11 - -##The length of the connector arrow base in pixels -CONNECTOR_ARROW_BASE = 13 - -##The length of the connector arrow height in pixels -CONNECTOR_ARROW_HEIGHT = 17 - -###################################################################################################### -## Signal block rotations -###################################################################################################### - -##List of possible angles (in degrees) that a block can be rotated to. -POSSIBLE_ROTATIONS = (0, 90, 180, 270) - -##direction of rotation left. -DIR_LEFT = 'left' - -##direction of rotation right. -DIR_RIGHT = 'right' - -###################################################################################################### -## Dimension constraints for the various windows (in pixels) -###################################################################################################### - -##main window constraints -MIN_WINDOW_WIDTH = 600 -MIN_WINDOW_HEIGHT = 400 - -##dialog constraints -MIN_DIALOG_WIDTH = 500 -MIN_DIALOG_HEIGHT = 500 - -##static height of reports window -REPORTS_WINDOW_HEIGHT = 100 - -##static width of block selection window -BLOCK_SELECTION_WINDOW_WIDTH = 200 - -###################################################################################################### -## Constraints on displayable labels and ports -###################################################################################################### - -LABEL_SEPARATION = 3 -LABEL_PADDING_WIDTH = 9 -LABEL_PADDING_HEIGHT = 9 - -PORT_SEPARATION = 17 -PORT_HEIGHT = 15 -PORT_WIDTH = 25 -PORT_BORDER_SEPARATION = 9 -MAX_NUM_PORTS = 7 - -PARAM_LABEL_FONT = 'Sans 9.5' -PARAM_FONT = 'Sans 7.5' -BLOCK_FONT = 'Sans 8' -PORT_FONT = 'Sans 7.5' - -###################################################################################################### -## Dragging, scrolling, and redrawing constants for the flow graph window in pixels -###################################################################################################### - -##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 - -##The redrawing sensitivity, how many seconds must pass between motion events before a redraw? -MOTION_DETECT_REDRAWING_SENSITIVITY = .02 - -##How close the mouse click can be to a connection and register a connection select. -CONNECTION_SELECT_SENSITIVITY = 5 - -###################################################################################################### -# A state is recorded for each change to the flow graph, the size dictates how many states we can record -###################################################################################################### - -##The size of the state saving cache in the flow graph (for undo/redo functionality) -STATE_CACHE_SIZE = 42 - -###################################################################################################### -## Constansts dealing with File Paths -###################################################################################################### - -##Location of external data files. -DATA_DIR = '@datadir@' - -##DTD validator for saved flow graphs. -FLOW_GRAPH_DTD = os.path.join(DATA_DIR, 'flow_graph.dtd') - -##The default file extension for flow graphs. -FLOW_GRAPH_FILE_EXTENSION = '.grc' - -##The default file extension for saving flow graph snap shots. -IMAGE_FILE_EXTENSION = '.png' - -##The default path for the open/save dialogs. -DEFAULT_FILE_PATH = os.getcwd() - -##The default icon for the gtk windows. -PY_GTK_ICON = os.path.join(DATA_DIR, 'grc-icon-256.png') - -##The users home directory. -HOME_DIR = os.path.expanduser('~') - diff --git a/grc/src/grc/Makefile.am b/grc/src/grc/Makefile.am deleted file mode 100644 index 06edf26c..00000000 --- a/grc/src/grc/Makefile.am +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/grc/Makefile.inc - -SUBDIRS = elements gui - -ourpythondir = $(pythondir)/grc - -ourpython_PYTHON = \ - __init__.py \ - Constants.py \ - converter.py \ - ActionHandler.py \ - Actions.py \ - Messages.py \ - ParseXML.py \ - Preferences.py \ - StateCache.py \ - Utils.py - -BUILT_SOURCES = Constants.py - -Constants.py: Makefile $(srcdir)/Constants.py.in - sed \ - -e 's|@VERSION[@]|@VERSION@|g' \ - -e 's|@datadir[@]|$(grc_data_dir)|g' \ - $(srcdir)/Constants.py.in > $@ - -EXTRA_DIST = Constants.py.in - -MOSTLYCLEANFILES = $(BUILT_SOURCES) diff --git a/grc/src/grc/Messages.py b/grc/src/grc/Messages.py deleted file mode 100644 index c3db894d..00000000 --- a/grc/src/grc/Messages.py +++ /dev/null @@ -1,104 +0,0 @@ -""" -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 -""" -##@package Messages -#Handle all of the system messages and error reports. - -from Constants import VERSION -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(): - send("""<<< Welcome to GRC %s >>>\n"""%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('Parser Error: %s\n'%error) - send(">>> Failue\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(">>> Failue\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('>>> Warning: A connection can only be created between a source and an unconnected sink.\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) - diff --git a/grc/src/grc/ParseXML.py b/grc/src/grc/ParseXML.py deleted file mode 100644 index cf6ce830..00000000 --- a/grc/src/grc/ParseXML.py +++ /dev/null @@ -1,102 +0,0 @@ -""" -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 -""" -##@package grc.gui.ParseXML -#Parse xml files to nested data and vice-versa. - -from lxml import etree -from Utils import odict - -XMLSyntaxError = etree.XMLSyntaxError - -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 - """ - if dtd_file: - dtd = etree.DTD(dtd_file) - xml = etree.parse(xml_file) - if not dtd.validate(xml.getroot()): - raise XMLSyntaxError, '\n'.join(map(str, dtd.error_log.filter_from_errors())) - else: - parser = etree.XMLParser(dtd_validation=True) - xml = etree.parse(xml_file, parser=parser) - if parser.error_log: - raise XMLSyntaxError, '\n'.join(map(str, parser.error_log.filter_from_errors())) - -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/src/grc/Preferences.py b/grc/src/grc/Preferences.py deleted file mode 100644 index e2161d64..00000000 --- a/grc/src/grc/Preferences.py +++ /dev/null @@ -1,133 +0,0 @@ -""" -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 -""" -##@package grc.Preferences -#Holds global paramerences - -from Constants import HOME_DIR, FLOW_GRAPH_DTD -import ParseXML -import Messages -import os - -##Access the loaded preferences in this module -_prefs = list() -def _set_prefs(prefs): _prefs.append(prefs) -def _get_prefs(): return _prefs[0] -def load(platform): _Preferences(platform) -def save(): _get_prefs().save() -def get_preferences(): return _get_prefs().get_preferences() - -class _Preferences(object): - - def __init__(self, platform): - #make self available to module - _set_prefs(self) - #get prefs block - self._prefs_block = platform.get_prefs_block() - #prefs file path - self._prefs_file_path = os.path.join(HOME_DIR, self._prefs_block.get_param('prefs_file').get_value()) - #load - try: - ParseXML.validate_dtd(self._prefs_file_path, FLOW_GRAPH_DTD) - n = ParseXML.from_file(self._prefs_file_path) - self._prefs_block.import_data(n['block']) - except: Messages.send_fail_load_preferences(self._prefs_file_path) - ##all params - self.snap_to_grid_param = self._prefs_block.get_param('snap_to_grid') - self.grid_size_param = self._prefs_block.get_param('grid_size') - self.show_grid_param = self._prefs_block.get_param('show_grid') - self.show_reports_param = self._prefs_block.get_param('show_reports') - self.restore_files_param = self._prefs_block.get_param('restore_files') - self.window_size_param = self._prefs_block.get_param('window_size') - self.file_open_param = self._prefs_block.get_param('file_open') - self.files_open_param = self._prefs_block.get_param('files_open') - self.show_params_param = self._prefs_block.get_param('show_params') - self.show_id_param = self._prefs_block.get_param('show_id') - - def save(self): - try: ParseXML.to_file({'block': self._prefs_block.export_data()}, self._prefs_file_path) - except IOError: Messages.send_fail_save_preferences(self._prefs_file_path) - - def get_preferences(self): - ##Preferences: title, notes, params - return [ - ( - 'Grid', - ''' -Show grid will draw a square grid onto the flow graph with grid points separated by grid size pixels. \ -Snap to Grid forces the upper right corner of the signal block to align with a grid point. -''', - [self.snap_to_grid_param, self.grid_size_param, self.show_grid_param], - ), - ( - 'Appearance', - ''' -Show or hide the reports window at the bottom of the main window. -Show or hide all paramater labels in the signal blocks. -Show or hide the ID label in the signal blocks. -''', - [self.show_reports_param, self.show_params_param, self.show_id_param], - ), - ( - 'Misc', - ''' -Restore previously opened files on start-up. -''', - [self.restore_files_param], - ), - ] - -########################################################################### -# Special methods for specific program functionalities -########################################################################### - -def window_size(size=None): - if size: _get_prefs().window_size_param.set_value(size) - else: - try: return eval(_get_prefs().window_size_param.get_value()) - except: return (-1, -1) - -def restore_files(): - return _get_prefs().restore_files_param.get_value() == 'yes' - -def file_open(file=None): - if file is not None: _get_prefs().file_open_param.set_value(file) - else: return _get_prefs().file_open_param.get_value() - -def files_open(files=None): - if files is not None: _get_prefs().files_open_param.set_value('\n'.join(files)) - else: return _get_prefs().files_open_param.get_value().split('\n') - -def show_reports_window(): - return _get_prefs().show_reports_param.get_value() == 'show' - -def get_grid_size(): - return int(_get_prefs().grid_size_param.get_value()) - -def snap_to_grid(): - return _get_prefs().snap_to_grid_param.get_value() == 'on' - -def show_grid(): - return _get_prefs().show_grid_param.get_value() == 'show' - -def show_params(): - return _get_prefs().show_params_param.get_value() == 'show' - -def show_id(): - return _get_prefs().show_id_param.get_value() == 'show' - diff --git a/grc/src/grc/StateCache.py b/grc/src/grc/StateCache.py deleted file mode 100644 index b973e274..00000000 --- a/grc/src/grc/StateCache.py +++ /dev/null @@ -1,97 +0,0 @@ -""" -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 -""" -##@package StateCache -#Stores the flow graph states to drive the undo/redo and save interface. - -from Actions import FLOW_GRAPH_UNDO, FLOW_GRAPH_REDO, get_action_from_name - -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. - """ - get_action_from_name(FLOW_GRAPH_REDO).set_sensitive(self.num_next_states != 0) - get_action_from_name(FLOW_GRAPH_UNDO).set_sensitive(self.num_prev_states != 0) - - diff --git a/grc/src/grc/Utils.py b/grc/src/grc/Utils.py deleted file mode 100644 index 1cc71b42..00000000 --- a/grc/src/grc/Utils.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -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 -""" -##@package grc.gui.Utils -#Utility methods and classes. - -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 exists_or_else(d, key, alt): - if d.has_key(key): return d[key] - else: return alt - -def listify(d, key): - obj = exists_or_else(d, key, []) - if isinstance(obj, list): return obj - return [obj] - diff --git a/grc/src/grc/__init__.py b/grc/src/grc/__init__.py deleted file mode 100644 index d9ba2559..00000000 --- a/grc/src/grc/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -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 -""" -##@package grc -#grc package. - diff --git a/grc/src/grc/converter.py b/grc/src/grc/converter.py deleted file mode 100644 index a69163e2..00000000 --- a/grc/src/grc/converter.py +++ /dev/null @@ -1,250 +0,0 @@ -""" -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 -""" -##@package grc.converter -#convert old flow graph file format to new format - -from grc.Constants import FLOW_GRAPH_DTD -from grc import ParseXML, Utils -from grc.Utils import odict -from lxml import etree -import difflib -import os - -def _make_param(key, value): - """! - Make a paramater dict from the key/value pair. - @param key the key - @param value the value - @return a dictionary object - """ - param = odict() - param['key'] = key - param['value'] = value - return param - -def _get_blocks(blocks, tag): - """! - Get a list of blocks with the tag. - @param blocks the old block list - @param tag the tag name - @retun a list of matching blocks - """ - return filter(lambda b: b['tag'] == tag, blocks) - -def _get_params(block): - """! - Get a list of params. - @param block the old block - @retun a list of params - """ - params = Utils.exists_or_else(block, 'params', {}) or {} - params = Utils.listify(params, 'param') - return params - -def _convert_id(id): - """! - Convert an old id to a new safe id. - Replace spaces with underscores. - Lower case the odl id. - @return the reformatted id - """ - return id.lower().replace(' ', '_') - -def convert(file_path, platform): - """! - Convert the flow graph to the new format. - Make a backup of the old file. - Save a reformated flow graph to the file path. - If this is a new format flow graph, do nothing. - @param file_path the path to the saved flow graph - @param platform the grc gnuradio platform - """ - try: #return if file passes validation - ParseXML.validate_dtd(file_path, FLOW_GRAPH_DTD) - try: - changed = False - #convert instances of gui_coordinate and gui_rotation - xml = etree.parse(file_path) - for find, replace in ( - ('gui_coordinate', '_coordinate'), - ('gui_rotation', '_rotation'), - ): - keys = xml.xpath('/flow_graph/block/param[key="%s"]/key'%find) - for key in keys: - key.text = replace - changed = True - if not changed: return - #backup after successful conversion - os.rename(file_path, file_path+'.bak') - #save new flow graph to file path - xml.write(file_path, xml_declaration=True, pretty_print=True) - except Exception, e: print e - return - except: pass #convert - ############################################################ - # extract window size, variables, blocks, and connections - ############################################################ - old_n = ParseXML.from_file(file_path)['flow_graph'] - try: window_width = min(3*int(old_n['window_width'])/2, 2048) - except: window_width = 2048 - try: window_height = min(3*int(old_n['window_height'])/2, 2048) - except: window_height = 2048 - window_size = '%d, %d'%(window_width, window_height) - variables = Utils.exists_or_else(old_n, 'vars', {}) or {} - variables = Utils.listify(variables, 'var') - blocks = Utils.exists_or_else(old_n, 'signal_blocks', {}) or {} - blocks = Utils.listify(blocks, 'signal_block') - connections = Utils.exists_or_else(old_n, 'connections', {}) or {} - connections = Utils.listify(connections, 'connection') - #initialize new nested data - new_n = odict() - new_n['block'] = list() - new_n['connection'] = list() - ############################################################ - # conversion - options block - ############################################################ - #get name - about_blocks = _get_blocks(blocks, 'About') - if about_blocks: title = _get_params(about_blocks[0])[0] - else: title = 'Untitled' - #get author - if about_blocks: author = _get_params(about_blocks[0])[1] - else: author = '' - #get desc - note_blocks = _get_blocks(blocks, 'Note') - if note_blocks: desc = _get_params(note_blocks[0])[0] - else: desc = '' - #create options block - options_block = odict() - options_block['key'] = 'options' - options_block['param'] = [ - _make_param('id', 'top_block'), - _make_param('title', title), - _make_param('author', author), - _make_param('description', desc), - _make_param('window_size', window_size), - _make_param('_coordinate', '(10, 10)'), - ] - #append options block - new_n['block'].append(options_block) - ############################################################ - # conversion - variables - ############################################################ - x = 100 - for variable in variables: - key = variable['key'] - value = variable['value'] - minimum = Utils.exists_or_else(variable, 'min', '') - maximum = Utils.exists_or_else(variable, 'max', '') - step = Utils.exists_or_else(variable, 'step', '') - x = x + 150 - coor = '(%d, %d)'%(x, 10) - var_block = odict() - if minimum and maximum: #slider varible - #determine num steps - try: num_steps = str(int((float(maximum) - float(minimum))/float(step))) - except: num_steps = '100' - var_block['key'] = 'variable_slider' - var_block['param'] = [ - _make_param('id', key), - _make_param('value', value), - _make_param('min', minimum), - _make_param('max', maximum), - _make_param('num_steps', num_steps), - _make_param('_coordinate', coor), - ] - else: #regular variable - var_block['key'] = 'variable' - var_block['param'] = [ - _make_param('id', key), - _make_param('value', value), - _make_param('_coordinate', coor), - ] - #append variable block - new_n['block'].append(var_block) - ############################################################ - # conversion - blocks - ############################################################ - #create name to key map for all blocks in platform - name_to_key = dict((b.get_name(), b.get_key()) for b in platform.get_blocks()) - for block in blocks: - #extract info - tag = block['tag'] - #ignore list - if tag in ('Note', 'About'): continue - id = _convert_id(block['id']) - coor = '(%s, %s + 100)'%( - Utils.exists_or_else(block, 'x_coordinate', '0'), - Utils.exists_or_else(block, 'y_coordinate', '0'), - ) - rot = Utils.exists_or_else(block, 'rotation', '0') - params = _get_params(block) - #new block - new_block = odict() - matches = difflib.get_close_matches(tag, name_to_key.keys(), 1) - if not matches: continue - #match found - key = name_to_key[matches[0]] - new_block['key'] = key - new_block['param'] = [ - _make_param('id', id), - _make_param('_coordinate', coor), - _make_param('_rotation', rot), - ] - #handle specific blocks - if key == 'wxgui_fftsink2': - params = params[0:3] + ['0'] + params[3:4] + ['8'] + params[4:] - #append params - for i, param in enumerate(params): - platform_block = platform.get_block(key) - try: platform_param = platform_block.get_params()[i+2] - except IndexError: break - if platform_param.is_enum(): - try: param_value = platform_param.get_option_keys()[int(param)] - except: param_value = platform_param.get_option_keys()[0] - else: - param_value = param.replace('$', '').replace('^', '**') - new_block['param'].append(_make_param(platform_param.get_key(), param_value)) - #append block - new_n['block'].append(new_block) - ############################################################ - # conversion - connections - ############################################################ - for connection in connections: - #extract info - input_signal_block_id = connection['input_signal_block_id'] - input_socket_index = connection['input_socket_index'] - output_signal_block_id = connection['output_signal_block_id'] - output_socket_index = connection['output_socket_index'] - #new connection - new_conn = odict() - new_conn['source_block_id'] = _convert_id(output_signal_block_id) - new_conn['sink_block_id'] = _convert_id(input_signal_block_id) - new_conn['source_key'] = output_socket_index - new_conn['sink_key'] = input_socket_index - #append connection - new_n['connection'].append(new_conn) - ############################################################ - # backup and replace - ############################################################ - #backup after successful conversion - os.rename(file_path, file_path+'.bak') - #save new flow graph to file path - ParseXML.to_file({'flow_graph': new_n}, file_path) - diff --git a/grc/src/grc/elements/Block.py b/grc/src/grc/elements/Block.py deleted file mode 100644 index ff43933e..00000000 --- a/grc/src/grc/elements/Block.py +++ /dev/null @@ -1,239 +0,0 @@ -""" -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 -""" -##@package grc.elements.Block -#Flow graph block. - -from grc import Utils -from grc.Utils import odict -from grc.elements.Element import Element -from grc.elements.Param import Param -from grc.elements.Port import Port - -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 eval 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 eval(self): - return self._param.evaluate() - -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 - """ - #grab the data - name = n['name'] - key = n['key'] - category = Utils.exists_or_else(n, 'category', '') - params = Utils.listify(n, 'param') - sources = Utils.listify(n, 'source') - sinks = Utils.listify(n, 'sink') - #build the block - Element.__init__(self, flow_graph) - #store the data - self._name = name - self._key = key - self._category = category - #create the param objects - self._params = odict() - #add the id param - self._params['id'] = self.get_parent().get_parent().Param( - self, - { - 'name': 'ID', - 'key': 'id', - 'type': 'id', - } - ) - self._params['_enabled'] = self.get_parent().get_parent().Param( - self, - { - 'name': 'Enabled', - 'key': '_enabled', - 'type': 'raw', - 'value': 'True', - 'hide': 'all', - } - ) - for param in map(lambda n: self.get_parent().get_parent().Param(self, n), params): - key = param.get_key() - #test against repeated keys - try: assert(key not in self.get_param_keys()) - except AssertionError: self._exit_with_error('Key "%s" already exists in params'%key) - #store the param - self._params[key] = param - #create the source objects - self._sources = odict() - for source in map(lambda n: self.get_parent().get_parent().Source(self, n), sources): - key = source.get_key() - #test against repeated keys - try: assert(key not in self.get_source_keys()) - except AssertionError: self._exit_with_error('Key "%s" already exists in sources'%key) - #store the port - self._sources[key] = source - #create the sink objects - self._sinks = odict() - for sink in map(lambda n: self.get_parent().get_parent().Sink(self, n), sinks): - key = sink.get_key() - #test against repeated keys - try: assert(key not in self.get_sink_keys()) - except AssertionError: self._exit_with_error('Key "%s" already exists in sinks'%key) - #store the port - self._sinks[key] = sink - #begin the testing - self.test() - - def test(self): - """! - Call test on all children. - """ - map(lambda c: c.test(), self.get_params() + self.get_sinks() + self.get_sources()) - - 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 validate(self): - """ - Validate the block. - All ports and params must be valid. - All checks must evaluate to true. - """ - if not self.get_enabled(): return - for c in self.get_params() + self.get_sinks() + self.get_sources(): - try: assert(c.is_valid()) - except AssertionError: - for msg in c.get_error_messages(): - self._add_error_message('%s: %s'%(c, msg)) - - 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_doc(self): return self._doc - - 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() - - ############################################## - # Access Params - ############################################## - def get_param_keys(self): return self._params.keys() - def get_param(self, key): return self._params[key] - def get_params(self): return self._params.values() - - ############################################## - # Access Sinks - ############################################## - def get_sink_keys(self): return self._sinks.keys() - def get_sink(self, key): return self._sinks[key] - def get_sinks(self): return self._sinks.values() - - ############################################## - # Access Sources - ############################################## - def get_source_keys(self): return self._sources.keys() - def get_source(self, key): return self._sources[key] - def get_sources(self): return self._sources.values() - - 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) - - ############################################## - ## 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. - @param n the nested data odict - """ - params_n = Utils.listify(n, 'param') - for param_n in params_n: - #key and value must exist in the n data - if 'key' in param_n.keys() and 'value' in param_n.keys(): - key = param_n['key'] - value = param_n['value'] - #the key must exist in this block's params - if key in self.get_param_keys(): - self.get_param(key).set_value(value) - self.validate() diff --git a/grc/src/grc/elements/Connection.py b/grc/src/grc/elements/Connection.py deleted file mode 100644 index 36ed1422..00000000 --- a/grc/src/grc/elements/Connection.py +++ /dev/null @@ -1,93 +0,0 @@ -""" -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 -""" -##@package grc.elements.Connection -#Flow graph connection. -#A connection exists between 2 ports. -#One port must be input, one output. -#The port decided whether it can have the connection. - -from grc.elements.Element import Element -from grc.Utils 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 - #verify the source and sink - assert(source and sink) - assert(not source.is_full()) - assert(not sink.is_full()) - self._source = source - self._sink = sink - - def __str__(self): return 'Connection (%s -> %s)'%(self.get_source(), self.get_sink()) - - def is_connection(self): return True - - def validate(self): - """ - Validate the connections. - The ports must match in type. - """ - source_type = self.get_source().get_type() - sink_type = self.get_sink().get_type() - try: assert source_type == sink_type - except AssertionError: 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/src/grc/elements/Element.py b/grc/src/grc/elements/Element.py deleted file mode 100644 index 936c9d5f..00000000 --- a/grc/src/grc/elements/Element.py +++ /dev/null @@ -1,96 +0,0 @@ -""" -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 -""" -##@package grc.elements.Element -#The base class for all elements. - -class Element(object): - - def __init__(self, parent=None): - self._parent = parent - self._error_messages = [] - self.flag() - - def test(self): - """ - Test the element against failures. - Overload this method in sub-classes. - """ - pass - - def validate(self): - """ - Validate the data in this element. - Set the error message non blank for errors. - Overload this method in sub-classes. - """ - pass - - def is_valid(self): - self._error_messages = []#reset err msgs - try: self.validate() - except: pass - return not self.get_error_messages() - - def _add_error_message(self, msg): - self._error_messages.append(msg) - - def get_error_messages(self): - return self._error_messages - - def get_parent(self): - return self._parent - - def _exit_with_error(self, error): - parent = self - #build hier list of elements - elements = list() - while(parent): - elements.insert(0, parent) - parent = parent.get_parent() - #build error string - err_str = ">>> Error:" - for i, element in enumerate(elements + [error]): - err_str = err_str + '\n' + ''.join(' '*(i+2)) + str(element) - err_str = err_str + '\n' - exit(err_str) - - ############################################## - ## Update flagging - ############################################## - def is_flagged(self): return self._flag - def flag(self): - self._flag = True - if self.get_parent(): self.get_parent().flag() - def deflag(self): - self._flag = False - if self.get_parent(): self.get_parent().deflag() - - ############################################## - ## 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/src/grc/elements/FlowGraph.py b/grc/src/grc/elements/FlowGraph.py deleted file mode 100644 index 94c786d0..00000000 --- a/grc/src/grc/elements/FlowGraph.py +++ /dev/null @@ -1,235 +0,0 @@ -""" -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 -""" -##@package grc.elements.FlowGraph -#Primative flow graph. - -from grc import Utils -from grc.Utils import odict -from grc.elements.Element import Element -from grc.elements.Block import Block -from grc.elements.Connection import Connection - -from grc 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 - """ - #hold connections and blocks - self._elements = list() - #initialize - Element.__init__(self, platform) - #inital blank import - self.import_data({'flow_graph': {}}) - - def __str__(self): return 'FlowGraph - "%s"'%self.get_option('name') - - 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).evaluate() - - 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_elements(self): - """! - Get a list of all the elements. - Always ensure that the options block is in the list. - @return the element list - """ - if self._options_block not in self._elements: self._elements.append(self._options_block) - #ensure uniqueness of the elements list - element_set = set() - element_list = list() - for element in self._elements: - if element not in element_set: element_list.append(element) - element_set.add(element) - #store cleaned up list - self._elements = element_list - 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 - """ - self.flag() - 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 - """ - self.flag() - connection = self.get_parent().Connection(self, porta, 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. - """ - self.flag() - 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(lambda c: self.remove_element(c), port.get_connections()) - #remove a connection - elif element.is_connection(): pass - self.get_elements().remove(element) - - def evaluate(self, expr): - """! - Evaluate the expression. - @param expr the string expression - @throw NotImplementedError - """ - raise NotImplementedError - - def validate(self): - """ - Validate the flow graph. - All connections and blocks must be valid. - """ - for c in self.get_elements(): - try: assert(c.is_valid()) - except AssertionError: self._add_error_message('Element "%s" is not valid.'%c) - - ############################################## - ## 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 {'flow_graph': n} - - def import_data(self, n): - """ - 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() - #the flow graph tag must exists, or use blank data - if 'flow_graph' in n.keys(): fg_n = n['flow_graph'] - else: - Messages.send_error_load('Flow graph data not found, loading blank flow graph.') - fg_n = {} - blocks_n = Utils.listify(fg_n, 'block') - connections_n = Utils.listify(fg_n, 'connection') - #create option block - self._options_block = self.get_parent().get_new_block(self, 'options') - self._options_block.get_param('id').set_value('options') - #build the blocks - for block_n in blocks_n: - key = block_n['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: - #test that the data tags exist - try: - assert('source_block_id' in connection_n.keys()) - assert('sink_block_id' in connection_n.keys()) - assert('source_key' in connection_n.keys()) - assert('sink_key' in connection_n.keys()) - except AssertionError: continue - #try to make the connection - try: - #get the block ids - source_block_id = connection_n['source_block_id'] - sink_block_id = connection_n['sink_block_id'] - #get the port keys - source_key = connection_n['source_key'] - sink_key = connection_n['sink_key'] - #verify the blocks - block_ids = map(lambda b: b.get_id(), self.get_blocks()) - assert(source_block_id in block_ids) - assert(sink_block_id in block_ids) - #get the blocks - source_block = self.get_block(source_block_id) - sink_block = self.get_block(sink_block_id) - #verify the ports - assert(source_key in source_block.get_source_keys()) - assert(sink_key in sink_block.get_sink_keys()) - #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 AssertionError: Messages.send_error_load('Connection between %s(%s) and %s(%s) could not be made.'%(source_block_id, source_key, sink_block_id, sink_key)) - self.validate() - diff --git a/grc/src/grc/elements/Makefile.am b/grc/src/grc/elements/Makefile.am deleted file mode 100644 index 2b97c977..00000000 --- a/grc/src/grc/elements/Makefile.am +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/Makefile.common - -ourpythondir = $(pythondir)/grc/elements - -ourpython_PYTHON = \ - __init__.py \ - Block.py \ - Connection.py \ - Element.py \ - FlowGraph.py \ - Param.py \ - Platform.py \ - Port.py diff --git a/grc/src/grc/elements/Param.py b/grc/src/grc/elements/Param.py deleted file mode 100644 index a8aa4300..00000000 --- a/grc/src/grc/elements/Param.py +++ /dev/null @@ -1,221 +0,0 @@ -""" -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 -""" -##@package grc.elements.Param -#Flow graph block parameters. -#And options for enum type paramater. - -from grc import Utils -from grc.Utils import odict -from grc.elements.Element import Element - -class Option(Element): - - def __init__(self, param, name, key, opts): - Element.__init__(self, param) - self._name = name - self._key = key - self._opts = dict() - for opt in opts: - #separate the key:value - try: key, value = opt.split(':') - except: self._exit_with_error('Error separating "%s" into key:value'%opt) - #test against repeated keys - try: assert(not self._opts.has_key(key)) - except AssertionError: self._exit_with_error('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() - - ############################################## - ## Static Make Methods - ############################################## - def make_option_from_n(param, n): - """ - Make a new option from nested data. - @param param the parent element - @param n the nested odict - @return a new option - """ - #grab the data - name = n['name'] - key = n['key'] - opts = Utils.listify(n, 'opt') - #build the option - return Option( - param=param, - name=name, - key=key, - opts=opts, - ) - make_option_from_n = staticmethod(make_option_from_n) - -class Param(Element): - - ##possible param types - TYPES = ['enum', 'raw'] - - def __init__(self, block, n): - """ - Make a new param from nested data. - @param block the parent element - @param n the nested odict - @return a new param - """ - #grab the data - name = n['name'] - key = n['key'] - value = Utils.exists_or_else(n, 'value', '') - type = n['type'] - hide = Utils.exists_or_else(n, 'hide', '') - options = Utils.listify(n, 'option') - #build the param - Element.__init__(self, block) - self._name = name - self._key = key - self._type = type - self._hide = hide - #create the Option objects from the n data - self._options = odict() - for option in map(lambda o: Option.make_option_from_n(self, o), options): - key = option.get_key() - #test against repeated keys - try: assert(key not in self.get_option_keys()) - except AssertionError: self._exit_with_error('Key "%s" already exists in options'%key) - #store the option - self._options[key] = option - #test the enum options - if self._options or self.is_enum(): - #test against bad combos of type and enum - try: assert(self._options) - except AssertionError: self._exit_with_error('At least one option must exist when type "enum" is set.') - try: assert(self.is_enum()) - except AssertionError: self._exit_with_error('Type "enum" must be set when options are present.') - #test against options with identical keys - try: assert(len(set(self.get_option_keys())) == len(self._options)) - except AssertionError: self._exit_with_error('Options keys "%s" are not unique.'%self.get_option_keys()) - #test against inconsistent keys in options - opt_keys = self._options.values()[0].get_opt_keys() - for option in self._options.values(): - try: assert(set(opt_keys) == set(option.get_opt_keys())) - except AssertionError: self._exit_with_error('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 or self.get_option_keys()[0] - try: assert(self.get_value() in self.get_option_keys()) - except AssertionError: self._exit_with_error('The value "%s" is not in the possible values of "%s".'%(self.get_value(), self.get_option_keys())) - else: self._value = value or '' - - def test(self): - """ - call test on all children - """ - map(lambda c: c.test(), self.get_options()) - - def validate(self): - """ - Validate the param. - The value must be evaluated and type must a possible type. - """ - try: - assert(self.get_type() in self.TYPES) - try: self.evaluate() - except: - #if the evaluate failed but added no error messages, add the generic one below - if not self.get_error_messages(): - self._add_error_message('Value "%s" cannot be evaluated.'%self.get_value()) - except AssertionError: self._add_error_message('Type "%s" is not a possible type.'%self.get_type()) - - def evaluate(self): - """! - Evaluate the value of this param. - @throw NotImplementedError - """ - raise NotImplementedError - - def to_code(self): - """! - Convert the value to code. - @throw NotImplementedError - """ - raise NotImplementedError - - 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) - - 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.flag() - 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 is_type_dependent(self): return '$' in self._type - - ############################################## - # Access Options - ############################################## - def get_option_keys(self): return self._options.keys() - def get_option(self, key): return self._options[key] - def get_options(self): return self._options.values() - - ############################################## - # Access Opts - ############################################## - def get_opt_keys(self): return self._options[self.get_value()].get_opt_keys() - def get_opt(self, key): return self._options[self.get_value()].get_opt(key) - def get_opts(self): return self._options[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/src/grc/elements/Platform.py b/grc/src/grc/elements/Platform.py deleted file mode 100644 index bf09bef0..00000000 --- a/grc/src/grc/elements/Platform.py +++ /dev/null @@ -1,146 +0,0 @@ -""" -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 -""" -##@package grc.elements.Platform -#A Platform contains all blocks in platform. - -import os -from grc import ParseXML -from grc import Utils -from grc.elements.Element import Element as _Element -from grc.elements.FlowGraph import FlowGraph as _FlowGraph -from grc.elements.Connection import Connection as _Connection -from grc.elements.Block import Block as _Block -from grc.elements.Port import Port as _Port -from grc.elements.Param import Param as _Param -from grc.Constants import DATA_DIR - -class Platform(_Element): - - def __init__(self, name, key, block_paths, block_dtd, block_tree, default_flow_graph, generator): - """! - Make a platform from the arguments. - @param name the platform name - @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 block_tree the nested tree of block keys and categories - @param default_flow_graph the default flow graph file path - @param load_one a single file to load into this platform or None - @return a platform object - """ - _Element.__init__(self) - self._name = name - self._key = key - self._block_paths = block_paths - self._block_dtd = block_dtd - self._block_tree = block_tree - self._default_flow_graph = default_flow_graph - self._generator = generator - #create a dummy flow graph for the blocks - self._flow_graph = _Element(self) - #load the blocks - self._blocks = dict() - self._blocks_n = dict() - for block_path in self._block_paths: - if os.path.isfile(block_path): self._load_block(block_path) - elif os.path.isdir(block_path): - for dirpath,dirnames,filenames in os.walk(block_path): - for filename in filter(lambda f: f.endswith('.xml'), filenames): - self._load_block(os.path.join(dirpath, filename)) - - def get_prefs_block(self): return self.get_new_flow_graph().get_new_block('preferences') - - def _load_block(self, f): - """! - Load the block wrapper from the file path. - The block wrapper must pass validation, and have a unique block key. - If any of the checks fail, exit with error. - @param f the file path - """ - try: ParseXML.validate_dtd(f, self._block_dtd) - except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block definition "%s" failed: \n\t%s'%(f, e)) - n = ParseXML.from_file(f)['block'] - block = self.Block(self._flow_graph, n) - key = block.get_key() - #test against repeated keys - try: assert(key not in self.get_block_keys()) - except AssertionError: self._exit_with_error('Key "%s" already exists in blocks'%key) - #store the block - self._blocks[key] = block - self._blocks_n[key] = n - - 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 = '%s/%s'%(parent, cat_n['name']) - block_tree.add_block(parent) - #recursive call to load sub categories - map(lambda c: load_category(c, parent), Utils.listify(cat_n, 'cat')) - #add blocks in this category - for block_key in Utils.listify(cat_n, 'block'): - block_tree.add_block(parent, self.get_block(block_key)) - #load the block tree - f = self._block_tree - try: ParseXML.validate_dtd(f, os.path.join(DATA_DIR, 'block_tree.dtd')) - except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block tree "%s" failed: \n\t%s'%(f, e)) - #add all blocks in the tree - load_category(ParseXML.from_file(f)['cat']) - #add all other blocks, use the catgory - for block in self.get_blocks(): - #blocks with empty categories are in the xml block tree or hidden - if block.get_category(): 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(self) - - def get_default_flow_graph(self): return self._default_flow_graph - - 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_key(self): return self._key - - ############################################## - # Constructors - ############################################## - FlowGraph = _FlowGraph - Connection = _Connection - Block = _Block - Source = _Port - Sink = _Port - Param = _Param diff --git a/grc/src/grc/elements/Port.py b/grc/src/grc/elements/Port.py deleted file mode 100644 index 9da52115..00000000 --- a/grc/src/grc/elements/Port.py +++ /dev/null @@ -1,108 +0,0 @@ -""" -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 -""" -##@package grc.elements.Port -#Flow graph block port (source or sink). - -from grc import Utils -from grc.elements.Element import Element - -class Port(Element): - - ##possible port types - TYPES = [] - - def __init__(self, block, n): - """ - Make a new port from nested data. - @param block the parent element - @param n the nested odict - @return a new port - """ - #grab the data - name = n['name'] - key = n['key'] - type = n['type'] - #build the port - Element.__init__(self, block) - self._name = name - self._key = key - self._type = type - - def validate(self): - """! - Validate the port. - The port must be non-empty and type must a possible type. - """ - try: assert(not self.is_empty()) - except AssertionError: self._add_error_message('is empty.') - try: assert(self.get_type() in self.TYPES) - except AssertionError: 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 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 in self.get_parent().get_sinks() - - def is_source(self): return self in self.get_parent().get_sources() - - 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 is_connected(self): - """! - Is this port connected? - @return true if at least one connection - """ - return bool(self.get_connections()) - - def is_full(self): - """! - Is this port full of connections? - Generally a sink can handle one connection and a source can handle many. - @return true if the port is full - """ - if self.is_source(): return False - if self.is_sink(): return bool(self.get_connections()) - - def is_empty(self): - """! - Is this port empty? - An empty port has no connections. - @return true if empty - """ - return not self.get_connections() diff --git a/grc/src/grc/elements/__init__.py b/grc/src/grc/elements/__init__.py deleted file mode 100644 index cb5e282e..00000000 --- a/grc/src/grc/elements/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -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 -""" -##@package grc.elements -#Package for flow graph elements. - diff --git a/grc/src/grc/gui/Bars.py b/grc/src/grc/gui/Bars.py deleted file mode 100644 index 00238b06..00000000 --- a/grc/src/grc/gui/Bars.py +++ /dev/null @@ -1,142 +0,0 @@ -""" -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 -""" -##@package grc.gui.Bars -#Create the GUI's toolbar and menubar - -from grc.Actions import * -import pygtk -pygtk.require('2.0') -import gtk - -##The list of actions for the toolbar. -TOOLBAR_LIST = ( - FLOW_GRAPH_NEW, - FLOW_GRAPH_OPEN, - FLOW_GRAPH_SAVE, - FLOW_GRAPH_CLOSE, - None, - FLOW_GRAPH_SCREEN_CAPTURE, - None, - BLOCK_CUT, - BLOCK_COPY, - BLOCK_PASTE, - ELEMENT_DELETE, - None, - FLOW_GRAPH_UNDO, - FLOW_GRAPH_REDO, - None, - FLOW_GRAPH_GEN, - FLOW_GRAPH_EXEC, - FLOW_GRAPH_KILL, - None, - BLOCK_ROTATE_LEFT, - BLOCK_ROTATE_RIGHT, - None, - BLOCK_ENABLE, - BLOCK_DISABLE, -) - -##The list of actions and categories for the menu bar. -MENU_BAR_LIST = ( - (gtk.Action('File', '_File', None, None), [ - FLOW_GRAPH_NEW, - FLOW_GRAPH_OPEN, - None, - FLOW_GRAPH_SAVE, - FLOW_GRAPH_SAVE_AS, - None, - FLOW_GRAPH_SCREEN_CAPTURE, - None, - FLOW_GRAPH_CLOSE, - APPLICATION_QUIT, - ]), - (gtk.Action('Edit', '_Edit', None, None), [ - FLOW_GRAPH_UNDO, - FLOW_GRAPH_REDO, - None, - BLOCK_CUT, - BLOCK_COPY, - BLOCK_PASTE, - ELEMENT_DELETE, - None, - BLOCK_ROTATE_LEFT, - BLOCK_ROTATE_RIGHT, - None, - BLOCK_ENABLE, - BLOCK_DISABLE, - None, - BLOCK_PARAM_MODIFY, - ]), - (gtk.Action('Build', '_Build', None, None), [ - FLOW_GRAPH_GEN, - FLOW_GRAPH_EXEC, - FLOW_GRAPH_KILL, - ]), - (gtk.Action('Options', '_Options', None, None), [ - PREFS_WINDOW_DISPLAY, - ]), - (gtk.Action('Help', '_Help', None, None), [ - ABOUT_WINDOW_DISPLAY, - HOTKEYS_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_name in TOOLBAR_LIST: - if action_name: #add a tool item - action = get_action_from_name(action_name) - 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,action_names 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_name in action_names: - if action_name: #append a menu item - action = get_action_from_name(action_name) - 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/src/grc/gui/BlockTreeWindow.py b/grc/src/grc/gui/BlockTreeWindow.py deleted file mode 100644 index 9543fdda..00000000 --- a/grc/src/grc/gui/BlockTreeWindow.py +++ /dev/null @@ -1,153 +0,0 @@ -""" -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 -""" -##@package grc.gui.BlockTreeWindow -#The block selection panel gives the user a tree selection to choose a block. - -from grc.Constants import * -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -NAME_INDEX = 0 -KEY_INDEX = 1 - -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) - 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) - #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(BLOCK_SELECTION_WINDOW_WIDTH, -1) - self.pack_start(scrolled_window) - #add button - self.add_button = gtk.Button(None, 'gtk-add') - self.add_button.connect('clicked', self._handle_add_button) - self.pack_start(self.add_button, False) - #map categories to iters - self.categories = dict() - self.categories[tuple()] = None - #add blocks and categories - self.platform.load_block_tree(self) - #initialize - self._update_add_button() - - ############################################################ - ## 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 string - @param block the block object or None - """ - #rectify category - category = filter(lambda x: x, category.split('/')) - #add category and all sub categories - for i in range(len(category)): - sub_category = tuple(category[:i+1]) - if sub_category not in self.categories.keys(): - iter = self.treestore.insert_before(self.categories[tuple(category[:i])], None) - self.treestore.set_value(iter, NAME_INDEX, '[ %s ]'%category[i]) - self.treestore.set_value(iter, KEY_INDEX, '') - self.categories[sub_category] = iter - #add block - if block is None: return - iter = self.treestore.insert_before(self.categories[tuple(category)], None) - self.treestore.set_value(iter, NAME_INDEX, block.get_name()) - self.treestore.set_value(iter, KEY_INDEX, block.get_key()) - - ############################################################ - ## 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_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/src/grc/gui/Dialogs.py b/grc/src/grc/gui/Dialogs.py deleted file mode 100644 index 55e26846..00000000 --- a/grc/src/grc/gui/Dialogs.py +++ /dev/null @@ -1,148 +0,0 @@ -""" -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 -""" -##@package grc.gui.Dialogs -#Misc dialogs. - -import pygtk -pygtk.require('2.0') -import gtk -from grc.Constants import * -from grc import Preferences - -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) - -###################################################################################################### -class PreferencesDialog(gtk.Dialog): - """A dialog box to display the preferences.""" - - def __init__(self): - """PreferencesDialog constructor.""" - gtk.Dialog.__init__(self, buttons=('gtk-close', gtk.RESPONSE_CLOSE)) - self.set_title("Preferences") - self.set_size_request(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT) - notebook = gtk.Notebook() - for title,desc,params in Preferences.get_preferences(): - vbox = gtk.VBox() - vbox.pack_start(gtk.Label(''), False) #blank label for spacing - for param in params: vbox.pack_start(param.get_input_object(), False) - desc = desc.strip('\n') - if desc: vbox.pack_start(TextDisplay(desc), False, padding=5) - notebook.append_page(vbox, gtk.Label(title)) - self.vbox.pack_start(notebook, True) - self.show_all() - self.run() - self.destroy() - -###################################################################################################### -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 != None: message_dialog.set_title(title) - if markup != None: message_dialog.set_markup(markup) - response = message_dialog.run() - message_dialog.destroy() - return response - -###################################################################################################### -class AboutDialog(gtk.AboutDialog): - """A cute little about dialog.""" - - def __init__(self): - """AboutDialog constructor.""" - gtk.AboutDialog.__init__(self) - self.set_version(VERSION) - self.set_name(MAIN_WINDOW_PREFIX) - self.set_license(__doc__) - self.set_copyright('Copyright 2008 Free Software Foundation, Inc.') - self.set_website('http://gnuradio.org/trac/wiki/GNURadioCompanion') - self.set_comments("""\ -Thank you to all those from the mailing list who tested GNU Radio Companion and offered advice. --- -Special Thanks: -A. Brinton Cooper -> starting the project -CER Technology Fellowship Grant -> initial funding -William R. Kenan Jr. Fund -> usrp & computers -Patrick Strasser -> the GRC icon -Achilleas Anastasopoulos -> trellis support ---""") - self.run() - self.destroy() - -###################################################################################################### -class HotKeysDialog(gtk.Dialog): - """Display each action with the associated hotkey.""" - - def __init__(self): - """HotKeysDialog constructor.""" - gtk.Dialog.__init__(self, buttons=('gtk-close', gtk.RESPONSE_CLOSE)) - self.set_title('Hot Keys') - markup = '' - for action, hotkey in ( - ('New Flow Graph', 'Ctrl + n'), - ('Open Flow Graph', 'Ctrl + o'), - ('Save Flow Graph', 'Ctrl + s'), - ('Close Flow Graph', 'Ctrl + q'), - ('Cut Block', 'Ctrl + x'), - ('Copy Block', 'Ctrl + c'), - ('Paste Block', 'Ctrl + v'), - ('Undo Change', 'Ctrl + z'), - ('Redo Change', 'Ctrl + y'), - ('Delete Block', 'Delete'), - ('Modify Parameters', 'Enter'), - ('Rotate Block', 'Right'), - ('Rotate Block', 'Left'), - ('Enable Block', 'e'), - ('Disable Block', 'd'), - ('Modify Data Type', 'Up'), - ('Modify Data Type', 'Down'), - ('Add a Port', '+'), - ('Remove a Port', '-'), - ('Flow Graph Generate', 'F5'), - ('Flow Graph Execute', 'F6'), - ('Flow Graph Kill', 'F7'), - ('Screen Shot', 'PrintScreen'), - ): markup = '%s\n%s:%s'%(markup, action, hotkey.rjust(25-len(action), ' ')) - label = gtk.Label() - label.set_markup('%s\n'%markup) #append newline - self.vbox.pack_start(label, False) - self.show_all() - self.run() - self.destroy() diff --git a/grc/src/grc/gui/DrawingArea.py b/grc/src/grc/gui/DrawingArea.py deleted file mode 100644 index 9100476a..00000000 --- a/grc/src/grc/gui/DrawingArea.py +++ /dev/null @@ -1,120 +0,0 @@ -""" -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 -""" -##@package grc.gui.DrawingArea -#Drawing area for graphical elements. - -import pygtk -pygtk.require('2.0') -import gtk -from grc.Constants import * - -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, main_window): - """! - DrawingArea contructor. - Connect event handlers. - @param main_window the main_window containing all flow graphs - """ - self.ctrl_mask = False - self._main_window = main_window - #inject drawing area into main_window - self._main_window.drawing_area = self - gtk.DrawingArea.__init__(self) - self.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) - 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.set_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 the focus flag - self._focus_flag = False - self.get_focus_flag = lambda: self._focus_flag - self.connect("leave-notify-event", self._handle_focus_event, False) - self.connect("enter-notify-event", self._handle_focus_event, True) - #pixmap for drawing - self.pixmap = None - self.gc = None - - def draw(self): - """! - Draw the pixmap onto this drawing area. - """ - self.window.draw_drawable(self.gc, self.pixmap, 0, 0, 0, 0, -1, -1) - - ########################################################################## - ## Handlers - ########################################################################## - def _handle_focus_event(self, widget, event, focus_flag): - """Record the focus state of the flow graph window.""" - self._focus_flag = focus_flag - - 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 - self._main_window.get_flow_graph().handle_mouse_button_press( - left_click=(event.button == 1), - double_click=(event.type == gtk.gdk._2BUTTON_PRESS), - coordinate=(event.x, event.y), - ) - return True - - 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 - self._main_window.get_flow_graph().handle_mouse_button_release( - left_click=(event.button == 1), - coordinate=(event.x, event.y), - ) - return True - - 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._main_window.get_flow_graph().handle_mouse_motion( - coordinate=(event.x, event.y), - ) - return True - - def _handle_window_expose(self, widget, event): - """! - Called when the window initially appears or is resized: create a new pixmap, draw the flow graph. - """ - self.gc = self.window.new_gc() - width, height = self.get_size_request() - if not self.pixmap or (width, height) != self.pixmap.get_size(): - self.pixmap = gtk.gdk.Pixmap(self.window, width, height, -1) - self._main_window.get_flow_graph().draw() - return True diff --git a/grc/src/grc/gui/FileDialogs.py b/grc/src/grc/gui/FileDialogs.py deleted file mode 100644 index 62024710..00000000 --- a/grc/src/grc/gui/FileDialogs.py +++ /dev/null @@ -1,154 +0,0 @@ -""" -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 -""" -##@package grc.gui.FileDialogs -#The open/save dialog for flow graph fFileDialogiles and screen shots. - -import pygtk -pygtk.require('2.0') -import gtk -from Dialogs import MessageDialogHelper -from grc.Constants import DEFAULT_FILE_PATH,FLOW_GRAPH_FILE_EXTENSION,IMAGE_FILE_EXTENSION,NEW_FLOGRAPH_TITLE -from os import path - -OPEN_FLOW_GRAPH = 'open flow graph' -SAVE_FLOW_GRAPH = 'save flow graph' -SAVE_IMAGE = 'save image' - -##the filter for flow graph files -FLOW_GRAPH_FILE_FILTER = gtk.FileFilter() -FLOW_GRAPH_FILE_FILTER.set_name('GRC Files') -FLOW_GRAPH_FILE_FILTER.add_pattern('*'+FLOW_GRAPH_FILE_EXTENSION) -FLOW_GRAPH_FILE_FILTER.add_pattern('*.xml') #TEMP - -##the filter for image files -IMAGE_FILE_FILTER = gtk.FileFilter() -IMAGE_FILE_FILTER.set_name('Image Files') -IMAGE_FILE_FILTER.add_pattern('*'+IMAGE_FILE_EXTENSION) - -##the filter for all files -ALL_FILE_FILTER = gtk.FileFilter() -ALL_FILE_FILTER.set_name('All Files') -ALL_FILE_FILTER.add_pattern('*') - -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(ALL_FILE_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 + FLOW_GRAPH_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(FLOW_GRAPH_FILE_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(FLOW_GRAPH_FILE_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(IMAGE_FILE_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() - for extension, filter in ( - (FLOW_GRAPH_FILE_EXTENSION, FLOW_GRAPH_FILE_FILTER), - (IMAGE_FILE_EXTENSION, IMAGE_FILE_FILTER), - ): #append the missing file extension if the filter matches - if filename[len(filename)-len(extension):] != extension \ - and filter == self.get_filter(): 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!', - 'File "%s" Exists!\nWould you like to overwrite the existing file?'%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!', - 'File "%s" Does not Exist!'%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/src/grc/gui/MainWindow.py b/grc/src/grc/gui/MainWindow.py deleted file mode 100644 index 6aafe66c..00000000 --- a/grc/src/grc/gui/MainWindow.py +++ /dev/null @@ -1,320 +0,0 @@ -""" -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 -""" -##@package grc.gui.MainWindow -#The main window, containing all windows, tool bars, and menu bars. - -from grc.Constants import * -from grc.Actions import * -import pygtk -pygtk.require('2.0') -import gtk -import Bars -from BlockTreeWindow import BlockTreeWindow -from Dialogs import TextDisplay,MessageDialogHelper -from DrawingArea import DrawingArea -from grc import Preferences -from grc import Messages -from NotebookPage import Page -import os - -############################################################ -# Main window -############################################################ - -class MainWindow(gtk.Window): - """The topmost window with menus, the tool bar, and other major windows.""" - - def __init__(self, handle_states, platform): - """! - MainWindow contructor. - @param handle_states the callback function - """ - self._platform = platform - #setup window - self.handle_states = handle_states - gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) - vbox = gtk.VBox() - hbox = gtk.HBox() - self.add(vbox) - #create the menu bar and toolbar - vbox.pack_start(Bars.MenuBar(), False) - vbox.pack_start(Bars.Toolbar(), False) - #setup scrolled window - 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) - self.scrolled_window.add_with_viewport(self.drawing_area) - #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) - fg_and_report_box = gtk.VBox(False, 0) - fg_and_report_box.pack_start(self.notebook, False, False, 0) - fg_and_report_box.pack_start(self.scrolled_window) - hbox.pack_start(fg_and_report_box) - vbox.pack_start(hbox) - #create the side windows - side_box = gtk.VBox() - hbox.pack_start(side_box, False) - side_box.pack_start(BlockTreeWindow(platform, self.get_flow_graph)) #allow resize, selection window can have more space - #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_size_request(-1, REPORTS_WINDOW_HEIGHT) - self.reports_scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.reports_scrolled_window.add_with_viewport(self.text_display) - fg_and_report_box.pack_end(self.reports_scrolled_window, False) #dont allow resize, fg should get all the space - #show all but the main window container and the reports window - vbox.show_all() - self.notebook.hide() - self._show_reports_window(False) - # load preferences and show the main window - Preferences.load(platform) - self.resize(*Preferences.window_size()) - self.show()#show after resize in preferences - - ############################################################ - # 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 - """ - self.handle_states(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()) - self.handle_states() - - ############################################################ - # 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') - - def _show_reports_window(self, show): - """! - Show the reports window when show is True. - Hide the reports window when show is False. - @param show boolean flag - """ - if show: self.reports_scrolled_window.show() - else: self.reports_scrolled_window.hide() - - ############################################################ - # 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() - #inject drawing area and handle states into flow graph - flow_graph.drawing_area = self.drawing_area - flow_graph.handle_states = self.handle_states - page = Page( - 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) - 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.window_size(self.get_size()) - 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_pid() 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(): - self.handle_states(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_pid(): self.handle_states(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 - """ - if self.get_page(): - title = ''.join(( - MAIN_WINDOW_PREFIX, - ' - Editing: ', - (self.get_page().get_file_path() or NEW_FLOGRAPH_TITLE), - (self.get_page().get_saved() and ' ' or '*'), #blank must be non empty - ) - ) - else: title = MAIN_WINDOW_PREFIX + ' - Editor ' - gtk.Window.set_title(self, title) - #set tab titles - for page in self._get_pages(): - title = os.path.basename(page.get_file_path()) - #strip file extension #TEMP - if title.endswith('.xml'): - title = title[0:-len('.xml')] - #strip file extension - if title.endswith(FLOW_GRAPH_FILE_EXTENSION): - title = title[0:-len(FLOW_GRAPH_FILE_EXTENSION)] - page.set_text(''.join(( - (title or NEW_FLOGRAPH_TITLE), - (page.get_saved() and ' ' or '*'), #blank must be non empty - ) - ) - ) - #reports window - self._show_reports_window(Preferences.show_reports_window()) - #show/hide notebook tabs - if len(self._get_pages()) > 1: self.notebook.show() - else: self.notebook.hide() - - 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() - - ############################################################ - # 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/src/grc/gui/Makefile.am b/grc/src/grc/gui/Makefile.am deleted file mode 100644 index c9069bea..00000000 --- a/grc/src/grc/gui/Makefile.am +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/Makefile.common - -SUBDIRS = elements - -ourpythondir = $(pythondir)/grc/gui - -ourpython_PYTHON = \ - __init__.py \ - Bars.py \ - BlockTreeWindow.py \ - Dialogs.py \ - DrawingArea.py \ - FileDialogs.py \ - MainWindow.py \ - NotebookPage.py \ - ParamsDialog.py diff --git a/grc/src/grc/gui/NotebookPage.py b/grc/src/grc/gui/NotebookPage.py deleted file mode 100644 index add31b6d..00000000 --- a/grc/src/grc/gui/NotebookPage.py +++ /dev/null @@ -1,175 +0,0 @@ -""" -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 -""" -##@package grc.gui.NotebookPage -#A page in the notebook, represents an individual flow graph. - -from grc.Actions import * -import pygtk -pygtk.require('2.0') -import gtk -from grc import ParseXML -from grc.StateCache import StateCache -from grc.Constants import FLOW_GRAPH_DTD -import os - -############################################################ -## Notebook Page -############################################################ - -class Page(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_pid(None) - #import the file - self.main_window = main_window - self.set_file_path(file_path) - file_path = file_path or flow_graph.get_parent().get_default_flow_graph() - ############################################################ - from grc import converter - converter.convert(file_path, flow_graph.get_parent()) - ############################################################ - ParseXML.validate_dtd(file_path, FLOW_GRAPH_DTD) - initial_state = ParseXML.from_file(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) - self.get_flow_graph().update() - #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() - - 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 - self.main_window.handle_states(FLOW_GRAPH_CLOSE) - - def set_text(self, text): - """ - Set the text in this label. - @param text the new text - """ - self.label.set_text(text) - - def get_tab(self): - """ - Get the gtk widget for this page's tab. - @return gtk widget - """ - return self.tab - - def get_pid(self): - """! - Get the pid for the flow graph. - @return the pid number - """ - return self.pid - - def set_pid(self, pid): - """! - Set the pid number. - @param pid the new pid number - """ - self.pid = pid - - def get_flow_graph(self): - """! - Get the flow graph. - @return the flow graph - """ - return self._flow_graph - - 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/src/grc/gui/ParamsDialog.py b/grc/src/grc/gui/ParamsDialog.py deleted file mode 100644 index 77179212..00000000 --- a/grc/src/grc/gui/ParamsDialog.py +++ /dev/null @@ -1,134 +0,0 @@ -""" -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 -""" -##@package grc.gui.ParamsDialog -#A dialog for editing a block's parameters. - -import pygtk -pygtk.require('2.0') -import gtk - -from Dialogs import TextDisplay -from grc.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%s:\n'%title) - hbox = gtk.HBox() - hbox.pack_start(label, False, False, padding=11) - return hbox - -class ParamsDialog(gtk.Dialog): - """A dialog box to set block parameters.""" - - def __init__(self, block): - """! - SignalBlockParamsDialog contructor. - @param block the signal block - """ - gtk.Dialog.__init__(self, buttons=('gtk-close', gtk.RESPONSE_CLOSE)) - self.block = block - self.set_title('Properties: %s'%block.get_name()) - self.set_size_request(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT) - vbox = gtk.VBox() - #Add the title label - vbox.pack_start(get_title_label('Parameters'), False) - #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) - #Error Messages for the block - self._error_messages_box = err_box = gtk.VBox() - self._error_messages_text_display = TextDisplay('') - err_box.pack_start(gtk.Label(''), False, False, 7) #spacing - err_box.pack_start(get_title_label('Error Messages'), False) - err_box.pack_start(self._error_messages_text_display, False) - #Add all the parameters - for param in self.block.get_params(): - vbox.pack_start(param.get_input_object(self._handle_changed), False) - vbox.pack_start(err_box, False) - #Done adding parameters - if self.block.get_doc(): - vbox.pack_start(gtk.Label(''), False, False, 7) #spacing - vbox.pack_start(get_title_label('Documentation'), False) - #Create the text box to display notes about the block - vbox.pack_start(TextDisplay(self.block.get_doc()), False) - self.connect('key_press_event', self._handle_key_press) - self.show_all() - #initial update - for param in self.block.get_params(): param.update() - self._update_error_messages() - - def _update_error_messages(self): - """ - Update the error messages in the error messages box. - Hide the box if there are no errors. - """ - if self.block.is_valid(): self._error_messages_box.hide() - else: self._error_messages_box.show() - messages = '\n'.join(self.block.get_error_messages()) - self._error_messages_text_display.set_text(messages) - - 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 - """ - keyname = gtk.gdk.keyval_name(event.keyval) - if keyname == 'Return': self.response(gtk.RESPONSE_OK) - return False #forward the keypress - - def _handle_changed(self, param): - """! - A change occured, update any dependent parameters: - The enum inside the variable type may have changed and, - the variable param will need an external update. - @param param the graphical parameter that initiated the callback - """ - self._update_error_messages() - #update dependent params - if param.is_enum(): - for other_param in param.get_parent().get_params(): - if param.get_key() is not other_param.get_key() and ( - param.get_key() in other_param._type or \ - param.get_key() in other_param._hide): other_param.update() - return True - - def run(self): - """! - Call run(). - @return true if a change occured. - """ - original_data = list() - for param in self.block.get_params(): - original_data.append(param.get_value()) - gtk.Dialog.run(self) - self.destroy() - new_data = list() - for param in self.block.get_params(): - new_data.append(param.get_value()) - return original_data != new_data - diff --git a/grc/src/grc/gui/__init__.py b/grc/src/grc/gui/__init__.py deleted file mode 100644 index 0e92cb11..00000000 --- a/grc/src/grc/gui/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -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 -""" -##@package grc.gui -#GTK based classes go into this package. - -#only import the modules that need external access -from MainWindow import MainWindow -from FileDialogs import OpenFlowGraphFileDialog,SaveFlowGraphFileDialog,SaveImageFileDialog -from Dialogs import PreferencesDialog,MessageDialogHelper,AboutDialog,HotKeysDialog - diff --git a/grc/src/grc/gui/elements/Block.py b/grc/src/grc/gui/elements/Block.py deleted file mode 100644 index ee19ee2f..00000000 --- a/grc/src/grc/gui/elements/Block.py +++ /dev/null @@ -1,194 +0,0 @@ -""" -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 -""" -##@package grc.gui.elements.Block -#The graphical signal block. - -from grc import Preferences -from Element import Element -import Utils -import Colors -from grc.Constants import * -import pygtk -pygtk.require('2.0') -import gtk -import pango - -class Block(Element): - """The graphical signal block.""" - - def __init__(self, *args, **kwargs): - """! - Block contructor. - Add graphics related params to the block. - """ - #add the position param - self._params['_coordinate'] = self.get_parent().get_parent().Param( - self, - { - 'name': 'GUI Coordinate', - 'key': '_coordinate', - 'type': 'raw', - 'value': '(0, 0)', - 'hide': 'all', - } - ) - self._params['_rotation'] = self.get_parent().get_parent().Param( - self, - { - '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 update(self): - """Update the block, parameters, and ports when a change occurs.""" - self.bg_color = self.get_enabled() and Colors.BG_COLOR or Colors.DISABLED_BG_COLOR - self.clear() - self._create_labels() - self.W = self.label_width + 2*LABEL_PADDING_WIDTH - max_ports = max(len(self.get_sinks()), len(self.get_sources()), 1) - self.H = max(self.label_height+2*LABEL_PADDING_HEIGHT, 2*PORT_BORDER_SEPARATION + max_ports*PORT_HEIGHT + (max_ports-1)*PORT_SEPARATION) - 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)) - map(lambda p: p.update(), self.get_sinks() + self.get_sources()) - - def _create_labels(self): - """Create the labels for the signal block.""" - layouts = list() - #create the main layout - layout = gtk.DrawingArea().create_pango_layout('') - layouts.append(layout) - if self.is_valid(): layout.set_markup(''+Utils.xml_encode(self.get_name())+'') - else: layout.set_markup(''+Utils.xml_encode(self.get_name())+'') - desc = pango.FontDescription(BLOCK_FONT) - layout.set_font_description(desc) - self.label_width, self.label_height = layout.get_pixel_size() - #display the params (except for the special params id and position) - if Preferences.show_params(): - for param in filter(lambda p: p.get_hide() not in ('all', 'part'), self.get_params()): - if not Preferences.show_id() and param.get_key() == 'id': continue - layout = param.get_layout() - layouts.append(layout) - w,h = layout.get_pixel_size() - self.label_width = max(w, self.label_width) - self.label_height = self.label_height + h + LABEL_SEPARATION - width = self.label_width - height = self.label_height - #setup the pixmap - pixmap = gtk.gdk.Pixmap(self.get_parent().get_window(), width, height, -1) - gc = pixmap.new_gc() - gc.foreground = self.bg_color - pixmap.draw_rectangle(gc, True, 0, 0, width, height) - gc.foreground = Colors.TXT_COLOR - #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 images - self.horizontal_label = image = pixmap.get_image(0, 0, width, height) - if self.is_vertical(): - self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), height, width) - for i in range(width): - for j in range(height): vimage.put_pixel(j, width-i-1, image.get_pixel(i, j)) - - def draw(self, window): - """! - Draw the signal block with label and inputs/outputs. - @param window the gtk window to draw on - """ - x, y = self.get_coordinate() - #draw main block - Element.draw(self, window, BG_color=self.bg_color) - #draw label image - gc = self.get_gc() - if self.is_horizontal(): - window.draw_image(gc, self.horizontal_label, 0, 0, x+LABEL_PADDING_WIDTH, y+(self.H-self.label_height)/2, -1, -1) - elif self.is_vertical(): - window.draw_image(gc, self.vertical_label, 0, 0, x+(self.H-self.label_height)/2, y+LABEL_PADDING_WIDTH, -1, -1) - #draw ports - map(lambda p: p.draw(window), self.get_ports()) - - 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/src/grc/gui/elements/Colors.py b/grc/src/grc/gui/elements/Colors.py deleted file mode 100644 index 1eedde0a..00000000 --- a/grc/src/grc/gui/elements/Colors.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -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 -""" -##@package grc.gui.elements.Colors -#Global Colors for the gui - -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) - -BACKGROUND_COLOR = get_color('#FFF9FF') #main window background -FG_COLOR = get_color('black') #normal border color -BG_COLOR = get_color('#F1ECFF') #default background -DISABLED_BG_COLOR = get_color('#CCCCCC') #disabled background -DISABLED_FG_COLOR = get_color('#999999') #disabled foreground -H_COLOR = get_color('#00FFFF') #Highlight border color -TXT_COLOR = get_color('black') #text color -ERROR_COLOR = get_color('red') #error color diff --git a/grc/src/grc/gui/elements/Connection.py b/grc/src/grc/gui/elements/Connection.py deleted file mode 100644 index 2d99518a..00000000 --- a/grc/src/grc/gui/elements/Connection.py +++ /dev/null @@ -1,131 +0,0 @@ -""" -Copyright 2007, 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 -""" -##@package grc.gui.elements.Connection -#The graphical connection for input/output ports. - -import Utils -from Element import Element -import Colors -from grc.Constants import CONNECTOR_ARROW_BASE,CONNECTOR_ARROW_HEIGHT - -class Connection(Element): - """A graphical connection for ports.""" - - 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 update(self): - """Precalculate relative coordinates.""" - 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() - - def _update_after_move(self): - """Calculate coordinates.""" - self.clear() - #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, window): - """! - Draw the connection. - @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.update() - 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 - fg_color = self.get_enabled() and Colors.FG_COLOR or Colors.DISABLED_FG_COLOR - Element.draw(self, window, FG_color=fg_color) - gc = self.get_gc() - if self.is_valid(): gc.foreground = Colors.FG_COLOR - else: gc.foreground = Colors.ERROR_COLOR - #draw arrow on sink port - window.draw_polygon(gc, True, self._arrow) diff --git a/grc/src/grc/gui/elements/Element.py b/grc/src/grc/gui/elements/Element.py deleted file mode 100644 index 1d7157eb..00000000 --- a/grc/src/grc/gui/elements/Element.py +++ /dev/null @@ -1,233 +0,0 @@ -""" -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 -""" -##@package grc.gui.elements.Element -#Base class for graphical elements such as: -#signal blocks, input sockets, output sockets and connections. - -import Colors -import pygtk -pygtk.require('2.0') -import gtk -import pango -from grc.Constants import * - -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, *args, **kwargs): - """! - 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 get_gc(self): return self._gc - - def draw(self, window, BG_color=Colors.BG_COLOR, FG_color=Colors.FG_COLOR): - """! - Draw in the given window. - @param window the gtk window to draw on - @param BG_color the background color - @param FG_color the foreground color - """ - gc = self.get_parent().get_gc() - self._gc = gc - X,Y = self.get_coordinate() - for (rX,rY),(W,H) in self.areas_dict[self.get_rotation()]: - aX = X + rX - aY = Y + rY - gc.foreground = BG_color - window.draw_rectangle(gc, True, aX, aY, W, H) - gc.foreground = self.is_highlighted() and Colors.H_COLOR or FG_color - window.draw_rectangle(gc, False, aX, aY, W, H) - for (x1, y1),(x2, y2) in self.lines_dict[self.get_rotation()]: - gc.foreground = self.is_highlighted() and Colors.H_COLOR or FG_color - window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2) - - def rotate(self, direction): - """! - Rotate all of the areas by 90 degrees. - @param direction 90 or 270 degrees - """ - self.set_rotation((self.get_rotation() + direction)%360) - - def clear(self): - """Empty the lines and areas.""" - self.areas_dict = dict((rotation, list()) for rotation in POSSIBLE_ROTATIONS) - self.lines_dict = dict((rotation, list()) for rotation in POSSIBLE_ROTATIONS) - - 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, rotation=None): - """! - 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. - If rotation is not specified, the element's current rotation is used. - @param rel_coor (x,y) offset from this element's coordinate - @param area (width,height) tuple - @param rotation rotation in degrees - """ - self.areas_dict[rotation or self.get_rotation()].append((rel_coor, area)) - - def add_line(self, rel_coor1, rel_coor2, rotation=None): - """! - 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. - If rotation is not specified, the element's current rotation is used. - @param rel_coor1 relative (x1,y1) tuple - @param rel_coor2 relative (x2,y2) tuple - @param rotation rotation in degrees - """ - self.lines_dict[rotation or self.get_rotation()].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_dict[self.get_rotation()]: - 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_dict[self.get_rotation()]: - 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_dict[self.get_rotation()]: - 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_dict[self.get_rotation()]: - if x1 == x2: x1, x2 = x1-CONNECTION_SELECT_SENSITIVITY, x2+CONNECTION_SELECT_SENSITIVITY - if y1 == y2: y1, y2 = y1-CONNECTION_SELECT_SENSITIVITY, y2+CONNECTION_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 - - def update(self): - """Do nothing for the update. Dummy method.""" - pass - - diff --git a/grc/src/grc/gui/elements/FlowGraph.py b/grc/src/grc/gui/elements/FlowGraph.py deleted file mode 100644 index b4d83527..00000000 --- a/grc/src/grc/gui/elements/FlowGraph.py +++ /dev/null @@ -1,563 +0,0 @@ -""" -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 -""" -##@package grc.gui.elements.FlowGraph -#A flow graph structure for storing signal blocks and their connections. - -from grc import Preferences -from grc import Utils -from grc.Constants import * -from grc.Actions import * -import Colors -import Utils -from grc.gui.ParamsDialog import ParamsDialog -from Element import Element -from grc.elements import FlowGraph as _FlowGraph - -import pygtk -pygtk.require('2.0') -import gtk - -import random -import time -from grc 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, *args, **kwargs): - """! - 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.time = 0 - self.press_coor = (0, 0) - #selected ports - self._old_selected_port = None - self._new_selected_port = None - - 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 = -1 - while True: - id = (index < 0) and base_id or '%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 - -########################################################################### -# Access Drawing Area -########################################################################### - def get_drawing_area(self): return self.drawing_area - def get_gc(self): return self.get_drawing_area().gc - def get_pixmap(self): return self.get_drawing_area().pixmap - 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_window(self): return self.get_drawing_area().window - def get_scroll_pane(self): return self.drawing_area.get_parent() - def get_ctrl_mask(self): return self.drawing_area.ctrl_mask - - def add_new_block(self, key): - """! - Add a block of the given key to this flow graph. - @param key the block key - """ - 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() - x = int(random.uniform(.25, .75)*h_adj.page_size + h_adj.get_value()) - y = 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((x, y)) - block.set_rotation(0) - block.get_param('id').set_value(id) - self.handle_states(ELEMENT_CREATE) - - ########################################################################### - # 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['key'] - if block_key == 'options': continue - block_id = self._get_unique_id(block_key) - block = self.get_new_block(block_key) - selected.add(block) - #set params - params_n = Utils.listify(block_n, 'param') - for param_n in params_n: - param_key = param_n['key'] - param_value = param_n['value'] - #setup id parameter - if param_key == 'id': - old_id2block[param_value] = block - param_value = block_id - #set value to key - block.get_param(param_key).set_value(param_value) - #move block to offset coordinate - block.move((x_off, y_off)) - #create connections - for connection_n in connections_n: - source = old_id2block[connection_n['source_block_id']].get_source(connection_n['source_key']) - sink = old_id2block[connection_n['sink_block_id']].get_sink(connection_n['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 - """ - changed = False - for selected_block in self.get_selected_blocks(): - for child in selected_block.get_params() + selected_block.get_ports(): - #find a param that controls a type - type_param = None - for param in selected_block.get_params(): - if not type_param and param.is_enum(): type_param = param - if param.is_enum() and param.get_key() in child._type: 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_selected(self, direction): - """! - Change port controller for the selected signal blocks. - @param direction +1 or -1 - @return true for changed - """ - changed = False - for selected_block in self.get_selected_blocks(): - for ports in (selected_block.get_sources(), selected_block.get_sinks()): - if ports and hasattr(ports[0], 'get_nports') and ports[0].get_nports(): - #find the param that controls port0 - for param in selected_block.get_params(): - if param.get_key() in ports[0]._nports: - #try to increment the port controller by direction - try: - value = param.evaluate() - value = value + direction - assert(0 < value <= MAX_NUM_PORTS) - param.set_value(value) - changed = True - except: pass - return changed - - def param_modify_selected(self): - """! - Create and show a param modification dialog for the selected block. - @return true if parameters were changed - """ - if self.get_selected_block(): - signal_block_params_dialog = ParamsDialog(self.get_selected_block()) - return signal_block_params_dialog.run() - return False - - 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, direction): - """! - Rotate the selected blocks by 90 degrees. - @param direction DIR_LEFT or DIR_RIGHT - @return true if changed, otherwise false. - """ - if not self.get_selected_blocks(): return False - #determine the number of degrees to rotate - rotation = {DIR_LEFT: 90, DIR_RIGHT:270}[direction] - #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): - """! - 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. - """ - if self.get_gc(): - W,H = self.get_size() - #draw the background - self.get_gc().foreground = Colors.BACKGROUND_COLOR - self.get_pixmap().draw_rectangle(self.get_gc(), True, 0, 0, W, H) - #draw grid (depends on prefs) - if Preferences.show_grid(): - grid_size = Preferences.get_grid_size() - points = list() - for i in range(W/grid_size): - for j in range(H/grid_size): - points.append((i*grid_size, j*grid_size)) - self.get_gc().foreground = Colors.TXT_COLOR - self.get_pixmap().draw_points(self.get_gc(), points) - #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 - self.get_gc().foreground = Colors.H_COLOR - self.get_pixmap().draw_rectangle(self.get_gc(), True, x, y, w, h) - self.get_gc().foreground = Colors.TXT_COLOR - self.get_pixmap().draw_rectangle(self.get_gc(), False, x, y, w, h) - #draw blocks on top of connections - for element in self.get_connections() + self.get_blocks(): - element.draw(self.get_pixmap()) - #draw selected blocks on top of selected connections - for selected_element in self.get_selected_connections() + self.get_selected_blocks(): - selected_element.draw(self.get_pixmap()) - self.get_drawing_area().draw() - - def update(self): - """! - Update highlighting so only the selected is highlighted. - Call update on all elements. - Resize the window if size changed. - """ - #update highlighting - map(lambda e: e.set_highlighted(False), self.get_elements()) - for selected_element in self.get_selected_elements(): - selected_element.set_highlighted(True) - #update all elements - map(lambda e: e.update(), self.get_elements()) - #set the size of the flow graph area - old_x, old_y = self.get_size() - try: new_x, new_y = self.get_option('window_size') - except: new_x, new_y = old_x, old_y - if new_x != old_x or new_y != old_y: self.set_size(new_x, new_y) - - ########################################################################## - ## 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 backwardssince 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) - #single select mode, break - if not coor_m: - self.get_elements().remove(element) - self.get_elements().append(element) - 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_selection = 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_selection and new_selection[0] in self.get_selected_elements() - ): selected_elements = new_selection - 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) - self.handle_states(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) - ) - self.handle_states(ELEMENT_SELECT) - - ########################################################################## - ## Event Handlers - ########################################################################## - def handle_mouse_button_press(self, left_click, double_click, coordinate): - """! - A mouse button is pressed, only respond to left clicks. - 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. - """ - if not left_click: return - self.press_coor = coordinate - self.set_coordinate(coordinate) - self.time = 0 - self.mouse_pressed = True - 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 - self.handle_states(BLOCK_PARAM_MODIFY) - - def handle_mouse_button_release(self, left_click, coordinate): - """! - A mouse button is released, record the state. - """ - if not left_click: return - self.set_coordinate(coordinate) - self.time = 0 - self.mouse_pressed = False - if self.element_moved: - if Preferences.snap_to_grid(): - grid_size = Preferences.get_grid_size() - X,Y = self.get_selected_element().get_coordinate() - deltaX = X%grid_size - if deltaX < grid_size/2: deltaX = -1 * deltaX - else: deltaX = grid_size - deltaX - deltaY = Y%grid_size - if deltaY < grid_size/2: deltaY = -1 * deltaY - else: deltaY = grid_size - deltaY - self.move_selected((deltaX, deltaY)) - self.handle_states(BLOCK_MOVE) - self.element_moved = False - self.update_selected_elements() - self.draw() - - 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, timediff large enough - if not self.mouse_pressed: return - if time.time() - self.time < MOTION_DETECT_REDRAWING_SENSITIVITY: 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') - #move the selected element 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.draw() - self.set_coordinate((x, y)) - #update time - self.time = time.time() diff --git a/grc/src/grc/gui/elements/Makefile.am b/grc/src/grc/gui/elements/Makefile.am deleted file mode 100644 index f075d420..00000000 --- a/grc/src/grc/gui/elements/Makefile.am +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/Makefile.common - -ourpythondir = $(pythondir)/grc/gui/elements - -ourpython_PYTHON = \ - __init__.py \ - Block.py \ - Colors.py \ - Connection.py \ - Element.py \ - FlowGraph.py \ - Param.py \ - Platform.py \ - Port.py \ - Utils.py diff --git a/grc/src/grc/gui/elements/Param.py b/grc/src/grc/gui/elements/Param.py deleted file mode 100644 index e2340772..00000000 --- a/grc/src/grc/gui/elements/Param.py +++ /dev/null @@ -1,223 +0,0 @@ -""" -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 -""" -##@package grc.gui.elements.Param -#GTK objects for handling input and the signal block parameter class. - -import Utils -from Element import Element -import pygtk -pygtk.require('2.0') -import gtk -import pango -import gobject -from grc.Constants import * -from os import path - -###################################################################################################### -# gtk objects for handling input -###################################################################################################### - -class InputParam(gtk.HBox): - """The base class for an input parameter inside the input parameters dialog.""" - - def __init__(self, param, _handle_changed): - gtk.HBox.__init__(self) - self.param = param - self._handle_changed = _handle_changed - 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 - -class EntryParam(InputParam): - """Provide an entry box for strings and numbers.""" - - def __init__(self, *args, **kwargs): - InputParam.__init__(self, *args, **kwargs) - self.entry = input = gtk.Entry() - input.set_text(self.param.get_value()) - input.connect('changed', self._handle_changed) - self.pack_start(input, True) - self.get_text = input.get_text - #tool tip - self.tp = gtk.Tooltips() - self.tp.set_tip(self.entry, '') - self.tp.enable() - -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. - """ - file_path = self.param.is_valid() and self.param.evaluate() or '' - #bad file paths will be redirected to default - if not path.exists(path.dirname(file_path)): file_path = DEFAULT_FILE_PATH - 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(path.basename(file_path)) #show the current filename - file_dialog.set_current_folder(path.dirname(file_path)) #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.entry.set_text(file_path) - self._handle_changed() - file_dialog.destroy() #destroy the dialog - -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) - input = gtk.ComboBox(gtk.ListStore(gobject.TYPE_STRING)) - cell = gtk.CellRendererText() - input.pack_start(cell, True) - input.add_attribute(cell, 'text', 0) - for option in self.param.get_options(): input.append_text(option.get_name()) - input.set_active(int(self.param.get_option_keys().index(self.param.get_value()))) - input.connect("changed", self._handle_changed) - self.pack_start(input, False) - self.get_text = lambda: str(input.get_active()) #the get text parses the selected index to a string - -###################################################################################################### -# A Flow Graph Parameter -###################################################################################################### - -class Param(Element): - """The graphical parameter.""" - - def update(self): - """! - Called when an external change occurs. - Update the graphical input by calling the change handler. - """ - if hasattr(self, 'input'): self._handle_changed() - - def get_input_object(self, callback=None): - """! - Get the graphical gtk class to represent this parameter. - Create the input object with this data type and the handle changed method. - @param callback a function of one argument(this param) to be called from the change handler - @return gtk input object - """ - self.callback = callback - if self.is_enum(): input = EnumParam - elif self.get_type() in ('file_open', 'file_save'): input = FileParam - else: input = EntryParam - self.input = input(self, self._handle_changed) - return self.input - - def _handle_changed(self, widget=None): - """! - When the input changes, write the inputs to the data type. - Finish by calling the exteral callback. - """ - value = self.input.get_text() - if self.is_enum(): value = self.get_option_keys()[int(value)] - self.set_value(value) - #set the markup on the label, red for errors in corresponding data type. - name = '%s'%(PARAM_LABEL_FONT, Utils.xml_encode(self.get_name())) - #special markups if param is involved in a callback - if hasattr(self.get_parent(), 'get_callbacks') and \ - filter(lambda c: self.get_key() in c, self.get_parent()._callbacks): - name = '%s'%name - if not self.is_valid(): - self.input.set_markup('%s'%name) - tip = '- ' + '\n- '.join(self.get_error_messages()) - else: - self.input.set_markup(name) - tip = self.evaluate() - #hide/show - if self.get_hide() == 'all': self.input.hide_all() - else: self.input.show_all() - #set the tooltip - if self.input.tp: self.input.tp.set_tip(self.input.entry, str(tip)) - #execute the external callback - if self.callback: self.callback(self) - - def get_markup(self): - """! - Create a markup to display the Param as a label on the SignalBlock. - If the data type is an Enum type, use the cname of the Enum's current choice. - Otherwise, use parsed the data type and use its string representation. - If the data type is not valid, use a red foreground color. - @return pango markup string - """ - ########################################################################### - # display logic for numbers - ########################################################################### - def float_to_str(var): - if var-int(var) == 0: return '%d'%int(var) - if var*10-int(var*10) == 0: return '%.1f'%var - if var*100-int(var*100) == 0: return '%.2f'%var - if var*1000-int(var*1000) == 0: return '%.3f'%var - else: return '%.3g'%var - def to_str(var): - if isinstance(var, str): return var - elif isinstance(var, complex): - if var.imag == var.real == 0: return '0' #value is zero - elif var.imag == 0: return '%s'%float_to_str(var.real) #value is real - elif var.real == 0: return '%sj'%float_to_str(var.imag) #value is imaginary - elif var.imag < 0: return '%s-%sj'%(float_to_str(var.real), float_to_str(var.imag*-1)) - else: return '%s+%sj'%(float_to_str(var.real), float_to_str(var.imag)) - elif isinstance(var, float): return float_to_str(var) - elif isinstance(var, int): return '%d'%var - else: return str(var) - ########################################################################### - if self.is_valid(): - data = self.evaluate() - t = self.get_type() - if self.is_enum(): - dt_str = self.get_option(self.get_value()).get_name() - elif isinstance(data, (list, tuple, set)): #vector types - dt_str = ', '.join(map(to_str, data)) - else: dt_str = to_str(data) #other types - #truncate - max_len = max(42 - len(self.get_name()), 3) - if len(dt_str) > max_len: - dt_str = dt_str[:max_len-3] + '...' - return '%s: %s'%(Utils.xml_encode(self.get_name()), Utils.xml_encode(dt_str)) - else: return '%s: error'%Utils.xml_encode(self.get_name()) - - def get_layout(self): - """! - Create a layout based on the current markup. - @return the pango layout - """ - layout = gtk.DrawingArea().create_pango_layout('') - layout.set_markup(self.get_markup()) - desc = pango.FontDescription(PARAM_FONT) - layout.set_font_description(desc) - return layout - diff --git a/grc/src/grc/gui/elements/Platform.py b/grc/src/grc/gui/elements/Platform.py deleted file mode 100644 index 779a1430..00000000 --- a/grc/src/grc/gui/elements/Platform.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -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 -""" -##@package grc.gui.elements.Platform -#Graphical platform to turn an existing platform into a gui platform. - -from FlowGraph import FlowGraph -from Connection import Connection -from Block import Block -from Port import Port -from Param import Param - -def conjoin_classes(name, c1, c2): - exec(""" -class %s(c1, c2): - def __init__(self, *args, **kwargs): - c1.__init__(self, *args, **kwargs) - c2.__init__(self, *args, **kwargs) -"""%name, locals()) - return locals()[name] - -def Platform(platform): - #combine with gui class - for attr, value in ( - ('FlowGraph', FlowGraph), - ('Connection', Connection), - ('Block', Block), - ('Source', Port), - ('Sink', Port), - ('Param', Param), - ): - old_value = getattr(platform, attr) - c = conjoin_classes(attr, old_value, value) - setattr(platform, attr, c) - return platform - diff --git a/grc/src/grc/gui/elements/Port.py b/grc/src/grc/gui/elements/Port.py deleted file mode 100644 index 3449f1b9..00000000 --- a/grc/src/grc/gui/elements/Port.py +++ /dev/null @@ -1,184 +0,0 @@ -""" -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 -""" -##@package grc.gui.elements.Port -#The graphical input/output sockets of the signal block. - -from Element import Element -from grc.Constants import * -import Colors -import pygtk -pygtk.require('2.0') -import gtk -import pango - -class Port(Element): - """The graphical port.""" - - def __init__(self, *args, **kwargs): - """! - Port contructor. - Create list of connector coordinates. - """ - Element.__init__(self) - self.connector_coordinates = dict() - - def update(self): - """Create new areas and labels for the port.""" - self.clear() - self.BG_color = Colors.get_color(self.get_color()) - self._create_labels() - #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 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*PORT_HEIGHT - (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*PORT_WIDTH - y = (PORT_SEPARATION+PORT_HEIGHT)*index+offset - self.add_area((x, y), (PORT_WIDTH, PORT_HEIGHT)) - self._connector_coordinate = (x-1, y+PORT_HEIGHT/2) - elif (self.is_source() and rotation == 0) or (self.is_sink() and rotation == 180): - x = self.get_parent().W - y = (PORT_SEPARATION+PORT_HEIGHT)*index+offset - self.add_area((x, y), (PORT_WIDTH, PORT_HEIGHT)) - self._connector_coordinate = (x+1+PORT_WIDTH, y+PORT_HEIGHT/2) - elif (self.is_source() and rotation == 90) or (self.is_sink() and rotation == 270): - y = -1*PORT_WIDTH - x = (PORT_SEPARATION+PORT_HEIGHT)*index+offset - self.add_area((x, y), (PORT_HEIGHT, PORT_WIDTH)) - self._connector_coordinate = (x+PORT_HEIGHT/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+PORT_HEIGHT)*index+offset - self.add_area((x, y), (PORT_HEIGHT, PORT_WIDTH)) - self._connector_coordinate = (x+PORT_HEIGHT/2, y+1+PORT_WIDTH) - #the connector length - self._connector_length = CONNECTOR_EXTENSION_INITIAL_LENGTH + CONNECTOR_EXTENSION_LENGTH*index - - def _create_labels(self): - """Create the labels for the socket.""" - #create the layout - layout = gtk.DrawingArea().create_pango_layout(self.get_name()) - desc = pango.FontDescription(PORT_FONT) - layout.set_font_description(desc) - w,h = self.w,self.h = layout.get_pixel_size() - #create the pixmap - pixmap = gtk.gdk.Pixmap(self.get_parent().get_parent().get_window(), w, h, -1) - gc = pixmap.new_gc() - gc.foreground = self.BG_color - pixmap.draw_rectangle(gc, True, 0, 0, w, h) - gc.foreground = Colors.TXT_COLOR - pixmap.draw_layout(gc, 0, 0, layout) - #create the images - self.horizontal_label = image = pixmap.get_image(0, 0, w, h) - if self.is_vertical(): - self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), h, w) - for i in range(w): - for j in range(h): vimage.put_pixel(j, w-i-1, image.get_pixel(i, j)) - - def draw(self, window): - """! - Draw the socket with a label. - @param window the gtk window to draw on - """ - Element.draw(self, window, BG_color=self.BG_color) - gc = self.get_gc() - gc.foreground = Colors.TXT_COLOR - X,Y = self.get_coordinate() - (x,y),(w,h) = self.areas_dict[self.get_rotation()][0] #use the first area's sizes to place the labels - if self.is_horizontal(): - window.draw_image(gc, self.horizontal_label, 0, 0, x+X+(PORT_WIDTH-self.w)/2, y+Y+(PORT_HEIGHT-self.h)/2, -1, -1) - elif self.is_vertical(): - window.draw_image(gc, self.vertical_label, 0, 0, x+X+(PORT_HEIGHT-self.h)/2, y+Y+(PORT_WIDTH-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/src/grc/gui/elements/Utils.py b/grc/src/grc/gui/elements/Utils.py deleted file mode 100644 index 602a7c54..00000000 --- a/grc/src/grc/gui/elements/Utils.py +++ /dev/null @@ -1,74 +0,0 @@ -""" -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 -""" -##@package grc.gui.elements.Utils -#Shared functions for flow graph elements. - -from grc.Constants import POSSIBLE_ROTATIONS - -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 - assert rotation in POSSIBLE_ROTATIONS - #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 xml_encode(string): - """ - Encode a string into an xml safe string by replacing special characters. - Needed for gtk pango markup in labels. - @param string the input string - @return output string with safe characters - """ - string = str(string) - for char, safe in ( - ('&', '&'), - ('<', '<'), - ('>', '>'), - ('"', '"'), - ("'", '''), - ): string = string.replace(char, safe) - return string - diff --git a/grc/src/grc/gui/elements/__init__.py b/grc/src/grc/gui/elements/__init__.py deleted file mode 100644 index e79167aa..00000000 --- a/grc/src/grc/gui/elements/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -""" -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 -""" -##@package grc.gui.elements -#All graphical elements used in a flow graph. - - diff --git a/grc/src/grc_gnuradio/Block.py b/grc/src/grc_gnuradio/Block.py deleted file mode 100644 index 84909e76..00000000 --- a/grc/src/grc_gnuradio/Block.py +++ /dev/null @@ -1,130 +0,0 @@ -""" -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 -""" -##@package grc_gnuradio.Block -#Flow graph block. - -from grc.elements.Block import Block as _Block -from grc import Utils -from utils import extract_docs - -class Block(_Block): - - ##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 - doc = Utils.exists_or_else(n, 'doc', '') - imports = map(lambda i: i.strip(), Utils.listify(n, 'import')) - make = n['make'] - checks = Utils.listify(n, 'check') - callbacks = Utils.listify(n, 'callback') - #build the block - _Block.__init__( - self, - flow_graph=flow_graph, - n=n, - ) - self._doc = doc - self._imports = imports - self._make = make - self._callbacks = callbacks - self._checks = checks - - def validate(self): - """! - Validate this block. - Call the base class validate. - Evaluate the checks: each check must evaluate to True. - Adjust the nports. - """ - _Block.validate(self) - #evaluate the checks - for check in self._checks: - check_res = self.resolve_dependencies(check) - try: - check_eval = self.get_parent().evaluate(check_res) - try: assert check_eval - except AssertionError: self._add_error_message('Check "%s" failed.'%check) - except: self._add_error_message('Check "%s" did not evaluate.'%check) - for ports, Port in ( - (self._sources, self.get_parent().get_parent().Source), - (self._sinks, self.get_parent().get_parent().Sink), - ): - #how many ports? - num_ports = len(ports) - #do nothing for 0 ports - if not num_ports: continue - #get the nports setting - port0 = ports[str(0)] - nports = port0.get_nports() - #do nothing for no nports - if not nports: continue - #do nothing if nports is already num ports - if nports == num_ports: continue - #remove excess ports and connections - if nports < num_ports: - #remove the connections - for key in map(str, range(nports, num_ports)): - port = ports[key] - for connection in port.get_connections(): - self.get_parent().remove_element(connection) - #remove the ports - for key in map(str, range(nports, num_ports)): ports.pop(key) - continue - #add more ports - if nports > num_ports: - for key in map(str, range(num_ports, nports)): - n = port0._n - n['key'] = key - port = Port(self, n) - ports[key] = port - continue - - 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_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_callbacks(self): - """! - Get a list of function callbacks for this block. - @return a list of strings - """ - return map(lambda c: self.get_id() + '.' + self.resolve_dependencies(c), self._callbacks) diff --git a/grc/src/grc_gnuradio/Connection.py b/grc/src/grc_gnuradio/Connection.py deleted file mode 100644 index fd2f7aa0..00000000 --- a/grc/src/grc_gnuradio/Connection.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -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 -""" -##@package grc_gnuradio.Connection -#Flow graph connection. -#A connection exists between 2 ports. -#One port must be input, one output. -#The port decided whether it can have the connection. - -from grc.elements.Connection import Connection as _Connection - -class Connection(_Connection): - - def validate(self): - """ - Validate the connections. - The ports must match in type and vector length. - """ - _Connection.validate(self) #checks type - #check vector length - source_vlen = self.get_source().get_vlen() - sink_vlen = self.get_sink().get_vlen() - try: assert(source_vlen == sink_vlen) - except AssertionError: self._add_error_message('Source vector length "%s" does not match sink vector length "%s".'%(source_vlen, sink_vlen)) - - diff --git a/grc/src/grc_gnuradio/Constants.py.in b/grc/src/grc_gnuradio/Constants.py.in deleted file mode 100644 index 66b773e7..00000000 --- a/grc/src/grc_gnuradio/Constants.py.in +++ /dev/null @@ -1,44 +0,0 @@ -""" -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 -""" -##@package grc_gnuradio.Constants -#Global constants for grc gnuradio package -#@author Josh Blum - -import os -import sys -import stat - -PYEXEC = '@PYTHONW@' - -#setup paths -DOCS_DIR = os.path.join('@docdir@', 'xml') -DATA_DIR = '@datadir@' -BLOCKS_DIR = '@blocksdir@' -HIER_BLOCKS_LIB_DIR = os.path.join(os.path.expanduser('~'), '.grc_gnuradio') - -#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 -FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl') -BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd') -BLOCK_TREE = os.path.join(DATA_DIR, 'block_tree.xml') -DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc.xml') - diff --git a/grc/src/grc_gnuradio/FlowGraph.py b/grc/src/grc_gnuradio/FlowGraph.py deleted file mode 100644 index e9e876bb..00000000 --- a/grc/src/grc_gnuradio/FlowGraph.py +++ /dev/null @@ -1,155 +0,0 @@ -""" -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 -""" -##@package grc_gnuradio.FlowGraph -#Primative flow graph. - -from utils import expr_utils -from grc.elements.FlowGraph import FlowGraph as _FlowGraph -from Block import Block -from Connection import Connection - -def get_variable_code(variable): - """! - Get the code representation for a variable. - Normally this is the value parameter. - For the variable chooser, use the index and choices. - Avoid using the to_code method of the variables, - as this forces evaluation before the variables are evaluated. - @param variable the variable block - @return the code string - """ - if variable.get_key() == 'variable_chooser': - choices = variable.get_param('choices').get_value() - value_index = variable.get_param('value_index').get_value() - return "(%s)[%s]"%(choices, value_index) - return variable.get_param('value').get_value() - -class FlowGraph(_FlowGraph): - - def _get_io_signature(self, pad_key): - """! - Get an io signature for this flow graph. - The pad key determines the directionality of the io signature. - @param pad_key a string of pad_source or pad_sink - @return a dict with: type, nports, vlen, size - """ - pads = filter(lambda b: b.get_key() == pad_key, self.get_enabled_blocks()) - if not pads: return { - 'nports': '0', - 'type': '', - 'vlen': '0', - 'size': '0', - } - pad = pads[0] #take only the first, user should not have more than 1 - #load io signature - return { - 'nports': str(pad.get_param('nports').evaluate()), - 'type': str(pad.get_param('type').evaluate()), - 'vlen': str(pad.get_param('vlen').evaluate()), - 'size': pad.get_param('type').get_opt('size'), - } - - def get_input_signature(self): - """! - Get the io signature for the input side of this flow graph. - The io signature with be "0", "0" if no pad source is present. - @return a string tuple of type, num_ports, port_size - """ - return self._get_io_signature('pad_source') - - def get_output_signature(self): - """! - Get the io signature for the output side of this flow graph. - The io signature with be "0", "0" if no pad sink is present. - @return a string tuple of type, num_ports, port_size - """ - return self._get_io_signature('pad_sink') - - 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: b.get_key() in ( - 'variable', 'variable_slider', 'variable_chooser', 'variable_text_box' - ), self.get_enabled_blocks()) - #map var id to variable block - id2var = dict([(var.get_id(), var) for var in variables]) - #map var id to variable code - #variable code is a concatenation of all param code (without the id param) - id2expr = dict([(var.get_id(), get_variable_code(var)) for var in variables]) - #sort according to dependency - sorted_ids = expr_utils.sort_variables(id2expr) - #create list of sorted variable blocks - variables = [id2var[id] for id in sorted_ids] - return variables - - 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: b.get_key() == 'parameter', self.get_enabled_blocks()) - return parameters - - def evaluate(self, expr): - """! - Evaluate the expression. - @param expr the string expression - @throw Exception bad expression - @return the evaluated data - """ - if self.is_flagged(): - self.deflag() - #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(get_variable_code(variable), n, n) - n[variable.get_id()] = e - except: pass - #make namespace public - self.n = n - #evaluate - e = eval(expr, self.n, self.n) - return e - diff --git a/grc/src/grc_gnuradio/Generator.py b/grc/src/grc_gnuradio/Generator.py deleted file mode 100644 index 2c84edb3..00000000 --- a/grc/src/grc_gnuradio/Generator.py +++ /dev/null @@ -1,134 +0,0 @@ -""" -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 -""" -##@package grc_gnuradio.Generator -#Create python based flow graphs. - -import os -import subprocess -from Cheetah.Template import Template -from utils import expr_utils -from Constants import * -from utils import convert_hier - -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_PATH - else: - self._mode = TOP_BLOCK_FILE_MODE - dirname = os.path.dirname(file_path) - 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): - #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 - """ - #execute - cmds = [PYEXEC, self.get_file_path()] - if self._generate_options == 'no_gui': - 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 - """ - imports = self._flow_graph.get_imports() - variables = self._flow_graph.get_variables() - parameters = self._flow_graph.get_parameters() - #list of variables with controls - controls = filter(lambda v: v.get_key().startswith('variable_'), variables) - #list of blocks not including variables and imports and parameters and disabled - blocks = sorted(self._flow_graph.get_enabled_blocks(), lambda x, y: cmp(x.get_id(), y.get_id())) - blocks = filter(lambda b: b not in (imports + parameters + variables), blocks) - #list of connections where each endpoint is enabled - connections = self._flow_graph.get_enabled_connections() - #list of variable names - var_ids = [var.get_id() for var in parameters + variables] - #list of callbacks (prepend self.) - callbacks = [ - expr_utils.expr_prepend(cb, var_ids, 'self.') - for cb in sum([block.get_callbacks() for block in self._flow_graph.get_blocks()], []) - ] - #map var id to the expression (prepend self.) - var_id2expr = dict( - [(var.get_id(), expr_utils.expr_prepend(var.get_make().split('\n')[0], var_ids, 'self.')) - for var in parameters + variables] - ) - #create graph structure for variables - variable_graph = expr_utils.get_graph(var_id2expr) - #map var id to direct dependents - #for each var id, make a list of all 2nd order edges - #use all edges of that id that are not also 2nd order edges - #meaning: list variables the ONLY depend directly on this variable - #and not variables that also depend indirectly on this variable - var_id2deps = dict( - [(var_id, filter(lambda e: e not in sum([list(variable_graph.get_edges(edge)) - for edge in variable_graph.get_edges(var_id)], []), variable_graph.get_edges(var_id) - ) - ) - for var_id in var_ids] - ) - #map var id to callbacks - var_id2cbs = dict( - [(var_id, filter(lambda c: var_id in expr_utils.expr_split(c), callbacks)) - for var_id in var_ids] - ) - #load the namespace - namespace = { - 'imports': imports, - 'flow_graph': self._flow_graph, - 'variables': variables, - 'controls': controls, - 'parameters': parameters, - 'blocks': blocks, - 'connections': connections, - 'generate_options': self._generate_options, - 'var_id2expr': var_id2expr, - 'var_id2deps': var_id2deps, - 'var_id2cbs': var_id2cbs, - } - #build the template - t = Template(open(FLOW_GRAPH_TEMPLATE, 'r').read(), namespace) - return str(t) - diff --git a/grc/src/grc_gnuradio/Makefile.am b/grc/src/grc_gnuradio/Makefile.am index bcee5189..767e8f67 100644 --- a/grc/src/grc_gnuradio/Makefile.am +++ b/grc/src/grc_gnuradio/Makefile.am @@ -21,33 +21,11 @@ include $(top_srcdir)/grc/Makefile.inc -SUBDIRS = blks2 usrp utils wxgui +SUBDIRS = \ + blks2 \ + usrp \ + wxgui -ourpythondir = $(pythondir)/grc_gnuradio +ourpythondir = $(grc_gnuradio_prefix) -ourpython_PYTHON = \ - __init__.py \ - Constants.py \ - Block.py \ - Connection.py \ - FlowGraph.py \ - Generator.py \ - Platform.py \ - Param.py \ - Port.py - -docdir = $(prefix)/share/doc/@PACKAGE@-@VERSION@ - -BUILT_SOURCES = Constants.py - -Constants.py: Makefile $(srcdir)/Constants.py.in - sed \ - -e 's|@PYTHONW[@]|$(PYTHONW)|g' \ - -e 's|@datadir[@]|$(grc_gnuradio_data_dir)|g' \ - -e 's|@blocksdir[@]|$(grc_gnuradio_blocks_dir)|g' \ - -e 's|@docdir[@]|$(docdir)|g' \ - $(srcdir)/Constants.py.in > $@ - -EXTRA_DIST = Constants.py.in - -MOSTLYCLEANFILES = $(BUILT_SOURCES) +ourpython_PYTHON = __init__.py diff --git a/grc/src/grc_gnuradio/Param.py b/grc/src/grc_gnuradio/Param.py deleted file mode 100644 index 1f5b967a..00000000 --- a/grc/src/grc_gnuradio/Param.py +++ /dev/null @@ -1,255 +0,0 @@ -""" -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 -""" -##@package grc_gnuradio.Param -#Flow graph block parameters. - -from utils import expr_utils -from grc.elements.Param import Param as _Param -import os - -class Param(_Param): - - _init = False - _hostage_cells = list() - - ##possible param types - TYPES = _Param.TYPES + [ - 'complex', 'real', 'int', - 'complex_vector', 'real_vector', 'int_vector', - 'hex', 'string', - 'file_open', 'file_save', - 'id', - 'grid_pos', 'import', - ] - - def get_hide(self): - """! - Get the hide value from the base class. - If hide was empty, and this is a type controller, set hide to part. - If hide was empty, and this is an id of a non variable, set hide to part. - @return hide the hide property string - """ - hide = _Param.get_hide(self) - #hide IO controlling params - if not hide and self.get_key() in ( - 'type', 'vlen', 'num_inputs', 'num_outputs' - ): hide = 'part' - #hide ID in non variable blocks - elif not hide and self.get_key() == 'id' and self.get_parent().get_key() not in ( - 'variable', 'variable_slider', 'variable_chooser', 'variable_text_box', 'parameter', 'options' - ): hide = 'part' - return hide - - def evaluate(self): - """! - Evaluate the value. - @return evaluated type - """ - 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) - assert(isinstance(e, str)) - return e - except: - self._stringify_flag = True - return v - t = self.get_type() - v = self.get_value() - ######################### - # Enum Type - ######################### - if self.is_enum(): return self.get_value() - ######################### - # Numeric Types - ######################### - elif t in ('raw', 'complex', 'real', 'int', 'complex_vector', 'real_vector', 'int_vector', 'hex'): - #raise exception if python cannot evaluate this value - try: e = self.get_parent().get_parent().evaluate(v) - except: - self._add_error_message('Value "%s" cannot be evaluated.'%v) - raise Exception - #raise an exception if the data is invalid - if t == 'raw': return e - elif t == 'complex': - try: assert(isinstance(e, (complex, float, int, long))) - except AssertionError: - self._add_error_message('Expression "%s" is invalid for type complex.'%str(e)) - raise Exception - return e - elif t == 'real': - try: assert(isinstance(e, (float, int, long))) - except AssertionError: - self._add_error_message('Expression "%s" is invalid for type real.'%str(e)) - raise Exception - return e - elif t == 'int': - try: assert(isinstance(e, (int, long))) - except AssertionError: - self._add_error_message('Expression "%s" is invalid for type integer.'%str(e)) - raise Exception - return e - elif t == 'complex_vector': - if not isinstance(e, (tuple, list, set)): - self._lisitify_flag = True - e = [e] - try: - for ei in e: - assert(isinstance(ei, (complex, float, int, long))) - except AssertionError: - self._add_error_message('Expression "%s" is invalid for type complex vector.'%str(e)) - raise Exception - return e - elif t == 'real_vector': - if not isinstance(e, (tuple, list, set)): - self._lisitify_flag = True - e = [e] - try: - for ei in e: - assert(isinstance(ei, (float, int, long))) - except AssertionError: - self._add_error_message('Expression "%s" is invalid for type real vector.'%str(e)) - raise Exception - return e - elif t == 'int_vector': - if not isinstance(e, (tuple, list, set)): - self._lisitify_flag = True - e = [e] - try: - for ei in e: - assert(isinstance(ei, (int, long))) - except AssertionError: - self._add_error_message('Expression "%s" is invalid for type integer vector.'%str(e)) - raise Exception - return e - elif t == 'hex': - return hex(e) - else: raise TypeError, 'Type "%s" not handled'%t - ######################### - # 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? - try: - assert(len(v) > 0) - assert(v[0].isalpha()) - for c in v: assert(c.isalnum() or c in ('_',)) - except AssertionError: - self._add_error_message('ID "%s" must be alpha-numeric or underscored, and begin with a letter.'%v) - raise Exception - params = self.get_all_params('id') - keys = [param.get_value() for param in params] - try: assert(len(keys) == len(set(keys))) - except: - self._add_error_message('ID "%s" is not unique.'%v) - raise Exception - return v - ######################### - # Grid Position Type - ######################### - elif t == 'grid_pos': - if not v: return '' #allow for empty grid pos - e = self.get_parent().get_parent().evaluate(v) - try: - assert(isinstance(e, (list, tuple)) and len(e) == 4) - for ei in e: assert(isinstance(ei, int)) - except AssertionError: - self._add_error_message('A grid position must be a list of 4 integers.') - raise Exception - row, col, row_span, col_span = e - #check row, col - try: assert(row >= 0 and col >= 0) - except AssertionError: - self._add_error_message('Row and column must be non-negative.') - raise Exception - #check row span, col span - try: assert(row_span > 0 and col_span > 0) - except AssertionError: - self._add_error_message('Row and column span must be greater than zero.') - raise Exception - #calculate hostage cells - for r in range(row_span): - for c in range(col_span): - self._hostage_cells.append((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 cell in param._hostage_cells: - if cell in self._hostage_cells: - self._add_error_message('Another graphical element is using cell "%s".'%str(cell)) - raise Exception - return e - ######################### - # Import Type - ######################### - elif t == 'import': - n = dict() #new namespace - try: exec v in n - except ImportError: - self._add_error_message('Import "%s" failed.'%v) - raise Exception - except Exception: - self._add_error_message('Bad import syntax: "%s".'%v) - raise Exception - 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. - @return a string representing the code - """ - #run init tasks in evaluate - #such as setting flags - if not self._init: - self.evaluate() - self._init = True - v = self.get_value() - t = self.get_type() - if t in ('string', 'file_open', 'file_save'): #string types - if self._stringify_flag: - return '"%s"'%v.replace('"', '\"') - else: - return v - elif t in ('complex_vector', 'real_vector', 'int_vector'): #vector types - 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_blocks()], []) - diff --git a/grc/src/grc_gnuradio/Platform.py b/grc/src/grc_gnuradio/Platform.py deleted file mode 100644 index 5512940c..00000000 --- a/grc/src/grc_gnuradio/Platform.py +++ /dev/null @@ -1,73 +0,0 @@ -""" -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 -""" -##@package grc_gnuradio.Platform -#Gnuradio python specific platform. - -import os -from grc.Constants import FLOW_GRAPH_FILE_EXTENSION -from grc.elements.Platform import Platform as _Platform -from FlowGraph import FlowGraph as _FlowGraph -from Connection import Connection as _Connection -from Block import Block as _Block -from Port import Source,Sink -from Param import Param as _Param -from Generator import Generator -from Constants import * - -class Platform(_Platform): - - def __init__(self, block_paths_internal_only=[], block_paths_external=[]): - """! - Make a platform for gnuradio. - The internal only list will replace the current block path. - @param block_paths_internal_only a list of blocks internal to this platform - @param block_paths_external a list of blocks to load in addition to the above blocks - """ - #ensure hier dir - if not os.path.exists(HIER_BLOCKS_LIB_DIR): os.mkdir(HIER_BLOCKS_LIB_DIR) - #handle internal/only - if block_paths_internal_only: - block_paths = map(lambda b: os.path.join(BLOCKS_DIR, b), ['options.xml'] + block_paths_internal_only) - else: block_paths = [BLOCKS_DIR] - #handle external - block_paths.extend(block_paths_external) - #append custom hiers - block_paths.append(HIER_BLOCKS_LIB_DIR) - #init - _Platform.__init__( - self, - name='GNURadio Python', - key='gnuradio_python', - block_paths=block_paths, - block_dtd=BLOCK_DTD, - block_tree=BLOCK_TREE, - default_flow_graph=DEFAULT_FLOW_GRAPH, - generator=Generator, - ) - - ############################################## - # Constructors - ############################################## - FlowGraph = _FlowGraph - Connection = _Connection - Block = _Block - Source = Source - Sink = Sink - Param = _Param - diff --git a/grc/src/grc_gnuradio/Port.py b/grc/src/grc_gnuradio/Port.py deleted file mode 100644 index 3981df7f..00000000 --- a/grc/src/grc_gnuradio/Port.py +++ /dev/null @@ -1,134 +0,0 @@ -""" -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 -""" -##@package grc_gnuradio.Port -#Flow graph block port (source or sink). - -from grc.elements.Port import Port as _Port -from grc import Utils -from grc.Constants import MAX_NUM_PORTS - -class Port(_Port): - - ##possible port types - TYPES = ['complex', 'float', 'int', 'short', 'byte'] - - def __init__(self, block, n): - """ - Make a new port from nested data. - @param block the parent element - @param n the nested odict - @return a new port - """ - vlen = Utils.exists_or_else(n, 'vlen', '1') - nports = Utils.exists_or_else(n, 'nports', '') - optional = Utils.exists_or_else(n, 'optional', '') - #build the port - _Port.__init__( - self, - block=block, - n=n, - ) - self._nports = nports - self._vlen = vlen - self._optional = bool(optional) - - 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)) - assert(0 < nports <= MAX_NUM_PORTS) - 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: - if self.get_vlen() == 1: - return {#vlen is 1 - 'complex': '#3399FF', - 'float': '#FF8C69', - 'int': '#00FF99', - 'short': '#FFFF66', - 'byte': '#FF66FF', - }[self.get_type()] - return {#vlen is non 1 - 'complex': '#3399AA', - 'float': '#CC8C69', - 'int': '#00CC99', - 'short': '#CCCC33', - 'byte': '#CC66CC', - }[self.get_type()] - except: return _Port.get_color(self) - - def is_empty(self): - """! - Is this port empty? - An empty port has no connections. - Not empty of optional is set. - @return true if empty - """ - return not self.get_optional() and not self.get_connections() - -class Source(Port): - - def __init__(self, block, n): - self._n = n #save n - #key is port index - n['key'] = str(block._source_count) - block._source_count = block._source_count + 1 - Port.__init__(self, block, n) - - def __del__(self): - self.get_parent()._source_count = self.get_parent()._source_count - 1 - -class Sink(Port): - - def __init__(self, block, n): - self._n = n #save n - #key is port index - n['key'] = str(block._sink_count) - block._sink_count = block._sink_count + 1 - Port.__init__(self, block, n) - - def __del__(self): - self.get_parent()._sink_count = self.get_parent()._sink_count - 1 diff --git a/grc/src/grc_gnuradio/__init__.py b/grc/src/grc_gnuradio/__init__.py index eac30516..8b137891 100644 --- a/grc/src/grc_gnuradio/__init__.py +++ b/grc/src/grc_gnuradio/__init__.py @@ -1,20 +1 @@ -""" -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 -""" -##@package grc_gnuradio -#gnuradio overloaded elements and supplemental python modules diff --git a/grc/src/grc_gnuradio/blks2/Makefile.am b/grc/src/grc_gnuradio/blks2/Makefile.am index 307ec863..e3a0b8a3 100644 --- a/grc/src/grc_gnuradio/blks2/Makefile.am +++ b/grc/src/grc_gnuradio/blks2/Makefile.am @@ -19,9 +19,9 @@ # Boston, MA 02110-1301, USA. # -include $(top_srcdir)/Makefile.common +include $(top_srcdir)/grc/Makefile.inc -ourpythondir = $(pythondir)/grc_gnuradio/blks2 +ourpythondir = $(grc_gnuradio_prefix)/blks2 ourpython_PYTHON = \ __init__.py \ diff --git a/grc/src/grc_gnuradio/blks2/__init__.py b/grc/src/grc_gnuradio/blks2/__init__.py index cd1b793c..a26228f8 100644 --- a/grc/src/grc_gnuradio/blks2/__init__.py +++ b/grc/src/grc_gnuradio/blks2/__init__.py @@ -1,22 +1,22 @@ # 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 queue import queue_sink_thread from queue import queue_sink_c, queue_sink_f, queue_sink_i, queue_sink_s, queue_sink_b @@ -25,4 +25,3 @@ from queue import queue_source_c, queue_source_f, queue_source_i, queue_source_s from selector import selector, valve from packet import packet_encoder, packet_decoder from error_rate import error_rate - diff --git a/grc/src/grc_gnuradio/blks2/error_rate.py b/grc/src/grc_gnuradio/blks2/error_rate.py index eb09940c..9b2df58e 100644 --- a/grc/src/grc_gnuradio/blks2/error_rate.py +++ b/grc/src/grc_gnuradio/blks2/error_rate.py @@ -1,22 +1,22 @@ # 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 @@ -31,7 +31,7 @@ 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 @@ -39,7 +39,7 @@ class input_watcher(_threading.Thread): self.setDaemon(1) self.keep_running = True self.start() - + def run(self): r = '' while True: @@ -49,27 +49,27 @@ class input_watcher(_threading.Thread): s = r + msg.to_string() i = (nitems-nitems%2)*itemsize r = s[i:] - s = s[:i] + s = s[:i] samples = numpy.fromstring(s, numpy.int8) - self._callback(samples) - + 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): - """! + + 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), + self, 'error_rate', + gr.io_signature(2, 2, gr.sizeof_char), gr.io_signature(1, 1, gr.sizeof_float), ) assert type in ('BER', 'SER') @@ -95,12 +95,12 @@ class error_rate(gr.hier_block2): 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] + 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 @@ -111,13 +111,13 @@ class error_rate(gr.hier_block2): 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) - + 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] + old_err = self._err_array[self._err_index] #record error ref = samples[i*2] res = samples[i*2 + 1] @@ -134,5 +134,4 @@ class error_rate(gr.hier_block2): 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) - + self._msgq_source.insert_tail(msg) diff --git a/grc/src/grc_gnuradio/blks2/packet.py b/grc/src/grc_gnuradio/blks2/packet.py index 5276de10..fcdfb9ae 100644 --- a/grc/src/grc_gnuradio/blks2/packet.py +++ b/grc/src/grc_gnuradio/blks2/packet.py @@ -1,22 +1,22 @@ # 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, packet_utils import gnuradio.gr.gr_threading as _threading @@ -31,11 +31,11 @@ DEFAULT_MSGQ_LIMIT = 2 DEFAULT_THRESHOLD = 12 ####################################################################################### -## Packet Encoder +## Packet Encoder ####################################################################################### class _packet_encoder_thread(_threading.Thread): - + def __init__(self, msgq, payload_length, send): self._msgq = msgq self._payload_length = payload_length @@ -44,24 +44,24 @@ class _packet_encoder_thread(_threading.Thread): 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: + sample = sample + msg.to_string() #get the body of the msg as a string + while len(sample) >= self._payload_length: payload = sample[0:self._payload_length] - sample = sample[self._payload_length:] - self._send(payload) + sample = sample[self._payload_length:] + self._send(payload) class packet_encoder(gr.hier_block2): """ Hierarchical block for wrapping packet-based modulators. """ - + def __init__(self, item_size_in, samples_per_symbol, bits_per_symbol, access_code='', pad_for_usrp=True, payload_length=-1): - """! + """ packet_mod constructor. @param item_size_in the size of the input data stream in bytes @param samples_per_symbol number of samples per symbol @@ -79,8 +79,8 @@ class packet_encoder(gr.hier_block2): 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 + self._access_code = access_code + self._pad_for_usrp = pad_for_usrp if payload_length < 0: #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 @@ -88,12 +88,12 @@ class packet_encoder(gr.hier_block2): self._payload_length = payload_length #create blocks msg_source = gr.message_source(gr.sizeof_char, DEFAULT_MSGQ_LIMIT) - self._msgq_out = msg_source.msgq() + self._msgq_out = msg_source.msgq() self._msgq_in = gr.msg_queue(DEFAULT_MSGQ_LIMIT) - msg_sink = gr.message_sink(self._item_size_in, self._msgq_in, False) #False -> blocking + msg_sink = gr.message_sink(self._item_size_in, self._msgq_in, False) #False -> blocking #initialize hier2 gr.hier_block2.__init__( - self, + self, "packet_encoder", gr.io_signature(1, 1, self._item_size_in), # Input signature gr.io_signature(1, 1, gr.sizeof_char) # Output signature @@ -103,12 +103,12 @@ class packet_encoder(gr.hier_block2): self.connect(msg_source, self) #start thread _packet_encoder_thread(self._msgq_in, self._payload_length, self._send_packet) - + def _send_packet(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, @@ -118,13 +118,13 @@ class packet_encoder(gr.hier_block2): ) msg = gr.message_from_string(packet) self._msgq_out.insert_tail(msg) - + ####################################################################################### -## Packet Decoder +## Packet Decoder ####################################################################################### class _packet_decoder_thread(_threading.Thread): - + def __init__(self, msgq, callback): _threading.Thread.__init__(self) self.setDaemon(1) @@ -144,9 +144,9 @@ class packet_decoder(gr.hier_block2): """ Hierarchical block for wrapping packet-based demodulators. """ - + def __init__(self, item_size_out, access_code='', threshold=-1): - """! + """ packet_demod constructor. @param item_size_out the size of the output data stream in bytes @param access_code AKA sync vector @@ -159,19 +159,19 @@ class packet_decoder(gr.hier_block2): 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._access_code = access_code #threshold - if threshold < 0: threshold = DEFAULT_THRESHOLD - self._threshold = threshold + if threshold < 0: threshold = DEFAULT_THRESHOLD + self._threshold = threshold #blocks self._msgq_in = gr.msg_queue(DEFAULT_MSGQ_LIMIT) #holds packets from the PHY correlator = gr.correlate_access_code_bb(self._access_code, self._threshold) - framer_sink = gr.framer_sink_1(self._msgq_in) + framer_sink = gr.framer_sink_1(self._msgq_in) msg_source = gr.message_source(self._item_size_out, DEFAULT_MSGQ_LIMIT) - self._msgq_out = msg_source.msgq() + self._msgq_out = msg_source.msgq() #initialize hier2 gr.hier_block2.__init__( - self, + self, "packet_decoder", gr.io_signature(1, 1, gr.sizeof_char), # Input signature gr.io_signature(1, 1, self._item_size_out) # Output signature @@ -183,12 +183,10 @@ class packet_decoder(gr.hier_block2): _packet_decoder_thread(self._msgq_in, self._recv_packet) def _recv_packet(self, ok, payload): - """! + """ Extract the payload from the packet and push onto message queue. @param ok boolean ok @param payload data received """ 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) - - + if ok: self._msgq_out.insert_tail(msg) diff --git a/grc/src/grc_gnuradio/blks2/queue.py b/grc/src/grc_gnuradio/blks2/queue.py index cec35e52..25ea1c61 100644 --- a/grc/src/grc_gnuradio/blks2/queue.py +++ b/grc/src/grc_gnuradio/blks2/queue.py @@ -1,37 +1,37 @@ # 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 import gnuradio.gr.gr_threading as _threading import numpy ####################################################################################### -## Queue Sink Thread +## Queue Sink Thread ####################################################################################### class queue_sink_thread(_threading.Thread): - """! + """ Read samples from the queue sink and execute the callback. """ - + def __init__(self, queue_sink, callback): - """! + """ Queue sink thread contructor. @param queue_sink the queue to pop messages from @param callback the function of one argument @@ -42,31 +42,31 @@ class queue_sink_thread(_threading.Thread): self.setDaemon(1) self.keep_running = True self.start() - + def run(self): while self.keep_running: self._callback(self._queue_sink.pop()) ####################################################################################### -## Queue Sink +## Queue Sink ####################################################################################### class _queue_sink_base(gr.hier_block2): - """! + """ Queue sink base, a queue sink for any size queue. Easy read access to a gnuradio data stream from python. Call pop to read a sample from a gnuradio data stream. Samples are cast as python data types, complex, float, or int. """ - + def __init__(self, vlen=1): - """! + """ Queue sink base contructor. @param vlen the vector length """ self._vlen = vlen #initialize hier2 gr.hier_block2.__init__( - self, + self, "queue_sink", gr.io_signature(1, 1, self._item_size*self._vlen), # Input signature gr.io_signature(0, 0, 0) # Output signature @@ -77,9 +77,9 @@ class _queue_sink_base(gr.hier_block2): #connect self.connect(self, message_sink) self.arr = '' - + def pop(self): - """! + """ Pop a new sample off the front of the queue. @return a new sample """ @@ -95,59 +95,59 @@ class _queue_sink_base(gr.hier_block2): class queue_sink_c(_queue_sink_base): _item_size = gr.sizeof_gr_complex _numpy = numpy.complex64 - def _cast(self, arg): return complex(arg.real, arg.imag) - + def _cast(self, arg): return complex(arg.real, arg.imag) + class queue_sink_f(_queue_sink_base): _item_size = gr.sizeof_float _numpy = numpy.float32 _cast = float - + class queue_sink_i(_queue_sink_base): _item_size = gr.sizeof_int _numpy = numpy.int32 _cast = int - + class queue_sink_s(_queue_sink_base): _item_size = gr.sizeof_short _numpy = numpy.int16 _cast = int - + class queue_sink_b(_queue_sink_base): _item_size = gr.sizeof_char _numpy = numpy.int8 _cast = int - + ####################################################################################### -## Queue Source +## Queue Source ####################################################################################### class _queue_source_base(gr.hier_block2): - """! + """ Queue source base, a queue source for any size queue. Easy write access to a gnuradio data stream from python. Call push to to write a sample into the gnuradio data stream. """ - + def __init__(self, vlen=1): - """! + """ Queue source base contructor. @param vlen the vector length """ self._vlen = vlen #initialize hier2 gr.hier_block2.__init__( - self, + self, "queue_source", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(1, 1, self._item_size*self._vlen) # Output signature ) #create message sink - message_source = gr.message_source(self._item_size*self._vlen, 1) + message_source = gr.message_source(self._item_size*self._vlen, 1) self._msgq = message_source.msgq() #connect self.connect(message_source, self) - + def push(self, item): - """! + """ Push an item into the back of the queue. @param item the item """ @@ -159,20 +159,19 @@ class _queue_source_base(gr.hier_block2): class queue_source_c(_queue_source_base): _item_size = gr.sizeof_gr_complex _numpy = numpy.complex64 - + class queue_source_f(_queue_source_base): _item_size = gr.sizeof_float _numpy = numpy.float32 - + class queue_source_i(_queue_source_base): _item_size = gr.sizeof_int _numpy = numpy.int32 - + class queue_source_s(_queue_source_base): _item_size = gr.sizeof_short _numpy = numpy.int16 - + class queue_source_b(_queue_source_base): _item_size = gr.sizeof_char _numpy = numpy.int8 - diff --git a/grc/src/grc_gnuradio/blks2/selector.py b/grc/src/grc_gnuradio/blks2/selector.py index 787f6547..0997a5ce 100644 --- a/grc/src/grc_gnuradio/blks2/selector.py +++ b/grc/src/grc_gnuradio/blks2/selector.py @@ -1,92 +1,92 @@ #!/usr/bin/env python # # Copyright 2008 Free Software Foundation, Inc. -# +# # This file is part of GNU Radio -# +# # GNU Radio is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3, or (at your option) # any later version. -# +# # GNU Radio is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with 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): - """! + def __init__(self, item_size, num_inputs, num_outputs, input_index, output_index): + """ SelectorHelper 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), + 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 + #terminator blocks for unused inputs and outputs self.input_terminators = [gr.null_sink(item_size)] * num_inputs self.output_terminators = [gr.head(item_size, 0)] * num_outputs self.copy = None - #connections + #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 + 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.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, + """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, self.input_index), self.input_terminators[self.input_index]) self.disconnect(self.output_terminators[self.output_index], (self, self.output_index)) self.copy = gr.skiphead(self.item_size, 0) 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]) - + 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, + """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]) - del self.copy - self.copy = None + del self.copy + self.copy = None 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 """ @@ -95,25 +95,25 @@ class selector(gr.hier_block2): self._disconnect_current() self.input_index = input_index self._connect_current() - self.unlock() - + 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: + """ + if self.output_index != output_index: self.lock() self._disconnect_current() self.output_index = output_index - self._connect_current() - self.unlock() + 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 @@ -121,13 +121,12 @@ class valve(selector): 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/src/grc_gnuradio/usrp/Makefile.am b/grc/src/grc_gnuradio/usrp/Makefile.am index 9689be8e..5416ced4 100644 --- a/grc/src/grc_gnuradio/usrp/Makefile.am +++ b/grc/src/grc_gnuradio/usrp/Makefile.am @@ -19,9 +19,9 @@ # Boston, MA 02110-1301, USA. # -include $(top_srcdir)/Makefile.common +include $(top_srcdir)/grc/Makefile.inc -ourpythondir = $(pythondir)/grc_gnuradio/usrp +ourpythondir = $(grc_gnuradio_prefix)/usrp ourpython_PYTHON = \ __init__.py \ diff --git a/grc/src/grc_gnuradio/usrp/__init__.py b/grc/src/grc_gnuradio/usrp/__init__.py index 0962df14..58e3b1df 100644 --- a/grc/src/grc_gnuradio/usrp/__init__.py +++ b/grc/src/grc_gnuradio/usrp/__init__.py @@ -1,25 +1,24 @@ # 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 simple_usrp import simple_source_c, simple_source_s from simple_usrp import dual_source_c, dual_source_s from simple_usrp import simple_sink_c, simple_sink_s from simple_usrp import dual_sink_c, dual_sink_s - diff --git a/grc/src/grc_gnuradio/usrp/simple_usrp.py b/grc/src/grc_gnuradio/usrp/simple_usrp.py index 118ccc16..dd33ef12 100644 --- a/grc/src/grc_gnuradio/usrp/simple_usrp.py +++ b/grc/src/grc_gnuradio/usrp/simple_usrp.py @@ -22,11 +22,11 @@ import sys from gnuradio import usrp, gr #################################################################### -# Helper Functions +# Helper Functions #################################################################### def _set_frequency(u, which, subdev, frequency, verbose=False): - """! + """ Set the carrier frequency for the given subdevice. @param u the usrp source/sink @param which specifies the DDC/DUC number @@ -44,7 +44,7 @@ def _set_frequency(u, which, subdev, frequency, verbose=False): else: print >> sys.stderr, 'Error calling tune on subdevice.' def _setup_rx_subdev(u, subdev_spec, ddc, gain, frequency, auto_tr=None, rx_ant=None): - """! + """ Setup a usrp receive subdevice by setting gain and frequency. Add the gain and frequency callbacks to the flow graph. FlexRF: Handle auto transmit/receive and set the receive antenna. @@ -65,7 +65,7 @@ def _setup_rx_subdev(u, subdev_spec, ddc, gain, frequency, auto_tr=None, rx_ant= return subdev def _setup_tx_subdev(u, subdev_spec, gain, frequency, auto_tr=None, tx_enb=None): - """! + """ Setup a usrp receive subdevice by setting gain and frequency. Add the gain and frequency callbacks to the flow graph. FlexRF: Handle auto transmit/receive and enable the transmitter. @@ -94,7 +94,7 @@ constructor_to_size = { #################################################################### #################################################################### -# Simple USRP Base Classes +# Simple USRP Base Classes #################################################################### #################################################################### @@ -102,7 +102,7 @@ class _simple_usrp(object): """A single usrp source/sink base class.""" def __init__(self, u, subdev, which): - """! + """ Create a simple usrp base class. @param u the usrp object @param subdev the subdevice object @@ -113,41 +113,41 @@ class _simple_usrp(object): self._which = which def get_u(self): - """! + """ Get the underlying usrp object. @return the usrp source/sink object. """ return self._u def get_subdev(self): - """! + """ Get the underlying subdevice. @return the subdev object. """ return self._subdev def set_frequency(self, frequency): - """! + """ Set the frequency of the subdevice. @param frequency the frequency to tune """ _set_frequency(self.get_u(), self._which, self.get_subdev(), frequency) def set_gain(self, gain): - """! + """ Set the gain of the subdevice. @param gain the gain to set """ self.get_subdev().set_gain(gain) #################################################################### -# Simple USRP Source +# Simple USRP Source #################################################################### class _simple_source(gr.hier_block2, _simple_usrp): """A single usrp source of IO type short or complex.""" def __init__(self, number, subdev_spec, frequency, decimation, gain, mux=None, auto_tr=None, rx_ant=None): - """! + """ USRP simple source contructor. @param number the unit number @param subdev_spec the sub-device specification tuple @@ -181,13 +181,13 @@ class simple_source_c(_simple_source): constructor = usrp.source_c class simple_source_s(_simple_source): constructor = usrp.source_s #################################################################### -# Simple USRP Sink +# Simple USRP Sink #################################################################### class _simple_sink(gr.hier_block2, _simple_usrp): """A single usrp sink of IO type short or complex.""" def __init__(self, number, subdev_spec, frequency, interpolation, gain, mux=None, auto_tr=None, tx_enb=None): - """! + """ USRP simple sink contructor. @param number the unit number @param subdev_spec the sub-device specification tuple @@ -222,7 +222,7 @@ class simple_sink_s(_simple_sink): constructor = usrp.sink_s #################################################################### #################################################################### -# Dual USRP Base Classes +# Dual USRP Base Classes #################################################################### #################################################################### @@ -230,7 +230,7 @@ class _dual_usrp(object): """A dual usrp source/sink base class.""" def __init__(self, u, subdev_a, subdev_b, which_a, which_b): - """! + """ Create a dual usrp base class. @param u the usrp object @param subdev_a the subdevice object side a @@ -245,62 +245,62 @@ class _dual_usrp(object): self._which_b = which_b def get_u(self): - """! + """ Get the underlying usrp object. @return the usrp source/sink object. """ return self._u def get_subdev_a(self): - """! + """ Get the underlying subdevice. @return the subdev object. """ return self._subdev_a def get_subdev_b(self): - """! + """ Get the underlying subdevice. @return the subdev object. """ return self._subdev_b def set_frequency_a(self, frequency): - """! + """ Set the frequency of the subdevice. @param frequency the frequency to tune """ _set_frequency(self.get_u(), self._which_a, self.get_subdev_a(), frequency) def set_frequency_b(self, frequency): - """! + """ Set the frequency of the subdevice. @param frequency the frequency to tune """ _set_frequency(self.get_u(), self._which_b, self.get_subdev_b(), frequency) def set_gain_a(self, gain): - """! + """ Set the gain of the subdevice. @param gain the gain to set """ self.get_subdev_a().set_gain(gain) def set_gain_b(self, gain): - """! + """ Set the gain of the subdevice. @param gain the gain to set """ self.get_subdev_b().set_gain(gain) #################################################################### -# Dual USRP Source +# Dual USRP Source #################################################################### class _dual_source(gr.hier_block2, _dual_usrp): """A dual usrp source of IO type short or complex.""" def __init__(self, number, frequency_a, frequency_b, decimation, gain_a, gain_b, mux=0x3210, auto_tr=None, rx_ant_a=None, rx_ant_b=None): - """! + """ USRP dual source contructor. @param number the unit number @param frequency_a the frequency to tune side a @@ -337,13 +337,13 @@ class dual_source_c(_dual_source): constructor = usrp.source_c class dual_source_s(_dual_source): constructor = usrp.source_s #################################################################### -# Dual USRP Sink +# Dual USRP Sink #################################################################### class _dual_sink(gr.hier_block2, _dual_usrp): """A dual usrp sink of IO type short or complex.""" def __init__(self, number, frequency_a, frequency_b, interpolation, gain_a, gain_b, mux=0xba98, auto_tr=None, tx_enb_a=None, tx_enb_b=None): - """! + """ USRP dual sink contructor. @param number the unit number @param subdev_spec the sub-device specification tuple @@ -376,4 +376,3 @@ class _dual_sink(gr.hier_block2, _dual_usrp): class dual_sink_c(_dual_sink): constructor = usrp.sink_c class dual_sink_s(_dual_sink): constructor = usrp.sink_s - diff --git a/grc/src/grc_gnuradio/utils/Makefile.am b/grc/src/grc_gnuradio/utils/Makefile.am deleted file mode 100644 index 01020139..00000000 --- a/grc/src/grc_gnuradio/utils/Makefile.am +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/Makefile.common - -ourpythondir = $(pythondir)/grc_gnuradio/utils - -ourpython_PYTHON = \ - __init__.py \ - convert_hier.py \ - expr_utils.py \ - extract_docs.py diff --git a/grc/src/grc_gnuradio/utils/__init__.py b/grc/src/grc_gnuradio/utils/__init__.py deleted file mode 100644 index 6cdfc263..00000000 --- a/grc/src/grc_gnuradio/utils/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -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 -""" -##@package grc_gnuradio.utils -#utility functions and classes - diff --git a/grc/src/grc_gnuradio/utils/convert_hier.py b/grc/src/grc_gnuradio/utils/convert_hier.py deleted file mode 100644 index 747d2f44..00000000 --- a/grc/src/grc_gnuradio/utils/convert_hier.py +++ /dev/null @@ -1,80 +0,0 @@ -""" -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 -""" -##@package grc_gnuradio.utils.convert_hier -#Utility functions to convert a grc hier block to an xml wrapper - -from grc_gnuradio.Constants import BLOCK_DTD -from grc import ParseXML -from grc.Utils import odict - -def convert_hier(flow_graph, python_file): - #extract info from the flow graph - input_sig = flow_graph.get_input_signature() - output_sig = flow_graph.get_output_signature() - parameters = flow_graph.get_parameters() - block_key = flow_graph.get_option('id') - block_name = flow_graph.get_option('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 - 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]), - ) - #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 - if int(input_sig['nports']): - sink_n = odict() - sink_n['name'] = 'in' - sink_n['type'] = input_sig['type'] - sink_n['vlen'] = input_sig['vlen'] - sink_n['nports'] = input_sig['nports'] - block_n['sink'] = sink_n - #source data - if int(output_sig['nports']): - source_n = odict() - source_n['name'] = 'out' - source_n['type'] = output_sig['type'] - source_n['vlen'] = output_sig['vlen'] - source_n['nports'] = output_sig['nports'] - block_n['source'] = source_n - #doc data - block_n['doc'] = "%s\n%s\n%s"%(block_author, block_desc, python_file) - #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/src/grc_gnuradio/utils/expr_utils.py b/grc/src/grc_gnuradio/utils/expr_utils.py deleted file mode 100644 index 9c729fb8..00000000 --- a/grc/src/grc_gnuradio/utils/expr_utils.py +++ /dev/null @@ -1,139 +0,0 @@ -""" -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 -""" -##@package grc_gnuradio.utils.expr_utils -#Utility functions to comprehend variable expressions. - -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_prepend(expr, vars, prepend): - """! - Search for vars in the expression and add the prepend. - @param expr an expression string - @param vars a list of variable names - @param prepend the prepend string - @return a new expression with the prepend - """ - expr_splits = expr_split(expr) - for i, es in enumerate(expr_splits): - if es in vars: expr_splits[i] = prepend + 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): - 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 AssertionError 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()) - assert indep_vars - #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) - -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/src/grc_gnuradio/utils/extract_docs.py b/grc/src/grc_gnuradio/utils/extract_docs.py deleted file mode 100644 index 55c7b783..00000000 --- a/grc/src/grc_gnuradio/utils/extract_docs.py +++ /dev/null @@ -1,111 +0,0 @@ -""" -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 -""" -##@package grc_gnuradio.utils.extract_docs -#Extract documentation from the gnuradio doxygen files. - -from grc_gnuradio.Constants import DOCS_DIR -from lxml import etree -import os - -DOXYGEN_NAME_XPATH = '/doxygen/compounddef/compoundname' -DOXYGEN_BRIEFDESC_GR_XPATH = '/doxygen/compounddef/briefdescription' -DOXYGEN_DETAILDESC_GR_XPATH = '/doxygen/compounddef/detaileddescription' -DOXYGEN_BRIEFDESC_BLKS2_XPATH = '/doxygen/compounddef/sectiondef[@kind="public-func"]/memberdef/briefdescription' -DOXYGEN_DETAILDESC_BLKS2_XPATH = '/doxygen/compounddef/sectiondef[@kind="public-func"]/memberdef/detaileddescription' - -def extract_txt(xml, parent_text=None): - """! - Recursivly pull the text out of an xml tree. - @param xml the xml tree - @param parent_text the text of the parent element - @return a string - """ - text = xml.text or '' - tail = parent_text and xml.tail or '' - return text + ''.join( - map(lambda x: extract_txt(x, text), xml) - ) + tail - -def is_match(key, file): - """! - Is the block key a match for the given file name? - @param key block key - @param file the xml file name - @return true if matches - """ - if not file.endswith('.xml'): return False - file = file.replace('.xml', '') #remove file ext - file = file.replace('__', '_') #doxygen xml files have 2 underscores - if key.startswith('gr_'): - if not file.startswith('classgr_'): return False - key = key.replace('gr_', 'classgr_') - elif key.startswith('trellis_'): - if not file.startswith('classtrellis_'): return False - key = key.replace('trellis_', 'classtrellis_') - elif key.startswith('blks2_'): - if not file.startswith('classgnuradio_'): return False - if 'blks2' not in file: return False - file = file.replace('_1_1', '_') #weird blks2 doxygen syntax - key = key.replace('blks2_', '') - else: return False - for k, f in zip(*map(reversed, map(lambda x: x.split('_'), [key, file]))): - if k == f: continue - ks = k.split('x') - if len(ks) == 2 and f.startswith(ks[0]) and f.endswith(ks[1]): continue - if len(ks) > 2 and all(ki in ('x', fi) for ki, fi in zip(k, f)): continue - return False - return True - -def extract(key): - """! - Extract the documentation from the doxygen generated xml files. - If multiple files match, combine the docs. - @param key the block key - @return a string with documentation - """ - #get potential xml file matches for the key - if os.path.exists(DOCS_DIR) and os.path.isdir(DOCS_DIR): - matches = filter(lambda f: is_match(key, f), os.listdir(DOCS_DIR)) - else: matches = list() - #combine all matches - doc_strs = list() - for match in matches: - try: - xml_file = DOCS_DIR + '/' + match - xml = etree.parse(xml_file) - #extract descriptions - comp_name = extract_txt(xml.xpath(DOXYGEN_NAME_XPATH)[0]).strip('\n') - comp_name = ' --- ' + comp_name + ' --- ' - if key.startswith('gr_') or key.startswith('trellis_'): - brief_desc = extract_txt(xml.xpath(DOXYGEN_BRIEFDESC_GR_XPATH)[0]).strip('\n') - detailed_desc = extract_txt(xml.xpath(DOXYGEN_DETAILDESC_GR_XPATH)[0]).strip('\n') - elif key.startswith('blks2_'): - brief_desc = extract_txt(xml.xpath(DOXYGEN_BRIEFDESC_BLKS2_XPATH)[0]).strip('\n') - detailed_desc = extract_txt(xml.xpath(DOXYGEN_DETAILDESC_BLKS2_XPATH)[0]).strip('\n') - else: - brief_desc = '' - detailed_desc = '' - #combine - doc_strs.append('\n'.join([comp_name, brief_desc, detailed_desc]).strip('\n')) - except IndexError: pass #bad format - return '\n\n'.join(doc_strs) - -if __name__ == '__main__': - import sys - print extract(sys.argv[1]) diff --git a/grc/src/grc_gnuradio/wxgui/Makefile.am b/grc/src/grc_gnuradio/wxgui/Makefile.am index 2e7072ea..6f731f2c 100644 --- a/grc/src/grc_gnuradio/wxgui/Makefile.am +++ b/grc/src/grc_gnuradio/wxgui/Makefile.am @@ -19,9 +19,9 @@ # Boston, MA 02110-1301, USA. # -include $(top_srcdir)/Makefile.common +include $(top_srcdir)/grc/Makefile.inc -ourpythondir = $(pythondir)/grc_gnuradio/wxgui +ourpythondir = $(grc_gnuradio_prefix)/wxgui ourpython_PYTHON = \ __init__.py \ diff --git a/grc/src/grc_gnuradio/wxgui/__init__.py b/grc/src/grc_gnuradio/wxgui/__init__.py index c0fdca52..0b13ead9 100644 --- a/grc/src/grc_gnuradio/wxgui/__init__.py +++ b/grc/src/grc_gnuradio/wxgui/__init__.py @@ -1,22 +1,22 @@ # 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 callback_controls import \ button_control, \ @@ -27,4 +27,3 @@ from callback_controls import \ slider_vertical_control, \ text_box_control from top_block_gui import top_block_gui - diff --git a/grc/src/grc_gnuradio/wxgui/callback_controls.py b/grc/src/grc_gnuradio/wxgui/callback_controls.py index c1ba784e..2bb0b994 100644 --- a/grc/src/grc_gnuradio/wxgui/callback_controls.py +++ b/grc/src/grc_gnuradio/wxgui/callback_controls.py @@ -48,7 +48,7 @@ class _chooser_control_base(_control_base): """House a drop down or radio buttons for variable control.""" def __init__(self, window, callback, label='Label', index=0, choices=[0], labels=[]): - """! + """ Chooser contructor. Create the slider, text box, and label. @param window the wx parent window @@ -68,14 +68,14 @@ class _chooser_control_base(_control_base): self._init() def _handle_changed(self, event=None): - """! + """ A change is detected. Call the callback. """ try: self.call() except Exception, e: print >> sys.stderr, 'Error in exec callback from handle changed.\n', e def get_value(self): - """! + """ Update the chooser. @return one of the possible choices """ @@ -83,7 +83,7 @@ class _chooser_control_base(_control_base): return self.choices[self.index] ############################################################################################## -# Button Control +# Button Control ############################################################################################## class button_control(_chooser_control_base): """House a button for variable control.""" @@ -98,7 +98,7 @@ class button_control(_chooser_control_base): self.button.SetLabel(self.labels[self.index]) ############################################################################################## -# Drop Down Control +# Drop Down Control ############################################################################################## class drop_down_control(_chooser_control_base): """House a drop down for variable control.""" @@ -113,7 +113,7 @@ class drop_down_control(_chooser_control_base): self.index = self.drop_down.GetSelection() ############################################################################################## -# Radio Buttons Control +# Radio Buttons Control ############################################################################################## class _radio_buttons_control_base(_chooser_control_base): """House radio buttons for variable control.""" @@ -147,13 +147,13 @@ class radio_buttons_vertical_control(_radio_buttons_control_base): radio_button_align = wx.ALIGN_LEFT ############################################################################################## -# Slider Control +# Slider Control ############################################################################################## class _slider_control_base(_control_base): """House a Slider and a Text Box for variable control.""" def __init__(self, window, callback, label='Label', value=50, min=0, max=100, num_steps=100): - """! + """ Slider contructor. Create the slider, text box, and label. @param window the wx parent window @@ -191,14 +191,14 @@ class _slider_control_base(_control_base): self.text_box.SetValue(str(self._value)) def get_value(self): - """! + """ Get the current set value. @return the value (float) """ return self._value def _set_slider_value(self, real_value): - """! + """ Translate the real numerical value into a slider value and, write the value to the slider. @param real_value the numeric value the slider should represent @@ -207,7 +207,7 @@ class _slider_control_base(_control_base): self.slider.SetValue(slider_value) def _handle_scroll(self, event=None): - """! + """ A scroll event is detected. Read the slider, call the callback. """ slider_value = self.slider.GetValue() @@ -218,7 +218,7 @@ class _slider_control_base(_control_base): except Exception, e: print >> sys.stderr, 'Error in exec callback from handle scroll.\n', e def _handle_enter(self, event=None): - """! + """ An enter key was pressed. Read the text box, call the callback. """ new_value = float(self.text_box.GetValue()) @@ -237,13 +237,13 @@ class slider_vertical_control(_slider_control_base): slider_size = 20, 200 ############################################################################################## -# Text Box Control +# Text Box Control ############################################################################################## class text_box_control(_control_base): """House a Text Box for variable control.""" def __init__(self, window, callback, label='Label', value=50): - """! + """ Text box contructor. Create the text box, and label. @param window the wx parent window @@ -264,14 +264,14 @@ class text_box_control(_control_base): self.text_box.SetValue(str(value)) def get_value(self): - """! + """ Get the current set value. @return the value (float) """ return self._value def _handle_enter(self, event=None): - """! + """ An enter key was pressed. Read the text box, call the callback. If the text cannot be evaluated, do not try callback. """ diff --git a/grc/src/grc_gnuradio/wxgui/top_block_gui.py b/grc/src/grc_gnuradio/wxgui/top_block_gui.py index d56d2005..fef9d18c 100644 --- a/grc/src/grc_gnuradio/wxgui/top_block_gui.py +++ b/grc/src/grc_gnuradio/wxgui/top_block_gui.py @@ -28,7 +28,7 @@ class top_block_gui(gr.top_block): """gr top block with wx gui app and grid sizer.""" def __init__(self, title='', size=default_gui_size, icon=None): - """! + """ Initialize the gr top block. Create the wx gui elements. @param title the main window title @@ -48,21 +48,21 @@ class top_block_gui(gr.top_block): self._wx_vbox = wx.BoxSizer(wx.VERTICAL) def GetWin(self): - """! + """ Get the window for wx elements to fit within. @return the wx frame """ return self._wx_frame def Add(self, win): - """! + """ Add a window to the wx vbox. @param win the wx window """ self._wx_vbox.Add(win, 0, wx.EXPAND) def GridAdd(self, win, row, col, row_span=1, col_span=1): - """! + """ Add a window to the wx grid at the given position. @param win the wx window @param row the row specification (integer >= 0) @@ -73,7 +73,7 @@ class top_block_gui(gr.top_block): self._wx_grid.Add(win, wx.GBPosition(row, col), wx.GBSpan(row_span, col_span), wx.EXPAND) def Run(self): - """! + """ Setup the wx gui elements. Start the gr top block. Block with the wx main loop. @@ -96,4 +96,3 @@ class top_block_gui(gr.top_block): gr.top_block.start(self) #blocking main loop self._wx_app.MainLoop() - diff --git a/grc/src/gui/ActionHandler.py b/grc/src/gui/ActionHandler.py new file mode 100644 index 00000000..ab4d6650 --- /dev/null +++ b/grc/src/gui/ActionHandler.py @@ -0,0 +1,445 @@ +""" +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 os +import signal +from .. platforms.base.Constants import PY_GTK_ICON, IMAGE_FILE_EXTENSION +from Constants import DIR_LEFT, DIR_RIGHT +import Actions +import pygtk +pygtk.require('2.0') +import gtk +import Preferences +from threading import Thread +import Messages +from .. utils import ParseXML +import random +from .. platforms.gui.Platform import Platform +from MainWindow import MainWindow +from Dialogs import PreferencesDialog, AboutDialog, HotKeysDialog +from FileDialogs import OpenFlowGraphFileDialog, SaveFlowGraphFileDialog, SaveImageFileDialog + +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 + platform = Platform(platform) + if PY_GTK_ICON: gtk.window_set_default_icon_from_file(PY_GTK_ICON) + for action in Actions.ACTIONS_LIST: action.connect('activate', self._handle_actions) + #setup the main window + self.main_window = MainWindow(self.handle_states, 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.drawing_area.get_focus_flag + #setup the messages + Messages.register_messenger(self.main_window.add_report_line) + Messages.send_init() + #initialize + self.init_file_paths = file_paths + self.handle_states(Actions.APPLICATION_INITIALIZE) + #enter the mainloop + gtk.gdk.threads_init() + gtk.main() + + def _handle_key_press(self, widget, event): + """ + Handle key presses from the keyboard. + Translate key combos into actions. + Key combinations that do not include special keys, such as ctrl or Fcn*, + Also, require that the flow graph has mouse focus when choosing to handle keys. + @return true if the flow graph is in active use + """ + keyname = gtk.gdk.keyval_name(event.keyval) + ctrl = event.state & gtk.gdk.CONTROL_MASK + alt = event.state & gtk.gdk.MOD1_MASK + shift = event.state & gtk.gdk.SHIFT_MASK + #################### save/open/new/close ############################### + if ctrl and keyname == 's': + self.handle_states(Actions.FLOW_GRAPH_SAVE) + elif ctrl and keyname == 'o': + self.handle_states(Actions.FLOW_GRAPH_OPEN) + elif ctrl and keyname == 'n': + self.handle_states(Actions.FLOW_GRAPH_NEW) + elif ctrl and keyname == 'q': + self.handle_states(Actions.FLOW_GRAPH_CLOSE) + #################### Cut/Copy/Paste ############################### + elif self.get_focus_flag() and ctrl and keyname == 'x': #mouse focus + self.handle_states(Actions.BLOCK_CUT) + elif self.get_focus_flag() and ctrl and keyname == 'c': #mouse focus + self.handle_states(Actions.BLOCK_COPY) + elif self.get_focus_flag() and ctrl and keyname == 'v': #mouse focus + self.handle_states(Actions.BLOCK_PASTE) + #################### Undo/Redo ############################### + elif ctrl and keyname == 'z': + self.handle_states(Actions.FLOW_GRAPH_UNDO) + elif ctrl and keyname == 'y': + self.handle_states(Actions.FLOW_GRAPH_REDO) + #################### Delete ############################### + elif self.get_focus_flag() and keyname == 'Delete': #mouse focus + self.handle_states(Actions.ELEMENT_DELETE) + #################### Params ############################### + elif self.get_focus_flag() and keyname == 'Return': #mouse focus + self.handle_states(Actions.BLOCK_PARAM_MODIFY) + #################### Rotate ############################### + elif self.get_focus_flag() and keyname == 'Right': #mouse focus + self.handle_states(Actions.BLOCK_ROTATE_RIGHT) + elif self.get_focus_flag() and keyname == 'Left': #mouse focus + self.handle_states(Actions.BLOCK_ROTATE_LEFT) + #################### Enable/Disable ############################### + elif self.get_focus_flag() and keyname == 'e': #mouse focus + self.handle_states(Actions.BLOCK_ENABLE) + elif self.get_focus_flag() and keyname == 'd': #mouse focus + self.handle_states(Actions.BLOCK_DISABLE) + #################### Data Type ############################### + elif self.get_focus_flag() and keyname == 'Down': #mouse focus + self.handle_states(Actions.BLOCK_INC_TYPE) + elif self.get_focus_flag() and keyname == 'Up': #mouse focus + self.handle_states(Actions.BLOCK_DEC_TYPE) + #################### Port Controllers ############################### + elif self.get_focus_flag() and keyname in ('equal','plus', 'KP_Add'): #mouse focus + self.handle_states(Actions.PORT_CONTROLLER_INC) + elif self.get_focus_flag() and keyname in ('minus', 'KP_Subtract'): #mouse focus + self.handle_states(Actions.PORT_CONTROLLER_DEC) + #################### Gen/Exec/Stop/Print ############################### + elif keyname == 'F5': + self.handle_states(Actions.FLOW_GRAPH_GEN) + elif keyname == 'F6': + self.handle_states(Actions.FLOW_GRAPH_EXEC) + elif keyname == 'F7': + self.handle_states(Actions.FLOW_GRAPH_KILL) + elif keyname == 'Print': + self.handle_states(Actions.FLOW_GRAPH_SCREEN_CAPTURE) + #propagate this if the fg is not in focus or nothing is selected + return self.get_focus_flag() and self.get_flow_graph().is_selected() + + 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 + """ + self.handle_states(Actions.APPLICATION_QUIT) + return True + + def _handle_actions(self, event): + """ + Handle all of the activate signals from the gtk actions. + The action signals derive from clicking on a toolbar or menu bar button. + Forward the action to the state handler. + """ + self.handle_states(event.get_name()) + + def handle_states(self, state=''): + """ + Handle the state changes in the GUI. + Handle all of the state changes that arise from the action handler or other gui and + inputs in the application. The state passed to the handle_states method is a string descriping + the change. A series of if/elif statements handle the state by greying out action buttons, causing + changes in the flow graph, saving/opening files... The handle_states method is passed to the + contructors of many of the classes used in this application enabling them to report any state change. + @param state a string describing the state change + """ + #print state + ################################################## + # Initalize/Quit + ################################################## + if state == Actions.APPLICATION_INITIALIZE: + for action in Actions.ACTIONS_LIST: 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.HOTKEYS_WINDOW_DISPLAY, Actions.PREFS_WINDOW_DISPLAY, + Actions.FLOW_GRAPH_SCREEN_CAPTURE, + ): Actions.get_action_from_name(action).set_sensitive(True) + if not self.init_file_paths and Preferences.restore_files(): + 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 state == Actions.APPLICATION_QUIT: + if self.main_window.close_pages(): + gtk.main_quit() + exit(0) + ################################################## + # Selections + ################################################## + elif state == Actions.ELEMENT_SELECT: + self.get_flow_graph().update() + elif state == Actions.NOTHING_SELECT: + self.get_flow_graph().unselect() + self.get_flow_graph().update() + ################################################## + # Enable/Disable + ################################################## + elif state == 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 state == 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 state == Actions.BLOCK_CUT: + self.handle_states(BLOCK_COPY) + self.handle_states(ELEMENT_DELETE) + elif state == Actions.BLOCK_COPY: + self.clipboard = self.get_flow_graph().copy_to_clipboard() + elif state == 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) + ################################################## + # Move/Rotate/Delete/Create + ################################################## + elif state == 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 state == Actions.BLOCK_ROTATE_LEFT: + if self.get_flow_graph().rotate_selected(DIR_LEFT): + 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 state == Actions.BLOCK_ROTATE_RIGHT: + if self.get_flow_graph().rotate_selected(DIR_RIGHT): + 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 state == Actions.ELEMENT_DELETE: + if self.get_flow_graph().remove_selected(): + self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) + self.handle_states(Actions.NOTHING_SELECT) + self.get_page().set_saved(False) + elif state == Actions.ELEMENT_CREATE: + self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) + self.handle_states(Actions.NOTHING_SELECT) + self.get_page().set_saved(False) + elif state == 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 state == 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 state == Actions.PORT_CONTROLLER_INC: + if self.get_flow_graph().port_controller_modify_selected(1): + self.get_flow_graph().update() + self.get_flow_graph().update() #2 times + self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) + self.get_page().set_saved(False) + elif state == Actions.PORT_CONTROLLER_DEC: + if self.get_flow_graph().port_controller_modify_selected(-1): + self.get_flow_graph().update() + self.get_flow_graph().update() #2 times + self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) + self.get_page().set_saved(False) + ################################################## + # Window stuff + ################################################## + elif state == Actions.PREFS_WINDOW_DISPLAY: + PreferencesDialog() + self.get_flow_graph().update() + elif state == Actions.ABOUT_WINDOW_DISPLAY: + AboutDialog() + elif state == Actions.HOTKEYS_WINDOW_DISPLAY: + HotKeysDialog() + ################################################## + # Param Modifications + ################################################## + elif state == Actions.BLOCK_PARAM_MODIFY: + if self.get_flow_graph().param_modify_selected(): + 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) + ################################################## + # Undo/Redo + ################################################## + elif state == 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 state == 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 state == Actions.FLOW_GRAPH_NEW: + self.main_window.new_page() + elif state == 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 state == Actions.FLOW_GRAPH_CLOSE: + self.main_window.close_page() + elif state == Actions.FLOW_GRAPH_SAVE: + if not self.get_page().get_file_path(): self.handle_states(Actions.FLOW_GRAPH_SAVE_AS) + else: + try: + ParseXML.to_file(self.get_flow_graph().export_data(), 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 state == Actions.FLOW_GRAPH_SAVE_AS: + file_path = SaveFlowGraphFileDialog(self.get_page().get_file_path()).run() + if file_path != None: + self.get_page().set_file_path(file_path) + self.handle_states(Actions.FLOW_GRAPH_SAVE) + elif state == Actions.FLOW_GRAPH_SCREEN_CAPTURE: + file_path = SaveImageFileDialog(self.get_page().get_file_path()).run() + if file_path != None: + pixmap = self.get_flow_graph().get_drawing_area().pixmap + width, height = pixmap.get_size() + pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, width, height) + pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(), 0, 0, 0, 0, width, height) + pixbuf.save(file_path, IMAGE_FILE_EXTENSION[1:]) + ################################################## + # Gen/Exec/Stop + ################################################## + elif state == Actions.FLOW_GRAPH_GEN: + if not self.get_page().get_pid(): + if not self.get_page().get_saved() or not self.get_page().get_file_path(): + self.handle_states(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 state == Actions.FLOW_GRAPH_EXEC: + if not self.get_page().get_pid(): + self.handle_states(Actions.FLOW_GRAPH_GEN) + if self.get_page().get_saved() and self.get_page().get_file_path(): + ExecFlowGraphThread(self) + elif state == Actions.FLOW_GRAPH_KILL: + if self.get_page().get_pid(): + try: os.kill(self.get_page().get_pid(), signal.SIGKILL) + except: print "could not kill pid: %s"%self.get_page().get_pid() + elif state == '': #pass and run the global actions + pass + else: print '!!! State "%s" not handled !!!'%state + ################################################## + # Global Actions for all States + ################################################## + #update general buttons + Actions.get_action_from_name(Actions.ELEMENT_DELETE).set_sensitive(bool(self.get_flow_graph().get_selected_elements())) + Actions.get_action_from_name(Actions.BLOCK_PARAM_MODIFY).set_sensitive(bool(self.get_flow_graph().get_selected_block())) + Actions.get_action_from_name(Actions.BLOCK_ROTATE_RIGHT).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + Actions.get_action_from_name(Actions.BLOCK_ROTATE_LEFT).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + #update cut/copy/paste + Actions.get_action_from_name(Actions.BLOCK_CUT).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + Actions.get_action_from_name(Actions.BLOCK_COPY).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + Actions.get_action_from_name(Actions.BLOCK_PASTE).set_sensitive(bool(self.clipboard)) + #update enable/disable + Actions.get_action_from_name(Actions.BLOCK_ENABLE).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + Actions.get_action_from_name(Actions.BLOCK_DISABLE).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + #set the exec and stop buttons + self.update_exec_stop() + #saved status + Actions.get_action_from_name(Actions.FLOW_GRAPH_SAVE).set_sensitive(not self.get_page().get_saved()) + self.main_window.update() + #draw the flow graph + self.get_flow_graph().draw() + + 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_pid() + Actions.get_action_from_name(Actions.FLOW_GRAPH_GEN).set_sensitive(sensitive) + Actions.get_action_from_name(Actions.FLOW_GRAPH_EXEC).set_sensitive(sensitive) + Actions.get_action_from_name(Actions.FLOW_GRAPH_KILL).set_sensitive(self.get_page().get_pid() != 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_pid(self.p.pid) + #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 flow graph.""" + #handle completion + r = "\n" + while(r): + gtk.gdk.threads_enter() + Messages.send_verbose_exec(r) + gtk.gdk.threads_leave() + r = os.read(self.p.stdout.fileno(), 1024) + gtk.gdk.threads_enter() + Messages.send_end_exec() + self.page.set_pid(None) + self.update_exec_stop() + gtk.gdk.threads_leave() diff --git a/grc/src/gui/Actions.py b/grc/src/gui/Actions.py new file mode 100644 index 00000000..ddd2573a --- /dev/null +++ b/grc/src/gui/Actions.py @@ -0,0 +1,103 @@ +""" +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 + +###################################################################################################### +# States +###################################################################################################### +APPLICATION_INITIALIZE = 'app init' +APPLICATION_QUIT = 'app quit' +PARAM_MODIFY = 'param modify' +BLOCK_MOVE = 'block move' +BLOCK_ROTATE_LEFT = 'block rotate left' +BLOCK_ROTATE_RIGHT = 'block rotate right' +BLOCK_PARAM_MODIFY = 'block param modify' +BLOCK_INC_TYPE = 'block increment type' +BLOCK_DEC_TYPE = 'block decrement type' +BLOCK_ENABLE = 'block enable' +BLOCK_DISABLE = 'block disable' +BLOCK_CUT = 'block cut' +BLOCK_COPY = 'block copy' +BLOCK_PASTE = 'block paste' +PORT_CONTROLLER_INC = 'port controller increment' +PORT_CONTROLLER_DEC = 'port controller decrement' +ELEMENT_CREATE = 'element create' +ELEMENT_DELETE = 'element delete' +ELEMENT_SELECT = 'element select' +NOTHING_SELECT = 'nothing select' +FLOW_GRAPH_OPEN = 'flow graph open' +FLOW_GRAPH_UNDO = 'flow graph undo' +FLOW_GRAPH_REDO = 'flow graph redo' +FLOW_GRAPH_SAVE = 'flow graph save' +FLOW_GRAPH_SAVE_AS = 'flow graph save as' +FLOW_GRAPH_CLOSE = 'flow graph close' +FLOW_GRAPH_NEW = 'flow graph new' +FLOW_GRAPH_GEN = 'flow graph gen' +FLOW_GRAPH_EXEC = 'flow graph exec' +FLOW_GRAPH_KILL = 'flow graph kill' +FLOW_GRAPH_SCREEN_CAPTURE = 'flow graph screen capture' +ABOUT_WINDOW_DISPLAY = 'about window display' +HOTKEYS_WINDOW_DISPLAY = 'hotkeys window display' +PREFS_WINDOW_DISPLAY = 'prefs window display' + +###################################################################################################### +# Actions +###################################################################################################### +ACTIONS_LIST = ( + gtk.Action(FLOW_GRAPH_NEW, '_New', 'Create a new flow graph', 'gtk-new'), + gtk.Action(FLOW_GRAPH_OPEN, '_Open', 'Open an existing flow graph', 'gtk-open'), + gtk.Action(FLOW_GRAPH_SAVE, '_Save', 'Save the current flow graph', 'gtk-save'), + gtk.Action(FLOW_GRAPH_SAVE_AS, 'Save _As', 'Save the current flow graph as...', 'gtk-save-as'), + gtk.Action(FLOW_GRAPH_CLOSE, '_Close', 'Close the current flow graph', 'gtk-close'), + gtk.Action(APPLICATION_QUIT, '_Quit', 'Quit program', 'gtk-quit'), + gtk.Action(FLOW_GRAPH_UNDO, '_Undo', 'Undo a change to the flow graph', 'gtk-undo'), + gtk.Action(FLOW_GRAPH_REDO, '_Redo', 'Redo a change to the flow graph', 'gtk-redo'), + gtk.Action(ELEMENT_DELETE, '_Delete', 'Delete the selected blocks', 'gtk-delete'), + gtk.Action(BLOCK_ROTATE_LEFT, 'Rotate _Left', 'Rotate the selected blocks 90 degrees', 'gtk-go-back'), + gtk.Action(BLOCK_ROTATE_RIGHT, 'Rotate _Right', 'Rotate the selected blocks -90 degrees', 'gtk-go-forward'), + gtk.Action(BLOCK_PARAM_MODIFY, '_Properties', 'Modify params for the selected block', 'gtk-properties'), + gtk.Action(BLOCK_ENABLE, 'E_nable', 'Enable the selected blocks', 'gtk-connect'), + gtk.Action(BLOCK_DISABLE, 'D_isable', 'Disable the selected blocks', 'gtk-disconnect'), + gtk.Action(BLOCK_CUT, 'Cu_t', 'Cut', 'gtk-cut'), + gtk.Action(BLOCK_COPY, '_Copy', 'Copy', 'gtk-copy'), + gtk.Action(BLOCK_PASTE, '_Paste', 'Paste', 'gtk-paste'), + gtk.Action(PREFS_WINDOW_DISPLAY, '_Preferences', 'Configure Preferences', 'gtk-preferences'), + gtk.Action(ABOUT_WINDOW_DISPLAY, '_About', 'About this program', 'gtk-about'), + gtk.Action(HOTKEYS_WINDOW_DISPLAY, '_HotKeys', 'Hot Keys', 'gtk-info'), + gtk.Action(FLOW_GRAPH_GEN, '_Generate', 'Generate the flow graph', 'gtk-convert'), + gtk.Action(FLOW_GRAPH_EXEC, '_Execute', 'Execute the flow graph', 'gtk-execute'), + gtk.Action(FLOW_GRAPH_KILL, '_Kill', 'Kill the flow graph', 'gtk-stop'), + gtk.Action(FLOW_GRAPH_SCREEN_CAPTURE, 'S_creen Capture', 'Create a screen capture of the flow graph', 'gtk-print'), +) + +ACTIONS_DICT = dict((action.get_name(), action) for action in ACTIONS_LIST) + +def get_action_from_name(action_name): + """ + Retrieve the action from the action list. + Search the list and find an action with said name. + @param action_name the action name(string) + @throw KeyError bad action name + @return a gtk action object + """ + if ACTIONS_DICT.has_key(action_name): return ACTIONS_DICT[action_name] + raise KeyError('Action Name: "%s" does not exist'%action_name) diff --git a/grc/src/gui/Bars.py b/grc/src/gui/Bars.py new file mode 100644 index 00000000..915e5abe --- /dev/null +++ b/grc/src/gui/Bars.py @@ -0,0 +1,139 @@ +""" +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 +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.FLOW_GRAPH_GEN, + Actions.FLOW_GRAPH_EXEC, + Actions.FLOW_GRAPH_KILL, + None, + Actions.BLOCK_ROTATE_LEFT, + Actions.BLOCK_ROTATE_RIGHT, + None, + Actions.BLOCK_ENABLE, + Actions.BLOCK_DISABLE, +) + +##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_LEFT, + Actions.BLOCK_ROTATE_RIGHT, + None, + Actions.BLOCK_ENABLE, + Actions.BLOCK_DISABLE, + None, + Actions.BLOCK_PARAM_MODIFY, + ]), + (gtk.Action('Build', '_Build', None, None), [ + Actions.FLOW_GRAPH_GEN, + Actions.FLOW_GRAPH_EXEC, + Actions.FLOW_GRAPH_KILL, + ]), + (gtk.Action('Options', '_Options', None, None), [ + Actions.PREFS_WINDOW_DISPLAY, + ]), + (gtk.Action('Help', '_Help', None, None), [ + Actions.ABOUT_WINDOW_DISPLAY, + Actions.HOTKEYS_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_name in TOOLBAR_LIST: + if action_name: #add a tool item + action = Actions.get_action_from_name(action_name) + 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,action_names 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_name in action_names: + if action_name: #append a menu item + action = Actions.get_action_from_name(action_name) + 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/src/gui/BlockTreeWindow.py b/grc/src/gui/BlockTreeWindow.py new file mode 100644 index 00000000..291cc6f3 --- /dev/null +++ b/grc/src/gui/BlockTreeWindow.py @@ -0,0 +1,150 @@ +""" +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 +""" + +from Constants import BLOCK_SELECTION_WINDOW_WIDTH +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +NAME_INDEX = 0 +KEY_INDEX = 1 + +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) + 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) + #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(BLOCK_SELECTION_WINDOW_WIDTH, -1) + self.pack_start(scrolled_window) + #add button + self.add_button = gtk.Button(None, 'gtk-add') + self.add_button.connect('clicked', self._handle_add_button) + self.pack_start(self.add_button, False) + #map categories to iters + self.categories = dict() + self.categories[tuple()] = None + #add blocks and categories + self.platform.load_block_tree(self) + #initialize + self._update_add_button() + + ############################################################ + ## 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 string + @param block the block object or None + """ + #rectify category + category = filter(lambda x: x, category.split('/')) + #add category and all sub categories + for i in range(len(category)): + sub_category = tuple(category[:i+1]) + if sub_category not in self.categories.keys(): + iter = self.treestore.insert_before(self.categories[tuple(category[:i])], None) + self.treestore.set_value(iter, NAME_INDEX, '[ %s ]'%category[i]) + self.treestore.set_value(iter, KEY_INDEX, '') + self.categories[sub_category] = iter + #add block + if block is None: return + iter = self.treestore.insert_before(self.categories[tuple(category)], None) + self.treestore.set_value(iter, NAME_INDEX, block.get_name()) + self.treestore.set_value(iter, KEY_INDEX, block.get_key()) + + ############################################################ + ## 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_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/src/gui/Constants.py b/grc/src/gui/Constants.py new file mode 100644 index 00000000..2f6af9a1 --- /dev/null +++ b/grc/src/gui/Constants.py @@ -0,0 +1,82 @@ +""" +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 +""" + +################################################## +## Global Titles +################################################## + +##The name to appear in the main window for a flow graph that has not been saved to file. +NEW_FLOGRAPH_TITLE = 'untitled' + +##The prefix title on the main window. +MAIN_WINDOW_PREFIX = "GRC" + +################################################## +## Signal block rotations +################################################## + +##direction of rotation left. +DIR_LEFT = 'left' + +##direction of rotation right. +DIR_RIGHT = 'right' + +################################################## +## Dimension constraints for the various windows (in pixels) +################################################## + +##main window constraints +MIN_WINDOW_WIDTH = 600 +MIN_WINDOW_HEIGHT = 400 + +##dialog constraints +MIN_DIALOG_WIDTH = 500 +MIN_DIALOG_HEIGHT = 500 + +##static height of reports window +REPORTS_WINDOW_HEIGHT = 100 + +##static width of block selection window +BLOCK_SELECTION_WINDOW_WIDTH = 200 + +################################################## +## Dragging, scrolling, and redrawing constants for the flow graph window in pixels +################################################## + +##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 + +##The redrawing sensitivity, how many seconds must pass between motion events before a redraw? +MOTION_DETECT_REDRAWING_SENSITIVITY = .02 + +##How close the mouse click can be to a connection and register a connection select. +CONNECTION_SELECT_SENSITIVITY = 5 + +################################################## +# A state is recorded for each change to the flow graph, the size dictates how many states we can record +################################################## + +##The size of the state saving cache in the flow graph (for undo/redo functionality) +STATE_CACHE_SIZE = 42 diff --git a/grc/src/gui/Dialogs.py b/grc/src/gui/Dialogs.py new file mode 100644 index 00000000..f7ba2954 --- /dev/null +++ b/grc/src/gui/Dialogs.py @@ -0,0 +1,146 @@ +""" +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 +from Constants import \ + MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT, \ + MAIN_WINDOW_PREFIX +from .. platforms.base.Constants import VERSION +import Preferences + +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) + +class PreferencesDialog(gtk.Dialog): + """A dialog box to display the preferences.""" + + def __init__(self): + """PreferencesDialog constructor.""" + gtk.Dialog.__init__(self, buttons=('gtk-close', gtk.RESPONSE_CLOSE)) + self.set_title("Preferences") + self.set_size_request(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT) + notebook = gtk.Notebook() + for title,desc,params in Preferences.get_preferences(): + vbox = gtk.VBox() + vbox.pack_start(gtk.Label(''), False) #blank label for spacing + for param in params: vbox.pack_start(param.get_input_object(), False) + desc = desc.strip('\n') + if desc: vbox.pack_start(TextDisplay(desc), False, padding=5) + notebook.append_page(vbox, gtk.Label(title)) + self.vbox.pack_start(notebook, True) + self.show_all() + self.run() + self.destroy() + +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 != None: message_dialog.set_title(title) + if markup != None: message_dialog.set_markup(markup) + response = message_dialog.run() + message_dialog.destroy() + return response + +class AboutDialog(gtk.AboutDialog): + """A cute little about dialog.""" + + def __init__(self): + """AboutDialog constructor.""" + gtk.AboutDialog.__init__(self) + self.set_version(VERSION) + self.set_name(MAIN_WINDOW_PREFIX) + self.set_license(__doc__) + self.set_copyright('Copyright 2008 Free Software Foundation, Inc.') + self.set_website('http://gnuradio.org/trac/wiki/GNURadioCompanion') + self.set_comments("""\ +Thank you to all those from the mailing list who tested GNU Radio Companion and offered advice. +-- +Special Thanks: +A. Brinton Cooper -> starting the project +CER Technology Fellowship Grant -> initial funding +William R. Kenan Jr. Fund -> usrp & computers +Patrick Strasser -> the GRC icon +Achilleas Anastasopoulos -> trellis support +--""") + self.run() + self.destroy() + +class HotKeysDialog(gtk.Dialog): + """Display each action with the associated hotkey.""" + + def __init__(self): + """HotKeysDialog constructor.""" + gtk.Dialog.__init__(self, buttons=('gtk-close', gtk.RESPONSE_CLOSE)) + self.set_title('Hot Keys') + markup = '' + for action, hotkey in ( + ('New Flow Graph', 'Ctrl + n'), + ('Open Flow Graph', 'Ctrl + o'), + ('Save Flow Graph', 'Ctrl + s'), + ('Close Flow Graph', 'Ctrl + q'), + ('Cut Block', 'Ctrl + x'), + ('Copy Block', 'Ctrl + c'), + ('Paste Block', 'Ctrl + v'), + ('Undo Change', 'Ctrl + z'), + ('Redo Change', 'Ctrl + y'), + ('Delete Block', 'Delete'), + ('Modify Parameters', 'Enter'), + ('Rotate Block', 'Right'), + ('Rotate Block', 'Left'), + ('Enable Block', 'e'), + ('Disable Block', 'd'), + ('Modify Data Type', 'Up'), + ('Modify Data Type', 'Down'), + ('Add a Port', '+'), + ('Remove a Port', '-'), + ('Flow Graph Generate', 'F5'), + ('Flow Graph Execute', 'F6'), + ('Flow Graph Kill', 'F7'), + ('Screen Shot', 'PrintScreen'), + ): markup = '%s\n%s:%s'%(markup, action, hotkey.rjust(25-len(action), ' ')) + label = gtk.Label() + label.set_markup('%s\n'%markup) #append newline + self.vbox.pack_start(label, False) + self.show_all() + self.run() + self.destroy() diff --git a/grc/src/gui/DrawingArea.py b/grc/src/gui/DrawingArea.py new file mode 100644 index 00000000..3588e122 --- /dev/null +++ b/grc/src/gui/DrawingArea.py @@ -0,0 +1,118 @@ +""" +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 Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT + +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, main_window): + """ + DrawingArea contructor. + Connect event handlers. + @param main_window the main_window containing all flow graphs + """ + self.ctrl_mask = False + self._main_window = main_window + #inject drawing area into main_window + self._main_window.drawing_area = self + gtk.DrawingArea.__init__(self) + self.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) + 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.set_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 the focus flag + self._focus_flag = False + self.get_focus_flag = lambda: self._focus_flag + self.connect("leave-notify-event", self._handle_focus_event, False) + self.connect("enter-notify-event", self._handle_focus_event, True) + #pixmap for drawing + self.pixmap = None + self.gc = None + + def draw(self): + """ + Draw the pixmap onto this drawing area. + """ + self.window.draw_drawable(self.gc, self.pixmap, 0, 0, 0, 0, -1, -1) + + ########################################################################## + ## Handlers + ########################################################################## + def _handle_focus_event(self, widget, event, focus_flag): + """Record the focus state of the flow graph window.""" + self._focus_flag = focus_flag + + 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 + self._main_window.get_flow_graph().handle_mouse_button_press( + left_click=(event.button == 1), + double_click=(event.type == gtk.gdk._2BUTTON_PRESS), + coordinate=(event.x, event.y), + ) + return True + + 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 + self._main_window.get_flow_graph().handle_mouse_button_release( + left_click=(event.button == 1), + coordinate=(event.x, event.y), + ) + return True + + 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._main_window.get_flow_graph().handle_mouse_motion( + coordinate=(event.x, event.y), + ) + return True + + def _handle_window_expose(self, widget, event): + """ + Called when the window initially appears or is resized: create a new pixmap, draw the flow graph. + """ + self.gc = self.window.new_gc() + width, height = self.get_size_request() + if not self.pixmap or (width, height) != self.pixmap.get_size(): + self.pixmap = gtk.gdk.Pixmap(self.window, width, height, -1) + self._main_window.get_flow_graph().draw() + return True diff --git a/grc/src/gui/FileDialogs.py b/grc/src/gui/FileDialogs.py new file mode 100644 index 00000000..320c1161 --- /dev/null +++ b/grc/src/gui/FileDialogs.py @@ -0,0 +1,154 @@ +""" +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 NEW_FLOGRAPH_TITLE +from .. platforms.base.Constants import \ + DEFAULT_FILE_PATH, FLOW_GRAPH_FILE_EXTENSION, \ + IMAGE_FILE_EXTENSION +from os import path + +OPEN_FLOW_GRAPH = 'open flow graph' +SAVE_FLOW_GRAPH = 'save flow graph' +SAVE_IMAGE = 'save image' + +##the filter for flow graph files +FLOW_GRAPH_FILE_FILTER = gtk.FileFilter() +FLOW_GRAPH_FILE_FILTER.set_name('GRC Files') +FLOW_GRAPH_FILE_FILTER.add_pattern('*'+FLOW_GRAPH_FILE_EXTENSION) +FLOW_GRAPH_FILE_FILTER.add_pattern('*.xml') #TEMP + +##the filter for image files +IMAGE_FILE_FILTER = gtk.FileFilter() +IMAGE_FILE_FILTER.set_name('Image Files') +IMAGE_FILE_FILTER.add_pattern('*'+IMAGE_FILE_EXTENSION) + +##the filter for all files +ALL_FILE_FILTER = gtk.FileFilter() +ALL_FILE_FILTER.set_name('All Files') +ALL_FILE_FILTER.add_pattern('*') + +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(ALL_FILE_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 + FLOW_GRAPH_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(FLOW_GRAPH_FILE_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(FLOW_GRAPH_FILE_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(IMAGE_FILE_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() + for extension, filter in ( + (FLOW_GRAPH_FILE_EXTENSION, FLOW_GRAPH_FILE_FILTER), + (IMAGE_FILE_EXTENSION, IMAGE_FILE_FILTER), + ): #append the missing file extension if the filter matches + if filename[len(filename)-len(extension):] != extension \ + and filter == self.get_filter(): 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!', + 'File "%s" Exists!\nWould you like to overwrite the existing file?'%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!', + 'File "%s" Does not Exist!'%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/src/gui/MainWindow.py b/grc/src/gui/MainWindow.py new file mode 100644 index 00000000..e4c60fce --- /dev/null +++ b/grc/src/gui/MainWindow.py @@ -0,0 +1,321 @@ +""" +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 Constants import \ + MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT, \ + NEW_FLOGRAPH_TITLE, MAIN_WINDOW_PREFIX, \ + REPORTS_WINDOW_HEIGHT +from .. platforms.base.Constants import FLOW_GRAPH_FILE_EXTENSION +from Actions import APPLICATION_QUIT, FLOW_GRAPH_KILL +import pygtk +pygtk.require('2.0') +import gtk +import Bars +from BlockTreeWindow import BlockTreeWindow +from Dialogs import TextDisplay, MessageDialogHelper +from DrawingArea import DrawingArea +from NotebookPage import NotebookPage +import Preferences +import Messages +import os + +############################################################ +# Main window +############################################################ + +class MainWindow(gtk.Window): + """The topmost window with menus, the tool bar, and other major windows.""" + + def __init__(self, handle_states, platform): + """ + MainWindow contructor. + @param handle_states the callback function + """ + self._platform = platform + #setup window + self.handle_states = handle_states + gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) + vbox = gtk.VBox() + hbox = gtk.HBox() + self.add(vbox) + #create the menu bar and toolbar + vbox.pack_start(Bars.MenuBar(), False) + vbox.pack_start(Bars.Toolbar(), False) + #setup scrolled window + 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) + self.scrolled_window.add_with_viewport(self.drawing_area) + #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) + fg_and_report_box = gtk.VBox(False, 0) + fg_and_report_box.pack_start(self.notebook, False, False, 0) + fg_and_report_box.pack_start(self.scrolled_window) + hbox.pack_start(fg_and_report_box) + vbox.pack_start(hbox) + #create the side windows + side_box = gtk.VBox() + hbox.pack_start(side_box, False) + side_box.pack_start(BlockTreeWindow(platform, self.get_flow_graph)) #allow resize, selection window can have more space + #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_size_request(-1, REPORTS_WINDOW_HEIGHT) + self.reports_scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.reports_scrolled_window.add_with_viewport(self.text_display) + fg_and_report_box.pack_end(self.reports_scrolled_window, False) #dont allow resize, fg should get all the space + #show all but the main window container and the reports window + vbox.show_all() + self.notebook.hide() + self._show_reports_window(False) + # load preferences and show the main window + Preferences.load(platform) + self.resize(*Preferences.window_size()) + self.show()#show after resize in preferences + + ############################################################ + # 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 + """ + self.handle_states(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()) + self.handle_states() + + ############################################################ + # 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') + + def _show_reports_window(self, show): + """ + Show the reports window when show is True. + Hide the reports window when show is False. + @param show boolean flag + """ + if show: self.reports_scrolled_window.show() + else: self.reports_scrolled_window.hide() + + ############################################################ + # 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() + #inject drawing area and handle states into flow graph + flow_graph.drawing_area = self.drawing_area + flow_graph.handle_states = self.handle_states + 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) + 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.window_size(self.get_size()) + 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_pid() 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(): + self.handle_states(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_pid(): self.handle_states(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 + """ + if self.get_page(): + title = ''.join(( + MAIN_WINDOW_PREFIX, + ' - Editing: ', + (self.get_page().get_file_path() or NEW_FLOGRAPH_TITLE), + (self.get_page().get_saved() and ' ' or '*'), #blank must be non empty + ) + ) + else: title = MAIN_WINDOW_PREFIX + ' - Editor ' + gtk.Window.set_title(self, title) + #set tab titles + for page in self._get_pages(): + title = os.path.basename(page.get_file_path()) + #strip file extension #TEMP + if title.endswith('.xml'): + title = title[0:-len('.xml')] + #strip file extension + if title.endswith(FLOW_GRAPH_FILE_EXTENSION): + title = title[0:-len(FLOW_GRAPH_FILE_EXTENSION)] + page.set_text(''.join(( + (title or NEW_FLOGRAPH_TITLE), + (page.get_saved() and ' ' or '*'), #blank must be non empty + ) + ) + ) + #reports window + self._show_reports_window(Preferences.show_reports_window()) + #show/hide notebook tabs + if len(self._get_pages()) > 1: self.notebook.show() + else: self.notebook.hide() + + 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() + + ############################################################ + # 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/src/gui/Makefile.am b/grc/src/gui/Makefile.am new file mode 100644 index 00000000..a6639af4 --- /dev/null +++ b/grc/src/gui/Makefile.am @@ -0,0 +1,41 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +ourpythondir = $(grc_src_prefix)/gui + +ourpython_PYTHON = \ + ActionHandler.py \ + Actions.py \ + Bars.py \ + BlockTreeWindow.py \ + Constants.py \ + Dialogs.py \ + DrawingArea.py \ + FileDialogs.py \ + MainWindow.py \ + Messages.py \ + NotebookPage.py \ + ParamsDialog.py \ + Preferences.py \ + StateCache.py \ + __init__.py diff --git a/grc/src/gui/Messages.py b/grc/src/gui/Messages.py new file mode 100644 index 00000000..1d9a8021 --- /dev/null +++ b/grc/src/gui/Messages.py @@ -0,0 +1,101 @@ +""" +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 +""" + +from .. platforms.base.Constants import VERSION +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(): + send("""<<< Welcome to GRC %s >>>\n"""%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('Parser Error: %s\n'%error) + send(">>> Failue\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(">>> Failue\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('>>> Warning: A connection can only be created between a source and an unconnected sink.\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) diff --git a/grc/src/gui/NotebookPage.py b/grc/src/gui/NotebookPage.py new file mode 100644 index 00000000..a25243b1 --- /dev/null +++ b/grc/src/gui/NotebookPage.py @@ -0,0 +1,172 @@ +""" +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 Actions import FLOW_GRAPH_CLOSE +import pygtk +pygtk.require('2.0') +import gtk +from .. utils import ParseXML +from StateCache import StateCache +from .. platforms.base.Constants import FLOW_GRAPH_DTD +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_pid(None) + #import the file + self.main_window = main_window + self.set_file_path(file_path) + file_path = file_path or flow_graph.get_parent().get_default_flow_graph() + ############################################################ + from .. utils import converter + converter.convert(file_path, flow_graph.get_parent()) + ############################################################ + ParseXML.validate_dtd(file_path, FLOW_GRAPH_DTD) + initial_state = ParseXML.from_file(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) + self.get_flow_graph().update() + #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() + + 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 + self.main_window.handle_states(FLOW_GRAPH_CLOSE) + + def set_text(self, text): + """ + Set the text in this label. + @param text the new text + """ + self.label.set_text(text) + + def get_tab(self): + """ + Get the gtk widget for this page's tab. + @return gtk widget + """ + return self.tab + + def get_pid(self): + """ + Get the pid for the flow graph. + @return the pid number + """ + return self.pid + + def set_pid(self, pid): + """ + Set the pid number. + @param pid the new pid number + """ + self.pid = pid + + def get_flow_graph(self): + """ + Get the flow graph. + @return the flow graph + """ + return self._flow_graph + + 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/src/gui/ParamsDialog.py b/grc/src/gui/ParamsDialog.py new file mode 100644 index 00000000..46940db2 --- /dev/null +++ b/grc/src/gui/ParamsDialog.py @@ -0,0 +1,131 @@ +""" +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 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%s:\n'%title) + hbox = gtk.HBox() + hbox.pack_start(label, False, False, padding=11) + return hbox + +class ParamsDialog(gtk.Dialog): + """A dialog box to set block parameters.""" + + def __init__(self, block): + """ + SignalBlockParamsDialog contructor. + @param block the signal block + """ + gtk.Dialog.__init__(self, buttons=('gtk-close', gtk.RESPONSE_CLOSE)) + self.block = block + self.set_title('Properties: %s'%block.get_name()) + self.set_size_request(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT) + vbox = gtk.VBox() + #Add the title label + vbox.pack_start(get_title_label('Parameters'), False) + #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) + #Error Messages for the block + self._error_messages_box = err_box = gtk.VBox() + self._error_messages_text_display = TextDisplay('') + err_box.pack_start(gtk.Label(''), False, False, 7) #spacing + err_box.pack_start(get_title_label('Error Messages'), False) + err_box.pack_start(self._error_messages_text_display, False) + #Add all the parameters + for param in self.block.get_params(): + vbox.pack_start(param.get_input_object(self._handle_changed), False) + vbox.pack_start(err_box, False) + #Done adding parameters + if self.block.get_doc(): + vbox.pack_start(gtk.Label(''), False, False, 7) #spacing + vbox.pack_start(get_title_label('Documentation'), False) + #Create the text box to display notes about the block + vbox.pack_start(TextDisplay(self.block.get_doc()), False) + self.connect('key_press_event', self._handle_key_press) + self.show_all() + #initial update + for param in self.block.get_params(): param.update() + self._update_error_messages() + + def _update_error_messages(self): + """ + Update the error messages in the error messages box. + Hide the box if there are no errors. + """ + if self.block.is_valid(): self._error_messages_box.hide() + else: self._error_messages_box.show() + messages = '\n'.join(self.block.get_error_messages()) + self._error_messages_text_display.set_text(messages) + + 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 + """ + keyname = gtk.gdk.keyval_name(event.keyval) + if keyname == 'Return': self.response(gtk.RESPONSE_OK) + return False #forward the keypress + + def _handle_changed(self, param): + """ + A change occured, update any dependent parameters: + The enum inside the variable type may have changed and, + the variable param will need an external update. + @param param the graphical parameter that initiated the callback + """ + self._update_error_messages() + #update dependent params + if param.is_enum(): + for other_param in param.get_parent().get_params(): + if param.get_key() is not other_param.get_key() and ( + param.get_key() in other_param._type or \ + param.get_key() in other_param._hide): other_param.update() + return True + + def run(self): + """ + Call run(). + @return true if a change occured. + """ + original_data = list() + for param in self.block.get_params(): + original_data.append(param.get_value()) + gtk.Dialog.run(self) + self.destroy() + new_data = list() + for param in self.block.get_params(): + new_data.append(param.get_value()) + return original_data != new_data diff --git a/grc/src/gui/Preferences.py b/grc/src/gui/Preferences.py new file mode 100644 index 00000000..a5591500 --- /dev/null +++ b/grc/src/gui/Preferences.py @@ -0,0 +1,130 @@ +""" +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 .. platforms.base.Constants import HOME_DIR, FLOW_GRAPH_DTD +from .. utils import ParseXML +import Messages +import os + +##Access the loaded preferences in this module +_prefs = list() +def _set_prefs(prefs): _prefs.append(prefs) +def _get_prefs(): return _prefs[0] +def load(platform): _Preferences(platform) +def save(): _get_prefs().save() +def get_preferences(): return _get_prefs().get_preferences() + +class _Preferences(object): + + def __init__(self, platform): + #make self available to module + _set_prefs(self) + #get prefs block + self._prefs_block = platform.get_prefs_block() + #prefs file path + self._prefs_file_path = os.path.join(HOME_DIR, self._prefs_block.get_param('prefs_file').get_value()) + #load + try: + ParseXML.validate_dtd(self._prefs_file_path, FLOW_GRAPH_DTD) + n = ParseXML.from_file(self._prefs_file_path) + self._prefs_block.import_data(n['block']) + except: Messages.send_fail_load_preferences(self._prefs_file_path) + ##all params + self.snap_to_grid_param = self._prefs_block.get_param('snap_to_grid') + self.grid_size_param = self._prefs_block.get_param('grid_size') + self.show_grid_param = self._prefs_block.get_param('show_grid') + self.show_reports_param = self._prefs_block.get_param('show_reports') + self.restore_files_param = self._prefs_block.get_param('restore_files') + self.window_size_param = self._prefs_block.get_param('window_size') + self.file_open_param = self._prefs_block.get_param('file_open') + self.files_open_param = self._prefs_block.get_param('files_open') + self.show_params_param = self._prefs_block.get_param('show_params') + self.show_id_param = self._prefs_block.get_param('show_id') + + def save(self): + try: ParseXML.to_file({'block': self._prefs_block.export_data()}, self._prefs_file_path) + except IOError: Messages.send_fail_save_preferences(self._prefs_file_path) + + def get_preferences(self): + ##Preferences: title, notes, params + return [ + ( + 'Grid', + ''' +Show grid will draw a square grid onto the flow graph with grid points separated by grid size pixels. \ +Snap to Grid forces the upper right corner of the signal block to align with a grid point. +''', + [self.snap_to_grid_param, self.grid_size_param, self.show_grid_param], + ), + ( + 'Appearance', + ''' +Show or hide the reports window at the bottom of the main window. +Show or hide all paramater labels in the signal blocks. +Show or hide the ID label in the signal blocks. +''', + [self.show_reports_param, self.show_params_param, self.show_id_param], + ), + ( + 'Misc', + ''' +Restore previously opened files on start-up. +''', + [self.restore_files_param], + ), + ] + +########################################################################### +# Special methods for specific program functionalities +########################################################################### + +def window_size(size=None): + if size: _get_prefs().window_size_param.set_value(size) + else: + try: return eval(_get_prefs().window_size_param.get_value()) + except: return (-1, -1) + +def restore_files(): + return _get_prefs().restore_files_param.get_value() == 'yes' + +def file_open(file=None): + if file is not None: _get_prefs().file_open_param.set_value(file) + else: return _get_prefs().file_open_param.get_value() + +def files_open(files=None): + if files is not None: _get_prefs().files_open_param.set_value('\n'.join(files)) + else: return _get_prefs().files_open_param.get_value().split('\n') + +def show_reports_window(): + return _get_prefs().show_reports_param.get_value() == 'show' + +def get_grid_size(): + return int(_get_prefs().grid_size_param.get_value()) + +def snap_to_grid(): + return _get_prefs().snap_to_grid_param.get_value() == 'on' + +def show_grid(): + return _get_prefs().show_grid_param.get_value() == 'show' + +def show_params(): + return _get_prefs().show_params_param.get_value() == 'show' + +def show_id(): + return _get_prefs().show_id_param.get_value() == 'show' diff --git a/grc/src/gui/StateCache.py b/grc/src/gui/StateCache.py new file mode 100644 index 00000000..04b18b18 --- /dev/null +++ b/grc/src/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 +""" + +from Actions import FLOW_GRAPH_UNDO, FLOW_GRAPH_REDO, get_action_from_name +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. + """ + get_action_from_name(FLOW_GRAPH_REDO).set_sensitive(self.num_next_states != 0) + get_action_from_name(FLOW_GRAPH_UNDO).set_sensitive(self.num_prev_states != 0) diff --git a/grc/src/gui/__init__.py b/grc/src/gui/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/grc/src/gui/__init__.py @@ -0,0 +1 @@ + diff --git a/grc/src/platforms/Makefile.am b/grc/src/platforms/Makefile.am new file mode 100644 index 00000000..1d3c385c --- /dev/null +++ b/grc/src/platforms/Makefile.am @@ -0,0 +1,31 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +SUBDIRS = \ + base \ + gui \ + python + +ourpythondir = $(grc_src_prefix)/platforms + +ourpython_PYTHON = __init__.py diff --git a/grc/src/platforms/__init__.py b/grc/src/platforms/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/grc/src/platforms/__init__.py @@ -0,0 +1 @@ + diff --git a/grc/src/platforms/base/Block.py b/grc/src/platforms/base/Block.py new file mode 100644 index 00000000..e3ef84d9 --- /dev/null +++ b/grc/src/platforms/base/Block.py @@ -0,0 +1,237 @@ +""" +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 ... import utils +from ... utils import odict +from Element import Element +from Param import Param +from Port import Port + +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 eval 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 eval(self): + return self._param.evaluate() + +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 + """ + #grab the data + name = n['name'] + key = n['key'] + category = utils.exists_or_else(n, 'category', '') + params = utils.listify(n, 'param') + sources = utils.listify(n, 'source') + sinks = utils.listify(n, 'sink') + #build the block + Element.__init__(self, flow_graph) + #store the data + self._name = name + self._key = key + self._category = category + #create the param objects + self._params = odict() + #add the id param + self._params['id'] = self.get_parent().get_parent().Param( + self, + { + 'name': 'ID', + 'key': 'id', + 'type': 'id', + } + ) + self._params['_enabled'] = self.get_parent().get_parent().Param( + self, + { + 'name': 'Enabled', + 'key': '_enabled', + 'type': 'raw', + 'value': 'True', + 'hide': 'all', + } + ) + for param in map(lambda n: self.get_parent().get_parent().Param(self, n), params): + key = param.get_key() + #test against repeated keys + try: assert(key not in self.get_param_keys()) + except AssertionError: self._exit_with_error('Key "%s" already exists in params'%key) + #store the param + self._params[key] = param + #create the source objects + self._sources = odict() + for source in map(lambda n: self.get_parent().get_parent().Source(self, n), sources): + key = source.get_key() + #test against repeated keys + try: assert(key not in self.get_source_keys()) + except AssertionError: self._exit_with_error('Key "%s" already exists in sources'%key) + #store the port + self._sources[key] = source + #create the sink objects + self._sinks = odict() + for sink in map(lambda n: self.get_parent().get_parent().Sink(self, n), sinks): + key = sink.get_key() + #test against repeated keys + try: assert(key not in self.get_sink_keys()) + except AssertionError: self._exit_with_error('Key "%s" already exists in sinks'%key) + #store the port + self._sinks[key] = sink + #begin the testing + self.test() + + def test(self): + """ + Call test on all children. + """ + map(lambda c: c.test(), self.get_params() + self.get_sinks() + self.get_sources()) + + 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 validate(self): + """ + Validate the block. + All ports and params must be valid. + All checks must evaluate to true. + """ + if not self.get_enabled(): return + for c in self.get_params() + self.get_sinks() + self.get_sources(): + try: assert(c.is_valid()) + except AssertionError: + for msg in c.get_error_messages(): + self._add_error_message('%s: %s'%(c, msg)) + + 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_doc(self): return self._doc + + 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() + + ############################################## + # Access Params + ############################################## + def get_param_keys(self): return self._params.keys() + def get_param(self, key): return self._params[key] + def get_params(self): return self._params.values() + + ############################################## + # Access Sinks + ############################################## + def get_sink_keys(self): return self._sinks.keys() + def get_sink(self, key): return self._sinks[key] + def get_sinks(self): return self._sinks.values() + + ############################################## + # Access Sources + ############################################## + def get_source_keys(self): return self._sources.keys() + def get_source(self, key): return self._sources[key] + def get_sources(self): return self._sources.values() + + 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) + + ############################################## + ## 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. + @param n the nested data odict + """ + params_n = utils.listify(n, 'param') + for param_n in params_n: + #key and value must exist in the n data + if 'key' in param_n.keys() and 'value' in param_n.keys(): + key = param_n['key'] + value = param_n['value'] + #the key must exist in this block's params + if key in self.get_param_keys(): + self.get_param(key).set_value(value) + self.validate() diff --git a/grc/src/platforms/base/Connection.py b/grc/src/platforms/base/Connection.py new file mode 100644 index 00000000..3c0b42d7 --- /dev/null +++ b/grc/src/platforms/base/Connection.py @@ -0,0 +1,88 @@ +""" +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 Element import Element +from ... utils 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 + #verify the source and sink + assert(source and sink) + assert(not source.is_full()) + assert(not sink.is_full()) + self._source = source + self._sink = sink + + def __str__(self): return 'Connection (%s -> %s)'%(self.get_source(), self.get_sink()) + + def is_connection(self): return True + + def validate(self): + """ + Validate the connections. + The ports must match in type. + """ + source_type = self.get_source().get_type() + sink_type = self.get_sink().get_type() + try: assert source_type == sink_type + except AssertionError: 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/src/platforms/base/Constants.py.in b/grc/src/platforms/base/Constants.py.in new file mode 100644 index 00000000..26ba72d9 --- /dev/null +++ b/grc/src/platforms/base/Constants.py.in @@ -0,0 +1,44 @@ +""" +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 os + +##The current version of this code +VERSION = '@VERSION@' + +##Location of external data files. +DATA_DIR = '@datadir@' + +##DTD validator for saved flow graphs. +FLOW_GRAPH_DTD = os.path.join(DATA_DIR, 'flow_graph.dtd') + +##The default file extension for flow graphs. +FLOW_GRAPH_FILE_EXTENSION = '.grc' + +##The default file extension for saving flow graph snap shots. +IMAGE_FILE_EXTENSION = '.png' + +##The default path for the open/save dialogs. +DEFAULT_FILE_PATH = os.getcwd() + +##The default icon for the gtk windows. +PY_GTK_ICON = os.path.join(DATA_DIR, 'grc-icon-256.png') + +##The users home directory. +HOME_DIR = os.path.expanduser('~') diff --git a/grc/src/platforms/base/Element.py b/grc/src/platforms/base/Element.py new file mode 100644 index 00000000..b6602a31 --- /dev/null +++ b/grc/src/platforms/base/Element.py @@ -0,0 +1,93 @@ +""" +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 +""" + +class Element(object): + + def __init__(self, parent=None): + self._parent = parent + self._error_messages = [] + self.flag() + + def test(self): + """ + Test the element against failures. + Overload this method in sub-classes. + """ + pass + + def validate(self): + """ + Validate the data in this element. + Set the error message non blank for errors. + Overload this method in sub-classes. + """ + pass + + def is_valid(self): + self._error_messages = []#reset err msgs + try: self.validate() + except: pass + return not self.get_error_messages() + + def _add_error_message(self, msg): + self._error_messages.append(msg) + + def get_error_messages(self): + return self._error_messages + + def get_parent(self): + return self._parent + + def _exit_with_error(self, error): + parent = self + #build hier list of elements + elements = list() + while(parent): + elements.insert(0, parent) + parent = parent.get_parent() + #build error string + err_str = ">>> Error:" + for i, element in enumerate(elements + [error]): + err_str = err_str + '\n' + ''.join(' '*(i+2)) + str(element) + err_str = err_str + '\n' + exit(err_str) + + ############################################## + ## Update flagging + ############################################## + def is_flagged(self): return self._flag + def flag(self): + self._flag = True + if self.get_parent(): self.get_parent().flag() + def deflag(self): + self._flag = False + if self.get_parent(): self.get_parent().deflag() + + ############################################## + ## 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/src/platforms/base/FlowGraph.py b/grc/src/platforms/base/FlowGraph.py new file mode 100644 index 00000000..bb20c61d --- /dev/null +++ b/grc/src/platforms/base/FlowGraph.py @@ -0,0 +1,231 @@ +""" +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 ... import utils +from ... utils import odict +from Element import Element +from Block import Block +from Connection import Connection +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 + """ + #hold connections and blocks + self._elements = list() + #initialize + Element.__init__(self, platform) + #inital blank import + self.import_data({'flow_graph': {}}) + + def __str__(self): return 'FlowGraph - "%s"'%self.get_option('name') + + 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).evaluate() + + 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_elements(self): + """ + Get a list of all the elements. + Always ensure that the options block is in the list. + @return the element list + """ + if self._options_block not in self._elements: self._elements.append(self._options_block) + #ensure uniqueness of the elements list + element_set = set() + element_list = list() + for element in self._elements: + if element not in element_set: element_list.append(element) + element_set.add(element) + #store cleaned up list + self._elements = element_list + 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 + """ + self.flag() + 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 + """ + self.flag() + connection = self.get_parent().Connection(self, porta, 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. + """ + self.flag() + 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(lambda c: self.remove_element(c), port.get_connections()) + #remove a connection + elif element.is_connection(): pass + self.get_elements().remove(element) + + def evaluate(self, expr): + """ + Evaluate the expression. + @param expr the string expression + @throw NotImplementedError + """ + raise NotImplementedError + + def validate(self): + """ + Validate the flow graph. + All connections and blocks must be valid. + """ + for c in self.get_elements(): + try: assert(c.is_valid()) + except AssertionError: self._add_error_message('Element "%s" is not valid.'%c) + + ############################################## + ## 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 {'flow_graph': n} + + def import_data(self, n): + """ + 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() + #the flow graph tag must exists, or use blank data + if 'flow_graph' in n.keys(): fg_n = n['flow_graph'] + else: + Messages.send_error_load('Flow graph data not found, loading blank flow graph.') + fg_n = {} + blocks_n = utils.listify(fg_n, 'block') + connections_n = utils.listify(fg_n, 'connection') + #create option block + self._options_block = self.get_parent().get_new_block(self, 'options') + self._options_block.get_param('id').set_value('options') + #build the blocks + for block_n in blocks_n: + key = block_n['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: + #test that the data tags exist + try: + assert('source_block_id' in connection_n.keys()) + assert('sink_block_id' in connection_n.keys()) + assert('source_key' in connection_n.keys()) + assert('sink_key' in connection_n.keys()) + except AssertionError: continue + #try to make the connection + try: + #get the block ids + source_block_id = connection_n['source_block_id'] + sink_block_id = connection_n['sink_block_id'] + #get the port keys + source_key = connection_n['source_key'] + sink_key = connection_n['sink_key'] + #verify the blocks + block_ids = map(lambda b: b.get_id(), self.get_blocks()) + assert(source_block_id in block_ids) + assert(sink_block_id in block_ids) + #get the blocks + source_block = self.get_block(source_block_id) + sink_block = self.get_block(sink_block_id) + #verify the ports + assert(source_key in source_block.get_source_keys()) + assert(sink_key in sink_block.get_sink_keys()) + #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 AssertionError: Messages.send_error_load('Connection between %s(%s) and %s(%s) could not be made.'%(source_block_id, source_key, sink_block_id, sink_key)) + self.validate() diff --git a/grc/src/platforms/base/Makefile.am b/grc/src/platforms/base/Makefile.am new file mode 100644 index 00000000..dca53b8b --- /dev/null +++ b/grc/src/platforms/base/Makefile.am @@ -0,0 +1,47 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +ourpythondir = $(grc_src_prefix)/platforms/base + +ourpython_PYTHON = \ + Block.py \ + Connection.py \ + Constants.py \ + Element.py \ + FlowGraph.py \ + Param.py \ + Platform.py \ + Port.py \ + __init__.py + +BUILT_SOURCES = Constants.py + +Constants.py: Makefile $(srcdir)/Constants.py.in + sed \ + -e 's|@VERSION[@]|$(VERSION)|g' \ + -e 's|@datadir[@]|$(grc_base_data_dir)|g' \ + $(srcdir)/Constants.py.in > $@ + +EXTRA_DIST = Constants.py.in + +MOSTLYCLEANFILES = $(BUILT_SOURCES) diff --git a/grc/src/platforms/base/Param.py b/grc/src/platforms/base/Param.py new file mode 100644 index 00000000..3a8d98c3 --- /dev/null +++ b/grc/src/platforms/base/Param.py @@ -0,0 +1,218 @@ +""" +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 ... import utils +from ... utils import odict +from Element import Element + +class Option(Element): + + def __init__(self, param, name, key, opts): + Element.__init__(self, param) + self._name = name + self._key = key + self._opts = dict() + for opt in opts: + #separate the key:value + try: key, value = opt.split(':') + except: self._exit_with_error('Error separating "%s" into key:value'%opt) + #test against repeated keys + try: assert(not self._opts.has_key(key)) + except AssertionError: self._exit_with_error('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() + + ############################################## + ## Static Make Methods + ############################################## + def make_option_from_n(param, n): + """ + Make a new option from nested data. + @param param the parent element + @param n the nested odict + @return a new option + """ + #grab the data + name = n['name'] + key = n['key'] + opts = utils.listify(n, 'opt') + #build the option + return Option( + param=param, + name=name, + key=key, + opts=opts, + ) + make_option_from_n = staticmethod(make_option_from_n) + +class Param(Element): + + ##possible param types + TYPES = ['enum', 'raw'] + + def __init__(self, block, n): + """ + Make a new param from nested data. + @param block the parent element + @param n the nested odict + @return a new param + """ + #grab the data + name = n['name'] + key = n['key'] + value = utils.exists_or_else(n, 'value', '') + type = n['type'] + hide = utils.exists_or_else(n, 'hide', '') + options = utils.listify(n, 'option') + #build the param + Element.__init__(self, block) + self._name = name + self._key = key + self._type = type + self._hide = hide + #create the Option objects from the n data + self._options = odict() + for option in map(lambda o: Option.make_option_from_n(self, o), options): + key = option.get_key() + #test against repeated keys + try: assert(key not in self.get_option_keys()) + except AssertionError: self._exit_with_error('Key "%s" already exists in options'%key) + #store the option + self._options[key] = option + #test the enum options + if self._options or self.is_enum(): + #test against bad combos of type and enum + try: assert(self._options) + except AssertionError: self._exit_with_error('At least one option must exist when type "enum" is set.') + try: assert(self.is_enum()) + except AssertionError: self._exit_with_error('Type "enum" must be set when options are present.') + #test against options with identical keys + try: assert(len(set(self.get_option_keys())) == len(self._options)) + except AssertionError: self._exit_with_error('Options keys "%s" are not unique.'%self.get_option_keys()) + #test against inconsistent keys in options + opt_keys = self._options.values()[0].get_opt_keys() + for option in self._options.values(): + try: assert(set(opt_keys) == set(option.get_opt_keys())) + except AssertionError: self._exit_with_error('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 or self.get_option_keys()[0] + try: assert(self.get_value() in self.get_option_keys()) + except AssertionError: self._exit_with_error('The value "%s" is not in the possible values of "%s".'%(self.get_value(), self.get_option_keys())) + else: self._value = value or '' + + def test(self): + """ + call test on all children + """ + map(lambda c: c.test(), self.get_options()) + + def validate(self): + """ + Validate the param. + The value must be evaluated and type must a possible type. + """ + try: + assert(self.get_type() in self.TYPES) + try: self.evaluate() + except: + #if the evaluate failed but added no error messages, add the generic one below + if not self.get_error_messages(): + self._add_error_message('Value "%s" cannot be evaluated.'%self.get_value()) + except AssertionError: self._add_error_message('Type "%s" is not a possible type.'%self.get_type()) + + def evaluate(self): + """ + Evaluate the value of this param. + @throw NotImplementedError + """ + raise NotImplementedError + + def to_code(self): + """ + Convert the value to code. + @throw NotImplementedError + """ + raise NotImplementedError + + 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) + + 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.flag() + 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 is_type_dependent(self): return '$' in self._type + + ############################################## + # Access Options + ############################################## + def get_option_keys(self): return self._options.keys() + def get_option(self, key): return self._options[key] + def get_options(self): return self._options.values() + + ############################################## + # Access Opts + ############################################## + def get_opt_keys(self): return self._options[self.get_value()].get_opt_keys() + def get_opt(self, key): return self._options[self.get_value()].get_opt(key) + def get_opts(self): return self._options[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/src/platforms/base/Platform.py b/grc/src/platforms/base/Platform.py new file mode 100644 index 00000000..c25b4a05 --- /dev/null +++ b/grc/src/platforms/base/Platform.py @@ -0,0 +1,144 @@ +""" +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 os +from ... utils import ParseXML +from ... import utils +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 DATA_DIR + +class Platform(_Element): + + def __init__(self, name, key, block_paths, block_dtd, block_tree, default_flow_graph, generator): + """ + Make a platform from the arguments. + @param name the platform name + @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 block_tree the nested tree of block keys and categories + @param default_flow_graph the default flow graph file path + @param load_one a single file to load into this platform or None + @return a platform object + """ + _Element.__init__(self) + self._name = name + self._key = key + self._block_paths = block_paths + self._block_dtd = block_dtd + self._block_tree = block_tree + self._default_flow_graph = default_flow_graph + self._generator = generator + #create a dummy flow graph for the blocks + self._flow_graph = _Element(self) + #load the blocks + self._blocks = dict() + self._blocks_n = dict() + for block_path in self._block_paths: + if os.path.isfile(block_path): self._load_block(block_path) + elif os.path.isdir(block_path): + for dirpath, dirnames, filenames in os.walk(block_path): + for filename in filter(lambda f: f.endswith('.xml'), filenames): + self._load_block(os.path.join(dirpath, filename)) + + def get_prefs_block(self): return self.get_new_flow_graph().get_new_block('preferences') + + def _load_block(self, f): + """ + Load the block wrapper from the file path. + The block wrapper must pass validation, and have a unique block key. + If any of the checks fail, exit with error. + @param f the file path + """ + try: ParseXML.validate_dtd(f, self._block_dtd) + except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block definition "%s" failed: \n\t%s'%(f, e)) + n = ParseXML.from_file(f)['block'] + block = self.Block(self._flow_graph, n) + key = block.get_key() + #test against repeated keys + try: assert(key not in self.get_block_keys()) + except AssertionError: self._exit_with_error('Key "%s" already exists in blocks'%key) + #store the block + self._blocks[key] = block + self._blocks_n[key] = n + + 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 = '%s/%s'%(parent, cat_n['name']) + block_tree.add_block(parent) + #recursive call to load sub categories + map(lambda c: load_category(c, parent), utils.listify(cat_n, 'cat')) + #add blocks in this category + for block_key in utils.listify(cat_n, 'block'): + block_tree.add_block(parent, self.get_block(block_key)) + #load the block tree + f = self._block_tree + try: ParseXML.validate_dtd(f, os.path.join(DATA_DIR, 'block_tree.dtd')) + except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block tree "%s" failed: \n\t%s'%(f, e)) + #add all blocks in the tree + load_category(ParseXML.from_file(f)['cat']) + #add all other blocks, use the catgory + for block in self.get_blocks(): + #blocks with empty categories are in the xml block tree or hidden + if block.get_category(): 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(self) + + def get_default_flow_graph(self): return self._default_flow_graph + + 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_key(self): return self._key + + ############################################## + # Constructors + ############################################## + FlowGraph = _FlowGraph + Connection = _Connection + Block = _Block + Source = _Port + Sink = _Port + Param = _Param diff --git a/grc/src/platforms/base/Port.py b/grc/src/platforms/base/Port.py new file mode 100644 index 00000000..61134791 --- /dev/null +++ b/grc/src/platforms/base/Port.py @@ -0,0 +1,106 @@ +""" +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 ... import utils +from Element import Element + +class Port(Element): + + ##possible port types + TYPES = [] + + def __init__(self, block, n): + """ + Make a new port from nested data. + @param block the parent element + @param n the nested odict + @return a new port + """ + #grab the data + name = n['name'] + key = n['key'] + type = n['type'] + #build the port + Element.__init__(self, block) + self._name = name + self._key = key + self._type = type + + def validate(self): + """ + Validate the port. + The port must be non-empty and type must a possible type. + """ + try: assert(not self.is_empty()) + except AssertionError: self._add_error_message('is empty.') + try: assert(self.get_type() in self.TYPES) + except AssertionError: 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 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 in self.get_parent().get_sinks() + + def is_source(self): return self in self.get_parent().get_sources() + + 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 is_connected(self): + """ + Is this port connected? + @return true if at least one connection + """ + return bool(self.get_connections()) + + def is_full(self): + """ + Is this port full of connections? + Generally a sink can handle one connection and a source can handle many. + @return true if the port is full + """ + if self.is_source(): return False + if self.is_sink(): return bool(self.get_connections()) + + def is_empty(self): + """ + Is this port empty? + An empty port has no connections. + @return true if empty + """ + return not self.get_connections() diff --git a/grc/src/platforms/base/__init__.py b/grc/src/platforms/base/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/grc/src/platforms/base/__init__.py @@ -0,0 +1 @@ + diff --git a/grc/src/platforms/gui/Block.py b/grc/src/platforms/gui/Block.py new file mode 100644 index 00000000..d38e1713 --- /dev/null +++ b/grc/src/platforms/gui/Block.py @@ -0,0 +1,196 @@ +""" +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 +""" + +from ... gui import Preferences +from Element import Element +import Utils +import Colors +from ... gui.Constants import BORDER_PROXIMITY_SENSITIVITY +from Constants import \ + BLOCK_FONT, LABEL_PADDING_WIDTH, \ + LABEL_PADDING_HEIGHT, PORT_HEIGHT, \ + PORT_SEPARATION, LABEL_SEPARATION, \ + PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS +import pygtk +pygtk.require('2.0') +import gtk +import pango + +class Block(Element): + """The graphical signal block.""" + + def __init__(self, *args, **kwargs): + """ + Block contructor. + Add graphics related params to the block. + """ + #add the position param + self._params['_coordinate'] = self.get_parent().get_parent().Param( + self, + { + 'name': 'GUI Coordinate', + 'key': '_coordinate', + 'type': 'raw', + 'value': '(0, 0)', + 'hide': 'all', + } + ) + self._params['_rotation'] = self.get_parent().get_parent().Param( + self, + { + '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 update(self): + """Update the block, parameters, and ports when a change occurs.""" + self.bg_color = self.get_enabled() and Colors.BG_COLOR or Colors.DISABLED_BG_COLOR + self.clear() + self._create_labels() + self.W = self.label_width + 2*LABEL_PADDING_WIDTH + max_ports = max(len(self.get_sinks()), len(self.get_sources()), 1) + self.H = max(self.label_height+2*LABEL_PADDING_HEIGHT, 2*PORT_BORDER_SEPARATION + max_ports*PORT_HEIGHT + (max_ports-1)*PORT_SEPARATION) + 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)) + map(lambda p: p.update(), self.get_sinks() + self.get_sources()) + + def _create_labels(self): + """Create the labels for the signal block.""" + layouts = list() + #create the main layout + layout = gtk.DrawingArea().create_pango_layout('') + layouts.append(layout) + if self.is_valid(): layout.set_markup(''+Utils.xml_encode(self.get_name())+'') + else: layout.set_markup(''+Utils.xml_encode(self.get_name())+'') + desc = pango.FontDescription(BLOCK_FONT) + layout.set_font_description(desc) + self.label_width, self.label_height = layout.get_pixel_size() + #display the params (except for the special params id and position) + if Preferences.show_params(): + for param in filter(lambda p: p.get_hide() not in ('all', 'part'), self.get_params()): + if not Preferences.show_id() and param.get_key() == 'id': continue + layout = param.get_layout() + layouts.append(layout) + w,h = layout.get_pixel_size() + self.label_width = max(w, self.label_width) + self.label_height = self.label_height + h + LABEL_SEPARATION + width = self.label_width + height = self.label_height + #setup the pixmap + pixmap = gtk.gdk.Pixmap(self.get_parent().get_window(), width, height, -1) + gc = pixmap.new_gc() + gc.foreground = self.bg_color + pixmap.draw_rectangle(gc, True, 0, 0, width, height) + gc.foreground = Colors.TXT_COLOR + #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 images + self.horizontal_label = image = pixmap.get_image(0, 0, width, height) + if self.is_vertical(): + self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), height, width) + for i in range(width): + for j in range(height): vimage.put_pixel(j, width-i-1, image.get_pixel(i, j)) + + def draw(self, window): + """ + Draw the signal block with label and inputs/outputs. + @param window the gtk window to draw on + """ + x, y = self.get_coordinate() + #draw main block + Element.draw(self, window, BG_color=self.bg_color) + #draw label image + gc = self.get_gc() + if self.is_horizontal(): + window.draw_image(gc, self.horizontal_label, 0, 0, x+LABEL_PADDING_WIDTH, y+(self.H-self.label_height)/2, -1, -1) + elif self.is_vertical(): + window.draw_image(gc, self.vertical_label, 0, 0, x+(self.H-self.label_height)/2, y+LABEL_PADDING_WIDTH, -1, -1) + #draw ports + map(lambda p: p.draw(window), self.get_ports()) + + 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/src/platforms/gui/Colors.py b/grc/src/platforms/gui/Colors.py new file mode 100644 index 00000000..353cd1c9 --- /dev/null +++ b/grc/src/platforms/gui/Colors.py @@ -0,0 +1,34 @@ +""" +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) + +BACKGROUND_COLOR = get_color('#FFF9FF') #main window background +FG_COLOR = get_color('black') #normal border color +BG_COLOR = get_color('#F1ECFF') #default background +DISABLED_BG_COLOR = get_color('#CCCCCC') #disabled background +DISABLED_FG_COLOR = get_color('#999999') #disabled foreground +H_COLOR = get_color('#00FFFF') #Highlight border color +TXT_COLOR = get_color('black') #text color +ERROR_COLOR = get_color('red') #error color diff --git a/grc/src/platforms/gui/Connection.py b/grc/src/platforms/gui/Connection.py new file mode 100644 index 00000000..44048e18 --- /dev/null +++ b/grc/src/platforms/gui/Connection.py @@ -0,0 +1,129 @@ +""" +Copyright 2007, 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 Utils +from Element import Element +import Colors +from Constants import CONNECTOR_ARROW_BASE, CONNECTOR_ARROW_HEIGHT + +class Connection(Element): + """A graphical connection for ports.""" + + 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 update(self): + """Precalculate relative coordinates.""" + 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() + + def _update_after_move(self): + """Calculate coordinates.""" + self.clear() + #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, window): + """ + Draw the connection. + @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.update() + 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 + fg_color = self.get_enabled() and Colors.FG_COLOR or Colors.DISABLED_FG_COLOR + Element.draw(self, window, FG_color=fg_color) + gc = self.get_gc() + if self.is_valid(): gc.foreground = Colors.FG_COLOR + else: gc.foreground = Colors.ERROR_COLOR + #draw arrow on sink port + window.draw_polygon(gc, True, self._arrow) diff --git a/grc/src/platforms/gui/Constants.py b/grc/src/platforms/gui/Constants.py new file mode 100644 index 00000000..b2e9bfed --- /dev/null +++ b/grc/src/platforms/gui/Constants.py @@ -0,0 +1,44 @@ +# +# 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. +# + +#label constraint dimensions +LABEL_SEPARATION = 3 +LABEL_PADDING_WIDTH = 9 +LABEL_PADDING_HEIGHT = 9 +#port constraint dimensions +PORT_SEPARATION = 17 +PORT_HEIGHT = 15 +PORT_WIDTH = 25 +PORT_BORDER_SEPARATION = 9 +#fonts +PARAM_LABEL_FONT = 'Sans 9.5' +PARAM_FONT = 'Sans 7.5' +BLOCK_FONT = 'Sans 8' +PORT_FONT = 'Sans 7.5' +#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) diff --git a/grc/src/platforms/gui/Element.py b/grc/src/platforms/gui/Element.py new file mode 100644 index 00000000..f97d85ff --- /dev/null +++ b/grc/src/platforms/gui/Element.py @@ -0,0 +1,229 @@ +""" +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 Colors +import pygtk +pygtk.require('2.0') +import gtk +import pango +from ... gui.Constants import CONNECTION_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, *args, **kwargs): + """ + 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 get_gc(self): return self._gc + + def draw(self, window, BG_color=Colors.BG_COLOR, FG_color=Colors.FG_COLOR): + """ + Draw in the given window. + @param window the gtk window to draw on + @param BG_color the background color + @param FG_color the foreground color + """ + gc = self.get_parent().get_gc() + self._gc = gc + X,Y = self.get_coordinate() + for (rX,rY),(W,H) in self.areas_dict[self.get_rotation()]: + aX = X + rX + aY = Y + rY + gc.foreground = BG_color + window.draw_rectangle(gc, True, aX, aY, W, H) + gc.foreground = self.is_highlighted() and Colors.H_COLOR or FG_color + window.draw_rectangle(gc, False, aX, aY, W, H) + for (x1, y1),(x2, y2) in self.lines_dict[self.get_rotation()]: + gc.foreground = self.is_highlighted() and Colors.H_COLOR or FG_color + window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2) + + def rotate(self, direction): + """ + Rotate all of the areas by 90 degrees. + @param direction 90 or 270 degrees + """ + self.set_rotation((self.get_rotation() + direction)%360) + + def clear(self): + """Empty the lines and areas.""" + self.areas_dict = dict((rotation, list()) for rotation in POSSIBLE_ROTATIONS) + self.lines_dict = dict((rotation, list()) for rotation in POSSIBLE_ROTATIONS) + + 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, rotation=None): + """ + 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. + If rotation is not specified, the element's current rotation is used. + @param rel_coor (x,y) offset from this element's coordinate + @param area (width,height) tuple + @param rotation rotation in degrees + """ + self.areas_dict[rotation or self.get_rotation()].append((rel_coor, area)) + + def add_line(self, rel_coor1, rel_coor2, rotation=None): + """ + 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. + If rotation is not specified, the element's current rotation is used. + @param rel_coor1 relative (x1,y1) tuple + @param rel_coor2 relative (x2,y2) tuple + @param rotation rotation in degrees + """ + self.lines_dict[rotation or self.get_rotation()].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_dict[self.get_rotation()]: + 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_dict[self.get_rotation()]: + 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_dict[self.get_rotation()]: + 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_dict[self.get_rotation()]: + if x1 == x2: x1, x2 = x1-CONNECTION_SELECT_SENSITIVITY, x2+CONNECTION_SELECT_SENSITIVITY + if y1 == y2: y1, y2 = y1-CONNECTION_SELECT_SENSITIVITY, y2+CONNECTION_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 + + def update(self): + """Do nothing for the update. Dummy method.""" + pass diff --git a/grc/src/platforms/gui/FlowGraph.py b/grc/src/platforms/gui/FlowGraph.py new file mode 100644 index 00000000..1e654e1b --- /dev/null +++ b/grc/src/platforms/gui/FlowGraph.py @@ -0,0 +1,563 @@ +""" +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 +""" + +from ... gui import Preferences +from ... gui.Constants import \ + DIR_LEFT, DIR_RIGHT, \ + SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE, \ + MOTION_DETECT_REDRAWING_SENSITIVITY +from ... gui.Actions import \ + ELEMENT_CREATE, ELEMENT_SELECT, \ + BLOCK_PARAM_MODIFY, BLOCK_MOVE +import Colors +import Utils +from ... gui.ParamsDialog import ParamsDialog +from Element import Element +from .. base import FlowGraph as _FlowGraph +import pygtk +pygtk.require('2.0') +import gtk +import random +import time +from ... gui 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, *args, **kwargs): + """ + 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.time = 0 + self.press_coor = (0, 0) + #selected ports + self._old_selected_port = None + self._new_selected_port = None + + 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 = -1 + while True: + id = (index < 0) and base_id or '%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 + +########################################################################### +# Access Drawing Area +########################################################################### + def get_drawing_area(self): return self.drawing_area + def get_gc(self): return self.get_drawing_area().gc + def get_pixmap(self): return self.get_drawing_area().pixmap + 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_window(self): return self.get_drawing_area().window + def get_scroll_pane(self): return self.drawing_area.get_parent() + def get_ctrl_mask(self): return self.drawing_area.ctrl_mask + + def add_new_block(self, key): + """ + Add a block of the given key to this flow graph. + @param key the block key + """ + 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() + x = int(random.uniform(.25, .75)*h_adj.page_size + h_adj.get_value()) + y = 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((x, y)) + block.set_rotation(0) + block.get_param('id').set_value(id) + self.handle_states(ELEMENT_CREATE) + + ########################################################################### + # 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['key'] + if block_key == 'options': continue + block_id = self._get_unique_id(block_key) + block = self.get_new_block(block_key) + selected.add(block) + #set params + params_n = Utils.listify(block_n, 'param') + for param_n in params_n: + param_key = param_n['key'] + param_value = param_n['value'] + #setup id parameter + if param_key == 'id': + old_id2block[param_value] = block + param_value = block_id + #set value to key + block.get_param(param_key).set_value(param_value) + #move block to offset coordinate + block.move((x_off, y_off)) + #create connections + for connection_n in connections_n: + source = old_id2block[connection_n['source_block_id']].get_source(connection_n['source_key']) + sink = old_id2block[connection_n['sink_block_id']].get_sink(connection_n['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 + """ + changed = False + for selected_block in self.get_selected_blocks(): + for child in selected_block.get_params() + selected_block.get_ports(): + #find a param that controls a type + type_param = None + for param in selected_block.get_params(): + if not type_param and param.is_enum(): type_param = param + if param.is_enum() and param.get_key() in child._type: 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_selected(self, direction): + """ + Change port controller for the selected signal blocks. + @param direction +1 or -1 + @return true for changed + """ + changed = False + for selected_block in self.get_selected_blocks(): + for ports in (selected_block.get_sources(), selected_block.get_sinks()): + if ports and hasattr(ports[0], 'get_nports') and ports[0].get_nports(): + #find the param that controls port0 + for param in selected_block.get_params(): + if param.get_key() in ports[0]._nports: + #try to increment the port controller by direction + try: + value = param.evaluate() + value = value + direction + assert 0 < value + param.set_value(value) + changed = True + except: pass + return changed + + def param_modify_selected(self): + """ + Create and show a param modification dialog for the selected block. + @return true if parameters were changed + """ + if self.get_selected_block(): + signal_block_params_dialog = ParamsDialog(self.get_selected_block()) + return signal_block_params_dialog.run() + return False + + 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, direction): + """ + Rotate the selected blocks by 90 degrees. + @param direction DIR_LEFT or DIR_RIGHT + @return true if changed, otherwise false. + """ + if not self.get_selected_blocks(): return False + #determine the number of degrees to rotate + rotation = {DIR_LEFT: 90, DIR_RIGHT:270}[direction] + #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): + """ + 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. + """ + if self.get_gc(): + W,H = self.get_size() + #draw the background + self.get_gc().foreground = Colors.BACKGROUND_COLOR + self.get_pixmap().draw_rectangle(self.get_gc(), True, 0, 0, W, H) + #draw grid (depends on prefs) + if Preferences.show_grid(): + grid_size = Preferences.get_grid_size() + points = list() + for i in range(W/grid_size): + for j in range(H/grid_size): + points.append((i*grid_size, j*grid_size)) + self.get_gc().foreground = Colors.TXT_COLOR + self.get_pixmap().draw_points(self.get_gc(), points) + #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 + self.get_gc().foreground = Colors.H_COLOR + self.get_pixmap().draw_rectangle(self.get_gc(), True, x, y, w, h) + self.get_gc().foreground = Colors.TXT_COLOR + self.get_pixmap().draw_rectangle(self.get_gc(), False, x, y, w, h) + #draw blocks on top of connections + for element in self.get_connections() + self.get_blocks(): + element.draw(self.get_pixmap()) + #draw selected blocks on top of selected connections + for selected_element in self.get_selected_connections() + self.get_selected_blocks(): + selected_element.draw(self.get_pixmap()) + self.get_drawing_area().draw() + + def update(self): + """ + Update highlighting so only the selected is highlighted. + Call update on all elements. + Resize the window if size changed. + """ + #update highlighting + map(lambda e: e.set_highlighted(False), self.get_elements()) + for selected_element in self.get_selected_elements(): + selected_element.set_highlighted(True) + #update all elements + map(lambda e: e.update(), self.get_elements()) + #set the size of the flow graph area + old_x, old_y = self.get_size() + try: new_x, new_y = self.get_option('window_size') + except: new_x, new_y = old_x, old_y + if new_x != old_x or new_y != old_y: self.set_size(new_x, new_y) + + ########################################################################## + ## 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 backwardssince 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) + #single select mode, break + if not coor_m: + self.get_elements().remove(element) + self.get_elements().append(element) + 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_selection = 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_selection and new_selection[0] in self.get_selected_elements() + ): selected_elements = new_selection + 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) + self.handle_states(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) + ) + self.handle_states(ELEMENT_SELECT) + + ########################################################################## + ## Event Handlers + ########################################################################## + def handle_mouse_button_press(self, left_click, double_click, coordinate): + """ + A mouse button is pressed, only respond to left clicks. + 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. + """ + if not left_click: return + self.press_coor = coordinate + self.set_coordinate(coordinate) + self.time = 0 + self.mouse_pressed = True + 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 + self.handle_states(BLOCK_PARAM_MODIFY) + + def handle_mouse_button_release(self, left_click, coordinate): + """ + A mouse button is released, record the state. + """ + if not left_click: return + self.set_coordinate(coordinate) + self.time = 0 + self.mouse_pressed = False + if self.element_moved: + if Preferences.snap_to_grid(): + grid_size = Preferences.get_grid_size() + X,Y = self.get_selected_element().get_coordinate() + deltaX = X%grid_size + if deltaX < grid_size/2: deltaX = -1 * deltaX + else: deltaX = grid_size - deltaX + deltaY = Y%grid_size + if deltaY < grid_size/2: deltaY = -1 * deltaY + else: deltaY = grid_size - deltaY + self.move_selected((deltaX, deltaY)) + self.handle_states(BLOCK_MOVE) + self.element_moved = False + self.update_selected_elements() + self.draw() + + 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, timediff large enough + if not self.mouse_pressed: return + if time.time() - self.time < MOTION_DETECT_REDRAWING_SENSITIVITY: 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') + #move the selected element 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.draw() + self.set_coordinate((x, y)) + #update time + self.time = time.time() diff --git a/grc/src/platforms/gui/Makefile.am b/grc/src/platforms/gui/Makefile.am new file mode 100644 index 00000000..2e3972ef --- /dev/null +++ b/grc/src/platforms/gui/Makefile.am @@ -0,0 +1,37 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +ourpythondir = $(grc_src_prefix)/platforms/gui + +ourpython_PYTHON = \ + Block.py \ + Colors.py \ + Constants.py \ + Connection.py \ + Element.py \ + FlowGraph.py \ + Param.py \ + Platform.py \ + Port.py \ + Utils.py \ + __init__.py diff --git a/grc/src/platforms/gui/Param.py b/grc/src/platforms/gui/Param.py new file mode 100644 index 00000000..f45d80bb --- /dev/null +++ b/grc/src/platforms/gui/Param.py @@ -0,0 +1,221 @@ +""" +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 Utils +from Element import Element +import pygtk +pygtk.require('2.0') +import gtk +import pango +import gobject +from Constants import PARAM_LABEL_FONT, PARAM_FONT +from os import path + +###################################################################################################### +# gtk objects for handling input +###################################################################################################### + +class InputParam(gtk.HBox): + """The base class for an input parameter inside the input parameters dialog.""" + + def __init__(self, param, _handle_changed): + gtk.HBox.__init__(self) + self.param = param + self._handle_changed = _handle_changed + 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 + +class EntryParam(InputParam): + """Provide an entry box for strings and numbers.""" + + def __init__(self, *args, **kwargs): + InputParam.__init__(self, *args, **kwargs) + self.entry = input = gtk.Entry() + input.set_text(self.param.get_value()) + input.connect('changed', self._handle_changed) + self.pack_start(input, True) + self.get_text = input.get_text + #tool tip + self.tp = gtk.Tooltips() + self.tp.set_tip(self.entry, '') + self.tp.enable() + +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. + """ + file_path = self.param.is_valid() and self.param.evaluate() or '' + #bad file paths will be redirected to default + if not path.exists(path.dirname(file_path)): file_path = DEFAULT_FILE_PATH + 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(path.basename(file_path)) #show the current filename + file_dialog.set_current_folder(path.dirname(file_path)) #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.entry.set_text(file_path) + self._handle_changed() + file_dialog.destroy() #destroy the dialog + +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) + input = gtk.ComboBox(gtk.ListStore(gobject.TYPE_STRING)) + cell = gtk.CellRendererText() + input.pack_start(cell, True) + input.add_attribute(cell, 'text', 0) + for option in self.param.get_options(): input.append_text(option.get_name()) + input.set_active(int(self.param.get_option_keys().index(self.param.get_value()))) + input.connect("changed", self._handle_changed) + self.pack_start(input, False) + self.get_text = lambda: str(input.get_active()) #the get text parses the selected index to a string + +###################################################################################################### +# A Flow Graph Parameter +###################################################################################################### + +class Param(Element): + """The graphical parameter.""" + + def update(self): + """ + Called when an external change occurs. + Update the graphical input by calling the change handler. + """ + if hasattr(self, 'input'): self._handle_changed() + + def get_input_object(self, callback=None): + """ + Get the graphical gtk class to represent this parameter. + Create the input object with this data type and the handle changed method. + @param callback a function of one argument(this param) to be called from the change handler + @return gtk input object + """ + self.callback = callback + if self.is_enum(): input = EnumParam + elif self.get_type() in ('file_open', 'file_save'): input = FileParam + else: input = EntryParam + self.input = input(self, self._handle_changed) + if not callback: self.update() + return self.input + + def _handle_changed(self, widget=None): + """ + When the input changes, write the inputs to the data type. + Finish by calling the exteral callback. + """ + value = self.input.get_text() + if self.is_enum(): value = self.get_option_keys()[int(value)] + self.set_value(value) + #set the markup on the label, red for errors in corresponding data type. + name = '%s'%(PARAM_LABEL_FONT, Utils.xml_encode(self.get_name())) + #special markups if param is involved in a callback + if hasattr(self.get_parent(), 'get_callbacks') and \ + filter(lambda c: self.get_key() in c, self.get_parent()._callbacks): + name = '%s'%name + if not self.is_valid(): + self.input.set_markup('%s'%name) + tip = '- ' + '\n- '.join(self.get_error_messages()) + else: + self.input.set_markup(name) + tip = self.evaluate() + #hide/show + if self.get_hide() == 'all': self.input.hide_all() + else: self.input.show_all() + #set the tooltip + if self.input.tp: self.input.tp.set_tip(self.input.entry, str(tip)) + #execute the external callback + if self.callback: self.callback(self) + + def get_markup(self): + """ + Create a markup to display the Param as a label on the SignalBlock. + If the data type is an Enum type, use the cname of the Enum's current choice. + Otherwise, use parsed the data type and use its string representation. + If the data type is not valid, use a red foreground color. + @return pango markup string + """ + ########################################################################### + # display logic for numbers + ########################################################################### + def float_to_str(var): + if var-int(var) == 0: return '%d'%int(var) + if var*10-int(var*10) == 0: return '%.1f'%var + if var*100-int(var*100) == 0: return '%.2f'%var + if var*1000-int(var*1000) == 0: return '%.3f'%var + else: return '%.3g'%var + def to_str(var): + if isinstance(var, str): return var + elif isinstance(var, complex): + if var.imag == var.real == 0: return '0' #value is zero + elif var.imag == 0: return '%s'%float_to_str(var.real) #value is real + elif var.real == 0: return '%sj'%float_to_str(var.imag) #value is imaginary + elif var.imag < 0: return '%s-%sj'%(float_to_str(var.real), float_to_str(var.imag*-1)) + else: return '%s+%sj'%(float_to_str(var.real), float_to_str(var.imag)) + elif isinstance(var, float): return float_to_str(var) + elif isinstance(var, int): return '%d'%var + else: return str(var) + ########################################################################### + if self.is_valid(): + data = self.evaluate() + t = self.get_type() + if self.is_enum(): + dt_str = self.get_option(self.get_value()).get_name() + elif isinstance(data, (list, tuple, set)): #vector types + dt_str = ', '.join(map(to_str, data)) + else: dt_str = to_str(data) #other types + #truncate + max_len = max(42 - len(self.get_name()), 3) + if len(dt_str) > max_len: + dt_str = dt_str[:max_len-3] + '...' + return '%s: %s'%(Utils.xml_encode(self.get_name()), Utils.xml_encode(dt_str)) + else: return '%s: error'%Utils.xml_encode(self.get_name()) + + def get_layout(self): + """ + Create a layout based on the current markup. + @return the pango layout + """ + layout = gtk.DrawingArea().create_pango_layout('') + layout.set_markup(self.get_markup()) + desc = pango.FontDescription(PARAM_FONT) + layout.set_font_description(desc) + return layout diff --git a/grc/src/platforms/gui/Platform.py b/grc/src/platforms/gui/Platform.py new file mode 100644 index 00000000..a32b0209 --- /dev/null +++ b/grc/src/platforms/gui/Platform.py @@ -0,0 +1,48 @@ +""" +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 FlowGraph import FlowGraph +from Connection import Connection +from Block import Block +from Port import Port +from Param import Param + +def conjoin_classes(name, c1, c2): + exec(""" +class %s(c1, c2): + def __init__(self, *args, **kwargs): + c1.__init__(self, *args, **kwargs) + c2.__init__(self, *args, **kwargs) +"""%name, locals()) + return locals()[name] + +def Platform(platform): + #combine with gui class + for attr, value in ( + ('FlowGraph', FlowGraph), + ('Connection', Connection), + ('Block', Block), + ('Source', Port), + ('Sink', Port), + ('Param', Param), + ): + old_value = getattr(platform, attr) + c = conjoin_classes(attr, old_value, value) + setattr(platform, attr, c) + return platform diff --git a/grc/src/platforms/gui/Port.py b/grc/src/platforms/gui/Port.py new file mode 100644 index 00000000..aeab85ea --- /dev/null +++ b/grc/src/platforms/gui/Port.py @@ -0,0 +1,185 @@ +""" +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 +""" + +from Element import Element +from Constants import \ + PORT_HEIGHT, PORT_SEPARATION, \ + PORT_WIDTH, CONNECTOR_EXTENSION_MINIMAL, \ + CONNECTOR_EXTENSION_INCREMENT, PORT_FONT +import Colors +import pygtk +pygtk.require('2.0') +import gtk +import pango + +class Port(Element): + """The graphical port.""" + + def __init__(self, *args, **kwargs): + """ + Port contructor. + Create list of connector coordinates. + """ + Element.__init__(self) + self.connector_coordinates = dict() + + def update(self): + """Create new areas and labels for the port.""" + self.clear() + self.BG_color = Colors.get_color(self.get_color()) + self._create_labels() + #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 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*PORT_HEIGHT - (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*PORT_WIDTH + y = (PORT_SEPARATION+PORT_HEIGHT)*index+offset + self.add_area((x, y), (PORT_WIDTH, PORT_HEIGHT)) + self._connector_coordinate = (x-1, y+PORT_HEIGHT/2) + elif (self.is_source() and rotation == 0) or (self.is_sink() and rotation == 180): + x = self.get_parent().W + y = (PORT_SEPARATION+PORT_HEIGHT)*index+offset + self.add_area((x, y), (PORT_WIDTH, PORT_HEIGHT)) + self._connector_coordinate = (x+1+PORT_WIDTH, y+PORT_HEIGHT/2) + elif (self.is_source() and rotation == 90) or (self.is_sink() and rotation == 270): + y = -1*PORT_WIDTH + x = (PORT_SEPARATION+PORT_HEIGHT)*index+offset + self.add_area((x, y), (PORT_HEIGHT, PORT_WIDTH)) + self._connector_coordinate = (x+PORT_HEIGHT/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+PORT_HEIGHT)*index+offset + self.add_area((x, y), (PORT_HEIGHT, PORT_WIDTH)) + self._connector_coordinate = (x+PORT_HEIGHT/2, y+1+PORT_WIDTH) + #the connector length + self._connector_length = CONNECTOR_EXTENSION_MINIMAL + CONNECTOR_EXTENSION_INCREMENT*index + + def _create_labels(self): + """Create the labels for the socket.""" + #create the layout + layout = gtk.DrawingArea().create_pango_layout(self.get_name()) + desc = pango.FontDescription(PORT_FONT) + layout.set_font_description(desc) + w,h = self.w,self.h = layout.get_pixel_size() + #create the pixmap + pixmap = gtk.gdk.Pixmap(self.get_parent().get_parent().get_window(), w, h, -1) + gc = pixmap.new_gc() + gc.foreground = self.BG_color + pixmap.draw_rectangle(gc, True, 0, 0, w, h) + gc.foreground = Colors.TXT_COLOR + pixmap.draw_layout(gc, 0, 0, layout) + #create the images + self.horizontal_label = image = pixmap.get_image(0, 0, w, h) + if self.is_vertical(): + self.vertical_label = vimage = gtk.gdk.Image(gtk.gdk.IMAGE_NORMAL, pixmap.get_visual(), h, w) + for i in range(w): + for j in range(h): vimage.put_pixel(j, w-i-1, image.get_pixel(i, j)) + + def draw(self, window): + """ + Draw the socket with a label. + @param window the gtk window to draw on + """ + Element.draw(self, window, BG_color=self.BG_color) + gc = self.get_gc() + gc.foreground = Colors.TXT_COLOR + X,Y = self.get_coordinate() + (x,y),(w,h) = self.areas_dict[self.get_rotation()][0] #use the first area's sizes to place the labels + if self.is_horizontal(): + window.draw_image(gc, self.horizontal_label, 0, 0, x+X+(PORT_WIDTH-self.w)/2, y+Y+(PORT_HEIGHT-self.h)/2, -1, -1) + elif self.is_vertical(): + window.draw_image(gc, self.vertical_label, 0, 0, x+X+(PORT_HEIGHT-self.h)/2, y+Y+(PORT_WIDTH-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/src/platforms/gui/Utils.py b/grc/src/platforms/gui/Utils.py new file mode 100644 index 00000000..17750ef4 --- /dev/null +++ b/grc/src/platforms/gui/Utils.py @@ -0,0 +1,71 @@ +""" +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 Constants import POSSIBLE_ROTATIONS + +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 + assert rotation in POSSIBLE_ROTATIONS + #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 xml_encode(string): + """ + Encode a string into an xml safe string by replacing special characters. + Needed for gtk pango markup in labels. + @param string the input string + @return output string with safe characters + """ + string = str(string) + for char, safe in ( + ('&', '&'), + ('<', '<'), + ('>', '>'), + ('"', '"'), + ("'", '''), + ): string = string.replace(char, safe) + return string diff --git a/grc/src/platforms/gui/__init__.py b/grc/src/platforms/gui/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/grc/src/platforms/gui/__init__.py @@ -0,0 +1 @@ + diff --git a/grc/src/platforms/python/Block.py b/grc/src/platforms/python/Block.py new file mode 100644 index 00000000..655a6ec5 --- /dev/null +++ b/grc/src/platforms/python/Block.py @@ -0,0 +1,128 @@ +""" +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 .. base.Block import Block as _Block +from utils import extract_docs +from ... import utils + +class Block(_Block): + + ##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 + doc = utils.exists_or_else(n, 'doc', '') + imports = map(lambda i: i.strip(), utils.listify(n, 'import')) + make = n['make'] + checks = utils.listify(n, 'check') + callbacks = utils.listify(n, 'callback') + #build the block + _Block.__init__( + self, + flow_graph=flow_graph, + n=n, + ) + self._doc = doc + self._imports = imports + self._make = make + self._callbacks = callbacks + self._checks = checks + + def validate(self): + """ + Validate this block. + Call the base class validate. + Evaluate the checks: each check must evaluate to True. + Adjust the nports. + """ + _Block.validate(self) + #evaluate the checks + for check in self._checks: + check_res = self.resolve_dependencies(check) + try: + check_eval = self.get_parent().evaluate(check_res) + try: assert check_eval + except AssertionError: self._add_error_message('Check "%s" failed.'%check) + except: self._add_error_message('Check "%s" did not evaluate.'%check) + for ports, Port in ( + (self._sources, self.get_parent().get_parent().Source), + (self._sinks, self.get_parent().get_parent().Sink), + ): + #how many ports? + num_ports = len(ports) + #do nothing for 0 ports + if not num_ports: continue + #get the nports setting + port0 = ports[str(0)] + nports = port0.get_nports() + #do nothing for no nports + if not nports: continue + #do nothing if nports is already num ports + if nports == num_ports: continue + #remove excess ports and connections + if nports < num_ports: + #remove the connections + for key in map(str, range(nports, num_ports)): + port = ports[key] + for connection in port.get_connections(): + self.get_parent().remove_element(connection) + #remove the ports + for key in map(str, range(nports, num_ports)): ports.pop(key) + continue + #add more ports + if nports > num_ports: + for key in map(str, range(num_ports, nports)): + n = port0._n + n['key'] = key + port = Port(self, n) + ports[key] = port + continue + + 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_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_callbacks(self): + """ + Get a list of function callbacks for this block. + @return a list of strings + """ + return map(lambda c: self.get_id() + '.' + self.resolve_dependencies(c), self._callbacks) diff --git a/grc/src/platforms/python/Connection.py b/grc/src/platforms/python/Connection.py new file mode 100644 index 00000000..f742ff63 --- /dev/null +++ b/grc/src/platforms/python/Connection.py @@ -0,0 +1,34 @@ +""" +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 .. base.Connection import Connection as _Connection + +class Connection(_Connection): + + def validate(self): + """ + Validate the connections. + The ports must match in type and vector length. + """ + _Connection.validate(self) #checks type + #check vector length + source_vlen = self.get_source().get_vlen() + sink_vlen = self.get_sink().get_vlen() + try: assert(source_vlen == sink_vlen) + except AssertionError: self._add_error_message('Source vector length "%s" does not match sink vector length "%s".'%(source_vlen, sink_vlen)) diff --git a/grc/src/platforms/python/Constants.py.in b/grc/src/platforms/python/Constants.py.in new file mode 100644 index 00000000..c2d878ba --- /dev/null +++ b/grc/src/platforms/python/Constants.py.in @@ -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 os +import sys +import stat + +PYEXEC = '@PYTHONW@' + +#setup paths +DOCS_DIR = os.path.join('@docdir@', 'xml') +DATA_DIR = '@datadir@' +BLOCKS_DIR = '@blocksdir@' +HIER_BLOCKS_LIB_DIR = os.path.join(os.path.expanduser('~'), '.grc_gnuradio') + +#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 +FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl') +BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd') +BLOCK_TREE = os.path.join(DATA_DIR, 'block_tree.xml') +DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc.xml') diff --git a/grc/src/platforms/python/FlowGraph.py b/grc/src/platforms/python/FlowGraph.py new file mode 100644 index 00000000..6c9b7f64 --- /dev/null +++ b/grc/src/platforms/python/FlowGraph.py @@ -0,0 +1,152 @@ +""" +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 utils import expr_utils +from .. base.FlowGraph import FlowGraph as _FlowGraph +from Block import Block +from Connection import Connection + +def get_variable_code(variable): + """ + Get the code representation for a variable. + Normally this is the value parameter. + For the variable chooser, use the index and choices. + Avoid using the to_code method of the variables, + as this forces evaluation before the variables are evaluated. + @param variable the variable block + @return the code string + """ + if variable.get_key() == 'variable_chooser': + choices = variable.get_param('choices').get_value() + value_index = variable.get_param('value_index').get_value() + return "(%s)[%s]"%(choices, value_index) + return variable.get_param('value').get_value() + +class FlowGraph(_FlowGraph): + + def _get_io_signature(self, pad_key): + """ + Get an io signature for this flow graph. + The pad key determines the directionality of the io signature. + @param pad_key a string of pad_source or pad_sink + @return a dict with: type, nports, vlen, size + """ + pads = filter(lambda b: b.get_key() == pad_key, self.get_enabled_blocks()) + if not pads: return { + 'nports': '0', + 'type': '', + 'vlen': '0', + 'size': '0', + } + pad = pads[0] #take only the first, user should not have more than 1 + #load io signature + return { + 'nports': str(pad.get_param('nports').evaluate()), + 'type': str(pad.get_param('type').evaluate()), + 'vlen': str(pad.get_param('vlen').evaluate()), + 'size': pad.get_param('type').get_opt('size'), + } + + def get_input_signature(self): + """ + Get the io signature for the input side of this flow graph. + The io signature with be "0", "0" if no pad source is present. + @return a string tuple of type, num_ports, port_size + """ + return self._get_io_signature('pad_source') + + def get_output_signature(self): + """ + Get the io signature for the output side of this flow graph. + The io signature with be "0", "0" if no pad sink is present. + @return a string tuple of type, num_ports, port_size + """ + return self._get_io_signature('pad_sink') + + 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: b.get_key() in ( + 'variable', 'variable_slider', 'variable_chooser', 'variable_text_box' + ), self.get_enabled_blocks()) + #map var id to variable block + id2var = dict([(var.get_id(), var) for var in variables]) + #map var id to variable code + #variable code is a concatenation of all param code (without the id param) + id2expr = dict([(var.get_id(), get_variable_code(var)) for var in variables]) + #sort according to dependency + sorted_ids = expr_utils.sort_variables(id2expr) + #create list of sorted variable blocks + variables = [id2var[id] for id in sorted_ids] + return variables + + 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: b.get_key() == 'parameter', self.get_enabled_blocks()) + return parameters + + def evaluate(self, expr): + """ + Evaluate the expression. + @param expr the string expression + @throw Exception bad expression + @return the evaluated data + """ + if self.is_flagged(): + self.deflag() + #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(get_variable_code(variable), n, n) + n[variable.get_id()] = e + except: pass + #make namespace public + self.n = n + #evaluate + e = eval(expr, self.n, self.n) + return e diff --git a/grc/src/platforms/python/Generator.py b/grc/src/platforms/python/Generator.py new file mode 100644 index 00000000..bd3d69cc --- /dev/null +++ b/grc/src/platforms/python/Generator.py @@ -0,0 +1,134 @@ +""" +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 os +import subprocess +from Cheetah.Template import Template +from utils import expr_utils +from Constants import \ + TOP_BLOCK_FILE_MODE, HIER_BLOCK_FILE_MODE, \ + HIER_BLOCKS_LIB_DIR, PYEXEC, \ + FLOW_GRAPH_TEMPLATE +from utils import convert_hier + +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) + 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): + #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 + """ + #execute + cmds = [PYEXEC, self.get_file_path()] + if self._generate_options == 'no_gui': + 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 + """ + imports = self._flow_graph.get_imports() + variables = self._flow_graph.get_variables() + parameters = self._flow_graph.get_parameters() + #list of variables with controls + controls = filter(lambda v: v.get_key().startswith('variable_'), variables) + #list of blocks not including variables and imports and parameters and disabled + blocks = sorted(self._flow_graph.get_enabled_blocks(), lambda x, y: cmp(x.get_id(), y.get_id())) + blocks = filter(lambda b: b not in (imports + parameters + variables), blocks) + #list of connections where each endpoint is enabled + connections = self._flow_graph.get_enabled_connections() + #list of variable names + var_ids = [var.get_id() for var in parameters + variables] + #list of callbacks (prepend self.) + callbacks = [ + expr_utils.expr_prepend(cb, var_ids, 'self.') + for cb in sum([block.get_callbacks() for block in self._flow_graph.get_blocks()], []) + ] + #map var id to the expression (prepend self.) + var_id2expr = dict( + [(var.get_id(), expr_utils.expr_prepend(var.get_make().split('\n')[0], var_ids, 'self.')) + for var in parameters + variables] + ) + #create graph structure for variables + variable_graph = expr_utils.get_graph(var_id2expr) + #map var id to direct dependents + #for each var id, make a list of all 2nd order edges + #use all edges of that id that are not also 2nd order edges + #meaning: list variables the ONLY depend directly on this variable + #and not variables that also depend indirectly on this variable + var_id2deps = dict( + [(var_id, filter(lambda e: e not in sum([list(variable_graph.get_edges(edge)) + for edge in variable_graph.get_edges(var_id)], []), variable_graph.get_edges(var_id) + ) + ) + for var_id in var_ids] + ) + #map var id to callbacks + var_id2cbs = dict( + [(var_id, filter(lambda c: var_id in expr_utils.expr_split(c), callbacks)) + for var_id in var_ids] + ) + #load the namespace + namespace = { + 'imports': imports, + 'flow_graph': self._flow_graph, + 'variables': variables, + 'controls': controls, + 'parameters': parameters, + 'blocks': blocks, + 'connections': connections, + 'generate_options': self._generate_options, + 'var_id2expr': var_id2expr, + 'var_id2deps': var_id2deps, + 'var_id2cbs': var_id2cbs, + } + #build the template + t = Template(open(FLOW_GRAPH_TEMPLATE, 'r').read(), namespace) + return str(t) diff --git a/grc/src/platforms/python/Makefile.am b/grc/src/platforms/python/Makefile.am new file mode 100644 index 00000000..e5845d0e --- /dev/null +++ b/grc/src/platforms/python/Makefile.am @@ -0,0 +1,51 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +SUBDIRS = utils + +ourpythondir = $(grc_src_prefix)/platforms/python + +ourpython_PYTHON = \ + Block.py \ + Connection.py \ + Constants.py \ + FlowGraph.py \ + Generator.py \ + Param.py \ + Platform.py \ + Port.py \ + __init__.py + +BUILT_SOURCES = Constants.py + +Constants.py: Makefile $(srcdir)/Constants.py.in + sed \ + -e 's|@PYTHONW[@]|$(PYTHONW)|g' \ + -e 's|@datadir[@]|$(grc_python_data_dir)|g' \ + -e 's|@blocksdir[@]|$(grc_python_blocks_dir)|g' \ + -e 's|@docdir[@]|$(gr_docdir)|g' \ + $(srcdir)/Constants.py.in > $@ + +EXTRA_DIST = Constants.py.in + +MOSTLYCLEANFILES = $(BUILT_SOURCES) diff --git a/grc/src/platforms/python/Param.py b/grc/src/platforms/python/Param.py new file mode 100644 index 00000000..ed5c6406 --- /dev/null +++ b/grc/src/platforms/python/Param.py @@ -0,0 +1,252 @@ +""" +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 utils import expr_utils +from .. base.Param import Param as _Param +import os + +class Param(_Param): + + _init = False + _hostage_cells = list() + + ##possible param types + TYPES = _Param.TYPES + [ + 'complex', 'real', 'int', + 'complex_vector', 'real_vector', 'int_vector', + 'hex', 'string', + 'file_open', 'file_save', + 'id', + 'grid_pos', 'import', + ] + + def get_hide(self): + """ + Get the hide value from the base class. + If hide was empty, and this is a type controller, set hide to part. + If hide was empty, and this is an id of a non variable, set hide to part. + @return hide the hide property string + """ + hide = _Param.get_hide(self) + #hide IO controlling params + if not hide and self.get_key() in ( + 'type', 'vlen', 'num_inputs', 'num_outputs' + ): hide = 'part' + #hide ID in non variable blocks + elif not hide and self.get_key() == 'id' and self.get_parent().get_key() not in ( + 'variable', 'variable_slider', 'variable_chooser', 'variable_text_box', 'parameter', 'options' + ): hide = 'part' + return hide + + def evaluate(self): + """ + Evaluate the value. + @return evaluated type + """ + 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) + assert(isinstance(e, str)) + return e + except: + self._stringify_flag = True + return v + t = self.get_type() + v = self.get_value() + ######################### + # Enum Type + ######################### + if self.is_enum(): return self.get_value() + ######################### + # Numeric Types + ######################### + elif t in ('raw', 'complex', 'real', 'int', 'complex_vector', 'real_vector', 'int_vector', 'hex'): + #raise exception if python cannot evaluate this value + try: e = self.get_parent().get_parent().evaluate(v) + except: + self._add_error_message('Value "%s" cannot be evaluated.'%v) + raise Exception + #raise an exception if the data is invalid + if t == 'raw': return e + elif t == 'complex': + try: assert(isinstance(e, (complex, float, int, long))) + except AssertionError: + self._add_error_message('Expression "%s" is invalid for type complex.'%str(e)) + raise Exception + return e + elif t == 'real': + try: assert(isinstance(e, (float, int, long))) + except AssertionError: + self._add_error_message('Expression "%s" is invalid for type real.'%str(e)) + raise Exception + return e + elif t == 'int': + try: assert(isinstance(e, (int, long))) + except AssertionError: + self._add_error_message('Expression "%s" is invalid for type integer.'%str(e)) + raise Exception + return e + elif t == 'complex_vector': + if not isinstance(e, (tuple, list, set)): + self._lisitify_flag = True + e = [e] + try: + for ei in e: + assert(isinstance(ei, (complex, float, int, long))) + except AssertionError: + self._add_error_message('Expression "%s" is invalid for type complex vector.'%str(e)) + raise Exception + return e + elif t == 'real_vector': + if not isinstance(e, (tuple, list, set)): + self._lisitify_flag = True + e = [e] + try: + for ei in e: + assert(isinstance(ei, (float, int, long))) + except AssertionError: + self._add_error_message('Expression "%s" is invalid for type real vector.'%str(e)) + raise Exception + return e + elif t == 'int_vector': + if not isinstance(e, (tuple, list, set)): + self._lisitify_flag = True + e = [e] + try: + for ei in e: + assert(isinstance(ei, (int, long))) + except AssertionError: + self._add_error_message('Expression "%s" is invalid for type integer vector.'%str(e)) + raise Exception + return e + elif t == 'hex': + return hex(e) + else: raise TypeError, 'Type "%s" not handled'%t + ######################### + # 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? + try: + assert(len(v) > 0) + assert(v[0].isalpha()) + for c in v: assert(c.isalnum() or c in ('_',)) + except AssertionError: + self._add_error_message('ID "%s" must be alpha-numeric or underscored, and begin with a letter.'%v) + raise Exception + params = self.get_all_params('id') + keys = [param.get_value() for param in params] + try: assert(len(keys) == len(set(keys))) + except: + self._add_error_message('ID "%s" is not unique.'%v) + raise Exception + return v + ######################### + # Grid Position Type + ######################### + elif t == 'grid_pos': + if not v: return '' #allow for empty grid pos + e = self.get_parent().get_parent().evaluate(v) + try: + assert(isinstance(e, (list, tuple)) and len(e) == 4) + for ei in e: assert(isinstance(ei, int)) + except AssertionError: + self._add_error_message('A grid position must be a list of 4 integers.') + raise Exception + row, col, row_span, col_span = e + #check row, col + try: assert(row >= 0 and col >= 0) + except AssertionError: + self._add_error_message('Row and column must be non-negative.') + raise Exception + #check row span, col span + try: assert(row_span > 0 and col_span > 0) + except AssertionError: + self._add_error_message('Row and column span must be greater than zero.') + raise Exception + #calculate hostage cells + for r in range(row_span): + for c in range(col_span): + self._hostage_cells.append((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 cell in param._hostage_cells: + if cell in self._hostage_cells: + self._add_error_message('Another graphical element is using cell "%s".'%str(cell)) + raise Exception + return e + ######################### + # Import Type + ######################### + elif t == 'import': + n = dict() #new namespace + try: exec v in n + except ImportError: + self._add_error_message('Import "%s" failed.'%v) + raise Exception + except Exception: + self._add_error_message('Bad import syntax: "%s".'%v) + raise Exception + 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. + @return a string representing the code + """ + #run init tasks in evaluate + #such as setting flags + if not self._init: + self.evaluate() + self._init = True + v = self.get_value() + t = self.get_type() + if t in ('string', 'file_open', 'file_save'): #string types + if self._stringify_flag: + return '"%s"'%v.replace('"', '\"') + else: + return v + elif t in ('complex_vector', 'real_vector', 'int_vector'): #vector types + 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_blocks()], []) diff --git a/grc/src/platforms/python/Platform.py b/grc/src/platforms/python/Platform.py new file mode 100644 index 00000000..c31701e0 --- /dev/null +++ b/grc/src/platforms/python/Platform.py @@ -0,0 +1,73 @@ +""" +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 os +from .. base.Constants import FLOW_GRAPH_FILE_EXTENSION +from .. base.Platform import Platform as _Platform +from FlowGraph import FlowGraph as _FlowGraph +from Connection import Connection as _Connection +from Block import Block as _Block +from Port import Source,Sink +from Param import Param as _Param +from Generator import Generator +from Constants import \ + HIER_BLOCKS_LIB_DIR, BLOCK_DTD, \ + BLOCK_TREE, DEFAULT_FLOW_GRAPH, \ + BLOCKS_DIR + +class Platform(_Platform): + + def __init__(self, block_paths_internal_only=[], block_paths_external=[]): + """ + Make a platform for gnuradio. + The internal only list will replace the current block path. + @param block_paths_internal_only a list of blocks internal to this platform + @param block_paths_external a list of blocks to load in addition to the above blocks + """ + #ensure hier dir + if not os.path.exists(HIER_BLOCKS_LIB_DIR): os.mkdir(HIER_BLOCKS_LIB_DIR) + #handle internal/only + if block_paths_internal_only: + block_paths = map(lambda b: os.path.join(BLOCKS_DIR, b), ['options.xml'] + block_paths_internal_only) + else: block_paths = [BLOCKS_DIR] + #handle external + block_paths.extend(block_paths_external) + #append custom hiers + block_paths.append(HIER_BLOCKS_LIB_DIR) + #init + _Platform.__init__( + self, + name='GNURadio Python', + key='gnuradio_python', + block_paths=block_paths, + block_dtd=BLOCK_DTD, + block_tree=BLOCK_TREE, + default_flow_graph=DEFAULT_FLOW_GRAPH, + generator=Generator, + ) + + ############################################## + # Constructors + ############################################## + FlowGraph = _FlowGraph + Connection = _Connection + Block = _Block + Source = Source + Sink = Sink + Param = _Param diff --git a/grc/src/platforms/python/Port.py b/grc/src/platforms/python/Port.py new file mode 100644 index 00000000..93fa087e --- /dev/null +++ b/grc/src/platforms/python/Port.py @@ -0,0 +1,131 @@ +""" +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 .. base.Port import Port as _Port +from ... import utils + +class Port(_Port): + + ##possible port types + TYPES = ['complex', 'float', 'int', 'short', 'byte'] + + def __init__(self, block, n): + """ + Make a new port from nested data. + @param block the parent element + @param n the nested odict + @return a new port + """ + vlen = utils.exists_or_else(n, 'vlen', '1') + nports = utils.exists_or_else(n, 'nports', '') + optional = utils.exists_or_else(n, 'optional', '') + #build the port + _Port.__init__( + self, + block=block, + n=n, + ) + self._nports = nports + self._vlen = vlen + self._optional = bool(optional) + + 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)) + assert 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: + if self.get_vlen() == 1: + return {#vlen is 1 + 'complex': '#3399FF', + 'float': '#FF8C69', + 'int': '#00FF99', + 'short': '#FFFF66', + 'byte': '#FF66FF', + }[self.get_type()] + return {#vlen is non 1 + 'complex': '#3399AA', + 'float': '#CC8C69', + 'int': '#00CC99', + 'short': '#CCCC33', + 'byte': '#CC66CC', + }[self.get_type()] + except: return _Port.get_color(self) + + def is_empty(self): + """ + Is this port empty? + An empty port has no connections. + Not empty of optional is set. + @return true if empty + """ + return not self.get_optional() and not self.get_connections() + +class Source(Port): + + def __init__(self, block, n): + self._n = n #save n + #key is port index + n['key'] = str(block._source_count) + block._source_count = block._source_count + 1 + Port.__init__(self, block, n) + + def __del__(self): + self.get_parent()._source_count = self.get_parent()._source_count - 1 + +class Sink(Port): + + def __init__(self, block, n): + self._n = n #save n + #key is port index + n['key'] = str(block._sink_count) + block._sink_count = block._sink_count + 1 + Port.__init__(self, block, n) + + def __del__(self): + self.get_parent()._sink_count = self.get_parent()._sink_count - 1 diff --git a/grc/src/platforms/python/__init__.py b/grc/src/platforms/python/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/grc/src/platforms/python/__init__.py @@ -0,0 +1 @@ + diff --git a/grc/src/platforms/python/utils/Makefile.am b/grc/src/platforms/python/utils/Makefile.am new file mode 100644 index 00000000..b12e51d8 --- /dev/null +++ b/grc/src/platforms/python/utils/Makefile.am @@ -0,0 +1,30 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +ourpythondir = $(grc_src_prefix)/platforms/python/utils + +ourpython_PYTHON = \ + convert_hier.py \ + expr_utils.py \ + extract_docs.py \ + __init__.py diff --git a/grc/src/platforms/python/utils/__init__.py b/grc/src/platforms/python/utils/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/grc/src/platforms/python/utils/__init__.py @@ -0,0 +1 @@ + diff --git a/grc/src/platforms/python/utils/convert_hier.py b/grc/src/platforms/python/utils/convert_hier.py new file mode 100644 index 00000000..49535898 --- /dev/null +++ b/grc/src/platforms/python/utils/convert_hier.py @@ -0,0 +1,78 @@ +""" +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 .. Constants import BLOCK_DTD +from .... utils import ParseXML +from .... utils import odict + +def convert_hier(flow_graph, python_file): + #extract info from the flow graph + input_sig = flow_graph.get_input_signature() + output_sig = flow_graph.get_output_signature() + parameters = flow_graph.get_parameters() + block_key = flow_graph.get_option('id') + block_name = flow_graph.get_option('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 + 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]), + ) + #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 + if int(input_sig['nports']): + sink_n = odict() + sink_n['name'] = 'in' + sink_n['type'] = input_sig['type'] + sink_n['vlen'] = input_sig['vlen'] + sink_n['nports'] = input_sig['nports'] + block_n['sink'] = sink_n + #source data + if int(output_sig['nports']): + source_n = odict() + source_n['name'] = 'out' + source_n['type'] = output_sig['type'] + source_n['vlen'] = output_sig['vlen'] + source_n['nports'] = output_sig['nports'] + block_n['source'] = source_n + #doc data + block_n['doc'] = "%s\n%s\n%s"%(block_author, block_desc, python_file) + #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/src/platforms/python/utils/expr_utils.py b/grc/src/platforms/python/utils/expr_utils.py new file mode 100644 index 00000000..40700993 --- /dev/null +++ b/grc/src/platforms/python/utils/expr_utils.py @@ -0,0 +1,137 @@ +""" +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 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_prepend(expr, vars, prepend): + """ + Search for vars in the expression and add the prepend. + @param expr an expression string + @param vars a list of variable names + @param prepend the prepend string + @return a new expression with the prepend + """ + expr_splits = expr_split(expr) + for i, es in enumerate(expr_splits): + if es in vars: expr_splits[i] = prepend + 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): + 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 AssertionError 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()) + assert indep_vars + #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) + +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/src/platforms/python/utils/extract_docs.py b/grc/src/platforms/python/utils/extract_docs.py new file mode 100644 index 00000000..dfc0b7e9 --- /dev/null +++ b/grc/src/platforms/python/utils/extract_docs.py @@ -0,0 +1,109 @@ +""" +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 .. Constants import DOCS_DIR +from lxml import etree +import os + +DOXYGEN_NAME_XPATH = '/doxygen/compounddef/compoundname' +DOXYGEN_BRIEFDESC_GR_XPATH = '/doxygen/compounddef/briefdescription' +DOXYGEN_DETAILDESC_GR_XPATH = '/doxygen/compounddef/detaileddescription' +DOXYGEN_BRIEFDESC_BLKS2_XPATH = '/doxygen/compounddef/sectiondef[@kind="public-func"]/memberdef/briefdescription' +DOXYGEN_DETAILDESC_BLKS2_XPATH = '/doxygen/compounddef/sectiondef[@kind="public-func"]/memberdef/detaileddescription' + +def extract_txt(xml, parent_text=None): + """ + Recursivly pull the text out of an xml tree. + @param xml the xml tree + @param parent_text the text of the parent element + @return a string + """ + text = xml.text or '' + tail = parent_text and xml.tail or '' + return text + ''.join( + map(lambda x: extract_txt(x, text), xml) + ) + tail + +def is_match(key, file): + """ + Is the block key a match for the given file name? + @param key block key + @param file the xml file name + @return true if matches + """ + if not file.endswith('.xml'): return False + file = file.replace('.xml', '') #remove file ext + file = file.replace('__', '_') #doxygen xml files have 2 underscores + if key.startswith('gr_'): + if not file.startswith('classgr_'): return False + key = key.replace('gr_', 'classgr_') + elif key.startswith('trellis_'): + if not file.startswith('classtrellis_'): return False + key = key.replace('trellis_', 'classtrellis_') + elif key.startswith('blks2_'): + if not file.startswith('classgnuradio_'): return False + if 'blks2' not in file: return False + file = file.replace('_1_1', '_') #weird blks2 doxygen syntax + key = key.replace('blks2_', '') + else: return False + for k, f in zip(*map(reversed, map(lambda x: x.split('_'), [key, file]))): + if k == f: continue + ks = k.split('x') + if len(ks) == 2 and f.startswith(ks[0]) and f.endswith(ks[1]): continue + if len(ks) > 2 and all(ki in ('x', fi) for ki, fi in zip(k, f)): continue + return False + return True + +def extract(key): + """ + Extract the documentation from the doxygen generated xml files. + If multiple files match, combine the docs. + @param key the block key + @return a string with documentation + """ + #get potential xml file matches for the key + if os.path.exists(DOCS_DIR) and os.path.isdir(DOCS_DIR): + matches = filter(lambda f: is_match(key, f), os.listdir(DOCS_DIR)) + else: matches = list() + #combine all matches + doc_strs = list() + for match in matches: + try: + xml_file = DOCS_DIR + '/' + match + xml = etree.parse(xml_file) + #extract descriptions + comp_name = extract_txt(xml.xpath(DOXYGEN_NAME_XPATH)[0]).strip('\n') + comp_name = ' --- ' + comp_name + ' --- ' + if key.startswith('gr_') or key.startswith('trellis_'): + brief_desc = extract_txt(xml.xpath(DOXYGEN_BRIEFDESC_GR_XPATH)[0]).strip('\n') + detailed_desc = extract_txt(xml.xpath(DOXYGEN_DETAILDESC_GR_XPATH)[0]).strip('\n') + elif key.startswith('blks2_'): + brief_desc = extract_txt(xml.xpath(DOXYGEN_BRIEFDESC_BLKS2_XPATH)[0]).strip('\n') + detailed_desc = extract_txt(xml.xpath(DOXYGEN_DETAILDESC_BLKS2_XPATH)[0]).strip('\n') + else: + brief_desc = '' + detailed_desc = '' + #combine + doc_strs.append('\n'.join([comp_name, brief_desc, detailed_desc]).strip('\n')) + except IndexError: pass #bad format + return '\n\n'.join(doc_strs) + +if __name__ == '__main__': + import sys + print extract(sys.argv[1]) diff --git a/grc/src/utils/Makefile.am b/grc/src/utils/Makefile.am new file mode 100644 index 00000000..c00102f9 --- /dev/null +++ b/grc/src/utils/Makefile.am @@ -0,0 +1,29 @@ +# +# Copyright 2008 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/grc/Makefile.inc + +ourpythondir = $(grc_src_prefix)/utils + +ourpython_PYTHON = \ + converter.py \ + ParseXML.py \ + __init__.py diff --git a/grc/src/utils/ParseXML.py b/grc/src/utils/ParseXML.py new file mode 100644 index 00000000..71f8c527 --- /dev/null +++ b/grc/src/utils/ParseXML.py @@ -0,0 +1,100 @@ +""" +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 .. utils import odict + +XMLSyntaxError = etree.XMLSyntaxError + +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 + """ + if dtd_file: + dtd = etree.DTD(dtd_file) + xml = etree.parse(xml_file) + if not dtd.validate(xml.getroot()): + raise XMLSyntaxError, '\n'.join(map(str, dtd.error_log.filter_from_errors())) + else: + parser = etree.XMLParser(dtd_validation=True) + xml = etree.parse(xml_file, parser=parser) + if parser.error_log: + raise XMLSyntaxError, '\n'.join(map(str, parser.error_log.filter_from_errors())) + +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/src/utils/__init__.py b/grc/src/utils/__init__.py new file mode 100644 index 00000000..21af4a8b --- /dev/null +++ b/grc/src/utils/__init__.py @@ -0,0 +1,56 @@ +""" +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 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 exists_or_else(d, key, alt): + if d.has_key(key): return d[key] + else: return alt + +def listify(d, key): + obj = exists_or_else(d, key, []) + if isinstance(obj, list): return obj + return [obj] diff --git a/grc/src/utils/converter.py b/grc/src/utils/converter.py new file mode 100644 index 00000000..d0ff94e6 --- /dev/null +++ b/grc/src/utils/converter.py @@ -0,0 +1,247 @@ +""" +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 .. platforms.base.Constants import FLOW_GRAPH_DTD +import ParseXML +from .. utils import odict +from lxml import etree +import difflib +import os + +def _make_param(key, value): + """ + Make a paramater dict from the key/value pair. + @param key the key + @param value the value + @return a dictionary object + """ + param = odict() + param['key'] = key + param['value'] = value + return param + +def _get_blocks(blocks, tag): + """ + Get a list of blocks with the tag. + @param blocks the old block list + @param tag the tag name + @retun a list of matching blocks + """ + return filter(lambda b: b['tag'] == tag, blocks) + +def _get_params(block): + """ + Get a list of params. + @param block the old block + @retun a list of params + """ + params = Utils.exists_or_else(block, 'params', {}) or {} + params = Utils.listify(params, 'param') + return params + +def _convert_id(id): + """ + Convert an old id to a new safe id. + Replace spaces with underscores. + Lower case the odl id. + @return the reformatted id + """ + return id.lower().replace(' ', '_') + +def convert(file_path, platform): + """ + Convert the flow graph to the new format. + Make a backup of the old file. + Save a reformated flow graph to the file path. + If this is a new format flow graph, do nothing. + @param file_path the path to the saved flow graph + @param platform the grc gnuradio platform + """ + try: #return if file passes validation + ParseXML.validate_dtd(file_path, FLOW_GRAPH_DTD) + try: + changed = False + #convert instances of gui_coordinate and gui_rotation + xml = etree.parse(file_path) + for find, replace in ( + ('gui_coordinate', '_coordinate'), + ('gui_rotation', '_rotation'), + ): + keys = xml.xpath('/flow_graph/block/param[key="%s"]/key'%find) + for key in keys: + key.text = replace + changed = True + if not changed: return + #backup after successful conversion + os.rename(file_path, file_path+'.bak') + #save new flow graph to file path + xml.write(file_path, xml_declaration=True, pretty_print=True) + except Exception, e: print e + return + except: pass #convert + ############################################################ + # extract window size, variables, blocks, and connections + ############################################################ + old_n = ParseXML.from_file(file_path)['flow_graph'] + try: window_width = min(3*int(old_n['window_width'])/2, 2048) + except: window_width = 2048 + try: window_height = min(3*int(old_n['window_height'])/2, 2048) + except: window_height = 2048 + window_size = '%d, %d'%(window_width, window_height) + variables = Utils.exists_or_else(old_n, 'vars', {}) or {} + variables = Utils.listify(variables, 'var') + blocks = Utils.exists_or_else(old_n, 'signal_blocks', {}) or {} + blocks = Utils.listify(blocks, 'signal_block') + connections = Utils.exists_or_else(old_n, 'connections', {}) or {} + connections = Utils.listify(connections, 'connection') + #initialize new nested data + new_n = odict() + new_n['block'] = list() + new_n['connection'] = list() + ############################################################ + # conversion - options block + ############################################################ + #get name + about_blocks = _get_blocks(blocks, 'About') + if about_blocks: title = _get_params(about_blocks[0])[0] + else: title = 'Untitled' + #get author + if about_blocks: author = _get_params(about_blocks[0])[1] + else: author = '' + #get desc + note_blocks = _get_blocks(blocks, 'Note') + if note_blocks: desc = _get_params(note_blocks[0])[0] + else: desc = '' + #create options block + options_block = odict() + options_block['key'] = 'options' + options_block['param'] = [ + _make_param('id', 'top_block'), + _make_param('title', title), + _make_param('author', author), + _make_param('description', desc), + _make_param('window_size', window_size), + _make_param('_coordinate', '(10, 10)'), + ] + #append options block + new_n['block'].append(options_block) + ############################################################ + # conversion - variables + ############################################################ + x = 100 + for variable in variables: + key = variable['key'] + value = variable['value'] + minimum = Utils.exists_or_else(variable, 'min', '') + maximum = Utils.exists_or_else(variable, 'max', '') + step = Utils.exists_or_else(variable, 'step', '') + x = x + 150 + coor = '(%d, %d)'%(x, 10) + var_block = odict() + if minimum and maximum: #slider varible + #determine num steps + try: num_steps = str(int((float(maximum) - float(minimum))/float(step))) + except: num_steps = '100' + var_block['key'] = 'variable_slider' + var_block['param'] = [ + _make_param('id', key), + _make_param('value', value), + _make_param('min', minimum), + _make_param('max', maximum), + _make_param('num_steps', num_steps), + _make_param('_coordinate', coor), + ] + else: #regular variable + var_block['key'] = 'variable' + var_block['param'] = [ + _make_param('id', key), + _make_param('value', value), + _make_param('_coordinate', coor), + ] + #append variable block + new_n['block'].append(var_block) + ############################################################ + # conversion - blocks + ############################################################ + #create name to key map for all blocks in platform + name_to_key = dict((b.get_name(), b.get_key()) for b in platform.get_blocks()) + for block in blocks: + #extract info + tag = block['tag'] + #ignore list + if tag in ('Note', 'About'): continue + id = _convert_id(block['id']) + coor = '(%s, %s + 100)'%( + Utils.exists_or_else(block, 'x_coordinate', '0'), + Utils.exists_or_else(block, 'y_coordinate', '0'), + ) + rot = Utils.exists_or_else(block, 'rotation', '0') + params = _get_params(block) + #new block + new_block = odict() + matches = difflib.get_close_matches(tag, name_to_key.keys(), 1) + if not matches: continue + #match found + key = name_to_key[matches[0]] + new_block['key'] = key + new_block['param'] = [ + _make_param('id', id), + _make_param('_coordinate', coor), + _make_param('_rotation', rot), + ] + #handle specific blocks + if key == 'wxgui_fftsink2': + params = params[0:3] + ['0'] + params[3:4] + ['8'] + params[4:] + #append params + for i, param in enumerate(params): + platform_block = platform.get_block(key) + try: platform_param = platform_block.get_params()[i+2] + except IndexError: break + if platform_param.is_enum(): + try: param_value = platform_param.get_option_keys()[int(param)] + except: param_value = platform_param.get_option_keys()[0] + else: + param_value = param.replace('$', '').replace('^', '**') + new_block['param'].append(_make_param(platform_param.get_key(), param_value)) + #append block + new_n['block'].append(new_block) + ############################################################ + # conversion - connections + ############################################################ + for connection in connections: + #extract info + input_signal_block_id = connection['input_signal_block_id'] + input_socket_index = connection['input_socket_index'] + output_signal_block_id = connection['output_signal_block_id'] + output_socket_index = connection['output_socket_index'] + #new connection + new_conn = odict() + new_conn['source_block_id'] = _convert_id(output_signal_block_id) + new_conn['sink_block_id'] = _convert_id(input_signal_block_id) + new_conn['source_key'] = output_socket_index + new_conn['sink_key'] = input_socket_index + #append connection + new_n['connection'].append(new_conn) + ############################################################ + # backup and replace + ############################################################ + #backup after successful conversion + os.rename(file_path, file_path+'.bak') + #save new flow graph to file path + ParseXML.to_file({'flow_graph': new_n}, file_path)